
링크 : https://developers.kakao.com/
회원가입을 하고 애플리케이션에 들어가 프로젝트를 추가해줍니다.
테스트는 앱 권한 신청을 할 필요 없이 url 등록으로 간편 로그인을 구현할 수 있습니다.
사이트 도메인을 등록해줍니다. 저는 로컬 환경에서 테스트 예정이기 때문에 해당 주소(http://localhost:8080) 로 설정했습니다. 그리고 아래 RdirectUrl 등록 하러 가기를 클릭해줍니다.

사용자가 카카오 로그인 후 Redirect로 이동할 Url을 입력해주면 됩니다.

동의 항목을 선택합니다. 프로젝트에 맞게 수집하는 고객의 정보를 설정해주면 됩니다.
저희는 사용자의 프로필사진과 배송지 정보도 받고 있기 때문에 해당 항목도 필수로 설정해주었습니다.

위 세과정을 완료했다면 아래처럼 api에 필요한 key들이 생성됩니다.

저희는 REST API 키 값을 사용하였습니다. 적용하기에 앞서 아래 카카오가 제공하는 REST API 문서를 읽고 오시면 아래 코드를 이해하는데 더 도움이 되실 것 같습니다.
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
<div>
<a class="btn btn-outline-dark mb-3" href="https://kauth.kakao.com/oauth/authorize?client_id=REST API 키 값&redirect_uri=http://localhost:8080/kakaoLogin&response_type=code" style="width:100%">카카오로 간편 로그인</a>
</div>
👾client_id= 뒤에 REST API 키 값을 넣어줍니다
👾redirect_uri= 뒤에 사용자가 카카오 로그인 후 Redirect로 이동할 Url을 넣어줍니다.
public class Member {
private String mbId;
private String mbPwd;
private String mbName;
private String mbPhoto;
private String mbIntro;
private String mbNickName;
private String mbEmail;
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date mbBirth;
private String mbTel;
private int mbPoint;
private String mbStatus;
private String isAdmin;
private String isPrivate;
private Date nextChange;
private String isKakao;
private String isBanned;
}
@SessionAttributes("loginUser")
@Controller
public class AccountController {
@Autowired
private KakaoLoginService kService;
@GetMapping("kakaoLogin")
public String kakaoLogin(@RequestParam(value="code", required=false) String code, Model model) {
System.out.println(code);
String accessToken = kService.getAccessToken(code);
System.out.println("###access_Token#### : " + accessToken);
// 위의 access_Token 받는 걸 확인한 후에 밑에 진행
HashMap<String, Object> userInfo = kService.getUserInfo(accessToken);
System.out.println("###id#### : " + userInfo.get("id"));
System.out.println("###name#### : " + userInfo.get("name"));
System.out.println("###profileImage#### : " + userInfo.get("profileImage"));
System.out.println("###birthday#### : " + userInfo.get("birthday"));
System.out.println("###birthyear#### : " + userInfo.get("birthyear"));
System.out.println("###phoneNumber#### : " + userInfo.get("phoneNumber"));
System.out.println("###email#### : " + userInfo.get("email"));
try {
String mbId = (String)userInfo.get("id") + "kAkAo"; //카카오 로그인 시 자동으로 ID뒤에 붙일 문자열
String name = (String)userInfo.get("name");
String profileImage = (String)userInfo.get("profileImage");
String email = (String)userInfo.get("email");
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Date date;
date = sdf.parse((String)userInfo.get("birthyear") + (String)userInfo.get("birthday"));
String phoneNumber = (String)userInfo.get("phoneNumber");
String phone = "0" + phoneNumber.substring(4).replace("-", ""); //DB 선택 사항
//사용자가 이미 회원가입한 회원인지 확인
Member m;
int result = aService.idCheck(mbId);
System.out.println(mbId);
System.out.println(name);
System.out.println(profileImage);
System.out.println(date);
System.out.println(phone);
int result2;
if (result > 0) { //이미 가입한 경우 회원 정보를 가져옴
m = new Member();
m.setMbId(mbId);
} else {
m = new Member();
m.setMbId(mbId);
m.setMbPwd(bcrypt.encode(mbId));
m.setMbName(name);
m.setMbPhoto(profileImage);
m.setMbNickName(mbId);
m.setMbBirth(date);
m.setMbTel(phone);
m.setMbEmail(email);
m.setIsKakao("Y");
result2 = aService.signUpMember(m);
}
m = aService.login(m);
model.addAttribute("loginUser", m); //로그인한 사용자 정보를 뷰로 전달
} catch (ParseException e) {
e.printStackTrace();
}
return "redirect:/"; //메인 페이지로 이동
}
}
👾 getAccessToken(code)를 호출하여 카카오로부터 액세스 토큰을 받아오고 이 토큰은 카카오 API를 호출하는데 사용됩니다.
👾 getUserInfo(accessToken)를 호출하여 DB에 필요한 사용자의 카카오 프로필 정보를 가져옵니다.
public interface KakaoLoginService {
String getAccessToken(String code);
HashMap<String, Object> getUserInfo(String accessToken);
}
@Service
public class KakaoLoginServiceImpl implements KakaoLoginService{
@Override
public String getAccessToken(String code) {
String access_Token = "";
String refresh_Token = "";
String reqURL = "https://kauth.kakao.com/oauth/token";
URL url;
try {
url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// POST 요청을 위해 기본값이 false인 setDoOutput을 true로
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id="); //💡REST_API키 본인이 발급받은 key 넣어주기
sb.append("&redirect_uri="); //💡REDIRECT_URI 본인이 설정한 주소 넣어주기
sb.append("&code=" + code);
bw.write(sb.toString());
bw.flush();
// 결과 코드가 200이라면 성공
int responseCode = conn.getResponseCode();
System.out.println("responseCode : " + responseCode);
// 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
System.out.println("response body : " + result);
// jackson objectmapper 객체 생성
ObjectMapper objectMapper = new ObjectMapper();
// JSON String -> Map
Map<String, Object> jsonMap = objectMapper.readValue(result, new TypeReference<Map<String, Object>>() {
});
access_Token = jsonMap.get("access_token").toString();
refresh_Token = jsonMap.get("refresh_token").toString();
System.out.println("access_token : " + access_Token);
System.out.println("refresh_token : " + refresh_Token);
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
return access_Token;
}
@Override
public HashMap<String, Object> getUserInfo(String accessToken) {
// 요청하는 클라이언트마다 가진 정보가 다를 수 있기에 HashMap타입으로 선언
HashMap<String, Object> userInfo = new HashMap<String, Object>();
String reqURL = "https://kapi.kakao.com/v2/user/me";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 요청에 필요한 Header에 포함될 내용
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
int responseCode = conn.getResponseCode();
System.out.println("responseCode : " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
System.out.println("response body : " + result);
System.out.println("result type" + result.getClass().getName()); // java.lang.String
// jackson objectmapper 객체 생성
ObjectMapper objectMapper = new ObjectMapper();
// JSON String -> Map
Map<String, Object> jsonMap = objectMapper.readValue(result, new TypeReference<Map<String, Object>>() {
});
System.out.println(jsonMap.get("properties"));
Map<String, Object> properties = (Map<String, Object>) jsonMap.get("properties");
Map<String, Object> kakao_account = (Map<String, Object>) jsonMap.get("kakao_account");
// System.out.println(properties.get("nickname"));
// System.out.println(kakao_account.get("email"));
String id = jsonMap.get("id").toString();
String name = kakao_account.get("name").toString();
String profileImage = properties.get("profile_image").toString();
String email = kakao_account.get("email").toString();
String birthday = kakao_account.get("birthday").toString();
String birthyear = kakao_account.get("birthyear").toString();
String phoneNumber = kakao_account.get("phone_number").toString();
userInfo.put("id", id);
userInfo.put("name", name);
userInfo.put("profileImage", profileImage);
userInfo.put("email", email);
userInfo.put("birthday", birthday);
userInfo.put("birthyear", birthyear);
userInfo.put("phoneNumber", phoneNumber);
} catch (IOException e) {
e.printStackTrace();
}
return userInfo;
}
}