네이버 로그인을 구현하면서 가장 신경 써야 하는 부분 중 하나는
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 로그인까지 그대로 확장 가능한 패턴이다.
[Xcode] .gitignore 파일 쉽고 빠르게(!) 만들기
이제 복붙하지 않아도 괜찮아,,🫠
velog.io
'PulseBoard' 카테고리의 다른 글
| 🤔 SocialAuthCoordinator 생성 조건 및 구조 설계 (0) | 2025.12.29 |
|---|---|
| 🤔 async, await VC CompletionHandler 언제 써야하나?(KakaoAuthHandler) (0) | 2025.12.28 |
| 🎫 KakaoAuthHandler 는 왜 async/await를 버리고 completion 기반으로 되돌렸나? (0) | 2025.12.28 |
| Firebase Functions + Kakao 로그인 문제 해결 정리 (0) | 2025.12.27 |
| 🤔 카카오, 네이버 로그인 - accessToken 처리 방향 (1) | 2025.12.26 |