사이먼's 코딩노트

[SpringBoot] 소셜 로그인(카카오톡) 본문

Java/SpringBoot

[SpringBoot] 소셜 로그인(카카오톡)

simonpark817 2024. 5. 27. 23:13

[소셜 로그인(카카오톡) 적용]

  • 웹 페이지를 구현할 때 카카오톡, 네이버, 구글 등을 이용한 소셜 로그인이 필요할 때가 있을 것이다.
  • 이번에는 위와 같은 소셜 로그인 중 카카오톡을 이용한 방법을 알아봅시다.
  • 앞서 진행했던 SBB 프로그램이 아닌 임시로 만들어 둔 다른 프로젝트를 통해 구현할 예정이기 때문에 코드를 참고하고 싶으시다면 아래 깃허브 리포지터리 주소를 통해 참고 부탁드립니다.
  • 깃허브 리포지터리 주소 : https://github.com/psm817/sb_blog_2405
 

소셜 로그인 세팅 - 카카오 · psm817/sb_blog_2405@17012f6

psm817 committed May 27, 2024

github.com

 

[Kakao Developer 설정]

  • 웹 브라우저를 통해 카카오 디벨로퍼에 접속하여 로그인을 해줘야한다.
  • 카카오 디벨로퍼 주소 : https://developers.kakao.com/
  • 로그인이 완료되었다면 메뉴 상단에 있는 '내 어플리케이션'을 클릭하여 아래와 같이 접속한다.

카카오 디벨로퍼 로그인 후 '내 애플리케이션' 메뉴 진입

 

  • '애플리케이션 추가하기' 를 클릭한 후 앱 아이콘, 앱 이름, 회사명, 카테고리를 입력한다.
  • 테스트를 위한 작업이라면 회사명은 앱 이름과 동일하게 작성해도 무방하고 카테고리는 본인이 진행하는 프로젝트와 연관지어 선택하는 것이 좋다.

애플리케이션 추가하기

 

  • 애플리케이션을 추가하고, 추가된 애플리케이션을 클릭하면 앱 설정을 하는 대시보드로 진입하게 된다.
  • 좌측에 나열된 메뉴 중 제품 설정의 '카카오 로그인' 메뉴를 클릭하고 활성화 설정에서 상태를 ON으로 변경해준다.

카카오 로그인 상태 활성화

 

  • 활성화를 해줬으면 좌측 메뉴에서 '동의항목' 메뉴를 클릭하고 개인정보에서 닉네임과 프로필 사진의 상태를 '필수 동의' 상태로 변경해준다.
  • 본인이 가지고있는 카카오톡 프로필 사진을 보이지 않게 하고 싶다면 프로필 사진에 대한 상태는 굳이 변경할 필요는 없다.
  • 상태를 변경할 때, 동의 목적란에는 로그인 또는 회원가입이라는 텍스트를 작성하고 저장해야한다.

동의항목 -> 개인정보
'필수 동의' 상태로 변경

 

  • 위 과정을 모두 마쳤다면 좌측 메뉴에서 앱 설정의 '앱 키' 메뉴를 클릭하면 애플리케이션의 키 값을 볼 수 있다.
  • 총 4가지 종류의 키 값이 나열되어 있는데, 그 중 REST API 키가 우리가 사용할 '클라이언트 ID' 라고 생각하면 된다.

 

[application-secert.yml 수정]

  • 현재 소셜 로그인을 적용할 프로그램의 구조는 기존의 application.yml만을 사용하지 않고, 개발용 application-dev.yml과 소셜 로그인과 같은 인증 키 유출을 막기 위한 application-secert.yml을 함께 사용하고 있다.
  • 또한 소셜 로그인을 적용하기 위해서는 OAuth2라는 Open Authorization 2.0 인증 및 권한 부여를 위한 개방형 표준 프로토콜을 사용해야 한다.
  • 그렇기 때문에 application-secert.yml에 아래의 코드를 적용하고, CLIENT_ID 부분에 초기 카카오 디벨로퍼에서 얻은 REST API 키 값을 넣어준다. 
spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            clientId: CLIENT_ID
  mail:
    password: NEED_TO_INPUT
custom:
  security:
    oauth2:
      client:
        registration:
          kakao:
            devUser:
              oauthId: oauthId
              nickname: nickname

 

[라이브러리 추가]

  • 위와 같이 세팅이 완료가 되면 build.gradle에서 OAuth2 라이브러를 아래와 같이 추가해준다.
  • 코드를 붙혀넣었을 때 반드시 Load Gradle Changes를 통해 라이브러리 활성화를 해줘야한다.
// oauth
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

 

[SecurityConfig.java 수정]

  • 현재 스프링 시큐리티에 대한 설정은 모두 SecurityConfig.java 클래스에서 담당하고 있다.
  • 전에 로그인, 로그아웃을 구현하면서 formLogin과 logout의 매핑 주소가 모두 세팅되어 있다면 아래 코드와 같이 중간에 oauth2Login 로그인 속성을 추가한다.
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests((authorizeHttpRequests) -> authorizeHttpRequests
                        .requestMatchers(new AntPathRequestMatcher("/**")).permitAll())
                .formLogin(
                        formLogin -> formLogin
                                .loginPage("/member/login")
                                .defaultSuccessUrl("/")
                )
                .oauth2Login(
                        oauth2Login -> oauth2Login
                                .loginPage("/member/login")
                )
                .logout(
                        logout -> logout
                                .logoutRequestMatcher(new AntPathRequestMatcher("/member/logout"))
                                .logoutSuccessUrl("/")
                                .invalidateHttpSession(true)
                )
        ;
        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
}

 

[application.yml 수정]

  • 다음은 oauth2를 적용하기 위해 application.yml에서 아래와 같이 코드 수정이 필요하다.
  • 항상 주의할 점은 application.yml은 들여쓰기와 내어쓰기를 꼼꼼히 확인해야 한다. 그렇지 않으면 스프링부트 자체가 실행되지 않을 수도 있기 때문에 항상 조심해야 한다.
spring:
  profiles:
    active: dev
    include: secret
  security:
    oauth2:
      client:
        registration:
          kakao:
            scope:
            client-name: Kakao
            authorization-grant-type: authorization_code
            redirect-uri: 'http://localhost:8010/{action}/oauth2/code/{registrationId}'
        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
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
  jpa:
    properties:
      hibernate:
        default_batch_fetch_size: 100
        show_sql: true
        format_sql: true
        use_sql_comments: true
  logging:
    level:
      org.hibernate.SQL: DEBUG
      org.hibernate.orm.jdbc.bind: TRACE
      org.hibernate.orm.jdbc.extract: TRACE
      org.springframework.transaction.interceptor: TRACE

 

[Redirect URI 설정]

  • 여기까지 완료됐다면 다시 카카오 디벨로퍼에 접속하여 '카카오 로그인' 메뉴를 선택한 후 하단의 'Redirect URI' 항목에 application.yml에서 작성한 redirect-uri 주소를 동일하게 입력해야 한다.

Redirect URL 설정

 

[MemberService.java 수정]

  • 이제는 소셜 로그인 처리를 위한 몇 가지 수정이 필요하다.
  • 소셜 로그인을 통해 가입 또는 로그인을 했을 경우, 비밀번호는 따로 필요없기 때문에 최초 회원 세팅을 해주는 메서드가 필요하다.
  • 아래 코드는 MemberService.java 클래스에서 whenSocailLogin() 메서드를 추가한 모습이다.
@Transactional
public Member whenSocialLogin(String providerTypeCode, String username, String nickname) {
    Optional<Member> opMember = findByUsername(username);

    if (opMember.isPresent()) return opMember.get();

    // 소셜 로그인를 통한 가입시 비번은 없다.
    return signup(username, "", nickname, ""); // 최초 로그인 시 딱 한번 실행
}

 

[CustomOAuth2UserService.java 생성]

  • 추가로 소셜(카카오톡) 로그인이 성공할 때 마다 위에서 생성한 whenSocialLogin() 메서드가 실행되어 문제없이 데이터베이스에 회원이 추가될 수 있게 기본 정보를 가공하고 데이터 필터 역할을 하는 서비스가 추가로 필요하다.
  • 아래는 CustomOAuth2UserService.java 클래스를 새로 생성하여 추가한 코드이다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {
    private final MemberService memberService;

    // 카카오톡 로그인이 성공할 때 마다 이 함수가 실행된다.
    @Override
    @Transactional
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
        OAuth2User oAuth2User = super.loadUser(userRequest);

        String oauthId = oAuth2User.getName();
        Map<String, Object> attributes = oAuth2User.getAttributes();

        Map attributesProperties = (Map) attributes.get("properties");
        String nickname = (String) attributesProperties.get("nickname");

        String providerTypeCode = userRequest.getClientRegistration().getRegistrationId().toUpperCase();

        String username = providerTypeCode + "__%s".formatted(oauthId);

        Member member = memberService.whenSocialLogin(providerTypeCode, username, nickname);

        List<GrantedAuthority> authorityList = new ArrayList<>();

        return new CustomOAuth2User(member.getUsername(), member.getPassword(), authorityList);
    }
}

class CustomOAuth2User extends User implements OAuth2User {

    public CustomOAuth2User(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        super(username, password, authorities);
    }

    @Override
    public Map<String, Object> getAttributes() {
        return null;
    }

    @Override
    public String getName() {
        return getUsername();
    }
}

 

[웹 페이지 수정]

  • 실제 웹 화면에 카카오와 연동되는 로그인 링크를 보여주기 위해 아래와 같이 웹 페이지 템플릿 수정이 필요하다.
  • 아래 작성된 코드는 디자인 없이 기능만 구현되도록 작성되어 있기 때문에 참고만 바랍니다.
<div>
    메인
    <a sec:authorize="isAnonymous()" href="/member/login">로그인</a>
    <div>
        <a sec:authorize="isAnonymous()" href="/oauth2/authorization/kakao">카카오 로그인</a>
    </div>
    <a sec:authorize="isAuthenticated()" href="/member/logout">로그아웃</a>
    <a href="/member/signup">회원가입</a>
</div>
  • sec:authorize="isAnonymous()" 속성을 추가하여 로그아웃인 상태에서만 '카카오 로그인' 이라는 버튼 링크가 보이도록 하고 로그인이 완료되면 보이지 않도록 하였다.
  • 실제로 프로그램을 재실행하면 '카카오 로그인' 이라는 버튼이 생긴 것을 확인할 수 있다.

카카오 로그인 버튼 생성

 

  • 생성된 '카카오 로그인' 버튼을 클릭하면 아래와 같이 애플리케이션에 대한 동의를 구하고 카카오 계정으로 로그인을 하는 화면이 나타난다.

카카오 계정으로 로그인

 

반응형