본문 바로가기
PulseBoard

🔐 iOS 네이버 로그인 키 관리 방법 (xcconfig + Info.plist + ClientConfiguration)

by 밤새는 탐험가89 2025. 12. 30.
728x90
SMALL

네이버 로그인을 구현하면서 가장 신경 써야 하는 부분 중 하나는
Client ID, Client Secret 같은 민감한 키를 어떻게 관리할 것인가다.


이번 글에서는
xcconfig + Info.plist + 코드 분리 구조를 사용해
네이버 로그인 키를 안전하고 깔끔하게 관리하는 방법을 정리한다.

 

✅ 목표 구조 요약

우리가 최종적으로 만든 구조는 아래와 같다.

Secrets.xcconfig        (실제 값, Git 추적 ❌)
        ↓ (Build Time 치환)
Info.plist              ($(VAR) 형태로 참조)
        ↓ (Runtime)
ClientConfiguration     (코드에서 안전하게 접근)
        ↓
AppDelegate             (SDK 초기화)

 

이 구조의 장점은 다음과 같다.

  • 민감한 키를 Git에 절대 올리지 않음
  • AppDelegate에 하드코딩 없음
  • SDK 교체 / 환경 분리(Debug, Release)에 유연
  • 설정 오류를 런타임에서 즉시 감지 가능

 

1️⃣ Secrets.xcconfig 생성 (실제 키 관리)

먼저 네이버 개발자 센터에서 발급받은 키들을
Secrets.xcconfig 파일에 정리한다.

// Secrets.xcconfig
// PulseBoard
//
// MARK: - Naver Login
NAVER_CLIENT_ID = O_XG2KfvLBS84MCXB3PM
NAVER_CLIENT_SECRET = CpWIrzb20g
NAVER_URL_SCHEME = O_XG2KfvLBS84MCXB3PM
NAVER_APP_NAME = PulseBoard

 

📌 포인트

  • 실제 값은 오직 이 파일에만 존재
  • Debug / Release 모두에서 사용할 수 있음
  • 이후 GitHub에 올라가지 않도록 처리 예정

2️⃣ Info.plist에 키 등록 (값이 아니라 “치환 키”)

Info.plist에는 실제 값을 넣지 않는다.
대신 xcconfig 값이 빌드 시 치환되도록 설정한다.

NAVER_APP_NAME        = $(NAVER_APP_NAME)
NAVER_CLIENT_ID      = $(NAVER_CLIENT_ID)
NAVER_CLIENT_SECRET  = $(NAVER_CLIENT_SECRET)
NAVER_URL_SCHEME     = $(NAVER_URL_SCHEME)

또한 URL Types에도 다음을 추가한다.

  • URL Schemes: $(NAVER_URL_SCHEME)

왜 Info.plist를 거치는가?

  • iOS SDK 대부분은 Info.plist 기반 설정을 전제로 함
  • Bundle.main을 통해 안전하게 읽을 수 있음
  • 런타임에서 값 검증 가능

3️⃣ ClientConfiguration enum으로 접근 추상화

이제 코드에서는 Info.plist를 직접 참조하지 않는다.
대신 전용 enum을 만들어 접근을 통제한다.

// MARK: - Naver Login 키 - 값 호출
enum ClientConfiguration {

    static var appName: String { plist("NAVER_APP_NAME") }
    static var clientID: String { plist("NAVER_CLIENT_ID") }
    static var clientSecret: String { plist("NAVER_CLIENT_SECRET") }
    static var urlScheme: String { plist("NAVER_URL_SCHEME") }

    private static func plist(_ key: String) -> String {
        guard let value = Bundle.main.object(forInfoDictionaryKey: key) as? String,
              value.isEmpty == false,
              value.hasPrefix("$(") == false  // xcconfig 치환 실패 방지
        else {
            fatalError("Missing or invalid Info.plist key: \(key)")
        }
        return value
    }
}

📌 이 구조의 핵심

  • $(NAVER_APP_NAME)처럼 치환 실패한 값을 즉시 감지
  • 설정이 잘못되면 앱 실행 시 바로 크래시
  • “조용히 실패하는 로그인”을 방지

 

4️⃣ AppDelegate에서 네이버 로그인 SDK 초기화

이제 AppDelegate에서는 ClientConfiguration만 사용한다.

import FirebaseCore
import KakaoSDKCommon
import NidThirdPartyLogin
import NidLogin

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        // MARK: - Firebase 초기화
        FirebaseApp.configure()

        // MARK: - Kakao 로그인
        if let kakaoAppKey = Bundle.main.object(
            forInfoDictionaryKey: "KAKAO_NATIVE_APP_KEY"
        ) as? String {
            KakaoSDK.initSDK(appKey: kakaoAppKey)
        }

        // MARK: - Naver 로그인
        LogManager.print(.success, "[NaverConfig] appName: \(ClientConfiguration.appName)")
        LogManager.print(.success, "[NaverConfig] clientID: \(ClientConfiguration.clientID)")
        LogManager.print(.success, "[NaverConfig] urlScheme: \(ClientConfiguration.urlScheme)")
        LogManager.print(
            .success,
            "[NaverConfig] clientSecret: \(String(repeating: "*", count: ClientConfiguration.clientSecret.count))"
        )

        NidOAuth.shared.initialize(
            appName: ClientConfiguration.appName,
            clientId: ClientConfiguration.clientID,
            clientSecret: ClientConfiguration.clientSecret,
            urlScheme: ClientConfiguration.urlScheme
        )

        LogManager.print(.success, "[NaverConfig] NidOAuth initialized")
        return true
    }
}

📌 장점

  • AppDelegate에 민감한 값 하드코딩 ❌
  • 네이버 SDK 초기화 코드가 명확하고 읽기 쉬움
  • 카카오 / Firebase 설정과 자연스럽게 공존

 

5️⃣ Secrets.xcconfig는 Git에서 제외

마지막으로 보안의 핵심.

.gitignore에 반드시 추가한다.

 

PulseBoard 상위에, Empty 파일을 선택한 후에 ".gitignore" 라는 이름으로 파일을 생성한다.

# Secrets
Secrets.xcconfig

 

이렇게 하면:

  • 로컬에서는 정상 동작
  • GitHub에는 절대 업로드되지 않음
  • 실수로 커밋할 가능성 차단

 

😦 이미 Git에 올라가 있었다면 (중요!)

한 번이라도 add 된 적 있으면:

git rm --cached Secrets.xcconfig

 

그 다음 커밋.

⚠️ 이거 안 하면 .gitignore 있어도 계속 추적됨

 

✅ 정리

이 방식의 핵심은 단순하다.

  • 실제 키는 xcconfig
  • Info.plist는 연결 고리
  • 코드는 ClientConfiguration만 신뢰
  • Git에는 절대 비밀 없음

네이버 로그인뿐 아니라
👉 Firebase, Kakao, Google, Apple 로그인까지 그대로 확장 가능한 패턴이다.

 

https://velog.io/@cur-ios-ity/Xcode-.gitignore-%ED%8C%8C%EC%9D%BC-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0

 

[Xcode] .gitignore 파일 쉽고 빠르게(!) 만들기

이제 복붙하지 않아도 괜찮아,,🫠

velog.io

 

728x90
LIST