📝오늘 공부한 것
- 실전프로젝트 - '행동대장' 카카오로그인 구현
- 인프런 김영한의 스프링 강의 섹션5
⛔문제점
[에러 메시지]
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.client.HttpClientErrorException$BadRequest: 400 Bad Request: "{"error":"invalid_grant","error_description":"authorization code not found for code=v7B6seKGSDCRLKpOvIwAfATwHgLiGfeddI7QNVmuXFkHrn6AZi5GY-n1D7ycl5VKre4tTAorDSAAAAGKMInl3A","error_code":"KOE320"}"] with root cause
-> 인증코드가 잘못 되었다는 에러가 뜸!
시도해 본 것들💦
✔ KakaoService
private String getToken(String code) throws JsonProcessingException {
URI uri = UriComponentsBuilder
.fromUriString("https://kauth.kakao.com")
.path("/oauth/token")
.encode()
.build()
.toUri();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", kakaoClientId);
body.add("redirect_uri", "http://localhost:3000/oauth/callback");
body.add("code", code);
RequestEntity<MultiValueMap<String, String>> requestEntity = RequestEntity
.post(uri)
.headers(headers)
.body(body);
ResponseEntity<String> response = restTemplate.exchange(
requestEntity,
String.class
);
JsonNode jsonNode = new ObjectMapper().readTree(response.getBody());
return jsonNode.get("access_token").asText();
}
프론트에서 넘겨주는 인가코드로 카카오에 엑세스 토큰을 요청하는 메서드이다.
이때 HTTP Body에 client_id와 redirect_uri를 넘겨줘야 한다.
이때 프론트의 rest api키와 도메인 주소를 넣어주었다. 그런데 계속 code에 관한 에러가 났다. 그래서 혹시나 하고 client_id와 redirect_uri 모두 백엔드것을 넣어보았다. 그런데도 해결되지 않아 로그를 찍어보았다.
💯해결
[프론트엔드 에러 메시지]
AxiosError {message: 'Request failed with status code 403', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …} code : "ERR_BAD_REQUEST" config : {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …} message : "Request failed with status code 403" name : "AxiosError" request : XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} response : {data: '', status: 403, statusText: '', headers: AxiosHeaders, config: {…}, …} stack : "AxiosError: Request failed with status code 403\n at settle (http://localhost:3000/static/js/bundle.js:98671:12)\n at XMLHttpRequest.onloadend (http://localhost:3000/static/js/bundle.js:97371:66)" [[Prototype]] : Error
{data: {…}, status: 200, statusText: '', headers: AxiosHeaders, config: {…}, …} config : {transitional: {…}, adapter: Array(2), transformRequest: Array(1), transformResponse: Array(1), timeout: 0, …} data : {msg: '로그인에 성공하였습니다.'} headers : AxiosHeaders {authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJjaGFsazMyM0…jc4fQ.3DjnyJmRr8Bb4taXJ25lo_nmBJULqNSh9W-YLuOPr8w', cache-control: 'no-cache, no-store, max-age=0, must-revalidate', content-type: 'application/json', expires: '0', pragma: 'no-cache'} request : XMLHttpRequest {onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …} status : 200 statusText : "" [[Prototype]] : Object
심지어 프론트에서는 이렇게 에러와 성공이 같이떴다. 그리고 엑세스 토큰도 잘 전달되었다.
그래서 어떻게 요청이 오는데 내가 그 요청에 대해서 response를 두번 날리게 되는거지?하고 생각을 해보았다.
또, KOE320이라는 에러가 계속나와서 인가코드 관련 문제가 뭐가 있을까 생각해봤다.
https://developers.kakao.com/docs/latest/ko/kakaologin/trouble-shooting
그런데 서버의 로그를 다시보니까 로그가 계속 두번씩 찍히고 있는 것이었다!!!
혹시나...하고 프론트분에게 '서버로 요청이 두번씩 온다 그래서 코드 에러가 나는 것같다. 프론트에서 서버로 요청을 어떻게 보내는지 알려주실 수 있나'하고 물어보았다.
프론트분이 확인을 하고 알려주신다 했다. 알고보니까 정말로 프론트에서 요청이 두번씩 날라오는 것이었다! 그게 React에서 그렇게 보낸다(?)고 하셨다.
암튼!!또 이렇게 무사히 에러를 해결할 수 있었다!
알게 된 점❗
✔ KakaoService
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", 프론트 키 적기);
body.add("redirect_uri", 프론트주소 적기);
body.add("code", code);
프론트의 주소를 적어야 내가 프론트로부터 code를 받을 수 있음!
✔ OAuth
인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다.
사용자가 애플리케이션에게 모든 권한을 넘기지 않고 사용자 대신 서비스를 이용할 수 있게 해주는 HTTP기반의 보안 프로토콜이다.
OAuth를 사용하는 서비스 제공자는 대표적으로 구글, 페이스북, 카카오, 네이버 등이 있다.
개선할 점💪🏻
오늘 멘토님의 피드백이 있었다.
Q. 목표로 했던 기능들이 모두 완료되어가고 있다. 앞으로 남은 기간동안 백엔드에서는 무엇을 하면 좋을까?
A.
- 백엔드는 계속 개선할 것들이 생긴다. 성능테스트를 계속 해봐라.
- 스프링배치에 대해서 찾아볼 것. JMeter test 계속 해볼 것.
- https://spring.io/projects/spring-hateoas/ 를 사용해봐라. (API tool)
- 더미데이터 생성 시 spring commandline runner 사용해 봐라.
Q. 테스트코드 작성을 해보면 프로젝트에 도움이 될 지?
A.
- 많은 도움이 됨. 꼭 해봤으면 좋겠다.
- 많이 어렵다면 https://symflower.com/en/ 를 써보는 것도 좋을 것.
마지막으로
😀 : 조만간 유저피드백을 진행하면 사용자들은 우리가 원하는데로만 사용하지 않는다. 따라서 버그가 많이 날 것이다. 우리가 발견하지 못했던 exception을 잡아주는 것이라고 생각해라.
라는 조언이 있으셨다. 기능 구현들이 거의 다 끝나간다. 테스트코드 작성의 중요성을 다시 한번 느끼고 빨리 작성해보고 싶다는 생각이 들었다.
'TIL(Today I Learned)' 카테고리의 다른 글
TIL-230829(항해99 실전 프로젝트-행동대장(19)) (0) | 2023.08.29 |
---|---|
TIL-230828(항해99 실전 프로젝트-행동대장(18)) (0) | 2023.08.28 |
TIL-230825(항해99 실전 프로젝트-행동대장(16), EC2에 Swap Memory 적용) (0) | 2023.08.25 |
TIL-230824(항해99 실전 프로젝트-행동대장(15)) (0) | 2023.08.25 |
TIL-230823(CI/CD) (0) | 2023.08.23 |