๊ฐ์
๊ธฐ์กด ํ์ ํํด ๋ฐฉ์์ ๋จ์ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ์ ์ ๋ณด๋ฅผ ์ญ์ ํ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ๋ง์ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค. ํ์ง๋ง ๋ณด๋ค ํ์คํ ํํด ์งํ์ ์ํด, ์์ ๋ก๊ทธ์ธ ์ ๊ณต์(Google, Kakao)์์ ๊ณ์ ์ฐ๊ฒฐ ํด์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ์ต๋๋ค.
๊ณ์ ์ฐ๊ฒฐ ํด์ ์์ฒญ
Google Developers - revoke ์์ ์ฐ๊ฒฐ ํด์ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.

โKakao
Kakao Developers - unlink ์์ ์ฐ๊ฒฐ ํด์ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.


Access ํ ํฐ ๋๋ ์ฑ ์ด๋๋ฏผ ํค(Admin key)๋ก ์ฐ๊ฒฐ ํด์ API๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค. ์ฐ๊ฒฐ ๋๊ธฐ ์์ฒญ์ ์ฑ๊ณตํ๋ฉด ํด๋น ์ฌ์ฉ์ ํ์ ๋ฒํธ๋ฅผ ์๋ต์ผ๋ก ๋ฐ๊ณ , ๋ก๊ทธ์์์ด ํจ๊ป ์งํ๋์ด Access ํ ํฐ๊ณผ Refresh ํ ํฐ์ด ๋ง๋ฃ ์ฒ๋ฆฌ๋ฉ๋๋ค.
1๏ธโฃ์ด๋๋ฏผ ํค ์ฌ์ฉ

Admin key๋ฅผ ์ฌ์ฉํ๋ REST API ์์ฒญ์ ๋ฐ๋์ ์๋ฒ์์๋ง ์ํํด์ผ ํ๋ฉฐ, ์์ค ์ฝ๋์ ๋ ธ์ถ๋์ง ์๋๋ก ์ฃผ์ํด์ผ ํฉ๋๋ค. ๋ํ, Admin key๋ฅผ ์ฌ์ฉํด ์ฐ๊ฒฐ ํด์ ์์ฒญ ์, ๋์ ์ฌ์ฉ์๋ฅผ ๋ช ์ํ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ํจ๊ป ๋ณด๋ด์ผ ํฉ๋๋ค.
2๏ธโฃํ ํฐ ์ฌ์ฉ

Google์์๋ Admin key ์ฌ์ฉ ๋ฐฉ์์ด ์์ผ๋ฏ๋ก, ์ผ๊ด์ฑ์ ์ํด, ํ ํฐ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ๊ณ์ ์ฐ๊ฒฐ ํด์ API ํธ์ถ ๋ฐฉ์์ ํต์ผํ์ต๋๋ค.
ํ ํฐ ๊ฐฑ์ ์์ฒญ
Google Developers - token ์์ Access ํ ํฐ ๊ฐฑ์ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.



โKakao
Kakao Developers - token ์์ ํ ํฐ ๊ฐฑ์ ๋ฐฉ๋ฒ์ ํ์ธํ ์ ์์ต๋๋ค.



Kakao์์๋ Google๊ณผ ๋ฌ๋ฆฌ Refresh ํ ํฐ์ด ์กฐ๊ฑด(์ ํจ ๊ธฐ๊ฐ์ด 1๊ฐ์ ๋ฏธ๋ง) ์ถฉ์กฑ ์, Access ํ ํฐ๊ณผ ํจ๊ป ์ฌ๋ฐ๊ธ์ด ๋ ์ ์์ต๋๋ค. ํ์ง๋ง ์ ํฌ ํ๋ก์ ํธ์์๋ ํด๋น Refresh ํ ํฐ ๊ธฐ๊ฐ์ 2์ฃผ๋ก ์ค์ ํ๊ธฐ์, ์ด๋ฌํ ์กฐ๊ฑด์ ๊ณ ๋ คํ์ง ์์๋ ๋ฉ๋๋ค. (2์ฃผ๋ก ์ค์ ํ ์ด์ ๋ ์๋์์ ๋ค์ ์ธ๊ธํ๊ฒ ์ต๋๋ค.)
Spring Cloud OpenFeign
์์ ์ธ๊ธํ ์์ ๋ก๊ทธ์ธ ์ ๊ณต์(Kakao, Google)์ API๋ฅผ ํธ์ถํ์ฌ ๊ณ์ ์ฐ๊ฒฐ ํด์ ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด Spring Cloud OpenFeign์ ์ฌ์ฉํ์ต๋๋ค. OpenFeign์ ์ ์ธํ HTTP ํด๋ผ์ด์ธํธ๋ก, REST API ํธ์ถ ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ณ ์ ์ง๋ณด์ ๊ฐ๋ฅํ๊ฒ ์์ฑํ ์ ์๋๋ก ํด์ค๋๋ค.
๊ธฐ๋ณธ ์ค์
- ์์กด์ฑ ์ถ๊ฐ
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:2023.0.1"
}
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
}
- ๊ธฐ๋ฅ ํ์ฑํ
@EnableFeignClients
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
API ํธ์ถ ์ฝ๋
๐ Google
@FeignClient(name = "googleClient", url = "https://oauth2.googleapis.com")
public interface GoogleClient {
// Refresh ํ ํฐ์ ์ฌ์ฉํ ํ ํฐ ์ฌ๋ฐ๊ธ ์์ฒญ
@PostMapping("/token")
TokenResponse reissueToken(
@RequestParam("grant_type") String grantType, // "refresh_token"์ผ๋ก ๊ณ ์
@RequestParam("client_id") String clientId,
@RequestParam("refresh_token") String refreshToken,
@RequestParam("client_secret") String clientSecret
);
// ์ฐ๊ฒฐ ํด์ ์์ฒญ
// Refresh, Access ํ ํฐ ๋ ๋ค ์ฌ์ฉ ๊ฐ๋ฅ
@PostMapping("/revoke")
void unlink(@RequestParam("token") String accessToken);
}
๐ Kakao
@FeignClient(name = "kakaoApiClient", url = "https://kapi.kakao.com")
public interface KakaoApiClient {
// Access ํ ํฐ์ ์ฌ์ฉํ ์ฐ๊ฒฐ ํด์ ์์ฒญ
@PostMapping("/v1/user/unlink")
UnlinkResponse unlink(@RequestHeader("Authorization") String accessToken);
}
@FeignClient(name = "kakaoAuthClient", url = "https://kauth.kakao.com")
public interface KakaoAuthClient {
// Refresh ํ ํฐ์ ์ฌ์ฉํ ํ ํฐ ์ฌ๋ฐ๊ธ ์์ฒญ
@PostMapping("/oauth/token")
TokenResponse reissueToken(
@RequestParam("grant_type") String grantType, // "refresh_token"์ผ๋ก ๊ณ ์
@RequestParam("client_id") String clientId,
@RequestParam("refresh_token") String refreshToken,
@RequestParam("client_secret") String clientSecret
);
}
Service๋ก ํตํฉ
Google๊ณผ Kakao์ API ํธ์ถ ๋ก์ง์ ํ๋์ Service๋ก ํตํฉํ์ฌ, ๊ฐ ์์ ๋ก๊ทธ์ธ ์ ๊ณต์์ ๋ํ ์ฐ๊ฒฐ ํด์ , ํ ํฐ ๊ฐฑ์ ์ ์ฒ๋ฆฌํฉ๋๋ค.
@Slf4j
@RequiredArgsConstructor
@Service
public class SocialClientService {
...
// Google ํ ํฐ ๊ฐฑ์ ์์ฒญ
public TokenResponse reissueGoogleToken(String refreshToken) {
return googleClient.reissueToken(
GRANT_TYPE_REFRESH_TOKEN,
googleClientId,
refreshToken,
googleClientSecret
);
}
// Google ์ฐ๊ฒฐ ํด์ ์์ฒญ
public void unlinkGoogle(String accessToken) {
googleClient.unlink(accessToken);
log.info("Google Unlink");
}
// Kakao ํ ํฐ ๊ฐฑ์ ์์ฒญ
public TokenResponse reissueKakaoToken(String refreshToken) {
return kakaoAuthClient.reissueToken(
GRANT_TYPE_REFRESH_TOKEN,
kakaoClientId,
refreshToken,
kakaoClientSecret
);
}
// Kakao ์ฐ๊ฒฐ ํด์ ์์ฒญ
public void unlinkKakao(String accessToken) {
UnlinkResponse response = kakaoApiClient.unlink(accessToken);
log.info("Kakao Unlink ํ์๋ฒํธ : {}", response.getId());
}
}
OAuth2 ์ธ์ฆ ์ฒ๋ฆฌ ๋ฐฉ์ ์ปค์คํฐ๋ง์ด์ง
OAuth2AuthorizedClientService ์ปค์คํฐ๋ง์ด์ง
OAuth2AuthorizedClientService์ ๊ธฐ๋ณธ ๊ตฌํ์ฒด๋ InMemoryOAuth2AuthorizedClientService๋ก, ์ธ์ฆ ์๋ฒ์์ ๋ฐ๊ธ๋ฐ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์๋ฒ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋๋ฐ, ์ด๋ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ์ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- ํ์ ๋ ๋ฉ๋ชจ๋ฆฌ ๋ฆฌ์์ค
- ์๋ฒ์ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ํ์ ์ ์ ๋๋ค. ์ฌ์ฉ์ ์๊ฐ ์ฆ๊ฐํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ ๋ถํ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ์๋ฒ ํ์ฅ์ฑ ๋ฌธ์
- ์๋ฒ๋ฅผ ํ์ฅํ ๊ฒฝ์ฐ, ๊ฐ ์๋ฒ๋ ๋ ๋ฆฝ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๊ฐ๊ฒ ๋ฉ๋๋ค. ์ด๋ก ์ธํด ์๋ฒ ๊ฐ ์ธ์ฆ ์ ๋ณด์ ๋ถ์ผ์น๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
ํ์ฌ ๋จ๊ณ์์ ์ด๋ฌํ ๋ฌธ์ ๋ค์ด ์ง์ ์ ์ธ ๊ณ ๋ ค ๋์์ ์๋์ง๋ง, ํฅํ ์์คํ ์ ํ์ฅ์ฑ๊ณผ TTL(Time To Live) ์ค์ ์ ํ์ฉํ ํจ์จ์ ์ธ ํ ํฐ ๊ด๋ฆฌ๋ฅผ ์ํด Redis๋ฅผ ํตํ ํ ํฐ ์ ์ฅ ๋ฐฉ์์ ์ ํํ์ต๋๋ค.
@Override
public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal) {
String loginId = principal.getName();
OAuth2RefreshToken refreshToken = authorizedClient.getRefreshToken();
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
// Refresh ํ ํฐ ์ ์ฅ
String key = RedisTokenService.OAUTH2_REFRESH_TOKEN_KEY_PREFIX + loginId;
redisTokenService.saveToken(
key,
refreshToken.getTokenValue(),
Date.from(
LocalDateTime.now()
.plusWeeks(2)
.atZone(ZoneId.systemDefault())
.toInstant()
)
);
// Access ํ ํฐ ์ ์ฅ
key = RedisTokenService.OAUTH2_ACCESS_TOKEN_KEY_PREFIX + loginId;
redisTokenService.saveToken(
key,
accessToken.getTokenValue(),
Date.from(accessToken.getExpiresAt())
);
}
๐ก Refresh ํ ํฐ ์ ํจ ๊ธฐ๊ฐ์ 2์ฃผ๋ก ์ค์ ํ ์ด์
์์ ๋ก๊ทธ์ธ ์ ๊ณต์(Google, Kakao)๊ฐ ์ ๊ณตํ๋ Refresh ํ ํฐ์ ์ ํจ ๊ธฐ๊ฐ์ ์ต์ 2๊ฐ์ ์ด์์ด์ง๋ง, ์ฌ๋ก๊ทธ์ธ ์ ์ ๊ณต์๊ฐ ์๋ก์ด Refresh ํ ํฐ์ ๋ค์ ๋ฐ๊ธํด ์ค๋๋ค. ์ด๋ฅผ ๊ณ ๋ คํด, ์ ํฌ ์๋ฒ์์ ๋ฐ๊ธํ๋ Refresh ํ ํฐ(JWT)๊ณผ ๋์ผํ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ค์ ํ๋ ๊ฒ์ด ์ ์ ํ๋ค๊ณ ํ๋จํ์ต๋๋ค. ๋ฐ๋ผ์ ์์ ๋ก๊ทธ์ธ ์ ๊ณต์์ Refresh ํ ํฐ ์ ํจ ๊ธฐ๊ฐ๋ ๋์ผํ๊ฒ 2์ฃผ๋ก ์ค์ ํ์์ต๋๋ค.
OAuth2AuthorizationRequestResolver ์ปค์คํฐ๋ง์ด์ง
Google์์๋ ๋ก๊ทธ์ธ์ ํตํด Refresh ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ผ๋ ค๋ฉด ์ถ๊ฐ์ ์ธ ํ๋ผ๋ฏธํฐ ์ค์ ์ด ํ์ํฉ๋๋ค. ๋ฌผ๋ก Refresh ํ ํฐ ์์ด๋ ์ฐ๊ฒฐ ํด์ ์์ฒญ์ ๊ฐ๋ฅํ์ง๋ง, Access ํ ํฐ์ ์ ํจ๊ธฐ๊ฐ์ด ์งง๊ธฐ ๋๋ฌธ์, ์ฐ๊ฒฐ ํด์ ์์ฒญ ์, ํ ํฐ์ด ๋ง๋ฃ๋์ด ์ฌ์ฉ์๊ฐ ๋ค์ ๋ก๊ทธ์ธํด์ผ ํ๋ ๋ถํธํจ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, OAuth2AuthorizationRequestResolver๋ฅผ ์ปค์ค๋ง์ด์งํ์ฌ ์์ ๋ก๊ทธ์ธ ์ ๊ณต์๊ฐ Google์ธ ๊ฒฝ์ฐ ํ์ํ ํ๋ผ๋ฏธํฐ๋ฅผ ๋์ ์ผ๋ก ์ถ๊ฐํ ์ ์๋๋ก ๊ตฌํํ์ต๋๋ค. ์ด๋ฅผ ํตํด Refresh ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ ์ธ์ฆ ์ํ๋ฅผ ์ง์์ ์ผ๋ก ์ ์งํ ์ ์๋๋ก ํ์ต๋๋ค.
ํ์ํ ํ๋ผ๋ฏธํฐ ์ค์


- access_type=offline
- prompt=consent
- ํญ์ ๋์ ํ๋ฉด์ ํ์ํ๊ณ , ๋ช ์์ ์ธ ๋์๋ฅผ ๊ตฌํด์ผ Refresh ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ ์ ์์ต๋๋ค.
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
return customizeAuthorizationRequest(defaultResolver.resolve(request));
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request, String clientRegistrationId) {
return customizeAuthorizationRequest(defaultResolver.resolve(request, clientRegistrationId));
}
private OAuth2AuthorizationRequest customizeAuthorizationRequest(OAuth2AuthorizationRequest authorizationRequest) {
if (authorizationRequest == null) {
return null;
}
Object registrationId = authorizationRequest.getAttribute("registration_id");
// Google์ผ ๋๋ง Refresh ํ ํฐ์ ๋ฐ๊ธฐ ์ํด, ํ๋ผ๋ฏธํฐ ์ถ๊ฐ
if (registrationId.equals("google")) {
return OAuth2AuthorizationRequest.from(authorizationRequest)
.additionalParameters(params -> {
params.put("prompt", "consent");
params.put("access_type", "offline");
})
.build();
}
// ๋ค๋ฅธ ์ ๊ณต์๋ ๊ทธ๋๋ก ๋ฐํ
return authorizationRequest;
}
ํ์ ํํด ์ฒ๋ฆฌ

@Transactional
public void deleteUserByLoginId(String loginId) {
String refreshKey = RedisTokenService.OAUTH2_REFRESH_TOKEN_KEY_PREFIX + loginId;
String accessKey = RedisTokenService.OAUTH2_ACCESS_TOKEN_KEY_PREFIX + loginId;
String accessToken = redisTokenService.getToken(accessKey);
String registrationId = loginId.split(PROVIDER_ID_DELIMITER)[0];
if (registrationId.equals(KAKAO)) {
// Access ํ ํฐ์ด null์ด๋ฉด Refresh ํ ํฐ์ ์ด์ฉํด ์ฌ๋ฐ๊ธ
if (accessToken == null) {
TokenResponse tokenResponse = socialClientService.reissueKakaoToken(redisTokenService.getToken(refreshKey));
// ํ์ ํํด๋ฅผ ์ํ ์ฌ๋ฐ๊ธ์ด๊ธฐ ๋๋ฌธ์, Redis์ ์ ์ฅํ์ง ์์
accessToken = tokenResponse.getAccess_token();
}
socialClientService.unlinkKakao(BEARER_PREFIX + accessToken);
}
if (registrationId.equals(GOOGLE)) {
if (accessToken == null) {
TokenResponse tokenResponse = socialClientService.reissueGoogleToken(redisTokenService.getToken(refreshKey));
accessToken = tokenResponse.getAccess_token();
}
socialClientService.unlinkGoogle(accessToken);
}
// Refresh ํ ํฐ์ ๋จ์์๊ธฐ ๋๋ฌธ์ ์ญ์
redisTokenService.deleteToken(refreshKey);
// ์ ์ ์ isDeleted๋ฅผ true๋ก ๋ณ๊ฒฝ
User user = userRepository.findByLoginId(loginId)
.orElseThrow(() -> new ApiException(USER_NOT_FOUND));
user.delete();
}
- ์์
๋ก๊ทธ์ธ ์ ๊ณต์๋ณ ํ ํฐ ์ฒ๋ฆฌ
- ์์ ๋ก๊ทธ์ธ ์ ๊ณต์(Google, Kakao)์ ๋ฐ๋ผ Redis์์ Access ํ ํฐ์ ๊ฐ์ ธ์ต๋๋ค
- Access ํ ํฐ์ด ๋ง๋ฃ๋์ด Redis์ ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ, Refresh ํ ํฐ์ ์ฌ์ฉํ์ฌ ์๋ก์ด Access ํ ํฐ์ ๋ฐ๊ธ๋ฐ์ต๋๋ค.
- ์์
๊ณ์ ์ฐ๊ฒฐ ํด์
- ๋ฐ๊ธ๋ฐ์ Access ํ ํฐ์ ์ฌ์ฉํด ์์ ๋ก๊ทธ์ธ ์ ๊ณต์์๊ฒ ๊ณ์ ์ฐ๊ฒฐ ํด์ ๋ฅผ ์์ฒญํฉ๋๋ค.
- ํ ํฐ ์ ๋ฆฌ
- Redis์ ๋จ์์๋ Refresh ํ ํฐ์ ์ญ์ ํฉ๋๋ค.
- ์ฌ์ฉ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ
- MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํด๋น ์ฌ์ฉ์์ isDeleted ์ปฌ๋ผ์ true๋ก ๋ฐ๊พธ์ด, ์ญ์ ์ํ๋ก ๋ณ๊ฒฝํฉ๋๋ค.
ํ์ ํํด ํ, ๋ค์ ๊ฐ์
ํ์ ํํด ํ ๋ค์ ๋ก๊ทธ์ธํ ๊ฒฝ์ฐ, ๋์ผํ ์ ํ๋ฆฌ์ผ์ด์
๋ด์์ ๊ณ ์ ID๋ ์ ์ง๋ฉ๋๋ค. ์ฆ, ๊ณ์ ์ฐ๊ฒฐ์ ํด์ ํ๊ณ ๋ค์ ์ฐ๊ฒฐํด๋ ๊ณ ์ ID๋ ๋ฐ๋์ง ์์ต๋๋ค. ๋ฐ๋ผ์ ํ์ ํํด ํ ์ฌ ๋ก๊ทธ์ธ ์, ๊ธฐ์กด ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ๋ฉฐ nickname๊ณผ profileImage ํ๋๋ฅผ ์
๋ฐ์ดํธํ๊ณ , isDeleted ์ํ๋ฅผ false๋ก ๋ณ๊ฒฝํ๋ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ์์ต๋๋ค.
(ํ์ ํํด ์, ์ฌ์ฉ์๊ฐ ์์ฑํ๋ ๋ฆฌ๋ทฐ, ๋ถ๋งํฌ ๋ฑ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ๊ณผ ๋ค์ ๊ฐ์
ํ ๊ฒฝ์ฐ์ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ถํ์ ์ถ๊ฐ๋ก ๋
ผ์ํ ์์ ์
๋๋ค.)
@Transactional
public OAuth2User processOAuth2User(OAuth2Response oAuth2Response) {
String uniqueProviderId = oAuth2Response.getProvider() + PROVIDER_ID_DELIMITER + oAuth2Response.getProviderId();
String nickname = oAuth2Response.getNickname();
String profileImage = oAuth2Response.getProfileImage();
if (!userRepository.existsByLoginId(uniqueProviderId)) {
userRepository.save(
new User(
uniqueProviderId,
null,
nickname,
profileImage,
null,
null
)
);
OAuth2UserDto oAuth2UserDto = new OAuth2UserDto(uniqueProviderId);
return new OAuth2UserImpl(oAuth2UserDto);
}
User user = userRepository.findByLoginId(uniqueProviderId)
.orElseThrow(() -> new ApiException(USER_NOT_FOUND));
if (user.isDeleted()) {
user.reactivate();
}
user.update(
null,
nickname,
profileImage
);
OAuth2UserDto oAuth2UserDto = new OAuth2UserDto(uniqueProviderId);
return new OAuth2UserImpl(oAuth2UserDto);
}
๊ฒฐ๊ณผ
ํ์ ํํด ์, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์์ ์ญ์ ๋ฟ๋ง ์๋๋ผ, ์์ ๋ก๊ทธ์ธ ์ ๊ณต์ ์ธก์์๋ ๊ณ์ ์ฐ๊ฒฐ์ ํด์ ํ์ฌ ๋ณด๋ค ์์ฑ๋ ์๋ ํ์ ํํด ๊ธฐ๋ฅ์ ๊ตฌํํ์ต๋๋ค.
- Redis๋ฅผ ํ์ฉํ์ฌ ์์ ๋ก๊ทธ์ธ ์ ๊ณต์๊ฐ ์ ๋ฌํด ์ฃผ๋ ํ ํฐ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌ
- OpenFeign์ ํตํ REST API ์์ฒญ
- OAuth2 ์ธ์ฆ ๊ด๋ จ ์ธํฐํ์ด์ค ์ปค์คํ ๊ตฌํ
- ๊ณ ์ ID์ ์ํํธ ๋๋ฆฌํธ๋ฅผ ํ์ฉํ์ฌ ํ์ ํํด ํ ์ฌ๊ฐ์ ์, ์ฌ์ฉ์ ๋ฐ์ดํฐ ์ ์ง
๋ํ, ์์ ์ธ๊ธํ ๊ฒ์ฒ๋ผ, ํํด ์ ์ฌ์ฉ์์ ์ฐ๊ด๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฐ ์ฌ๊ฐ์ ์์ ์ฒ๋ฆฌ์ ๋ํด์๋ ์ถ๊ฐ์ ์ผ๋ก ๋ ผ์ ํ ๊ตฌํํ ๊ณํ์ ๋๋ค.
์ฐธ๊ณ ์๋ฃ
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
https://developers.google.com/identity/protocols/oauth2/web-server?hl=ko
'ํ๋ก์ ํธ > NolGoat' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| ์นด์นด์ค ๋ก๊ทธ์ธ ๋์ ํญ๋ชฉ ๋ฌธ์ ํด๊ฒฐ (1) | 2024.12.11 |
|---|---|
| ๋ณด์ ์ทจ์ฝ์ ํด๊ฒฐ์ ์ํ AWS S3 ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ณ๊ฒฝ (0) | 2024.12.07 |
| JPA ๋ฝ์ผ๋ก ๋์์ฑ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ (0) | 2024.11.29 |
| ์ธ์ฆ์ด ํ์ํ URL ๊ณตํต ๊ด๋ฆฌ (0) | 2024.11.27 |
| Spring Security ์ธ์ฆ ํํฐ ์์ธ ์ฒ๋ฆฌํ๊ธฐ (0) | 2024.11.27 |