[Spring, Vue.js] ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ ๋ง๋ค๊ธฐโก - Vue๋ก ํ๋ก ํธ์๋ ์์ฑํ๊ธฐ (REST API)
[Spring,Vue.js] ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ ๋ง๋ค๊ธฐ โ - ๊ตฌ์กฐ์ ํ๋ฆ ํ์ ํ๊ณ ์นด์นด์ค ๋๋ฒจ๋กํผ์ค ์ค์ ํ๊ธฐ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ์ ๋ง๋ค์ด๋ณด์!๋จผ์ ์ด๋ป๊ฒ ๋ง๋ค์ด์ผํ๋์ง ๊ตฌ์กฐ์ ํ๋ฆ์ ํ์ ํ๊ณ ์นด์นด์ค
post-this.tistory.com
ํ๋ก ํธ์๋๊น์ง ์์ฑํ๋ค.
์ด์ ๋ฐฑ์๋๋ก ๋์ด์์ ํ ํฐ ๊ตํ๊น์ง ๋ง๋ค์ด๋ณด์!
1. ํ๋ฉด
- ๋ก๊ทธ์ธ ์ฑ๊ณต
- ๋ฉ์ธํ๋ฉด (๋๋ค์ O)
2. ์ ์ฒด ์ฝ๋
package ์ฌ๋ฌ๋ถ๊ฑธ๋ก ๋ฃ์ผ์ธ์ &_&
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.LinkedHashMap;
import java.util.Map;
@RestController
@RequestMapping("/oauth")
@CrossOrigin(origins = "http://localhost:5173", allowCredentials = "true")
public class KakaoController {
@Value("23558386d3608da96ec5a589aabe5a2b")
private String clientId;
@Value("${kakao.redirect-uri}")
private String redirectUri;
private final RestTemplate rest = new RestTemplate();
@PostMapping("/kakao")
public ResponseEntity<?> kakao(@RequestBody Map<String, String> body) {
// 1) ํ ํฐ ๊ตํ
String code = body.get("code");
if (!StringUtils.hasText(code)) {
return ResponseEntity.badRequest().body("code ๋๋ฝ");
}
try {
HttpHeaders tokenHeaders = new HttpHeaders();
tokenHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add("grant_type", "authorization_code");
form.add("client_id", clientId);
form.add("redirect_uri", redirectUri);
form.add("code", code);
HttpEntity<MultiValueMap<String, String>> tokenReq = new HttpEntity<>(form, tokenHeaders);
ResponseEntity<Map> tokenRes = rest.postForEntity(
"https://kauth.kakao.com/oauth/token", tokenReq, Map.class);
if (!tokenRes.getStatusCode().is2xxSuccessful() || tokenRes.getBody() == null) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("ํ ํฐ ๊ตํ ์คํจ");
}
String accessToken = (String) tokenRes.getBody().get("access_token");
if (!StringUtils.hasText(accessToken)) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("access_token ์์");
}
// 2) ์ฌ์ฉ์ ์ ๋ณด ์กฐํ (๋๋ค์๋ง ํ์)
HttpHeaders userHeaders = new HttpHeaders();
userHeaders.setBearerAuth(accessToken);
HttpEntity<Void> userReq = new HttpEntity<>(userHeaders);
ResponseEntity<Map> userRes = rest.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.GET,
userReq,
Map.class
);
if (!userRes.getStatusCode().is2xxSuccessful() || userRes.getBody() == null) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("์ฌ์ฉ์ ์ ๋ณด ์์ฒญ ์คํจ");
}
// 3) JSON(Map)์์ nickname๋ง ๊บผ๋
Map bodyMap = userRes.getBody();
Map kakaoAccount = (Map) bodyMap.get("kakao_account");
Map profile = kakaoAccount != null ? (Map) kakaoAccount.get("profile") : null;
String nickname = profile != null ? (String) profile.get("nickname") : null;
Map<String, Object> result = new HashMap<>();
String safeNickname = (nickname != null) ? nickname : "KakaoUser";
result.put("nickname", safeNickname);
return ResponseEntity.ok(result);
} catch (Exception ex) {
ex.printStackTrace();
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("์นด์นด์ค ์ฐ๋ ์ค ์ค๋ฅ");
}
}
}
3. application.properties
kakao.client-id= ๋ฐ๊ธ๋ฐ์ REST API KEY ๋ฃ๊ธฐ
kakao.redirect-uri=http://localhost:5173/oauth/code/kakao
resources ๋๋ ํฐ๋ฆฌ๊ฐ src ํ์์ ์์ ๊ฒ์ด๋ค. resources ๋๋ ํฐ๋ฆฌ ์์ application.properties๊ฐ ์๋ค. ๊ฑฐ๊ธฐ์ ์ฝ๋๋ฅผ ์ ์ด์ฃผ๋ฉด ๋๋ค. ๋ฌผ๋ก REST API KEY์ redirect-uri๋ ๊ฐ์ ์ ํด๋ ๊ฑธ๋ก ๋ณ๊ฒฝํด์ ์ ์ด์ผ ํ๋ค.
3. KakaoController.java
// โ
@RestController
// โก
@RequestMapping("/oauth")
// โข
@CrossOrigin(origins = "http://localhost:5173", allowCredentials = "true")
public class KakaoController {
}
โ
REST API๋ ์น์์ ์์์ HTTP ๊ท์น์ ๋ง์ถฐ ์ฃผ๊ณ ๋ฐ๋ ๋ฐฉ์์ด๋ค. URL๋ก ์์์ ๊ฐ๋ฆฌํค๊ณ , HTTP ๋ฉ์๋(GET, POST ๋ฑ)๋ก ๋ฌด์จ ๋์์ธ์ง ํํํ๋ค. ๊ทธ๋ฆฌ๊ณ 200 OK, 400 Bad Request์ ๊ฐ์ด ์๋ต ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ค. ์๋ฌดํผ ์ด๋ฐ ๊ท์น์ ๊ฐ์ง๊ณ ์์ฑํ๋๊ฒ REST API๋ผ๊ณ ํ๋ฉฐ, @RestController๋ REST API๋ฅผ ๊ฐ๋ฐํ ๋ ์ฃผ๋ก ์ฌ์ฉํ๋ค.
@RestController๋ View๊ฐ ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผํ๋ ๊ฒฝ์ฐ์ ์ ํฉํ๋ค. return ResponseEntity.ok(result);์ด๋ฐ ์ฝ๋๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด, 200 ์๋ต์ฝ๋์ JSON ๋ฐ๋๋ฅผ ๊ฐ์ด ๋ณด๋ธ๋ค. ์ด๋ ๊ฒ ํ๋ฉด์ด ์๋ result๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํด์ผํ๋ ๊ฒฝ์ฐ @RestController๋ฅผ ์ฌ์ฉํด์ผํ๋ค. (๊ทธ๋ฅ ๋ฐฑ์๋, ํ๋ก ํธ์๋ ๋๋ ์ ํ๋ ๊ฑฐ๋ฉด @RestController ์ด๋ค๊ณ ๋ณด๋ฉด ๋๋ค)
โก
@RequestMapping์ ๊ณตํต ๊ฒฝ๋ก๋ฅผ ์ ์ด์คฌ๋ค. /oauth๋ก ์ค๋ ์์ฒญ์ KakaoController์์ ์ฒ๋ฆฌํ๋ค๊ณ ์ ์ํ ๊ฒ์ด๋ค.
โข
@Crossorigin์ http://localhost:5173์์ ๋ณด๋ด๋ ํฌ๋ก์ค ์ค๋ฆฌ์ง ์์ฒญ์ ํ์ฉํ๊ฒ ํ๋ค. ๊ทธ๋ฆฌ๊ณ allowCredentials ์ฟ ํค/์ธ์ฆ์ ๋ณด๋ฅผ ํจ๊ป ์ค์ด ๋ณด๋ด๋ ๋๊ฒ ํ์ฉํ๋ผ๋ ์ค์ ํ๋ค. ํ๋ก ํธ(http://localhost:5173)์ ๋ฐฑ์๋(http://localhost:8080)์ ์ค๋ฆฌ์ง์ด ๋ค๋ฅด๋ฉด, ๋ธ๋ผ์ฐ์ ๊ฐ CORS ๊ท์น์ ์ ์ฉํฉ๋๋ค.
์ด ์ฝ๋๋ฅผ ์ ์ํ์ง ์์ผ๋ฉด, ํ๋ฉด์์ ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ์ด ์ ๋๋ก ์ํ๋์ง ์๋๋ค. ์ค๋ฆฌ์ง์ด ๋ฌ๋ผ์ KakaoController๋ก ์ด๋ค ์์ฒญ๋ ๋ฐ์ดํฐ๋ ์ค์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด ๋ค์ ์ฝ๋๋ถํฐ๋ KakaoController์ ์ ์ด์ค๋ค.
// โ
@Value("${kakao.client-id}")
private String clientId;
// โก
@Value("${kakao.redirect-uri}")
private String redirectUri;
โ
์ฝ๋ ๋ด๋ถ์ ์ํฌ๋ฆฟ ํค๋ฅผ ์ ์ฅํ ๊ฒฝ์ฐ ๊นํ๋ธ์ ์ฝ๋๊ฐ ์ฌ๋ผ๊ฐ๋ฉด ์๋๋ค. ๊ทธ๋ด ๊ฒฝ์ฐ application.properties์ ๋ณด์์ด ํ์ํ ๊ฐ์ ๋ฃ์ด๋๊ณ ์ธ๋ถ์ ๋ ธ์ถ๋์ง ์๋๋ก ํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ application.properties์ ๋ณด๊ด๋ ๊ฐ์ ๊บผ๋ด์ค๋ ์ด๋ ธํ ์ด์ ์ด @Value๊ฐ ๋๋ค.
โก
๋์ผํ๊ฒ ์ ์ด์ค๋ค. ๊ทธ๋ฌ๋ ๊ผญ application.properties์ ์ ์ด ํ์ฌ ์ฝ๋์ ๊ฐ์ด ๋ฐ์ง ์์๋ ๋๋ค. @Value("๋ฐ๊ธ๋ฐ์ REST_API_KEY")๋ก ์ ์ด๋ ๋๋ค.(๊ทผ๋ฐ ๊ทธ๋ ๊ฒํ๋ฉด @Value๋ฅผ ์ด ์๋ฏธ๋ ์ฌ๋ผ์ง๋ค) ์๋๋ฉด ๋ฐ๋ก ๋ฃ์ด์ค๋ ๋๋ค.
// โ
private final RestTemplate rest = new RestTemplate();
โ
RestTemplate๋ ์คํ๋ง์์ ์ธ๋ถ HTTP API๋ฅผ ํธ์ถํ ๋ ์ฐ๋ ๋๊ธฐ ๋ฐฉ์์ ๊ฐ๋จํ ํด๋ผ์ด์ธํธ์ด๋ค. ์ฌ๊ธฐ์ ๋๊ธฐ ๋ฐฉ์์ด๋, ์์ ์ ๋ง์น ๋๊น์ง ๋ค์ ์์ ์ ๊ธฐ๋ค๋ฆฌ๋ ์์ฐจ์ ์ธ ๋ฐฉ์์ผ๋ก ๋์ฉ๋ ์ฒ๋ฆฌ๋ฅผ ํด์ผํ๋ ๊ฒฝ์ฐ๋ณด๋ค ๋ฐ์ดํฐ์ ์์ฐจ์ ์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
์นด์นด์ค์ ๋ก๊ทธ์ธ ํ๋ฆ์ ๋ณด๋ฉด ์ธ๊ฐ์ฝ๋๋ฅผ ๋ฐ๊ณ -> ๋ฐ์๊ฑธ๋ก ํ ํฐ ๊ตํ์ ํ๊ณ -> ํ ํฐ์ผ๋ก ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์กฐํ ํ๋ ์์๋ก ์ด๋ค์ ธ ์๋ค. ์์ฐจ์ ์ธ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ ํ์ํ์ง๋ง, ๊ฒฐ๊ตญ ํ ํฐ๋ ์ฌ์ฉ์ ์ ๋ณด ์กฐํ๋ ์ธ๋ถ HTTP API์ธ ์นด์นด์ค๋ฅผ ํธ์ถํด์ผํ๊ธฐ ๋๋ฌธ์ RestTemplate๊ฐ ๋ณต์กํ๊ฒ ์์ฑ๋ ์ฝ๋๋ฅผ ๊ฐ๋จํ๊ฒ ๋ง๋ค์ด์ค๋ค.
๊ฑฐ๊ธฐ๋ค ์ฒซ๋ฒ์งธ ํฌ์คํ ์์ ํ ํฐ ๊ตํํ ๋, application/x-www-form-urlencoded๋ก ์ ์กํ๊ณ JSON ์๋ต์ ๋ฐ๋๋ค๊ณ ๋์ด์๋ค. ์ด๋ ๊ฒ ์ ์ก, ์๋ตํ๋ ํํ์ ๋ง์ถฐ ๋ณํํด์ผํ๋๋ฐ ๊ทธ๊ฑธ ํ ์ค๋ก ๊น๋ํ๊ฒ ํ ์ ์๋ค.
์ฌ๊ธฐ์ ์ค์ํ ์ ์ ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ์ RestTemplate๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋จํ๊ฒ ๋๋ผ ์ ์๋ค๋๊ฑฐ์ง, ์ด๊ฒ ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ด๋ผ๋ ๊ฒ์ ์๋๋ค. RestTemplate๋ฅผ ๊ณต๋ถํ๋ฉด WebClient์ ๋ํด์๋ ์์ฐ์ค๋ ์๊ฒ๋๋๋ฐ, WebClient๊ฐ ๋น๋๊ธฐ ๋ฐฉ์์ผ๋ก ์ด๋ค์ ธ ๋๋์ผ๋ก ๋์ ํธ์ถ์ด ๋ค์ด์๋ ์ฒ๋ฆฌํ ์ ์์ด์ ๋ ๊ถ์ฅํ๋ ์ถ์ธ์ด๋ค. ์ง๊ธ ํ๊ณ ์๋ ๊ฒ์ ๊ฐ๋จํ ํ๋ก์ ํธ๋ก ์ค์ ์ ํฌํ ๊ฒ ์๋๊ธฐ ๋๋ฌธ์ RestTemplate๋ก ์์ฑํ๋ค.
// โ
@PostMapping("/kakao")
// โก
public ResponseEntity<?> kakao(@RequestBody Map<String, String> body) {
}
โ
Vue์์ await axios.post("http://localhost:8080/oauth/kakao", { code }); ์ด ์ฝ๋๋ฅผ ๊ธฐ์ตํด์ผํ๋ค. ํ๋ก ํธ์์ ์ธ๊ฐ์ฝ๋๋ฅผ ๋ฐ์ ๋ฐฑ์๋๋ก ๋ณด๋ธ ์ฝ๋์ด๋ค. ์ด๋ post๋ก ๋ณด๋ด์, ๋ฐฑ์๋ ์์ ์์ ๋ค์ PostMapping์ผ๋ก ๋ฐ์๋ค.
โก
์ธ๊ฐ์ฝ๋๊ฐ ์์ฒญ ๋ฐ๋๋ก ๋์ฐฉํ์ ๊ฒ์ด๋ค. ๋์ฐฉํ ํํ๋ JSON์ด๋ค. JSON์ ์ฌ๋์ด ์ฝ๊ณ ์ฐ๊ธฐ ์ฌ์ฐ๋ฉด์ ๊ธฐ๊ณ๊ฐ ์ฒ๋ฆฌํ๊ธฐ ์ฌ์ด ํ ์คํธ ๊ธฐ๋ฐ์ ๋ฐ์ดํฐ ๊ตํ ํ์์ด๋ค. ์ด๋ ๊ฒ ์จ body๋ฅผ Map<String, String>์ผ๋ก ๋ณํํ ๊ฒ์ด๋ค. ๋ณํ์ ์ด๋ ต์ง ์๋ค. @RequestBody๋ฅผ ๋ถ์ฌ ๋ฐ๋๋ฅผ ์ฐพ์ ์ฝ๋๋ก ํ๋ฉฐ, ์คํ๋ง์ด ์์์ ์๊ตฌ ํ์ ์ ๋ง๋ HttpMessageConverter๋ฅผ ๋ถ๋ฌ ์ญ์ง๋ ฌํ ํ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด ์ Map์ผ๋ก ๋ฐ๊พผ๊ฑธ๊น? ์ง๊ธ ์ด ํ๋ก์ ํธ๋ ๊ฐ๋จํ๊ฒ ์นด์นด์ค ๊ฐํธ ๋ก๊ทธ์ธ์ ์ํํ๋ ค๊ณ ํ๋ค. ๊ทธ๋์ ํ๋ก ํธ์์ ์ค๋ , ์นด์นด์ค์์ ๋ณด๋ด์ค๋ JSON์ ํค=๊ฐ ํํ๋ก ๋ณํํด ๋น ๋ฅด๊ฒ ๋นผ์ค๊ธฐ ์ํด Map์ ๊ณ ๋ฅธ ๊ฒ์ด๋ค. ๋ฌผ๋ก ๊ทธ๋งํผ ๋จ์ ๋ ์๋ค. ๊ฐ๋จํ๊ฒ ๋ง๋ ๊ฒ๋งํผ ์์ ์ฑ์ด ๋จ์ด์ง๋ค. ๊ทธ๋ฐ๊ฒ ์ซ๋ค๋ฉด DTO๋ฅผ ๋ง๋๋ ๊ฑธ ์ถ์ฒํ๋ค.
ResponseEntity๋ Spring MVC์์ HTTP ์์ฒญ์ ๋ํ ์๋ต์ ์ ์ดํ๋ ๋ฐ ์ฌ์ฉํ๋ ํด๋์ค๋ก Response Body, Header, Status Code๋ฅผ ํฌํจํ ์ ์์ด, ์ธ๋ฐํ ์๋ต ๊ด๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํ๋ค.
์๋ ์ฝ๋๋ kakao ๋ฉ์๋ ์์ ๋ค์ด๊ฐ๋ค.
// โ
String code = body.get("code");
// โก
if (!StringUtils.hasText(code)) {
return ResponseEntity.badRequest().body("code ๋๋ฝ");
}
โ
์ญ์ง๋ ฌํํ body์์ ์ธ๊ฐ์ฝ๋(code)๋ฅผ ๊ฐ์ ธ์ code์ ๋ฃ๋๋ค.
โก
StringUtils.hasText๋ฅผ ํตํด code๊ฐ null/""/" "์ ์๋์ง, ์ค์ ๋ฌธ์๊ฐ ํ๋๋ผ๋ ๋ค์ด๊ฐ ์๋์ง ๊ฒ์ฌํ๋ค. ๋ง์ฝ ํต๊ณผ๋์ง ์๋๋ค๋ฉด, badRequest ์๋ต์ฝ๋์ ํจ๊ป "code ๋๋ฝ"์ด๋ผ๋ ๋ฌธ์์ด์ ํ๋ก ํธ๋ก ๋ณด๋ธ๋ค.
// โ
try {
} catch(e) {
}
โ
์ ํฌ์คํ ์์ ์ค๋ช ํ๋ try-catch ๊ตฌ๋ฌธ์ด๋ค. try์๋ ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ ์ํฉ์ ๋์ดํ๊ณ , catch๋ ์์ธ๋ฅผ ์ด๋ป๊ฒ ์ฒ๋ฆฌํ ์ง ์ ๋๋ค. ์ด ๋ค์๋ถํฐ ์ฝ๋๋ try ์์ ๋ค์ด๊ฐ ์ฝ๋์ด๋ค.
// โ
HttpHeaders tokenHeaders = new HttpHeaders();
// โก
tokenHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
โ
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ํ ํฐ ๊ตํ์ ํ ์ฐจ๋ก๊ฐ ์๋ค. ์นด์นด์ค์์ ํ ํฐ์ ๊ตํํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ ์ด๋จ๋ค. Content-Type์ด x-www-form-urlencoded์ด๋ฉฐ, POST๋ก ์์ฒญํ๋๋ก ๋์ด์๋ค. ์๋ฒ๋ ํค๋๋ฅผ ๋ณด๊ณ ๋ณด๋ด์ง ๋ฐ๋๋ฅผ ์ด๋ค ๋ฐฉ์์ผ๋ก ํ์ฑํ ์ง ๊ฒฐ์ ํ๋ค. ๊ทธ๋์ ํค๋์ ๋ฏธ๋ฆฌ ํผ๋ฐฉ์์ด๋ผ๊ณ ์ ์ด์ค์ผํ๋ค. ๊ทธ๋์ ํผ ํ์์์ ์๋ฆฌ๊ธฐ ์ํด tokenHeaders๋ฅผ ์ ์ธํ๋ค.
โก
tokenHeaders์ Content-Type์ ํผ ํ์์ ๋ง์ถฐ MediaType.APPLICATION_FORM_URLENCODED๋ก ์ค์ ํ๋ค.
// โ
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
// โก
form.add("grant_type", "authorization_code");
form.add("client_id", clientId);
form.add("redirect_uri", redirectUri);
form.add("code", code);
โ
๋ฐ๋๋ฅผ ๋ด์ ๊ทธ๋ฆ์ ๋ง๋ค์ด์ผํ๋ค. form์ ์ค์ ๋ฐ๋ ๋ด์ฉ์ด ๋ค์ด๊ฐ๊ฒ ๋๋ค. ๊ทธ๋์ ์ด ๋ฐ๋๋ฅผ ์ด๋ป๊ฒ ๋ด์๊ฑด์ง ์ ์ํ๋ค. MultiValueMap์ ์๋ฐ์์ ์ ๊ณตํ๋ ๊ฒ์ด ์๋ spring์์ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค์ด๋ค. Map ์ธํฐํ์ด์ค๋ฅผ ์์ํ ๋, Value์ ๊ฐ์ List๋ก ๊ฐ์ผ ์ฑ ์์๋ฐ๋๋ค. ๋ ํ๋์ key์ ์ฌ๋ฌ ๊ฐ์ ๋ฃ๊ฑฐ๋, ์ฝ์ ์์๊ฐ ์ ์ง๋๋ ํน์ง์ ๊ฐ์ง๊ณ ์๋ค.
โก
์นด์นด์ค๊ฐ ์๊ตฌํ ๊ฒ์ ๋ง์ถฐ form์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ค. ์๋ง ํํ๋ key=value&key=value.. ์ด๋ฐ ์์ด ๋๋ค. ์ด๋ ๊ฒ ํ ํฐ์ ์์ฒญํ ๊ฐ์ฒด๋ ์ด์ ๋ง๋ค์ด์ก๋ค.
// โ
HttpEntity<MultiValueMap<String, String>> tokenReq = new HttpEntity<>(form, tokenHeaders);
โ
HttpEntity๋ ๋ฐ๋์ ํค๋ ์ปจํ ํธ ํ์ ์ ํจ๊ป ๋ณด๋ด๊ธฐ ๋๋ฌธ์ ํ์ฌ ์ฌ์ฉํ๊ณ ์๋ ํผ ํ์์ ๋ง์ถฐ ์ฌ์ฉํ๊ธฐ ์์ฃผ ์ ์ฉํ๋ค. ๋ฐ๋์๋ ํค=๊ฐ&ํค=๊ฐ์ด ๋ค์ด๊ฐ๊ณ , ํค๋ ์ปจํ ํธ ํ์ ์๋ ํผํ์์ด ๋ค์ด๊ฐ๋ค.
// โ
ResponseEntity<Map> tokenRes = rest.postForEntity("https://kauth.kakao.com/oauth/token", tokenReq, Map.class);
โ
("https://kauth.kakao.com/oauth/token", tokenReq, Map.class)๋ฅผ ๋ณด๋ฉด ("์์ฒญ์ ๋ณด๋ผ ๊ฒฝ๋ก", ๋ณด๋ผ ๊ฐ์ฒด, ์๋ต์ ์ญ์ง๋ ฌํํ ํ์ )์ ์ ์ด์ postForEntity๋ก POST ์์ฒญ์ ๋ณด๋๋ค. postForEntity๋ RestTemplate๊ฐ ์ ๊ณตํ๋ ํธ์๋ฉ์๋์ธ๋ฐ, ์ฃผ๋ก ์ํ/ํค๋/๋ฐ๋๋ฅผ ํ๊บผ๋ฒ์ ๋ฐ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ค.
์นด์นด์ค์ ์๋ต ํํ๋ JSON์ด๋ค. ๊ทธ๋ฐ๋ฐ ์ด๊ฑธ Map์ผ๋ก ์ญ์ง๋ ฌํํ ๊ฒ์ด๋ค. ๊ทธ๋์ tokenRes ์์ ์๋ต ํ์ ์ Map์ผ๋ก ์ ์ธํ๋ค.
// โ
if (!tokenRes.getStatusCode().is2xxSuccessful() || tokenRes.getBody() == null) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("ํ ํฐ ๊ตํ ์คํจ");
}
// โก
String accessToken = (String) tokenRes.getBody().get("access_token");
if (!StringUtils.hasText(accessToken)) {
return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body("access_token ์์");
}
โ
tokenRes์ ๋ฐ์์จ ์ํ ์ฝ๋๊ฐ ์ฑ๊ณต์ ์ด์ง ์๊ฑฐ๋, ๋ฐ์์จ ๋ฐ๋๊ฐ null์ธ ๊ฒฝ์ฐ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ค.
โก
tokenRes์ ๋ฐ๋์์ access_token์ ๋ค์ด์๋ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์๋ค. ๊ทธ๋ฆฌ๊ณ ์ด accessToken์ ๋ฌธ์์ด ์ ํจ์ฑ ๊ฒ์ฆ์ด False์ด๋ฉด ์ค๋ฅ๋ฅผ ๋ฐํํ๋ค.
๋ค์์ ๋ฐฑ์๋๋ก ์ฌ์ฉ์ ์ ๋ณด ์กฐํ ๋ถ๋ถ์ ์ ์ด๋ณด๊ฒ ์ต๋๋ค.
๋ง์ฝ ๋ค ํ๊ณ ๋์๋ ์ ๋๋ ๋ถ๋ถ์ด ์๋ค๋ฉด ๋๊ธ์ ๋จ๊ฒจ์ฃผ์ธ์.
์ ๊ฐ ๋นผ๋จน์ ๋ถ๋ถ์ด ์์์ง๋ ๋ชฐ๋ผ์,,, ํท ๐ฅ
! ํ์ดํ !