Backend
home
🕛

2024. 9. 19 (REST TEMPLATE, OAuth)

생성일
2025/01/24 05:52
태그

REST TEMPLATE

Spring Framework 에서 HTTP 요청을 보내는 클래스
GET, POST, PUT, PATCH, DELETE 모두 호출 가능
JSON, XML 등의 데이터로 받아올 수 있음
해당 페이지 접속
// 20240919091348 // https://jsonplaceholder.typicode.com/posts/2 // https://jsonplaceholder.typicode.com/posts?userId=2 { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla" }
JSON
복사
https://jsonplaceholder.typicode.com/posts?userId=2
// 20240919091522 // https://jsonplaceholder.typicode.com/posts?userId=2 [ { "userId": 2, "id": 11, "title": "et ea vero quia laudantium autem", "body": "delectus reiciendis molestiae occaecati non minima eveniet qui voluptatibus\naccusamus in eum beatae sit\nvel qui neque voluptates ut commodi qui incidunt\nut animi commodi" }, { "userId": 2, "id": 12, "title": "in quibusdam tempore odit est dolorem", "body": "itaque id aut magnam\npraesentium quia et ea odit et ea voluptas et\nsapiente quia nihil amet occaecati quia id voluptatem\nincidunt ea est distinctio odio" }, { "userId": 2, "id": 13, "title": "dolorum ut in voluptas mollitia et saepe quo animi", "body": "aut dicta possimus sint mollitia voluptas commodi quo doloremque\niste corrupti reiciendis voluptatem eius rerum\nsit cumque quod eligendi laborum minima\nperferendis recusandae assumenda consectetur porro architecto ipsum ipsam" }, { "userId": 2, "id": 14, "title": "voluptatem eligendi optio", "body": "fuga et accusamus dolorum perferendis illo voluptas\nnon doloremque neque facere\nad qui dolorum molestiae beatae\nsed aut voluptas totam sit illum" }, { "userId": 2, "id": 15, "title": "eveniet quod temporibus", "body": "reprehenderit quos placeat\nvelit minima officia dolores impedit repudiandae molestiae nam\nvoluptas recusandae quis delectus\nofficiis harum fugiat vitae" }, { "userId": 2, "id": 16, "title": "sint suscipit perspiciatis velit dolorum rerum ipsa laboriosam odio", "body": "suscipit nam nisi quo aperiam aut\nasperiores eos fugit maiores voluptatibus quia\nvoluptatem quis ullam qui in alias quia est\nconsequatur magni mollitia accusamus ea nisi voluptate dicta" }, { "userId": 2, "id": 17, "title": "fugit voluptas sed molestias voluptatem provident", "body": "eos voluptas et aut odit natus earum\naspernatur fuga molestiae ullam\ndeserunt ratione qui eos\nqui nihil ratione nemo velit ut aut id quo" }, { "userId": 2, "id": 18, "title": "voluptate et itaque vero tempora molestiae", "body": "eveniet quo quis\nlaborum totam consequatur non dolor\nut et est repudiandae\nest voluptatem vel debitis et magnam" }, { "userId": 2, "id": 19, "title": "adipisci placeat illum aut reiciendis qui", "body": "illum quis cupiditate provident sit magnam\nea sed aut omnis\nveniam maiores ullam consequatur atque\nadipisci quo iste expedita sit quos voluptas" }, { "userId": 2, "id": 20, "title": "doloribus ad provident suscipit at", "body": "qui consequuntur ducimus possimus quisquam amet similique\nsuscipit porro ipsam amet\neos veritatis officiis exercitationem vel fugit aut necessitatibus totam\nomnis rerum consequatur expedita quidem cumque explicabo" } ]
JSON
복사
Spring 5.0 → WebClient 를 사용할 것을 권장
but rest_template으로 진행
방식
GET 방식
getForEntity: Get 요청 후, 응답을 ResponseEntity로 반환
getForObject: Get 요청 후, 응답을 원하는 객체로 반환
POST 방식
postForEntity: Post 요청 후, 응다븡ㄹ ResponseEntity로 반환
postForObject: Post 요청 후, 응답을 원하는 객체로 반환
Put, Patch, Delete…
rest template 실습
@GetMapping("/news/{id}") public ResponseEntity<String> getNewsById(@PathVariable("id") int id) { // RestTemplate 인스턴스를 하나 생성 RestTemplate rt = new RestTemplate(); // 헤더 인스턴스 생성 HttpHeaders headers = new HttpHeaders(); // header 적용 headers.add("Content-Type", "application/json; charset=UTF-8"); HttpEntity<String> httpEntity = new HttpEntity<>(headers); // URL 주소 만들기 String url = "https://jsonplaceholder.typicod.com/posts/" + id; try { // ResponseEntity<String> result = rt.getForEntity(url, String.class); ResponseEntity<String> result = rt.exchange(url, HttpMethod.GET, httpEntity, String.class); return result; } catch (Exception e) { return ResponseEntity .status(HttpStatus.INTERNAL_SERVER_ERROR) .headers(headers).body("에러!"); } }
Java
복사

oAuth (Google Login 기준)

구글 로그인 React에 구성
// 구글 로그인 핸들러 const handleGoogleLogin = () => { // 구글 로그인 버튼 클릭 시 이동하는 경로 지정 const params = new URLSearchParams({ scope: "email profile", response_type: "code", // code 응답 redirect_uri: "http://localhost:3000/oauth/google", client_id: "530115480345-84amh51vqf0h8iq9h06o9qu3g8e0s9np.apps.googleusercontent.com", }); const GOOGLE_URL = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`; // 경로로 이동 window.location.href = GOOGLE_URL; }
JavaScript
복사
// App.js 쪽 const GoogleLogin = () => { const code = new URLSearchParams(window.location.search).get("code"); console.log("서버에 전달해야 하는 코드 값 : ", code) const login = async () => { try { const response = await oauthAPI.googleLogin(code); if (response.status !== 200) { throw new Error("로그인 실패"); } else { setCookie("accessToken", response.data.accessToken, { path: "/"} ); window.location.href = "/"; } } catch (error) { console.error(error); } } return ( <div>로그인 처리 중 ~</div> ); }
JavaScript
복사
SpringBoot
구글 로그인 기능 구현
controller
package com.kosta.controller; import com.kosta.domain.response.LoginResponse; import com.kosta.service.OAuthService; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @Slf4j @RequestMapping("/api/oauth") @RequiredArgsConstructor public class OAuthController { private final OAuthService oAuthService; // 구글 로그인 기능 - code 전달 @GetMapping("/google") public ResponseEntity<?> googleSignIn(@RequestParam("code") final String code, HttpServletResponse res) { log.info("들어온 코드 값 : {}", code); String accessToken = oAuthService.googleSignIn(code, res); // code를 통해 사용자 정보를 받아서 // 사용자 정보를 조회하고, 만약 기존에 있는 사용자라면 (oauth 값을 true 로 변경) // 만약 기존에 없는 사용자라면 (새로 가입 -> DB 추가) // 사용자에 대한 정보롤 accessToken과 refreshToken을 만들어서 반환 if (accessToken == null || accessToken.equals("")) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null); } LoginResponse loginResponse = LoginResponse.builder() .accessToken(accessToken) .build(); return ResponseEntity.ok(loginResponse); } }
Java
복사
service
package com.kosta.service.Impl; import com.fasterxml.jackson.databind.JsonNode; import com.kosta.entity.User; import com.kosta.repository.UserRepository; import com.kosta.service.OAuthService; import com.kosta.util.TokenUtils; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.server.ResponseStatusException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Map; @Service @RequiredArgsConstructor public class OAuthServiceImpl implements OAuthService { private final UserRepository userRepository; private final TokenUtils tokenUtils; @Override public String googleSignIn(String code, HttpServletResponse res) { // 1. code를 통해 google에서 제공하는 accessToken 가져온다. String providedAccessToken = getAccessToken(code); // 2. google에서 제공하는 accessToken으로 사용자 정보를 추출한다. User user = generateOAuthUser(providedAccessToken); // 3. 사용자 정보를 조회하고 // 만약 기존에 있는 사용자라면 (oAuth 인증 여부에 따라 OAUTH True 로 변경) // 만약 기존에 없는 사용자라면 (새로 가입 -> DB 추가) user = userRepository.findByEmail(user.getEmail()).orElse(user); if (user.isOAuth()) { user.setOAuth(true); userRepository.save(user); } // 4. 자동 로그인 (사용자에 대한 정보롤 accessToken과 refreshToken을 만들어서 반환) Map<String, String> tokenMap = tokenUtils.generateToken(user); // DB에 기록 user.setRefreshToken(tokenMap.get("refreshToken")); userRepository.save(user); // HEADER에 추가 tokenUtils.setRefreshTokenCookie(res, tokenMap.get("refreshToken")); // BODY에 추가 return tokenMap.get("accessToken"); } // Code를 전달, 사용자 정보 요청 // {"sub":"102830464863109364648", // "name":"Minsung HA", // "given_name":"Minsung", // "family_name":"HA", // "picture":"https://lh3.googleusercontent.com/a/ACg8ocKsuif1zx11QSgpVnO1jmvcfr5STPrCPoEQ3GxXTkiFcAKzWg=s96-c", // "email":"codesche@gmail.com","email_verified":true} private User generateOAuthUser(String accessToken) { String userInfoURI = "https://www.googleapis.com/oauth2/v3/userinfo"; HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + accessToken); RestTemplate rt = new RestTemplate(); // 구글에 저장된 사용자 정보 ResponseEntity<JsonNode> responseEntity = rt.exchange(userInfoURI, HttpMethod.GET, new HttpEntity<>(headers), JsonNode.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } JsonNode jsonNode = responseEntity.getBody(); String email = null; String name = null; User user = null; try { if (jsonNode.has("email") && jsonNode.has("name")) { email = jsonNode.get("email").asText(); name = jsonNode.get("name").asText(); user = User.builder() .email(email) .name(name) .build(); } } catch (RuntimeException e) { throw new RuntimeException("해당 사용자를 찾을 수 없습니다."); } return user; } private String getAccessToken(String code) { // 1. code를 통해 google에서 제공하는 accessToken 가져온다. String decodedCode = URLDecoder.decode(code, StandardCharsets.UTF_8); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); String clientId = "530115480345-84amh51vqf0h8iq9h06o9qu3g8e0s9np.apps.googleusercontent.com"; String clientSecret = "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"; String redirectURI = "http://localhost:3000/oauth/google"; headers.setBasicAuth(clientId, clientSecret); MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("client_id", clientId); params.add("client_secret", clientSecret); params.add("code", decodedCode); params.add("grant_type", "authorization_code"); params.add("redirect_uri", redirectURI); // accessToken 받아오기 String tokenURI = "https://oauth2.googleapis.com/token"; RestTemplate rt = new RestTemplate(); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers); ResponseEntity<Map> responseEntity = rt.postForEntity(tokenURI, requestEntity, Map.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } return (String) responseEntity.getBody().get("access_token"); } }
Java
복사
security
http.authorizeHttpRequests(auth -> // 특정 URL 경로에 대해서는 인증 없이 접근 가능 auth.requestMatchers( new AntPathRequestMatcher("/api/oauth/**"), // 추가 // oAuth 처리 (20240919) new AntPathRequestMatcher("/api/auth/signup"), // 회원가입 new AntPathRequestMatcher("/api/auth/duplicate"), // 이메일 중복체크 new AntPathRequestMatcher("/img/**"), // 이미지 new AntPathRequestMatcher("/api/auth/refresh-token"), // 토큰 재발급 new AntPathRequestMatcher("/api/post/**", "GET") ).permitAll() // AuthController 중 나머지들은 "ADMIN"만 가능 .requestMatchers( new AntPathRequestMatcher("/api/auth/") // "ADMIN"만 가능 ).hasRole("ADMIN") // 그 밖의 다른 요청들은 인증을 통과한(로그인한) 사용자라면 모두 접근할 수 있도록 한다. .anyRequest().authenticated() );
Java
복사

oAuth (객체지향에 맞게 코드 리팩토링)

application.yml
oauth2: clients: google: client-id: 530115480345-84amh51vqf0h8iq9h06o9qu3g8e0s9np.apps.googleusercontent.com client-secret: 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 redirect-uri: http://localhost:3000/oauth/google token-uri: https://oauth2.googleapis.com/token user-info-request-uri: https://www.googleapis.com/oauth2/v3/userinfo kakao: client-id: client-secret: redirect-uri: token-uri: user-info-request-uri:
YAML
복사
util
package com.kosta.util; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.Map; @Data @Component @ConfigurationProperties(prefix = "oauth2") public class OAuth2Properties { private Map<String, Client> clients; @Data public static class Client { private String clientId; private String clientSecret; private String redirectUri; private String tokenUri; private String userInfoRequestUri; } }
Java
복사
service
private User generateOAuthUser(String accessToken, String provider) { // 설정 가져오기 OAuth2Properties.Client client = oAuth2Properties.getClients().get(provider); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + accessToken); RestTemplate rt = new RestTemplate(); // 구글에 저장된 사용자 정보 ResponseEntity<JsonNode> responseEntity = rt.exchange(client.getUserInfoRequestUri(), HttpMethod.GET, new HttpEntity<>(headers), JsonNode.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } JsonNode jsonNode = responseEntity.getBody(); System.out.println(jsonNode); String email = null; String name = null; User user = null; try { if (jsonNode.has("email") && jsonNode.has("name")) { email = jsonNode.get("email").asText(); name = jsonNode.get("name").asText(); user = User.builder() .email(email) .name(name) .build(); } } catch (RuntimeException e) { throw new RuntimeException("해당 사용자를 찾을 수 없습니다."); } return user; } private String getAccessToken(String code, String provider) { // 설정 가져오기 OAuth2Properties.Client client = oAuth2Properties.getClients().get(provider); // 1. code를 통해 google에서 제공하는 accessToken 가져온다. String decodedCode = URLDecoder.decode(code, StandardCharsets.UTF_8); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.setBasicAuth(client.getClientId(), client.getClientSecret()); MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("client_id", client.getClientId()); params.add("client_secret", client.getClientSecret()); params.add("code", decodedCode); params.add("grant_type", "authorization_code"); params.add("redirect_uri", client.getRedirectUri()); // accessToken 받아오기 RestTemplate rt = new RestTemplate(); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers); ResponseEntity<Map> responseEntity = rt.postForEntity(client.getTokenUri(), requestEntity, Map.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } return (String) responseEntity.getBody().get("access_token"); }
Java
복사

카카오 소셜 로그인 구현 (객체지향에 맞게 수정, react도 유사하게 수정)

카카오 소셜 로그인 참고 링크 https://ddonghyeo.tistory.com/16
spring
package com.kosta.service.Impl; import com.fasterxml.jackson.databind.JsonNode; import com.kosta.entity.User; import com.kosta.repository.UserRepository; import com.kosta.service.OAuthService; import com.kosta.util.OAuth2Properties; import com.kosta.util.TokenUtils; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import org.springframework.web.server.ResponseStatusException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Map; @Service @RequiredArgsConstructor public class OAuthServiceImpl implements OAuthService { private final OAuth2Properties oAuth2Properties; private final UserRepository userRepository; private final TokenUtils tokenUtils; @Override public String oAuthSignIn(String code, String provider, HttpServletResponse res) { // 1. code를 통해 provider에서 제공하는 accessToken 가져온다. String providedAccessToken = getAccessToken(code, provider); // 2. provider에서 제공하는 accessToken으로 사용자 정보를 추출한다. User user = generateOAuthUser(providedAccessToken, provider); // 3. 사용자 정보를 조회하고 // 만약 기존에 있는 사용자라면 (oAuth 인증 여부에 따라 OAUTH True 로 변경) // 만약 기존에 없는 사용자라면 (새로 가입 -> DB 추가) user = userRepository.findByEmail(user.getEmail()).orElse(user); if (user.isOAuth()) { user.setOAuth(true); userRepository.save(user); } // 4. 자동 로그인 (사용자에 대한 정보롤 accessToken과 refreshToken을 만들어서 반환) Map<String, String> tokenMap = tokenUtils.generateToken(user); // DB에 기록하기 user.setRefreshToken(tokenMap.get("refreshToken")); userRepository.save(user); // HEADER에 추가 tokenUtils.setRefreshTokenCookie(res, tokenMap.get("refreshToken")); // BODY에 추가 return tokenMap.get("accessToken"); } // Code를 전달, 사용자 정보 요청 // {"sub":"102830464863109364648", // "name":"Minsung HA", // "given_name":"Minsung", // "family_name":"HA", // "picture":"https://lh3.googleusercontent.com/a/ACg8ocKsuif1zx11QSgpVnO1jmvcfr5STPrCPoEQ3GxXTkiFcAKzWg=s96-c", // "email":"codesche@gmail.com","email_verified":true} private User generateOAuthUser(String accessToken, String provider) { // 설정 가져오기 OAuth2Properties.Client client = oAuth2Properties.getClients().get(provider); HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + accessToken); RestTemplate rt = new RestTemplate(); // 구글에 저장된 사용자 정보 ResponseEntity<JsonNode> responseEntity = rt.exchange(client.getUserInfoRequestUri(), HttpMethod.GET, new HttpEntity<>(headers), JsonNode.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } JsonNode jsonNode = responseEntity.getBody(); System.out.println(jsonNode); String email = null; String name = null; User user = null; try { if (jsonNode.has("email") && jsonNode.has("name")) { email = jsonNode.get("email").asText(); name = jsonNode.get("name").asText(); } else if (jsonNode.has("id") && jsonNode.has("properties")) { email = jsonNode.get("id").asText() + "@kakao.com"; name = jsonNode.get("properties").get("nickname").asText(); } user = User.builder() .email(email) .name(name) .build(); } catch (RuntimeException e) { throw new RuntimeException("해당 사용자를 찾을 수 없습니다."); } return user; } private String getAccessToken(String code, String provider) { // 설정 가져오기 OAuth2Properties.Client client = oAuth2Properties.getClients().get(provider); // 1. code를 통해 google에서 제공하는 accessToken 가져온다. String decodedCode = URLDecoder.decode(code, StandardCharsets.UTF_8); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.setBasicAuth(client.getClientId(), client.getClientSecret()); MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("client_id", client.getClientId()); params.add("client_secret", client.getClientSecret()); params.add("code", decodedCode); params.add("grant_type", "authorization_code"); params.add("redirect_uri", client.getRedirectUri()); // accessToken 받아오기 RestTemplate rt = new RestTemplate(); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers); ResponseEntity<Map> responseEntity = rt.postForEntity(client.getTokenUri(), requestEntity, Map.class); // response 상태에 따라 구분 if (!responseEntity.getStatusCode().is2xxSuccessful() || responseEntity.getBody() == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, "사용자 정보를 가져올 수 없음"); } return (String) responseEntity.getBody().get("access_token"); } }
Java
복사
react
// Login.jsx를 수정 // 구글 로그인 핸들러 const handleGoogleLogin = () => { // 구글 로그인 버튼 클릭 시 이동하는 경로 지정 const params = new URLSearchParams({ scope: "email profile", response_type: "code", // code 응답 redirect_uri: process.env.REACT_APP_GOOGLE_REDIRECT_URI, client_id: process.env.REACT_APP_GOOGLE_ID, }); const GOOGLE_URL = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`; // 지정한 경로로 이동 window.location.href = GOOGLE_URL; } // 카카오 로그인 핸들러 const handleKakaoLogin = () => { // 구글 로그인 버튼 클릭 시 이동하는 경로 지정 const params = new URLSearchParams({ response_type: "code", // code 응답 redirect_uri: process.env.REACT_APP_KAKAO_REDIRECT_URI, client_id: process.env.REACT_APP_KAKAO_ID, }); const KAKAO_URL = `https://kauth.kakao.com/oauth/authorize?${params.toString()}`; // 지정한 경로로 이동 window.location.href = KAKAO_URL; }
JavaScript
복사
// OAuthLogin.jsx import { useEffect } from "react"; import { useParams } from "react-router-dom"; import { oauthAPI } from "../../api/services/oauth"; import { setCookie } from "../../utils/cookieUtil"; // google or kakao 소셜로그인 기능 구분하여 적용될 수 있도록 수정 const OAuthLogin = () => { const { provider } = useParams(); const code = new URLSearchParams(window.location.search).get("code"); console.log("서버에 전달해야 하는 코드 값 : ", code); const oAuthAPI = { "kakao": (code) => oauthAPI.kakaoLogin(code), "google": (code) => oauthAPI.googleLogin(code) } const login = async () => { try { console.log(provider); const response = await oAuthAPI[provider](code); if (response.status !== 200) { throw new Error("로그인 실패"); } else { setCookie("accessToken", response.data.accessToken, { path: "/" }); window.location.href = "/"; } } catch (error) { console.error(error); } } useEffect(() => { login(); }, [code]); return ( <div>로그인 처리 중 ~</div> ); } export default OAuthLogin;
JavaScript
복사
// App.js // 라우팅 수정 ... 중략 ... <Route path='/oauth/:provider' element={<OAuthLogin />} />
JavaScript
복사