Swift의 `#if DEBUG` 컴파일러 디렉티브 활용하기

cheshire0105·2025년 1월 29일

iOS

목록 보기
33/46
post-thumbnail

Swift의 #if DEBUG 컴파일러 디렉티브 활용하기

iOS 개발을 진행하다 보면, 디버그(테스트) 환경에서만 실행되어야 하는 코드를 작성해야 하는 상황이 빈번히 발생한다. 예를 들어, 테스트 중에만 특정 데이터를 초기화하거나, 개발자 전용 기능을 활성화하고 싶을 때가 있다. 이러한 요구를 효과적으로 충족시키기 위해 Swift에서는 #if DEBUG 컴파일러 디렉티브를 제공한다. 이번 글에서는 #if DEBUG의 개념과 활용 방법을 쉽게 설명하고, 실제 코드 예제를 통해 그 사용법을 알아본다.

#if DEBUG란?

#if DEBUG는 Swift에서 제공하는 컴파일러 디렉티브 중 하나로, 특정 코드 블록이 디버그 빌드에서만 컴파일되고 실행되도록 조건을 설정할 수 있게 해준다. 이는 릴리즈(배포) 빌드에서는 해당 코드가 무시되도록 하여, 프로덕션 환경에 불필요한 코드가 포함되지 않도록 도와준다.

#if DEBUG를 사용할까?

개발 과정에서 다음과 같은 경우에 #if DEBUG를 활용할 수 있다:

  1. 테스트용 데이터 초기화: 개발 중에만 특정 데이터를 초기화하거나, 테스트용으로만 필요한 설정을 적용할 때.
  2. 디버깅 툴 활성화: 디버깅을 용이하게 하기 위해 로그 출력이나 디버그 패널을 활성화할 때.
  3. 개발자 전용 기능: 앱의 배포 버전에서는 필요하지 않거나 보안상 문제가 될 수 있는 기능을 개발 단계에서만 활성화할 때.

이러한 기능들을 프로덕션 환경에 포함시키지 않음으로써, 앱의 안정성과 보안성을 유지할 수 있다.

#if DEBUG 사용 방법

Swift에서 #if DEBUG를 사용하는 기본적인 방법은 다음과 같다:

#if DEBUG
// 디버그 빌드에서만 실행되는 코드
#endif

이 디렉티브는 디버그 빌드 설정DEBUG 플래그가 자동으로 설정되어 있다는 전제 하에 동작한다. Xcode의 기본 설정에서는 디버그 빌드에만 DEBUG 플래그가 포함되므로, 추가 설정 없이도 정상적으로 작동한다.

실제 코드 예제

다음은 filterButtonTapped 메서드를 예로 들어, 디버그 빌드에서만 UserDefaults를 초기화하도록 구현한 예제이다.

@objc func filterButtonTapped() {
    #if DEBUG
    // UserDefaults 초기화 (특정 키만 제거)
    UserDefaults.standard.removeObject(forKey: hasShownSwipeGuideKey)
    sharedUserDefaults.removeObject(forKey: "hasShownSwipeGuide")
    #endif

    // 필터 화면 표시
    let filterVC = FilterAlertViewController()
    filterVC.modalPresentationStyle = .overFullScreen
    filterVC.modalTransitionStyle = .crossDissolve
    filterVC.onApplyFilter = { [weak self] selectedDrippers, selectedTemperatures in
        self?.applyFilter(drippers: selectedDrippers, temperatures: selectedTemperatures)
    }
    present(filterVC, animated: true, completion: nil)
}

위 코드에서 #if DEBUG 블록 내의 코드는 디버그 빌드에서만 실행되며, 릴리즈 빌드에서는 무시된다. 이를 통해 테스트 시에만 UserDefaults를 초기화할 수 있어, 개발 과정에서의 유연성을 높일 수 있다.

#if DEBUG의 장점

  1. 코드 관리 용이성: 디버그와 릴리즈 빌드에서 필요한 코드를 명확하게 구분할 수 있다.
  2. 보안성 향상: 프로덕션 환경에 불필요한 디버그 정보나 테스트용 코드가 포함되지 않도록 방지할 수 있다.
  3. 앱 성능 최적화: 릴리즈 빌드에서는 불필요한 코드가 제거되므로, 앱의 성능이 향상될 수 있다.

릴리즈 빌드 테스트

그렇다면 실제 디버그 환경에서만 작동해야 하는 코드가 릴리즈 빌드에서 작동하지 않는 경우를 테스트하려면 어떻게 해야 할까? 그 방법은 다음과 같다.

  1. 릴리즈 빌드를 생성한다.

    Xcode에서 Product > Scheme > Edit Scheme... > Run > Build ConfigurationRelease로 설정한다.

  2. 창을 닫고 앱을 실행하여 filterButtonTapped 메서드를 호출한다.

    앱을 실행한 후, filterButtonTapped 메서드를 트리거하는 UI 요소(예: 버튼)를 눌러 해당 메서드를 호출한다.

  3. UserDefaults가 초기화되지 않았는지 확인한다.

    콘솔 로그나 UserDefaults의 값을 확인하여 디버그 빌드에서는 초기화되고, 릴리즈 빌드에서는 초기화되지 않았는지 검증한다. 이를 통해 #if DEBUG 블록 내의 코드가 릴리즈 빌드에서 실행되지 않았음을 확인할 수 있다.


주의사항

  • 전체 UserDefaults 초기화는 피한다: 테스트 용도로 모든 UserDefaults를 초기화하는 코드는 #if DEBUG 블록 내에서만 사용해야 하며, 프로덕션 환경에서는 절대 포함되지 않도록 주의해야 한다.

    @objc func filterButtonTapped() {
        #if DEBUG
        // 전체 UserDefaults 초기화 (테스트 용도)
        if let appDomain = Bundle.main.bundleIdentifier {
            UserDefaults.standard.removePersistentDomain(forName: appDomain)
        }
        sharedUserDefaults.removePersistentDomain(forName: "group.com.cheshire0105.TeaLike")
        #endif
    
        // 필터 화면 표시
        let filterVC = FilterAlertViewController()
        filterVC.modalPresentationStyle = .overFullScreen
        filterVC.modalTransitionStyle = .crossDissolve
        filterVC.onApplyFilter = { [weak self] selectedDrippers, selectedTemperatures in
            self?.applyFilter(drippers: selectedDrippers, temperatures: selectedTemperatures)
        }
        present(filterVC, animated: true, completion: nil)
    }
  • 필요한 키만 선택적으로 제거: UserDefaults를 초기화할 때는, 필요한 키만 선택적으로 제거하여 데이터 손실을 최소화하는 것이 좋다.

결론

Swift의 #if DEBUG 컴파일러 디렉티브는 개발 과정에서만 필요한 코드를 안전하게 관리할 수 있는 강력한 도구이다. 이를 통해 디버그 빌드와 릴리즈 빌드 간의 코드 차이를 명확히 구분하고, 프로덕션 환경의 안정성과 보안성을 향상시킬 수 있다. 이번 글에서 소개한 예제와 함께, #if DEBUG를 적절히 활용하여 효율적인 iOS 개발을 진행해보자.

0개의 댓글