4 minute read

카카오 API 로그인

1. Kakao Developer 접속

https://developers.kakao.com/

2. 우측 상단 ‘내 애플리케이션’ 클릭

image

3. 애플리케이션 추가하기

image

4. 앱 이름 및 사업자명 등록

image

5. 애플리케이션 등록 확인

image

애플리케이션 설정

6. 앱 키 확인

image

메모장에 적어두기 추천

7. Web 플랫폼 등록(자신의 공인아이피 또는 배포 url 입력)

image

8. redirect URI 등록

redirect URI = 카카오에 요청 보내면 카카오가 응답을 돌려줘야되는데 그 응답을 redirect URI에 보내준다.

image

9. 적당한 redirect URI를 입력

image

나는 로컬 서버와 localhost8080 서버와, 배포 서버 두개를 설정했다. 로컬url 은 테스트 용이고, 배포용 url은 실제 서버 구동 시 연결될 url 이다.

해당 redirect URL 을 REST API 키와 함께 메모해두자

10. 카카오 로그인 활성화

image

redirect URI 등록 후 바로 보이는 창에서 카카오 로그인 활성화도 on으로 변경해준다.

11. 동의화면 구성

image

동의 항목으로 가서 필요한 정보를 체크 해준다.

image

미리보기 화면

12. 보안 코드 생성(생성만 하고 사용안함으로 설정해두기)

미리보기 화면

image

기본값이 사용안함으로 설정

인증코드받기

13. header.th.xml

<attr
  sel="#kakao-login"
  sec:authorize="!isAuthenticated()"
  th:href="@{/oauth2/authorization/kakao}"
/>
  1. sec:authorize="!isAuthenticated()": Spring Security 표현식이다.
    사용자가 인증되지 않았을 때 (즉, 로그인되지 않았을 때) 이 태그의 내용이 적용되도록 하는 조건이다.
  2. th:href="@{/oauth2/authorization/kakao}": Thymeleaf 템플릿 엔진의 문법으로 선택된 HTML 요소의 href 속성을 /oauth2/authorization/kakao로 설정한다. 이 주소는 OAuth2 인증 프로세스를 시작하는 엔드포인트이다. 즉, 사용자가 이 링크를 클릭하면 카카오 OAuth2 인증 프로세스가 시작되도록 한다.

총정리하면, 해당 코드는 ID가 “kakao-login”인 HTML 요소에 로그인이 되지 않은 사용자를 위한 카카오 OAuth2 인증 링크를 설정하는 코드로. 사용자가 해당 링크를 클릭하면 카카오로 리다이렉트되어 로그인 프로세스를 시작하게 된다.

package com.example.projectboard.dto.security;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Map;

@SuppressWarnings("unchecked") // TODO: Map -> Object 변환 로직이 있어 제네릭 타입 캐스팅 문제를 무시한다. 더 좋은 방법이 있다면 고려할 수 있음.
public record KakaoOAuth2Response(
  Long id,
  LocalDateTime connectedAt,
  Map<String, Object> properties,
  KakaoAccount kakaoAccount
) {
  public record KakaoAccount(
    Boolean profileNicknameNeedsAgreement,
    Profile profile,
    Boolean hasEmail,
    Boolean emailNeedsAgreement,
    Boolean isEmailValid,
    Boolean isEmailVerified,
    String email
  ) {
    public record Profile(String nickname) {
      public static Profile from(Map<String, Object> attributes) {
        return new Profile(String.valueOf(attributes.get("nickname")));
      }
    }

    public static KakaoAccount from(Map<String, Object> attributes) {
      return new KakaoAccount(
        Boolean.valueOf(String.valueOf(attributes.get("profile_nickname_needs_agreement"))),
        Profile.from((Map<String, Object>) attributes.get("profile")),
        Boolean.valueOf(String.valueOf(attributes.get("has_email"))),
        Boolean.valueOf(String.valueOf(attributes.get("email_needs_agreement"))),
        Boolean.valueOf(String.valueOf(attributes.get("is_email_valid"))),
        Boolean.valueOf(String.valueOf(attributes.get("is_email_verified"))),
        String.valueOf(attributes.get("email"))
      );
    }

    public String nickname() { return this.profile().nickname(); }
  }

  public static KakaoOAuth2Response from(Map<String, Object> attributes) {
    return new KakaoOAuth2Response(
      Long.valueOf(String.valueOf(attributes.get("id"))),
      LocalDateTime.parse(
        String.valueOf(attributes.get("connected_at")),
        DateTimeFormatter.ISO_INSTANT.withZone(ZoneId.systemDefault())
      ),
      (Map<String, Object>) attributes.get("properties"),
      KakaoAccount.from((Map<String, Object>) attributes.get("kakao_account"))
    );
  }

  public String email() { return this.kakaoAccount().email(); }
  public String nickname() { return this.kakaoAccount().nickname(); }
}

해당 코드는 카카오 OAuth2 인증을 통해 반환받는 사용자 정보를 Java 객체로 표현하기 위한 클래스입니다. 코드를 자세히 살펴보면 다음과 같다.

  1. KakaoOAuth2Response record 클래스:
    • Java 16에서 도입된 record 기능을 사용하여 데이터 전용 클래스를 간단하게 정의한다.
    • 필드: id, connectedAt, properties, kakaoAccount.
    • from 메서드: Map 객체를 파라미터로 받아 KakaoOAuth2Response 객체를 생성한다.
  2. KakaoAccount record 클래스:
    • 사용자의 카카오 계정 정보를 나타낸다.
    • 필드: profileNicknameNeedsAgreement, profile, hasEmail, emailNeedsAgreement, isEmailValid, isEmailVerified, email 등.
    • from 메서드: Map 객체를 파라미터로 받아 KakaoAccount 객체를 생성한다.
    • nickname 메서드: 사용자의 닉네임을 반환한다.
  3. Profile record 클래스:
    • 사용자의 프로필 정보를 나타냅니다. 현재는 nickname만 포함된다.
    • from 메서드: Map 객체를 파라미터로 받아 Profile 객체를 생성한다.

해당 코드에서는 Map 객체로부터 데이터를 받아서 Java 객체로 변환하는 로직이 포함되어 있다. 이는 OAuth2 인증 과정에서 받아온 JSON 형식의 데이터를 Java 객체로 변환하기 위한 작업이다.

주의할 점은 @SuppressWarnings("unchecked") 주석인데, 해당 주석은 제네릭 타입 관련 경고를 무시하도록 지시한다. 이는 코드에서 Map에서 Object로의 변환 로직 때문에 발생하는 경고를 무시하기 위한 것이다. 코드에서는 여러번 Map<String, Object> 형태로 캐스팅하는데, 이 때 발생하는 타입 안전성 문제에 대한 경고를 무시하기 위해 추가되었다.

마지막으로, KakaoOAuth2Response 클래스와 KakaoAccount 클래스에는 각각 emailnickname 메서드가 있는데, 해당 메서드들은 사용자의 이메일과 닉네임 정보를 쉽게 가져올 수 있도록 도와준다.

14. application.yml

security:
    oauth2:
      client:
        registration:
          kakao:
            client-id: ${KAKAO_OAUTH_CLIENT_ID}
            client-secret: ${KAKAO_OAUTH_CLIENT_SECRET}
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/kakao"

            client-authentication-method: POST
        provider:
          kakao:
            authorization-uri: https://kauth.kakao.com/oauth/authorize
            token-uri: https://kauth.kakao.com/oauth/token
            user-info-uri: https://kapi.kakao.com/v2/user/me
            user-name-attribute: id

이 코드는 Spring Security OAuth2의 클라이언트 설정을 위한 것으로, 이를 통해 카카오 OAuth2 인증과 연동하기 위한 설정을 정의하게 된다.

KAKAO_OAUTH_CLIENT_ID, KAKAO_OAUTH_CLIENT_SECRET, baseUrl 은 환경변수 지정을 통해

외부로 고유 키 값이 노출 되지 않게 설정해주었다. 그리고 인텔리제이 내에서도 환경 변수 설정을 해주고, 배포한 헤로쿠 서버에서도 환경변수 지정을 해주었다.

해당 설정을 통해 Spring Boot 애플리케이션은 카카오 OAuth2 인증 서비스와 손쉽게 연동할 수 있다. 사용자는 카카오 계정을 사용하여 애플리케이션에 로그인할 수 있게 되며, 애플리케이션은 카카오에서 제공하는 인증 토큰 및 사용자 정보를 받아 올 수 있게 된다.

로그인 버튼을 누르면 카카오톡과 연동이 되서 자동으로 로그인이 진행된다.

15. 실행화면

image

우측에 Login 은 기본 로그인, kakao Login 은 카카오 API 사용 로그인

image

동의 후 다음 단계로

image

로그인이 성공한 걸 확인 할 수 있다.

Leave a comment