Weekoding

[Swift] How to Debugging 2(Console, Logger) 본문

공부 노트(Swift)

[Swift] How to Debugging 2(Console, Logger)

Weekoding 2024. 3. 3. 02:48

1편 - https://weekoding.tistory.com/18

 

[Swift] How to Debugging(LLDB, breakpoint)

Android Studio나 Xcode 등의 개발툴을 사용하게 되었을 때를 돌이켜보면, 바다에 무작정 입수하는 느낌이었던 것 같다. 여러 컴포넌트를 여러 레이아웃으로 만들어 보고, 여러 에러들과 직접 몸통박

weekoding.tistory.com

 

Xcode에서 Build하는 환경이 아니라, 실 사용 기기에서 App을 다운받아 구동하는 환경에서 디버깅이 필요한 경우가 있었다.

이 때는 breakpoint로 확인하는 것이 불가능했기에, 디버깅을 할 수 있는 다른 방법을 물색하던 도중 요놈을 알게 되었다. 

두-둥 탁!

 

 

📂  Console.app

로그메시지를 확인하고, 공유할 수 있는 기능을 갖춘 기본 App

 

https://support.apple.com/ko-kr/guide/console/welcome/mac

 

Mac용 콘솔 사용 설명서

Mac의 콘솔을 사용하여 Mac 및 연결된 기기에 관한 시스템 정보를 제공하는 로그 메시지 및 리포트를 찾아보는 방법을 알아보십시오.

support.apple.com

위 웹사이트에 console.app에 대한 개요와 사용법이 나와있다. 

 

앱을 켜보면, 어렵지 않다. 직관적으로 많은 것들을 알 수 있다.

'스트리밍 시작'을 누르게 되면 기본적으로 출력되는 로그들이 촤 라 라 락 찍힌다.

 

이는 Terminal에서 'log stream' 명령어를 입력한 것과 같다.

Terminal은 가독성이 떨어지고, 검색/분류가 어려우니 consol을 사용하는 것이다.

 

로그 메시지의 유형은 '유형 열'에 점으로 표시되며, 색상별로 다음의 의미를 지닌다.(색상이 없다면 기본 로그 메시지)

빨간색 : 장애 로그 메시지

노란색 : 오류 로그 메시지

어두운 회색 : 디버그 로그 메시지

밝은 회색 : 정보 로그 메시지

 

검색하는 방법도 쉽다. 우측 상단의 검색창에 입력을 통해 가능하며, 검색 후에 카테고리를 설정하여 결과를 더 세분화 할 수 있다.

💡 날짜 및 시간 검색 필터를 사용하려면 날짜를 YYYY-MM-DD 포맷으로 입력해야 한다. 💡

ex) 2024년 3월 02일의 경우 : 2024-03-02

 

좌측에는 기기에서 출력되는 로그 메시지 뿐만 아니라 '리포트'도 확인할 수 있는데, 메뉴별 내용은 다음과 같다.

  • 충돌 리포트 : 충돌하는 앱 및 프로세스에 관한 시스템 및 사용자 리포트(.ips)
  • 멈춤(Spin) 리포트 : 앱 또는 프로세스 문제에 관한 세부사항이 있는 시스템 및 사용자 리포트(.spin)
  • 로그 리포트 : 시스템 또는 특정 앱이 진행될 때 발생하는 이벤트에 관한 정보가 있는 시스템 및 사용자 리포트(.log, ._log or .its)
  • 진단 리포트 : 하드웨어 리소스, 시스템 응답 시간 등에 관한 정보가 있는 시스템 및 사용자 리포트 진단 리포트(.diag or .dpsub)
  • Mac 분석 데이터 : /var/log/DiagnosticMessages 경로에 있는 Message Tracer Store 데이터 콘텐츠
  • system.log : /private/var/log/system.log.에 있는 레거시 시스템 로그 파일 콘텐츠

사용자 리포트는 현재 사용자가 사용하는 앱을 기반으로 하며,  

시스템 리포트는 모든 사용자에게 적용되는 운영 체제 구성 요소를 기반으로 한다.

 

 

📂  Logger

'Logging'에 관련하여, Apple Developer 문서를 살펴보면

Create a Log Object to Organize Messages 항목에 다음과 같은 글이 있다.

In Swift, create a Logger structure and use its methods to generate log messages.
In Objective-C, create an OSLog object and pass it to logging functions.

Swift에서는, Logger structure를 생성 및 해당 메소드를 사용하여 로그 메시지를 생성하세요.
Objective-C에서는, OSLog object를 생성하고 logging 함수로 전달하세요.

 

이러한 통합 로깅 시스템(unified logging system)은  작성시간 기준 iOS 10.0 and later, macOS 10.12 이상에서 사용 가능하다.

 

사용 및 출력 방법은 간단하다.

import UIKit
import OSLog //import Framework

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let logger = Logger() //Logger instance
        let x = "WEEKODING0303"
        
        logger.log("log test : plain \(x)")
    }
}

이러면 print문처럼 Xcode에 로그가 찍히면서 console.app에도 로그가 남는다. 사용이 정말 쉽고 편리하다.

그러나 이렇게 단순한 출력만 지원하는 것이 아니다. 좀 더 깊게 알아보자.

 

 

OSLogType

The various log levels that the unified logging system provides.
통합 로깅 시스템에서 제공하는 다양한 로그 레벨의 structure

 

.log 메소드를 사용할 때, 메시지만을 출력할 수 있지만 동시에 Log의 level을 지정할 수도 있다.

logger.log(level: OSLogType, "message")

 

종류는 .debug / .info / .default / .error / .fault 가 있다.

logger.log(level: .debug, "OSLogLevel : .debug")
logger.log(level: .default, "OSLogLevel : .default")
logger.log(level: .error, "OSLogLevel : .error")
logger.log(level: .fault, "OSLogLevel : .fault")
logger.log(level: .info, "OSLogLevel : .info")

info, debug level은 consol에 출력되지 않는다. 또한, error와 fault는 유형에 색상이 붙는다.

다양한 OSLogType을 이용하여 좀 더 직관적으로 로그를 확인 / 분류할 수 있다.

 

 

OSLogPrivacy

Xcode의 자동완성 기능을 통해 Logger를 막 뒤져보다가 이런 녀석을 발견했다.

The OSLogPrivacy structure determines the visibility of interpolated values in log messages.
Because people have access to log messages that your app generates,
use the privacy options to hide potentially sensitive information.
For example, you might use it to hide account information or personal data.

OSLogPrivacy 구조체는 log messages의 내용 중 보간법으로 되어있는 값에 대한 visibility를 결정합니다.
당신의 앱이 동작할 때 log message에 접근할 수 있는 권한이 있기 때문에,
privacy options를 사용하여 잠재적으로 (노출에)예민할 수 있는 정보를 숨겨야합니다.
예를 들어, 출력되는 개인정보나 계정정보를 숨기는데 이용될 것입니다.
logger.log("\(var, privacy: OSLogPrivacy)")

 

.auto : system이 value를 수정할지 표기할지 결정하는 standard option

.public : 보간(interpolated)된 value를 항상 표기하는 standard option

.private : 보간(interpolated)된 value를 항상 수정하는 standard option

.sensitive : 보간(interpolated)된 민감한 value를 항상 수정하는 standard option

 

OSLogPrivacy.Mask

A mask that establishes how the system displays a redacted value in a log message.

log message 내의 수정된 값을 system이 어떻게 표현하는지 설정하는 Mask.

 

- hash : hashed version으로 된 string으로 수정된 값을 대체

- none : generic string으로 수정된 값을 대체

logger.log("log test : plain \(x)")
logger.log("log test : .public \(x, privacy: .public)")
logger.log("log test : .private \(x, privacy: .private)")
logger.log("log test : .sensitive \(x, privacy: .sensitive)")
logger.log("log test : .auto .hash \(x, privacy: .auto(mask: .hash))")
logger.log("log test : .private .none \(x, privacy: .private(mask: .none))")

?????????

왜 모두 결과값이 똑같을까...???

아하..! 구글링 해보니 Simulator에서는 .private나 hash를 먹여도 <private>나 hash값으로 log가 출력되지 않는다고 한다.

실기기로 돌리면 정상적으로 적용되는 것을 확인할 수 있다.

Simulator도 어엿한 기기인데!

 

 

그 외 메소드 :

OSLogType이 지정된 메소드들이 있다. 

- Logger.info(OSLogMessage) : 정보(plain)가 담긴 message를 전달

- Logger.error(OSLogMessage): error에 대한 정보가 담긴 message를 전달

- Logger.warning(OSLogMessage) : 경고에 대한 정보가 담긴 message를 전달

- Logger.critical(OSLogMessage) : app 실행 중 치명적인 이벤트가 발생했을 때 log message를 전달

- Logger.notice(OSLogMessage) : default type의 log message를 전달

- Logger.fault(OSLogMessage) : app 실행 중 bug가 발생했을 때 log message를 전달

.info는 console에서 출력되지 않는다.

 

 

 

🗝 Maybe..

Logging API는 기기의 내부가 아닌 console.app에서 App의 Runtime동안 끊임없이 메시지를 계속 출력하기 때문에, 

다음 상황에서 쓰면 정말 유용하다고 한다.

- When you are unable to attach a debugger to the app, such as when you’re diagnosing problems on a user’s machine.
- When the problem is intermittent, and is difficult to catch in the debugger.
- When you want to get a general sense of your app’s behavior—for example, you want to know when certain tasks start and end.

- User의 기기에서의 확인이 필요할 때
- 현상이 간헐적으로 발생할 때
- 특정 작업이 어디서부터 시작하고 끝나는지 확인해야 할 때

 

 

 

📌 마치며

공부하면서 그래 이거야! 싶었다

이전에 공부했던 breakpoint의 한계점을 극복할 수 있는 방법이고, 기본적으로 지원하는 API라서

단순 기기를 연결을 통해 확인할 수 있다는 점도 너무 편리한 것 같다.

 

 

 

오류 및 지적사항은 댓글로 남겨주시면 감사하겠습니다!

참고 : 

https://leeari95.tistory.com/62#google_vignette

https://sunidev.tistory.com/77

https://hururuek-chapchap.tistory.com/244

https://developer.apple.com/documentation/os/logging

https://stackoverflow.com/questions/62901969/os-logger-os-log-ignores-the-new-privacy-string-interpolation

Comments