1. 카카오 로그인 로직 구현하기
UserController
@GetMapping("/oauth/callback")
public String callback(String code) {
System.out.println("콜백 완료 : " + code);
User sessionUser = userService.카카오로그인(code);
session.setAttribute("sessionUser", sessionUser);
return "redirect:/shop";
}
UserService
public void 카카오로그인(String code) {
// 1. code로 카카오에서 토큰 받기 (위임완료)
// 2. 토큰으로 사용자 정보 받기 (PK, Email)
// 3. 해당정보로 DB조회 (있을수, 없을수)
// 4. 있으면? - 조회된 유저정보 리턴
// 5. 없으면? - 강제 회원가입
// 유저네임 : (provider_pk)
// 비밀번호 : UUID
// 이메일 : email 받은 값
// 프로바이더 : kakao
}
카카오에 등록한 Redirect URI 주소에 연결된 서비스 코드를 만든다.
순서는 1. 토큰 받기 - 2. 토큰으로 사용자 정보 받기 - 3. 정보로 스프링 서버에서 DB 조회 후 로그인 OR 회원가입 과정을 거친다.
2. 카카오에서 토큰 받기
UserService/카카오로그인(){}
// 1.1 RestTemplate 설정
RestTemplate rt = new RestTemplate();
// 1.2 http header 설정
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// 1.3 http body 설정
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", REST API 키 넣으면 됨);
body.add("redirect_uri", "http://localhost:8080/oauth/callback");
body.add("code", code);
// 1.4 body+header 객체 만들기
HttpEntity<MultiValueMap<String, String>> request =
new HttpEntity<>(body, headers);
// 1.5 api 요청하기 (토큰 받기)
ResponseEntity<KakaoResponse.TokenDTO> response = rt.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
request,
KakaoResponse.TokenDTO.class);
// 1.6 값 확인
System.out.println(response.getBody().toString());

카카오에서 받은 토큰을 확인할 수 있다.
3. 토큰으로 사용자 정보 받기
HttpHeaders headers2 = new HttpHeaders();
headers2.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
headers2.add("Authorization", "Bearer "+response.getBody().getAccessToken());
HttpEntity<MultiValueMap<String, String>> request2 =
new HttpEntity<>(headers2);
ResponseEntity<KakaoResponse.KakaoUserDTO> response2 = rt.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.GET,
request2,
KakaoResponse.KakaoUserDTO.class);
System.out.println("response2 : "+response2.getBody().toString());
4. 받은 정보로 DB 조회
String username = "kakao_"+response2.getBody().getId();
User userPS = userRepository.findByUsername(username);
아이디는 API 요청한 플랫폼(카카오, 네이버, 구글 등) + “_” + 전달받은 primary key 를 사용한다. 이렇게 만들면 아이디가 중복될 수 없다.
if(userPS != null){
System.out.println("회원 정보 있음. 강제로그인 진행");
return userPS;
}else{
System.out.println("회원 정보 없음. 강제회원가입 and 강제로그인 진행");
// 5. 없으면? - 강제 회원가입
// 유저네임 : (provider_pk)
// 비밀번호 : UUID
// 이메일 : email 받은 값
// 프로바이더 : kakao
User user = User.builder()
.username(username)
.password(UUID.randomUUID().toString())
.email(response2.getBody().getProperties().getNickname()+"@nate.com")
.provider("kakao")
.build();
User returnUser = userRepository.save(user);
return returnUser;
}
조회된 데이터가 있다면 바로 로그인을 한다. 만약 데이터가 없다면 회원가입 후 로그인을 진행한다.
아이디는 : provider(카카오,네이버,구글 등)_pk
비밀번호 : UUID 사용 (비밀번호는 회원이 알 필요 없다.)
이메일 : 카카오에게 받은 이메일(현재는 이메일을 받을 수 없기 때문에 닉네임@nate.com 으로 등록한다.
UserService 전체 코드
package org.example.loginapp.user;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.util.UUID;
@RequiredArgsConstructor
@Service
public class UserService {
private final UserRepository userRepository;
@Transactional
public void 회원가입(String username, String password, String email) {
User user = User.builder()
.username(username)
.password(password)
.email(email)
.build();
userRepository.save(user);
}
public User 로그인(String username, String password) {
User user = userRepository.findByUsername(username);
if(user == null){
throw new RuntimeException("아이디가 없습니다");
}else{
if(user.getPassword().equals(password)){
return user;
}else{
throw new RuntimeException("비밀번호가 틀렸습니다");
}
}
}
public User 카카오로그인(String code) {
// 1. code로 카카오에서 토큰 받기 (위임완료) - oauth2.0
// 1.1 RestTemplate 설정
RestTemplate rt = new RestTemplate();
// 1.2 http header 설정
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// 1.3 http body 설정
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", REST API 키 넣으면 됨);
body.add("redirect_uri", "http://localhost:8080/oauth/callback");
body.add("code", code);
// 1.4 body+header 객체 만들기
HttpEntity<MultiValueMap<String, String>> request =
new HttpEntity<>(body, headers);
// 1.5 api 요청하기 (토큰 받기)
ResponseEntity<KakaoResponse.TokenDTO> response = rt.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
request,
KakaoResponse.TokenDTO.class);
// 1.6 값 확인
System.out.println(response.getBody().toString());
// 2. 토큰으로 사용자 정보 받기 (PK, Email)
HttpHeaders headers2 = new HttpHeaders();
headers2.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
headers2.add("Authorization", "Bearer "+response.getBody().getAccessToken());
HttpEntity<MultiValueMap<String, String>> request2 =
new HttpEntity<>(headers2);
ResponseEntity<KakaoResponse.KakaoUserDTO> response2 = rt.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.GET,
request2,
KakaoResponse.KakaoUserDTO.class);
System.out.println("response2 : "+response2.getBody().toString());
// 3. 해당정보로 DB조회 (있을수, 없을수)
String username = "kakao_"+response2.getBody().getId();
User userPS = userRepository.findByUsername(username);
// 4. 있으면? - 조회된 유저정보 리턴
if(userPS != null){
System.out.println("회원 정보 있음. 강제로그인 진행");
return userPS;
}else{
System.out.println("회원 정보 없음. 강제회원가입 and 강제로그인 진행");
// 5. 없으면? - 강제 회원가입
// 유저네임 : (provider_pk)
// 비밀번호 : UUID
// 이메일 : email 받은 값
// 프로바이더 : kakao
User user = User.builder()
.username(username)
.password(UUID.randomUUID().toString())
.email(response2.getBody().getProperties().getNickname()+"@nate.com")
.provider("kakao")
.build();
User returnUser = userRepository.save(user);
return returnUser;
}
}
}


DB에 회원가입이 완료되었다.
Share article