소셜 로그인 API 가이드 (모바일 앱용)

버전: 1.0
최종 수정일: 2025-11-25
담당자: Backend Team


📋 목차

  1. 개요
  2. 지원 플랫폼
  3. 전체 플로우
  4. API 엔드포인트
  5. 상세 시나리오
  6. 에러 처리
  7. 테스트
  8. FAQ

개요

AKC B2C 서비스의 소셜 로그인 API는 Google, Kakao, Naver 소셜 플랫폼을 통한 간편 가입/로그인을 지원합니다.

주요 특징


지원 플랫폼

1. Google 로그인

2. Kakao 로그인

////fdr

3. Naver 로그인


전체 플로우

소셜 로그인 플로우

API 엔드포인트

Base URL

Production: https://api.akc-b2c.com
Development: http://localhost:8081
Unified: http://localhost:8090

1. Google 소셜 로그인

요청

POST /api/auth/social/google
Content-Type: application/json

{
  "idToken": "eyJhbGciOiJSUzI1NiIs...",
  "deviceInfo": {
    "platform": "android",
    "appVersion": "1.0.0",
    "osVersion": "14",
    "deviceModel": "Galaxy S23",
    "deviceId": "unique-device-id"
  }
}

응답 - 즉시 로그인 성공

{
  "success": true,
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
  "tokenType": "Bearer",
  "expiresIn": 3600,
  "userInfo": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com",
    "name": "홍길동",
    "profileImageUrl": "https://...",
    "role": "USER",
    "isNewUser": false
  },
  "needsAdditionalInfo": false,
  "needsUsernameInput": false,
  "needsAccountLink": false,
  "message": "로그인이 완료되었습니다!"
}

응답 - 추가 정보 필요

{
  "success": true,
  "accessToken": null,
  "refreshToken": null,
  "tokenType": "Bearer",
  "expiresIn": 0,
  "userInfo": {
    "id": null,
    "email": "newuser@example.com",
    "name": "홍길동",
    "profileImageUrl": "https://...",
    "role": "USER",
    "isNewUser": true
  },
  "needsAdditionalInfo": true,
  "needsUsernameInput": true,
  "needsAccountLink": false,
  "message": "회원가입이 완료되었습니다! 추가 정보를 입력해주세요."
}

2. Kakao 소셜 로그인

요청

POST /api/auth/social/kakao
Content-Type: application/json

{
  "accessToken": "mHBN_qKk3Mj...",
  "deviceInfo": {
    "platform": "ios",
    "appVersion": "1.0.0",
    "osVersion": "17.0",
    "deviceModel": "iPhone 15 Pro",
    "deviceId": "unique-device-id"
  }
}

응답

Google과 동일한 형식

3. Naver 소셜 로그인

요청

POST /api/auth/social/naver
Content-Type: application/json

{
  "accessToken": "AAAAQosjWDJieBiQZc3to...",
  "deviceInfo": {
    "platform": "android",
    "appVersion": "1.0.0",
    "osVersion": "14",
    "deviceModel": "Galaxy S23",
    "deviceId": "unique-device-id"
  }
}

응답

Google과 동일한 형식

4. 소셜 회원가입 (추가 정보 입력)

요청

POST /api/auth/social/signup
Content-Type: application/json

{
  "provider": "GOOGLE",
  "socialId": "106123456789012345678",
  "email": "newuser@example.com",
  "name": "홍길동",
  "userId": "honggildong",
  "phoneNumber": "01012345678",
  "termsAgreed": true,
  "privacyAgreed": true,
  "marketingAgreed": false,
  "deviceInfo": {
    "platform": "android",
    "appVersion": "1.0.0"
  }
}

응답

{
  "success": true,
  "accessToken": "eyJhbGciOiJIUzI1NiIs...",
  "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
  "tokenType": "Bearer",
  "expiresIn": 3600,
  "userId": "honggildong",
  "email": "newuser@example.com",
  "name": "홍길동",
  "memberUuid": "550e8400-e29b-41d4-a716-446655440000",
  "message": "회원가입이 완료되었습니다!"
}

5. 지원 플랫폼 목록 조회

요청

GET /api/auth/social/providers

응답

{
  "providers": ["GOOGLE", "KAKAO", "NAVER"],
  "version": "1.0.0",
  "status": "active"
}

6. 헬스체크

요청

GET /api/auth/social/health

응답

{
  "status": "UP",
  "service": "social-auth-service",
  "timestamp": 1732492800000
}

상세 시나리오

시나리오 1: 신규 사용자 - 소셜 로그인 + 추가 정보 입력

// 1. 소셜 SDK로 토큰 획득
val googleToken = googleSignIn.getIdToken()

// 2. 백엔드에 로그인 요청
val response = authApi.googleLogin(
    GoogleLoginRequest(
        idToken = googleToken,
        deviceInfo = DeviceInfo(
            platform = "android",
            appVersion = "1.0.0",
            osVersion = Build.VERSION.RELEASE,
            deviceModel = Build.MODEL,
            deviceId = getDeviceId()
        )
    )
)

// 3. 응답 처리
when {
    response.success && response.needsAdditionalInfo -> {
        // 추가 정보 입력 화면으로 이동
        navigateToSignUpForm(
            email = response.userInfo.email,
            name = response.userInfo.name,
            provider = "GOOGLE",
            socialId = response.userInfo.id
        )
    }
    response.success && !response.needsAdditionalInfo -> {
        // 즉시 로그인 완료
        saveTokens(response.accessToken, response.refreshToken)
        navigateToHome()
    }
    else -> {
        // 에러 처리
        showError(response.message)
    }
}

// 4. 추가 정보 입력 후 회원가입
val signUpResponse = authApi.socialSignUp(
    SocialSignUpRequest(
        provider = "GOOGLE",
        socialId = socialId,
        email = email,
        name = name,
        userId = enteredUserId,
        phoneNumber = enteredPhoneNumber,
        termsAgreed = true,
        privacyAgreed = true,
        marketingAgreed = marketingChecked,
        deviceInfo = deviceInfo
    )
)

if (signUpResponse.success) {
    saveTokens(signUpResponse.accessToken, signUpResponse.refreshToken)
    navigateToHome()
}

시나리오 2: 기존 사용자 - 즉시 로그인

// 1. 소셜 SDK로 토큰 획득
val kakaoToken = kakaoLogin.getAccessToken()

// 2. 백엔드에 로그인 요청
val response = authApi.kakaoLogin(
    KakaoLoginRequest(
        accessToken = kakaoToken,
        deviceInfo = deviceInfo
    )
)

// 3. 즉시 로그인 완료
if (response.success && !response.needsAdditionalInfo) {
    saveTokens(response.accessToken, response.refreshToken)
    saveUserInfo(response.userInfo)
    navigateToHome()
}

시나리오 3: 기존 사용자 - 다른 소셜 계정 연결

// 사용자가 이미 Google로 가입했고, Kakao로 로그인 시도

// 1. Kakao로 로그인
val response = authApi.kakaoLogin(
    KakaoLoginRequest(
        accessToken = kakaoToken,
        deviceInfo = deviceInfo
    )
)

// 2. 같은 이메일로 기존 계정 존재
// -> 자동으로 Kakao 계정이 연결되고 로그인 처리됨
if (response.success) {
    // message: "기존 계정에 Kakao 소셜 계정이 연결되었습니다!"
    saveTokens(response.accessToken, response.refreshToken)
    navigateToHome()
}

에러 처리

HTTP 상태 코드

코드 설명
200 성공
400 잘못된 요청 (토큰 검증 실패, 필수 값 누락 등)
401 인증 실패 (토큰 만료, 유효하지 않은 토큰)
403 권한 없음 (계정 정지 등)
500 서버 오류

에러 응답 형식

{
  "success": false,
  "error": "소셜 로그인에 실패했습니다",
  "details": "Invalid ID token",
  "timestamp": 1732492800000
}

주요 에러 케이스

1. 유효하지 않은 토큰

{
  "success": false,
  "error": "Google 로그인에 실패했습니다",
  "details": "Invalid ID token"
}

처리 방법: 소셜 SDK에서 토큰을 다시 획득하여 재시도

2. 필수 약관 미동의

{
  "success": false,
  "error": "필수 약관에 동의하지 않았습니다"
}

처리 방법: 약관 동의 체크 확인

3. 중복된 userId

{
  "success": false,
  "error": "이미 사용 중인 사용자 ID입니다"
}

처리 방법: 다른 userId 입력 요청

4. 계정 정지

{
  "success": false,
  "error": "정지된 계정입니다",
  "details": "Account is suspended"
}

처리 방법: 고객 지원 안내


테스트

Postman Collection

프로젝트 루트의 AuthService-API-Tests.postman_collection.json 파일을 Postman에 import하여 테스트 가능합니다.

테스트 환경

환경 Base URL 설명
Local http://localhost:8081 로컬 개발 환경
Development http://dev-api.akc-b2c.com 개발 서버
Production https://api.akc-b2c.com 운영 서버

테스트 계정

개발 환경에서 사용 가능한 테스트 계정은 백엔드 팀에 문의해주세요.


FAQ

Q1. 전화번호는 필수인가요?

A: 네, 소셜 회원가입 시 전화번호는 필수입니다. SMS 인증은 선택사항이지만, 전화번호 자체는 반드시 입력해야 합니다.

Q2. 사용자 ID(userId) 규칙은?

A:

Q3. 한 사용자가 여러 소셜 계정을 연결할 수 있나요?

A: 네, 가능합니다. 동일한 이메일을 사용하는 경우 자동으로 연결되며, 수동으로도 추가 연결이 가능합니다.

Q4. 토큰 만료 시간은?

A:

Q5. Refresh Token으로 Access Token 갱신은 어떻게?

A:

POST /api/auth/refresh
Content-Type: application/json

{
  "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
}

Q6. 로그아웃은?

A:

POST /api/auth/logout
Authorization: Bearer {accessToken}

Q7. 소셜 계정 연결 해제는?

A: 현재 버전에서는 백엔드 팀에 문의하여 수동으로 처리합니다. 향후 API가 추가될 예정입니다.

Q8. 프로필 이미지는 자동으로 동기화되나요?

A: 네, 소셜 플랫폼에서 제공하는 프로필 이미지 URL이 자동으로 저장되고, 매 로그인 시 업데이트됩니다.

Q9. 이메일이 없는 소셜 계정은?

A: 현재는 이메일이 필수입니다. 소셜 로그인 시 이메일 제공 동의를 받아야 합니다.

Q10. deviceInfo는 필수인가요?

A: 선택사항이지만, 보안 및 통계를 위해 제공을 권장합니다.


데이터 모델

DeviceInfo

interface DeviceInfo {
  platform: "android" | "ios";      // 필수
  appVersion: string;                 // 앱 버전 (예: "1.0.0")
  osVersion?: string;                 // OS 버전 (예: "14", "17.0")
  deviceModel?: string;               // 기기 모델 (예: "Galaxy S23")
  deviceId?: string;                  // 기기 고유 ID
}

UserInfo (응답)

interface UserInfo {
  id: string;                         // UUID
  email: string;
  name: string;
  profileImageUrl?: string;
  role: string;                       // "USER" | "CORPORATE"
  isNewUser: boolean;
}

SocialLoginResponse

interface SocialLoginResponse {
  success: boolean;
  accessToken: string | null;
  refreshToken: string | null;
  tokenType: "Bearer";
  expiresIn: number;                  // 초 단위
  userInfo: UserInfo;
  needsAdditionalInfo: boolean;       // 추가 정보 입력 필요
  needsUsernameInput: boolean;        // userId 입력 필요
  needsAccountLink: boolean;          // 계정 연결 필요
  message: string;
}

보안 고려사항

1. 토큰 저장

2. HTTPS 사용

3. 토큰 갱신

4. 앱 간 공유 주의


변경 이력

날짜 버전 변경 내용
2025-11-25 1.0 최초 작성

문의


참고 자료