문의 시, 디벨로퍼스 앱ID를 알려주세요.
- 비즈니스 정보 심사는 운영하시는 서비스와 디벨로퍼스앱이 일치하는지, 운영정책을 준수하는 신뢰할 수 있는 서비스인지 확인하는 절차입니다.
- 개인정보 항목 심사는 운영하시는 서비스 일반회원가입에서 입력 받는 항목을 기준으로 제공됩니다.
sw*****@nate.com
동의항목에 카카오계정 (전화번호) 필수동의 상태인데 유저 로그인시 전화번호 정보 수집이 안됩니다.
문의 시, 디벨로퍼스 앱ID를 알려주세요.
sw*****@nate.com
동의항목에 카카오계정 (전화번호) 필수동의 상태인데 유저 로그인시 전화번호 정보 수집이 안됩니다.
안녕하세요.
확인을 위해 앱 ID 부탁드립니다.
앱ID
https://developers.kakao.com/console/app 에 표시되는 ID 값 입니다.
숫자로된 ID 입니다
ex) 123456
1410344 입니다
로그상 전화번호가 잘 전달되었습니다.
전달 안되었다는 유저의 앱유저ID 기재 해주시겠어요?
4b4fe46d-e97b-468d-b25d-dde2315c728d 입니다
기재하신 값은 앱유저ID가 아닙니다.
v2/user/me에서 전달하는 숫자로된 id 기재해주시면되고 함께 전달된 전화번호가 있는지 체크 해주시면됩니다.
4806995728 입니다
“phone_number”:“+82 10-35**-89**” 전화번호 전달된 것으로 확인됩니다.
현재 수파베이스 이용중인데 다른 정보는 정상적으로 수집되는데 전화번호만 null로 나옵니다
정상 전달되었으니 개발하신 시스템 매핑 로직 살펴보시면 좋을 것 같습니다.
가장 복잡한 매핑 로직으로, 카카오 OAuth 로그인 후 사용자 프로필 데이터를 추출·정규화·저장합니다.
전화번호는 아래 우선순위로 여러 경로를 탐색합니다:
1순위: client_kakao_phone (클라이언트가 직접 카카오 API 호출하여 전달한 값)
2순위: kakaoApi.phone_number (서버에서 provider_token으로 카카오 /v2/user/me 호출)
3순위: kakaoApi.mobile / kakaoApi.mobile_number
4순위: identityData.kakao_account.phone_number (Supabase identities 배열)
5순위: identityData.phone_number / identityData.phone
6순위: meta.phone_number / meta.phone / meta.mobile
7순위: meta.kakao_account.phone_number
8순위: meta.provider_metadata.phone_number
9순위: meta.raw_user_meta_data.phone_number / phone / mobile
10순위: meta.custom_claims.phone_number
11순위: meta.user_metadata.phone_number
12순위: meta.identity_data.phone_number
13순위: deep_scan (재귀적으로 +82 또는 01X 패턴 탐색)
카카오에서 반환하는 전화번호 형식을 통일합니다:
입력 → 출력
"+82 10-1234-5678" → "01012345678"
"+82-10-1234-5678" → "01012345678"
"+8210-1234-5678" → "01012345678"
"+82 010-1234-5678" → "01012345678"
"010-1234-5678" → "01012345678"
"01012345678" → "01012345678"
처리 파이프라인:
공백·하이픈·점·괄호 제거
+82(0?) → 0 변환
남은 비숫자 문자 제거
01[016789]\d{7,8} 패턴 검증
1순위: client_kakao_name (클라이언트 전달)
2순위: kakaoApi.kakao_account.name (카카오 API 실명)
3순위: kakaoApi.kakao_account.profile.nickname
4순위: kakaoApi.properties.nickname
5순위: identityData.kakao_account.name
6순위: identityData.name / identityData.full_name
7순위: meta.full_name / meta.name / meta.nickname / meta.preferred_username
[1차] OIDC 모드: Supabase GoTrue가 id_token(JWT)에서 클레임 자동 파싱
→ user_metadata/identity_data에 phone_number, name 등 포함
[2차] provider_token 폴백: OIDC에서 phone 못 얻은 경우
→ POST https://kapi.kakao.com/v2/user/me
→ Authorization: Bearer {provider_token}
[3차] Admin Key 폴백: provider_token 없는 경우
→ POST https://kapi.kakao.com/v2/user/me
→ Authorization: KakaoAK {KAKAO_ADMIN_KEY}
→ Body: target_id_type=user_id&target_id={kakaoUserId}
[4차] kakaoAccount 직접 참조: Admin Key도 없는 경우
→ kakaoAccount.phone_number 값이 있으면 직접 사용
kakaoAccount =
kakaoIdentityData.kakao_account // identities[].identity_data.kakao_account
|| meta.kakao_account // user_metadata.kakao_account
|| meta.raw_user_meta_data?.kakao_account
|| meta.provider_metadata?.kakao_account
|| meta.user_metadata?.kakao_account
|| kakaoIdentity?.identity_data?.kakao_account
|| meta.raw_user_meta_data?.provider_metadata?.kakao_account
카카오 동의항목 상태를 다음 필드로 점검합니다:
| 필드 | 설명 |
|---|---|
has_phone_number |
카카오 계정에 전화번호 등록 여부 |
phone_number_needs_agreement |
전화번호 수집 동의 필요 여부 |
is_phone_number_verified |
전화번호 인증 여부 |
has_email |
이메일 등록 여부 |
email_needs_agreement |
이메일 수집 동의 필요 여부 |
profile_nickname_needs_agreement |
닉네임 수집 동의 필요 여부 |
권한 문제 감지 조건:
phone_number_needs_agreement=true 인데 값 없음 → 사용자 미동의 또는 비즈앱 설정 필요
has_phone_number=false → 카카오 계정에 전화번호 미등록
kakao_account 자체가 비어있음 → Supabase가 카카오 응답을 user_metadata에 미포함
phone_number 관련 필드가 전혀 없음 → 카카오 개발자 콘솔에서 “전화번호” 동의항목 미활성화
카카오 데이터 → Supabase profiles 테이블
─────────────────────────────────────────────────
phone (정규화됨) → profiles.phone
kakao_id (provider_id/sub) → profiles.kakao_id
avatar_url/picture → profiles.avatar_url
name/nickname → profiles.full_name
email → profiles.email
카카오 데이터 → Supabase auth.users
─────────────────────────────────────────────────
phone (E.164 변환) → auth.users.phone (+821012345678 형식)
phone_confirm: true → auth.users.phone_confirmed_at
openid, profile_nickname, account_email, phone_number, name
Solapi를 통해 카카오 알림톡을 발송하며, 실패 시 SMS 대체 발송합니다.
입력: { phone?, username?, message, templateId?, variables? }
[전화번호 확보]
phone 직접 전달 → 사용
또는 username → Supabase profiles.phone 조회
[전화번호 정규화]
phone.replace(/[^0-9]/g, '') → 숫자만 추출
[알림톡 발송] (PFID + 템플릿 설정 시)
to: 정규화된 전화번호
from: SOLAPI_FROM_NUMBER
text: message (SMS 대체 텍스트)
kakaoOptions:
pfId: SOLAPI_KAKAO_PFID
templateId: 전달값 또는 SOLAPI_KAKAO_PROPOSAL_TEMPLATE_ID
variables: 전달된 템플릿 변수 맵
[SMS 대체 발송] (알림톡 실패 또는 미설정 시)
to/from/text만 사용
variables: {
'#{이름}': influencerDisplayName, // 인플루언서 표시명
'#{업체명}': proposal.company_name, // 제안 업체명
'#{제안내용}': proposalSummary, // 제안 요약 (200자 제한)
}
실제로는 Solapi SMS로 발송합니다 (카카오 친구톡 대신).
입력: { phone?, username?, message }
전화번호: phone 직접 또는 username → DB 조회
정규화: phone.replace(/[^0-9]/g, '')
발송: Solapi SMS (to, from, text)
카카오톡 공유 시 OG 메타 캐시를 갱신합니다.
입력: { url: targetUrl }
API 호출:
POST https://kapi.kakao.com/v2/util/scrape/flush
Authorization: KakaoAK {KAKAO_REST_API_KEY}
Content-Type: application/x-www-form-urlencoded
Body: scrape_url={targetUrl}
interface KakaoUser {
nickname: string;
profileImage?: string;
}
// OAuth 로그인 스코프
scopes: 'openid profile_nickname account_email phone_number name'
// 로컬 저장
localStorage.setItem('picks_kakao_user', JSON.stringify(kakaoUser))
// 라이브 카트 연동
viewerNickname → cart.viewerNickname
viewerProfileImage → cart.viewerProfileImage
| 환경변수 | 용도 |
|---|---|
VITE_KAKAO_APP_KEY |
프론트엔드 카카오 SDK 앱키 |
KAKAO_ADMIN_KEY |
서버 Admin API 호출 (provider_token 폴백) |
KAKAO_REST_API_KEY |
카카오 캐시 갱신 API |
SOLAPI_API_KEY / SOLAPI_API_SECRET |
Solapi 인증 |
SOLAPI_FROM_NUMBER |
SMS 발신번호 |
SOLAPI_KAKAO_PFID |
카카오 비즈 채널 ID (알림톡 발송) |
SOLAPI_KAKAO_PROPOSAL_TEMPLATE_ID |
제안 알림톡 기본 템플릿 ID |
현재 매핑인데 오류 있을까요
카카오 v2/user/me API 호출 응답 Response 가 어떻게 전달되었는지 로깅하셔서 가공전 데이터 먼저 확인 해보시겠어요?
안녕하세요, 답변 감사합니다.
말씀하신 대로 v2/user/me API 응답의 가공 전 데이터를 확인해 봤습니다. 현재 저희 서버 로그에서 확인되는 가공 전 원본 데이터 구조는 다음과 같습니다:
저희는 Supabase GoTrue를 통해 카카오 OAuth를 처리하고 있습니다. 대부분의 경우 **v2/user/me**를 직접 호출하지 않고, Supabase가 카카오 id_token(JWT)을 파싱하여 전달한 데이터를 사용합니다.
이 경우 Supabase에서 전달받는 가공 전 데이터는:
// user_metadata (Supabase가 id_token에서 파싱한 데이터)
{
"iss": "https://kauth.kakao.com",
"sub": "카카오_사용자_ID",
"nickname": "닉네임",
"picture": "프로필이미지_URL",
"email": "이메일"
// ← phone_number 필드가 여기에 포함되지 않는 경우가 많음
}
// identities[].identity_data (카카오 provider)
{
"sub": "카카오_사용자_ID",
"nickname": "닉네임",
"picture": "프로필이미지_URL",
"email": "이메일"
// ← kakao_account 객체 자체가 없거나, 있어도 phone_number가 없음
}
문제점: OIDC id_token 클레임에 **phone_number**가 포함되지 않아, Supabase **user_metadata**와 **identity_data**에 전화번호가 전달되지 않습니다.
OIDC에서 전화번호를 못 얻은 경우, **provider_token**으로 **v2/user/me**를 직접 호출합니다. 이때 받는 가공 전 원본 응답:
// POST https://kapi.kakao.com/v2/user/me
// Authorization: Bearer {provider_token}
{
"id": 카카오_사용자_ID,
"connected_at": "2024-XX-XXTXX:XX:XXZ",
"properties": {
"nickname": "닉네임",
"profile_image": "이미지URL",
"thumbnail_image": "이미지URL"
},
"kakao_account": {
"profile_nickname_needs_agreement": false,
"profile": {
"nickname": "닉네임",
"is_default_nickname": false
},
"has_email": true,
"email_needs_agreement": false,
"is_email_valid": true,
"is_email_verified": true,
"email": "이메일",
"has_phone_number": true,
"phone_number_needs_agreement": true,
"phone_number": "(값이 없거나 동의 필요)"
}
}
문제점: **has_phone_number: true**이고 **phone_number_needs_agreement: true**인데, 실제 phone_number 값이 비어있거나 전달되지 않습니다.
현재 OAuth 요청 시 사용하는 스코프:
openid, profile_nickname, account_email, phone_number, name
실제 응답되는 로그를 확인요청 드린 것인데요. 먼저 확인해보시겠어요?
중요 개인정보는 일부 마스킹하시고 출력로그 그대로 첨부 부탁드려요. (호출 시간 확인하여 카카오측 로그와 대조해보겠습니다.)
참고로
id_token 에 추가 개인정보는 포함되지 않으므로 전화번호가 없는 것이 정상동작입니다.
개인정보 ——– 처리했습니다
phone_number값이 없다고 하셨는데, 전달 받으셨네요?