일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- Xcode
- Method
- Unicode
- Protocol
- Class
- initalizer
- Swift
- UIKit
- 이니셜라이저
- init
- 코딩테스트
- property
- 스위프트
- Git
- Foundation
- Terminal
- tuist
- interpace
- IOS
- type
- delegate
- initializer
- extension
- instance
- enum
- struct
- String
- 디자인패턴
- url
- optional
- Today
- Total
아리의 iOS 탐구생활
[Swift] OSLog란? 그리고 StaticString은 뭘까? 본문
안녕하세요. 아리입니다. 🐥
어느날 프로젝트를 하고 있는데, 리뷰어 엘림에게 이런 피드백을 받았습니다.
개발자에게만 어떤 에러가 발생했을 때 알려주기 위해 print문을 사용했었는데,
따로 프로그래머에게만 보여지는 전용 print문이 있더군요.
log, assert, debugPrint 등이 있는데 그중 OSLog라는 애를 배워볼겁니다.
그 이유는 사용하기는 조금 어렵고 번거롭지만, 추후 로그를 통해 데이터를 관리하기 수월해지기 때문입니다.
아직 제가 하고 있는 프로젝트에서 log까지는 필요없다고 판단되었지만 한번 써먹어보며 배워볼겸 정리해보았습니다.
시작해볼까요?
# OSLog란?
과거의 데이터를 읽기 위한 통합 로깅 시스템
OSLog 프레임워크는 사용자(프로그래머)가 로그를 읽을 수 있게 해준다
통합 로깅 시스템을 사용하면 instrument 및 Console과 같은 Apple 툴과 함께 사용할 사용자 지정 디버깅 및 분석 툴을 구축할 수 있게 해준다.
## 통합 로깅 시스템(unified logging system)
- 통합이란?
로그 데이터 저장을 level에 따라 메모리와 디스크의 데이터 저장소에 모으는 것(iOS 10+ 에서 가능) - 장점
모든 레벨의 시스템에서 로깅 표출이 가능하다 - Xcode를 실행하지 않아도 console앱을 실행시키면 로깅이 가능하다.
- os_log를 사용하면 mac의 콘솔 앱에서 로그를 쉽게 확인할 수 있다. (필터도 가능)
- 저장 기능 등을 활용할 수 있다.
## Logging
통합 로깅 시스템을 사용하여 디버깅 및 성능 분석을 위해 앱에서 원격 측정(telemetry)을 캡쳐한다.
통합 로깅 시스템은 시스템의 모든 수준에서 원격 측정을 캡쳐할 수 있는 포괄적이고 성능이 뛰어난 API를 제공한다. 이 시스템은 데이터를 텍스트 기반 로그 파일에 쓰지 않고 메모리 및 디스크에 로그 데이터를 중앙 집중식으로 저장한다. 콘솔 앱, 로그 명령줄 도구 또는 Xcode 디버그 콘솔을 사용하여 로그 메세지를 보거나 OSLog 프레임워크를 사용하여 로그메세지에 프로그래밍 방식으로 엑세스할 수도 있다.
## level
- 주로 Fault를 제외한 4가지를 사용한다.
level 종류 | disk에 저장 | 내용 |
Default (notice) | o | 문제 해결을 위한 level |
Info | o | Error케이스와 유사하지만, 에러 설명이 긴 경우, 문제해걀시 활용할 수 있는, 도움이 되지만 필수적이지 않은 정보 |
Debug | x | 개발 환경에서의 간단한 로깅 (mac의 '콘솔'앱에는 찍히지 않고 xcode console에만 표출) |
Error | o | Info케이스와 유사하지만, 간단한 에러인 경우, 활동 객체가 존재하는 경우 관련 프로세스 체인에 대한 정보 캡쳐 |
Fault | o | Error와 유사하지만 시스템 레벨 or 다중 프로세스 오류 캡쳐를 위한 것 |
## 제약사항
통합 로깅 시스템은 iOS 10, macOS 10.12, tvOS 10.0, watchOS 3.0 이후 버전부터 지원한다.
## os_log로 로그 찍어보기
- os_log(_:)
os_log("error")
- os_log(_:log_:)
os_log(.fault, log: .default, "error")
## extension을 활용하기
아래와 같이 OSLog 클래스의 인스턴스를 OSLog 프레임워크에 타입 프로퍼티로 만들어 확장해주면 원하는 subsystem과 카테고리로 메세지를 로깅할 수 있다.
extension OSLog {
private static var subsystem = Bundle.main.bundleIdentifier!
static let error = OSLog(subsystem: subsystem, category: "Error")
}
// 메세지 로깅이 필요한 위치에서 아래 메소드를 호출
os_log(.error, log: .error, “%@“, OSLogMessage.error)
## StaticString 타입 장벽 해결하기
메세지 타입으로 StaticString을 요구하는데, 아래와 같은 방법으로 우회적으로 적용해볼 수 있다.
let message = "에러 발생"
os_log(.error, log: .error, "%@", message)
보너스. StaticString은 무엇일까?
# StaticString이란?
String은 원래 바이너리에 있는 원래 문자열의 메모리 주소를 알고
그 주위에 전체 데이터 구조를 구축하지만 StaticString은 해당 주소를 저장한다.
따라서 문자열을 절대 수정하고 싶지않고 고정하고 싶을 때 활용하는 타입이다.
예제를 통해 이해해보자
var myNumber = 10
let myString = "My number is \(myNumber)"
print(myString)
myNumber = 20
print(myString)
기존에 String을 사용하면 문자열 보간법을 통해 런타임 때 문자열에 정보를 추가할 수 있다.
따라서 위 코드의 결과는 아래와 같다.
myNumber를 변경하더라도 텍스트는 변경되지 않는 것을 볼 수 있다.
문자열 보간법은 값을 할당하는 순간의 값만 고려하므로 나중에 값을 변경해도 동일한 결과가 나오는 것이다.
그러나 문자열 보간법을 사용하면 문자열의 값을 컴파일 시점에는 값이 제대로 있는지 확인할 수가 없다.
따라서 컴파일 시점에 문자열의 값을 알고싶다면 StaticString 타입을 사용한다.
var myNumber = 10
let myString : StaticString = "My number is \(myNumber)"
print(myString)
위 코드는 컴파일 에러가 난다.
그리고 다음과 같은 동작도 불가능하다.
var myNumber = 10
let myString : StaticString = "My number is " + "\(myNumber)"
print(myString)
이런식으로 컴파일 시점에 항상 완성된 문자열을 갖도록 개발을 강제할 수 있다.
let myString : StaticString = "My number is "
let myString2 : StaticString = "23"
myString2 = myString + myString2
위와 같이 문자열을 추가하는 것도 할 수 없다.
# Reference