화이트라벨 앱에 소셜 로그인을 붙일 때 본앱 SDK를 그대로 못 쓰는 이유
화이트라벨 앱 개발 시 본앱의 소셜 로그인 SDK를 그대로 재사용할 수 없는 이유를 분석합니다. 앱별 고유 식별자 문제, 플랫폼 설정의 종속성, 그리고 서버의 계정 매핑 오류 등 테스트에서 쉽게 발견되지 않는 핵심 기술적 지뢰와 해결 방안을 정리했습니다

본앱에 이미 소셜 로그인이 붙어 있다. 같은 코드베이스에서 파생시킨 화이트라벨 앱에도 소셜 로그인을 넣어달라는 요청이 왔다.
"SDK는 이미 들어 있으니 버튼만 붙이면 되는 거 아닌가?"
절반은 맞다. 같은 코드베이스에서 빌드 변형으로 파생시킨 앱이라면 SDK 의존성도, 초기화 코드도, 로그인 호출부도 이미 들어 있다. 다시 깔 것은 없다.
문제는 SDK가 혼자서는 동작하지 않는다는 데 있다. SDK는 앱 식별자와 플랫폼 콘솔 등록에 묶여 있고, 그 두 가지가 파생 앱에서 전부 갈린다. 그리고 서버 쪽에는 아무도 예상하지 않는 지뢰가 하나 더 있다.
세 가지를 나눠 보자.
1. 소셜 플랫폼의 사용자 ID는 "앱 단위 스코프"다
대부분의 소셜 플랫폼에서 사용자 식별자는 전역 고유값이 아니라 앱(서비스)별로 발급된다. 같은 사람이 같은 소셜 계정으로 로그인해도 앱이 다르면 다른 번호가 나온다.
화이트라벨에서는 파생 앱이 다른 조직 소유의 소셜 앱을 쓰는 경우가 흔하다. 파트너사가 자기 이름으로 개발자 콘솔에 앱을 등록해두는 것이다. 이때 본앱 키를 그대로 재사용하면 어떻게 될까?
로그인은 된다. 그게 함정이다.
토큰도 정상으로 떨어지고 사용자 정보도 잘 내려온다. 문제는 그 식별자를 파트너 서버로 넘겨 회원을 매핑하는 순간 터진다. 파트너의 웹 서비스는 자기 앱 기준 식별자를 갖고 있는데, 우리 앱이 보낸 건 본앱 기준 식별자다. 같은 사람인데 값이 다르니 "가입된 적 없는 사용자"가 된다.
통합 테스트 단계에서, 그것도 파트너 쪽 데이터가 붙고 나서야 발견되는 유형의 버그다.
2. SDK 설정은 앱 식별자에 묶여 있다
SDK 초기화 키, OAuth 복귀용 URL 스킴, 번들 ID, 패키지명, 키해시 — 전부 앱 식별자에 종속된다. 바이너리가 갈리는 순간 전부 새로 등록해야 한다.
<!-- 복귀 스킴부터 앱 키에 종속된다 -->
<activity android:name=".auth.AuthCodeHandlerActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- {NATIVE_APP_KEY} 가 파생 앱에서는 다른 값이 된다 -->
<data android:scheme="socialsdk${NATIVE_APP_KEY}" android:host="oauth" />
</intent-filter>
</activity>특히 Android 키해시는 3종이 필요하다.
| 키해시 | 언제 쓰이나 | 빠뜨리면 |
|---|---|---|
| 디버그 | 로컬 개발 빌드 | 개발 중 바로 발견 |
| 릴리스 | 자체 서명 APK | 사내 배포에서 발견 |
| 스토어 재서명분 | 스토어가 앱을 다시 서명한 배포본 | 스토어 버전만 로그인 실패 |
세 번째가 실무에서 가장 자주 터진다. 스토어에 앱 서명을 위임하는 방식(Play App Signing 등)을 쓰면 업로드한 APK와 사용자가 내려받는 APK의 서명이 다르다. 개발 빌드에서는 멀쩡하고, QA 빌드에서도 멀쩡하고, 스토어에 올린 순간부터 로그인이 안 된다. 배포 직전에 발견되는 전형적인 유형이다.
3. 서버가 "인증수단 코드" 하나로 계정 체계를 정한다면 — 지뢰
여기가 진짜 문제다. 레거시 서버에서 아주 흔한 패턴이 있다.
// 인증수단 코드만 보고 계정 prefix를 결정
if ("2".equals(input.getAuthType())) { // 2 = 소셜 A
userId = "social_a_" + input.getUserId();
} else if ("3".equals(input.getAuthType())) { // 3 = 소셜 B
userId = input.getUserId();
}authType 은 "어떤 수단으로 인증했나" 를 뜻한다. 그런데 이 코드는 그 값 하나로 "어느 계정 체계에 속하나" 까지 결정해버린다. 두 개의 서로 다른 질문에 답이 하나뿐인 것이다.
본앱 하나만 있을 때는 아무 문제가 없다. 소셜 A로 로그인하면 소셜 A 계정이 맞으니까. 파생 앱이 생기는 순간 전제가 깨진다.
파생 앱이 본앱 로그인 코드를 그대로 재사용해서 같은 authType 으로 요청을 보내면, 서버는 그것이 어느 앱에서 온 요청인지 알 방법이 없다.

파생 앱 사용자가 본앱 계정을 갖게 된다. 그리고 이건 에러가 아니라 정상 응답이다. 로그인은 성공하고, 세션도 발급되고, 앱은 아무 이상 없이 동작한다. 계정이 엉뚱한 체계에 만들어졌다는 사실만 아무도 모른다.
해결: 축을 하나 더 만든다
인증수단과 앱 출처는 직교하는 두 축이다. 그러니 파라미터도 두 개여야 한다.
// Before — 한 축에 두 의미가 섞여 있다
String userId = resolvePrefix(input.getAuthType()) + input.getUserId();
// After — 인증수단과 앱 출처를 분리
String prefix = resolvePrefix(input.getAuthType(), input.getAppOrigin());
String userId = prefix + input.getUserId();private String resolvePrefix(String authType, String appOrigin) {
// 파생 앱은 소셜 로그인이어도 자체 계정 체계를 탄다
if (PARTNER_APP.equals(appOrigin)) {
return PARTNER_PREFIX;
}
return MAIN_APP_PREFIXES.get(authType);
}파생 앱의 인증 흐름은 결과적으로 이렇게 된다.
소셜 SDK 인증 → 소셜 식별자 획득
→ 파트너 인증서버로 전달 (여기서 회원 매핑)
→ 파트너 계정 ID 수신
→ 파생 앱 prefix 부착 → 세션 발급본앱은 소셜 식별자를 그대로 계정 ID로 쓰지만, 파생 앱은 소셜 식별자를 파트너 계정으로 교환한 뒤 쓴다. 같은 SDK를 쓰지만 그 뒤의 경로가 완전히 다르다.
정리
| 항목 | 재사용 가능? |
|---|---|
| SDK 통합 노하우 · 코드 구조 | 그대로 재사용 |
| 소셜 플랫폼 앱 키 / 콘솔 설정 | 소유자가 다르면 전부 새로 |
| 번들 ID · 패키지명 · 키해시 3종 | 앱이 갈리면 전부 새로 |
| 서버 계정 prefix 분기 | 축을 하나 더 만들어야 함 |
이 구분은 공수를 산정하거나 방어할 때도 그대로 쓸 수 있다.
"학습 비용은 넣지 않았습니다. 해본 일이니까요. 넣은 건 설정 비용인데, 앱도 다르고 소셜 앱도 달라서 설정은 재사용이 되지 않습니다."
세 가지 중 1번과 3번은 테스트에서 에러로 잡히지 않는다는 공통점이 있다. 로그인이 성공하기 때문이다. 잘못된 값이 조용히 흘러가다가 한참 뒤 매핑 단계에서 드러난다. 화이트라벨 파생 작업을 시작할 때 이 두 가지를 먼저 확인해두면 통합 단계에서 며칠을 아낀다.