본문 바로가기

개발일지

Vue3와 Spring Boot를 사용하여 카카오 OAuth 로그인

백엔드(Spring Boot)에서 카카오 인증 요청을 처리하고,

프론트엔드(Vue3)에서 인증 요청을 시작하며,

인증이 성공적으로 완료되면 JWT 토큰을 발급하여 유지하는 구조


1. 카카오 개발자 콘솔에서 애플리케이션 생성 및 설정

1. [카카오 디벨로퍼스](https://developers.kakao.com/)에 접속해 애플리케이션을 생성하세요.
2. 애플리케이션 설정에서 `Redirect URI`로 사용할 주소를 등록합니다. 예를 들어, `http://localhost:8080/oauth/kakao/callback`와 같은 URL을 등록합니다.
3. Client ID(REST API 키)를 확인하고 저장해 둡니다. 이 키는 카카오 API를 호출할 때 사용됩니다.


 2. Spring Boot - 카카오 OAuth 서버와 통신하기


(1) 의존성 추가

Spring Boot 프로젝트의 `build.gradle` 또는 `pom.xml` 파일에 OAuth2 관련 라이브러리를 추가하세요.

- Gradle:

 implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
   implementation 'org.springframework.boot:spring-boot-starter-security'
   implementation 'cohttp://m.fasterxml.jackson.core:jackson-databind'



 (2) 카카오 API 정보와 JWT 설정을 application.yml 파일에 추가

spring:
  security:
    oauth2:
      client:
        registration:
          kakao:
            client-id: <카카오 REST API 키>
            client-secret: <카카오 REST API 시크릿>
            authorization-grant-type: authorization_code
            redirect-uri: http://localhost:8080/oauth/kakao/callback
            scope: profile_nickname, profile_image, account_email
  jwt:
    secret: <JWT 시크릿 키>
    expiration: 3600000 # 1시간



(3) 카카오 OAuth 인증 처리 로직 작성


카카오 서버와 통신하여 토큰을 받아와 사용자 정보를 가져오는 `OAuthController`를 작성합니다.

@RestController
@RequestMapping("/oauth")
public class OAuthController {

    private final RestTemplate restTemplate;
    private final JwtTokenProvider jwtTokenProvider; // JWT 발급용 클래스 생성 필요

    @Autowired
    public OAuthController(RestTemplate restTemplate, JwtTokenProvider jwtTokenProvider) {
        this.restTemplate = restTemplate;
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @GetMapping("/kakao/callback")
    public ResponseEntity<?> kakaoCallback(@RequestParam String code) {
        String kakaoTokenUrl = "https://kauth.kakao.com/oauth/token";
        
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("client_id", "<카카오 REST API 키>");
        params.add("redirect_uri", "http://localhost:8080/oauth/kakao/callback");
        params.add("code", code);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(params, headers);

        // 토큰 요청
        ResponseEntity<KakaoTokenResponse> response = restTemplate.postForEntity(kakaoTokenUrl, kakaoTokenRequest, KakaoTokenResponse.class);
        String accessToken = response.getBody().getAccessToken();

        // 사용자 정보 요청
        String kakaoUserInfoUrl = "https://kapi.kakao.com/v2/user/me";
        HttpHeaders userInfoHeaders = new HttpHeaders();
        userInfoHeaders.add("Authorization", "Bearer " + accessToken);
        HttpEntity<MultiValueMap<String, String>> userInfoRequest = new HttpEntity<>(userInfoHeaders);

        ResponseEntity<Map> userInfoResponse = restTemplate.exchange(kakaoUserInfoUrl, HttpMethod.GET, userInfoRequest, Map.class);
        Map<String, Object> kakaoAccount = (Map<String, Object>) userInfoResponse.getBody().get("kakao_account");

        // JWT 토큰 생성 및 반환
        String jwtToken = jwtTokenProvider.createToken((String) kakaoAccount.get("email"));
        return ResponseEntity.ok(new LoginResponse(jwtToken));
    }
}



`JwtTokenProvider` 클래스는 JWT를 생성해주는 유틸 클래스로 별도 작성이 필요합니다.

 

 (4) JWT 발급 클래스 - JwtTokenProvider

@Component
public class JwtTokenProvider {
    
    @Value("${spring.jwt.secret}")
    private String secretKey;
    @Value("${spring.jwt.expiration}")
    private long validityInMilliseconds;

    public String createToken(String email) {
        Claims claims = Jwts.claims().setSubject(email);
        Date now = new Date();
        Date validity = new Date(now.getTime() + validityInMilliseconds);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(SignatureAlgorithm.HS256, secretKey)
                .compact();
    }
}


 3. Vue3 - 카카오 로그인 버튼 생성 및 백엔드 요청 처리


 (1) 로그인 버튼 컴포넌트


Vue3에서 카카오 로그인 버튼을 만들고 로그인 API를 호출하는 컴포넌트를 만듭니다.

<template>
  <div>
    <button @click="redirectToKakaoLogin">카카오 로그인</button>
  </div>
</template>

<script>
export default {
  methods: {
    redirectToKakaoLogin() {
      const clientId = '<카카오 REST API 키>';
      const redirectUri = 'http://localhost:8080/oauth/kakao/callback';
      const kakaoAuthUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code`;
      window.location.href = kakaoAuthUrl;
    }
  }
};
</script>



(2) 로그인 콜백 처리


로그인 후 백엔드에서 받은 JWT 토큰을 로컬 스토리지나 쿠키에 저장하여 인증 상태를 관리합니다.

// src/store/auth.js
import { defineStore } from 'pinia';

export const useAuthStore = defineStore('auth', {
  state: () => ({
    token: null,
  }),
  actions: {
    setToken(token) {
      this.token = token;
      localStorage.setItem('jwt-token', token);
    },
    clearToken() {
      this.token = null;
      localStorage.removeItem('jwt-token');
    },
    async login(code) {
      const response = await fetch(`http://localhost:8080/oauth/kakao/callback?code=${code}`);
      const data = await response.json();
      this.setToken(data.token);
    },
  },
});



4. 로그인 확인 및 인증 유지

Vue3의 라우터 가드나 Pinia 상태 관리를 통해 페이지 이동 시 인증 여부를 확인하여 접근을 제어할 수 있습니다.

'개발일지' 카테고리의 다른 글

현재 진행 상황 + 해야 할 것  (0) 2024.11.15
Api 명세서 작성하기  (0) 2024.11.13
흐름도 플로우 차트 draw.io  (1) 2024.11.12
[DB] ERD Cloud  (3) 2024.11.11
Vue.js  (5) 2024.11.10