상세 컨텐츠

본문 제목

[iOS] WWDC 20: Explore logging in Swift

iOS

by 홍루피 2025. 6. 1. 23:04

본문

요즘 오류를 쉽게 찾기 위해서 어떤식으로 로그를 찍어야 하는지 관심이 생겨서 찾아본 영상을 정리함

로깅을 해야 하는 이유는 무엇일까?

1. 재생성하기 어려운 버그를 재생할 필요 없이 파악하고, 이해하는데 도움을 줌

2. 로그는 운영체제에 의해 보관되어 장치에서 검색이 가능

3. 성능 저하 없이 사용 가능

로깅은 어떻게 할 수 있을까?

1. os 모듈 import 

2. Logger 인스턴스를 만들어 서브시스템, 카테고리를 전달

     - 서브시스템은 주로 번들 아이디로 구성

     - 카테고리는 프로그램의 다른 부분에서 오는 오류 메시지를 구별하기 위해 사용

3. 문자열 보간을 사용해 런타임 데이터 추가 가능

 

print와 다른점

로그메시지는 느리기 때문에 문자열로 완전히 변환되지 않음

* 대신 컴파일러와 로깅 라이브러리가 함께 작동하여 최적화된 표현을 생성

최적화된 표현을 사용한다면, 로그 메시지가 실제로 표시될 때만 문자열로 변환하는 비용을 지불

 

로그 메시지에 포함되는 다양한 타입

1. Int, Double, Objc 객체와 같은 숫자 유형

2. Swift의 CustomStringConvertible을 준수하는 모든 유형

* CustomStringConvertible만 준수한다면 유형 추가가 자유롭게 가능

3. 문자열이나 객체와 다른 유형은 기본적으로 로그에서 편집됨

     - 로그에 계좌정보 같은 개인정보가 표시되지 않게 하기 위함

     - privacy 인자에 public을 설정하면 값을 표시하게 할 수 있음

 

커맨드 라인드로 기기에 저장된 로그 가져오기

앱이 메시지를 기록하면 운영체제는 장치에 압축된 형태로 저장

콘솔 앱에서 로그 아카이브를 두 번 클릭하여 열 수 있음

 

로그 레벨

debug: 디버깅 중에만 유용한 메시지

info: 도움은 되지만 문제 해결 오류에 필수적이지 않은 메시지

notice: 문제해결에 절대적으로 필수적인 메시지

error: 실행 중 발생하는 오류 기록 → 콘솔앱 노란색 버블 강조

fault: 심각한 에러 메시지, 잠재적 버그로 인해 발생화는 상황을 기록 → 콘솔앱 빨간색 버블 강조

 

레벨을 설정하기 위해서는 레벨을 설정하려면 logger.debug(_ messge:) 와 같이 사용

 

로그의 지속성

로그메시지 보관 여부와, 앱 실행 이후 검색을 할 수 있는 지에 대한 여부

지속되지 않은 로그는 실행중인 경우에만 스트리밍 가능

메시지의 지속 여부 = 로그 레벨에 따라 다름 → 중요도에 따라 지속성 증가

 

레벨에 따른 지속성

debug: 지속되지 않음. 앱 실행 완료 이후에는 검색이 불가능

info: 로그 수집 명령 전 잠시 생성된 경우 제외, 대부분 지속되지 않음

notice, error, fault: 지속되며 나중에 검색 가능

 

보관 시일

보관 메시지 수에 대한 저장 제한이 있음 → 오래된 것은 제거되어 사용 불가

일반적으로 메시지는 며칠동안 지속되나 장치 저장공간에 따라 보관 시일이 다름

 

로그레벨에 따른 성능

로그레벨과 성능은 반비례. 덜 중요한 수준이 더 빠름

기본적으로 로깅은 오버헤드가 낮지만 로그레벨은 서로의 성능이 다름

  • 오류 레벨이 가장 느리고, 디버그 레벨이 성능이 가장 좋음
  • 디버그 메시지는 지속되지 않기 때문에 로깅이 훨씬 빠름 → 디버깅 되고 폐기
  • 디버그 레벨에서 비용이 많이 드는 메시지를 구성할 수 있음 → 사용자가 비용을 지불하지 않음

가독성을 높이기 위한 로그 데이터 포맷 제공

숫자 및 문자열과 같은 원시데이터는 해석이 어려울 수 있으므로  런타임 비용없이 가독성을 위해 데이터를 형식화 하는 방법 제공

서버에 따라 데이터 조회 시간 통계를 내기 위해 로깅을 사용할 수 있음

가독성을 높여 로그를 찾기 쉽게 하기 위해 포맷팅을 할 수 있음

기프트 카드 식별자를 고정범위로 만들고 소숫점 둘째까지만 보여지도록 고정

format 과 align 매개변수를 사용해 포맷을 변경할 수 있음. 이 포맷변경은 비용을 지불하지 않음

이외에도 16진수, 지수 등으로 형식화 등 다양한 옵션을 제공하고 있음

 

사용자의 민감정보는 Public으로 설정하지 말것

로깅은 항상 발생하기 때문에 민감정보는 로깅하지 말것

해시를 사용해 공개하는 것과 같은 이점을 얻을 수 있음

* 해시를 사용하면 계정 정보를 공개하지 않고 동일한 계좌를 참조하는 시점을 찾을 수 있음

 

Logger 사용 가능 버전

iOS 14 이상

이전 버전에서는 os_log 사용이 가능


+ 추가: WWDC 2023: Debug with structured logging 에서 소개된 내용들

Xcode 15의 디버그 콘솔의 변경점

메타데이터 옵션을 통해 로그에 대한 서브시스템, 카테고리, 라이브러리 등에 대한 정보를 확인할 수 있음

또한 로그라인에 보면 우측 하단에 소스코드 위치가 출력되고 있음. 클릭 시 해당 로그를 출력하는 곳으로 바로 이동이 가능

 

단일 로그에 대한 메타데이터는 스페이스 + 해당 로그라인 클릭으로 확인해볼 수 있음

로그를 전송한 함수 이름도 확인해 볼 수 있음

특정 로그라인에서 우클릭을 할 경우에 비슷한 로그 아이템을 보여주거나, 숨길 수 있는 기능도 제공

하단 필터링 콘솔을 이용해서도 내가 원하는 로그에 관련해서 필터링을 할 수 있음

 

LLDB + Log를 사용한 오류 해결

로깅을 통해 클래스의 값이 변경되지 않는 오류를 확인하고, 해당 지점으로 이동

해당 지점에 브레이크 포인트를 걸고 LLDB 명령어 po를 사용해 해당 객체를 디버깅 

* 해당 객체가 Custom Debug Description을 제공하지 않기 때문에 주소값만 나오게 됨 -> p를 사용해서 디버깅

데이터베이스 업데이트만으로는 값이 변경되지 않기 때문에 account 객체의 값을 새로운 값으로 갱신해야함

따라서 갱신해주는 코드를 추가해주고 다시 디버깅을 해보면 값이 정상적으로 변경되는 것을 알 수 있음

 

Xcode15의 LLDB 변경점

적절하지 않은 곳에 po를 사용하면 표현식 수행이 더 오래 걸릴 수도 있지만 최악의 경우 프로퍼티 주소만 반환(CustomStringConvertible 구현을 하지 않았다면)

그 외에도 v, vo, frame variable 등 기억해야 하는 다른 커맨드가 많음

그래서 Do What I Mean Print(dwin-print)를 소개하게 되었음

 

Do What I Mean Print?

한 가지 명령으로 다양한 표현식을 평가해 시간 절약과 빠른 결과 반환

변수를 검사할 때마다 이 긴 커맨드를 입력할 필요가 없음

"p"나 "po"로 해당 커맨드를 대체할 수 있게 제공

 

로깅에 관한 팁

1. print 말고 메타데이터를 얻을 수 있는 OSLog를 사용할 것

2. 앱의 다양한 요소마다 별도의 로그 핸들을 만들것

-> 그래야 중요 검색어를 설정해 앱의 섹션과 관련이 높은 로그를 찾기 쉬움

3. OSLogStore를 활용하면 실제로 앱에 문제가 생겼을 때 유용한 진단 정보 수집이 가능

4. OSLog는 추적도구이므로 instruments와 함께 사용해 복잡한 성능 분석이 가능

 

참고자료

'iOS' 카테고리의 다른 글

[iOS] CoreBluetooth 블루투스 권한 처리에 대한 고찰  (2) 2025.07.10
[스탠포드iOS] Swift 기초문법 정리(Optional, Tuple, Data Structure)  (1) 2024.03.16
RxSwift(2) - 연산  (0) 2020.04.04
RxSwift(1)  (0) 2020.04.03
MVVM패턴  (0) 2020.04.02

관련글 더보기