-
debugPrint와 print 알고쓰기 (feat. dump)Swift 2023. 5. 8. 09:21
안녕하세요. 그린입니다🍏
이번 포스팅에서는 debugPrint와 print에 대해 알아보려 합니다 (조금 더 나아가서 간단히 dump까지!)🙋🏻
사실 많은 iOS 개발자라면 이미 익숙하고 차이도 잘 아실텐데 한번 확실히 좀 더 명확하게 왜 로깅용으로 debugPrint를 써야하는지 그리고 모든 로깅 상황에서 debugPrint를 가져가는게 좋은건지 정리해보려고 이번 포스팅의 주제로 가져와봤습니다🕺🏻
그럼 우선 개념적으로 간단하게 짚고 넘어가야하니 debugPrint와 print의 개념부터 훑어보시죠!
debugPrint
우선 공식문서에서는 디버깅에 가장 적합한 텍스트 표현을 출력에 사용한다고 아주 로깅용으로 써라!라고 대놓고 강조하고 있는 느낌입니다😲
선언을 보시면 아래와 같습니다.
func debugPrint( _ items: Any..., separator: String = " ", terminator: String = "\n" )
어디선가 많이 보신것 같지 않나요? 이후 나오겠지만 이 선언은 print와 다를게 없습니다!
공통적으로 모든 항목들이 출력된 후 개행시켜주도록 terminator가 달려있습니다.
그럼 바로 이어서 print는 어떻게 생겨먹었는지 볼까요?
print
debugPrint에서 로깅용을 강조했다면 print에서는 그냥 주어진 항목의 텍스트 표현 출력을 위해 사용한다고 해요.
어떻게 보면 print가 조금 더 포괄적인 느낌이죠.
선언은 아래와 같아요.
func print( _ items: Any..., separator: String = " ", terminator: String = "\n" )
debugPrint와 동일하죠?
그럼 알겠으니 이 둘의 차이를 실제 로깅을 해보면서 찾아보겠습니다!
debugPrint와 print의 출력 차이
우선 간단하게 문자열을 출력해볼께요.
let value: String = "Green is Green" debugPrint(value) print(value) // "Green is Green" // Green is Green
debugPrint는 문자열임으로 ""가 붙어 해당 지금 로깅 출력한 친구가 String 값이라는걸 출력을 통해 알 수 있죠.
반면 print는 그냥 그 문자열이 갖는 값 그대로를 출력합니다.
지금은 사실 print로 출력을 해도 Green is Green이라는 값은 누가봐도 String이기에 헷갈리는게 더 어렵다고 쳐볼께요.
그럼 아래와 같을때는 어떨까요?
let value: String = "123123" print(value) // 123123
이렇게 보면 실제 print를 사용해 로깅 시 해당 값이 만약 알파벳 문자열이 아니라 "123123"과 같은 숫자 문자열이라면 이게 String인지 Int값인지 헷갈릴 수 있을거에요.
그럼 조금 더 나아가볼께요.
아래와 같이 1~10까지의 숫자 범위를 출력할 때는 어떨까요?
debugPrint(1...10) print(1...10) // ClosedRange(1...10) // 1...10
debugPrint가 명확하게 어떤 타입인지 출력해주고 있습니다.
이처럼 로깅 시에는 타입 미스매치 오류가 있을 수 있기에 확실히 타입 정보까지 준다면 더 명확할 수 있을거에요.
그럼 사실 디버그 로깅을 많이 하는 통신에서는 어떤게 좀 더 이점이 있을지 살펴볼까요?
let urlReq = URLRequest(url: URL(string: "https://itunes.apple.com/search?term=jack+johnson&limit=1")!) Alamofire.request(urlReq).responseJSON { (data) in print("Print 로깅") print(data) print("=========") print("debugPrint 로깅") debugPrint(data) }
요렇게 실제 통신하여 받아온 data를 출력할때 차이를 보시죠.
print 로깅의 경우 아래와 같이 실제 전달되는 data의 핵심 정보만 노출시켜 줍니다.
SUCCESS: { resultCount = 1; results = ( { artistId = 909253; artistName = "Jack Johnson"; artistViewUrl = "https://itunes.apple.com/us/artist/jack-johnson/id909253?uo=4"; } ); }
반면 debugPrint 로깅의 경우는 어떤 request였고 response로 온 상세한 정보들을 다 담아서 보내주죠.
[Request]: GET https://itunes.apple.com/search?term=jack+johnson&limit=1 [Response]: <NSHTTPURLResponse: 0x610000223860> { URL: https://itunes.apple.com/search?term=jack+johnson&limit=1 } { status code: 200, headers { "Access-Control-Allow-Origin" = "*"; "Cache-Control" = "max-age=86345"; Connection = "keep-alive"; "Content-Disposition" = "attachment; filename=1.txt"; "Content-Length" = 1783; "Content-Type" = "text/javascript; charset=utf-8"; Date = "Sat, 23 Sep 2017 14:29:11 GMT"; "Strict-Transport-Security" = "max-age=31536000"; Vary = "Accept-Encoding"; "X-Apple-Partner" = "origin.0"; "X-Cache" = "TCP_MISS from a23-76-156-143.deploy.akamaitechnologies.com (AkamaiGHost/9.1.0.4-20866905) (-)"; "X-Cache-Remote" = "TCP_MISS from a23-45-232-92.deploy.akamaitechnologies.com (AkamaiGHost/9.1.0.4-20866905) (-)"; "X-True-Cache-Key" = "/L/itunes.apple.com/search ci2=limit=1&term=jack+johnson__"; "apple-originating-system" = MZStoreServices; "apple-seq" = 0; "apple-timing-app" = "86 ms"; "apple-tk" = false; "x-apple-application-instance" = 1000492; "x-apple-application-site" = NWK; "x-apple-jingle-correlation-key" = VEF3J3UWCHKUSGPHDZRI6RB2QY; "x-apple-orig-url" = "https://itunes.apple.com/search?term=jack+johnson&limit=1"; "x-apple-request-uuid" = "a90bb4ee-9611-d549-19e7-1e628f443a86"; "x-apple-translated-wo-url" = "/WebObjects/MZStoreServices.woa/ws/wsSearch?term=jack+johnson&limit=1&urlDesc="; "x-content-type-options" = nosniff; "x-webobjects-loadaverage" = 0; } } [Data]: 1783 bytes [Result]: SUCCESS: { resultCount = 1; results = ( { artistId = 909253; artistName = "Jack Johnson"; artistViewUrl = "https://itunes.apple.com/us/artist/jack-johnson/id909253?uo=4"; } ); } [Timeline]: Timeline: { "Request Start Time": 527869893.013, "Initial Response Time": 527869893.033, "Request Completed Time": 527869893.034, "Serialization Completed Time": 527869893.035, "Latency": 0.020secs, "Request Duration": 0.021secs, "Serialization Duration": 0.001secs, "Total Duration": 0.021secs }
사실 필요한 data 정보만 로깅한다면 print로도 충분하겠지만 실제 에러가 났을때 로그로 파악이 필요하다면 어떤게 누락되고 잘못되었는지 또 타임아웃은 걸리지 않았는지 등 더 상세하고 유용한 정보를 봐야할때가 많을거에요.
이럴때는 debugPrint가 확실한 이점을 가져갈 수 있습니다.
즉 정리해보자면 단순한 로깅 시 분기처리 혹은 여기서부터 로그 시작입니다~ 같은 타입 등과 같은 상세한 정보가 필요하지 않은 부분은 print가 조금 더 깔끔할 수 있고 실제 타입 및 상세한 정보가 필요한 로깅에서는 debugPrint를 사용하는게 적절할 것 같아요!
이 이점 때문에 애플에서도 로깅 시에는 debugPrint를 권장하는것 같습니다.
그럼 마무리로 dump라는것도 많이 보셨을것 같은데 어떨때 쓰게 될까요?
dump
dump는 mirror라는 개념을 사용해 주어진 객체의 정보를 출력해줍니다.
쉽게 말해 객체를 조금 더 보기 좋게 가공해서 출력해줄 수 있다는것이죠.
선언은 아래와 같아요.
@discardableResult func dump<T>( _ value: T, name: String? = nil, indent: Int = 0, maxDepth: Int = .max, maxItems: Int = .max ) -> T
이 dump를 사용할때와 print를 사용할때의 차이를 봐볼까요?
struct Person{ var name = "Green" var age = 10 var footSize = 290.5 } let green = Person() print(green) dump(green) // Person(name: "Green", age: 10, footSize: 290.5) // ▿ Project.Person // - name: "Green" // - age: 10 // - footSize: 290.5
보시면 위 print를 사용하여 green 객체 정보를 출력하는것보다 dump를 사용한다면 조금 더 가공되어 보여주게 됩니다.
요럴때 dump를 적절히 사용하면 좋을것 같아요.
마무리
너무나 당연하게 사용하는것들에 대해 조금 더 명확한 기준을 세우고자 한번 정리해봤습니다!
이럴땐 이렇게 사용한다 라는 명확한 답보다는 개인적으로 기준을 잘 세우면 좋을것 같습니다🙌
[참고 자료]
https://developer.apple.com/documentation/swift/debugprint(_:separator:terminator:)
https://developer.apple.com/documentation/swift/print(_:separator:terminator:)
https://developer.apple.com/documentation/swift/dump(_:name:indent:maxdepth:maxitems:)
https://stackoverflow.com/questions/41826683/print-vs-debugprint-in-swift
'Swift' 카테고리의 다른 글
@discardableResult를 왜 쓰지? (8) 2023.06.01 Mirror (15) 2023.05.16 Swift 5.8 (4) 2023.04.04 compare과 ComparisonResult (5) 2023.02.08 CGFloat (3) 2023.01.20