React

[React] 소셜 로그인 (2)

HoneyIT 2025. 3. 21. 15:43
반응형

[인가 코드의 페이지 처리]

- 리액트 애블리케이션에서 Redirect Uri로 전달되는 경로의 페이지를 추가

import { useSearchParams } from "react-router-dom";

const KakaoRedirectPage = () => {

    const [searchParams] = useSearchParams()

    const authCode = searchParams.get("code")

    return (
        <div>
            <div>Kakao Login Redirect</div>
            <div>{authCode}</div>
        </div>
    )
}

export default KakaoRedirectPage

- redirect용 KakaoRedirectPage 추가

const KakaoRedirect = lazy(() => import("../pages/member/KakaoRedirectPage"))

{
    path:"kakao",
    element: <Suspense fallback={Loading}><KakaoRedirect/></Suspense>
}

- router에 kakao 경로 추가

 

- 인가 코드를 정상적으로 받아 오는 것을 확인 할 수 있음

 

[Access Token 호출]

 

- 위와 같이 Access Token 발급을 위한 값들을 확인할 수 있음(https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#refresh-token-response-body)

 

import axios from "axios"

const rest_api_key = `ffcbe30c51b11b3d8d2b9e1110c0ecfc`
const redirect_uri = `http://localhost:3000/member/kakao`

const auth_code_path = `https://kauth.kakao.com/oauth/authorize`

const access_token_url = `https://kauth.kakao.com/oauth/token`

export const getKakaoLoginLink = () => {

    const kakaoURL = `${auth_code_path}?client_id=${rest_api_key}&redirect_uri=${redirect_uri}&response_type=code`;

    return kakaoURL
}

export const getAccessToken = async (authCode) => {

    const header = {
        headers: {
            "Content-Type": "application/x-www-from-urlencoded",
        }
    }
    const params = {
        grant_type: "authorization_code",
        client_id: rest_api_key,
        redirect_uri: redirect_uri,
        code: authCode
    }

    const res = await axios.post(access_token_url, params, header)

    const accessToken = res.data.access_token

    return accessToken
}

- 필요 파라미터로 요청하여 Access Token을 응답 받도록 kakaoApi에 getAccessToken을 추가

 

 

- 에러 발생 새로고침이 아닌 새로 로그인해서 확인해야 함

- 새로고침의 경우 한번 사용한 authCode를 다시 사용하기 때문에 발생하는 오류

- 새로 로그인하니 정상적으로 동작 확인

 

[API 서버에서 Access Token 처리]

- Front-end에서 받은 Access Token을 API로 전달해서 사용자 정보를 처리하는 방식 개발

- https://kapi.kakao.com/v2/user/me 에서 사용자 정보를 가져옵니다.

 

[MemberService 개발]

- API 서버에서는 Access Token으로 기존의 회원정보를 이용하거나 새로운 회원으로 서비스 계층을 만들어서 추가

package org.zerock.mallapi.service;

import org.springframework.transaction.annotation.Transactional;
import org.zerock.mallapi.dto.MemberDTO;

@Transactional
public interface MemberService {
    
    MemberDTO getKakaoMember(String accessToken);
}

 

private String getEmailFromKakaoAccessToken(String accessToken) {
        
        String kakaoGetUserURL = "https://kapi.kakao.com/v2/user/me";

        if(accessToken == null){
            throw new RuntimeException("Access Token is null");
        }
        RestTemplate restTemplate = new RestTemplate();

        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + accessToken);
        headers.add("Content-Type", "application/x-www-form-urlencoded");
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        UriComponents uriBuilder = UriComponentsBuilder.fromUriString(kakaoGetUserURL).build();

        ResponseEntity<LinkedHashMap> response = restTemplate.exchange(uriBuilder.toString(), HttpMethod.GET, entity, LinkedHashMap.class);

        log.info(response);

        LinkedHashMap<String, LinkedHashMap> bodyMap = response.getBody();

        log.info("-----------------------");
        log.info(bodyMap);

        LinkedHashMap<String, String> kakaoAccount = bodyMap.get("kakao_account");

        log.info("kakaoAccount: " + kakaoAccount);

        return kakaoAccount.get("email");
    }

- MemberServiceImple에서 RestTemplate을 이용해 카카오 서비스를 호출합니다.

- Map 타입의 이메일을 추출하는 과정에서 fromHttpUrl 대신 Spring 6.2 이후에 권장되는 fromUriString를 사용합니다.

 

- 간혹 500 에러 발생하면서 email 값이 null로 나오는 경우 내 애플리케이션에서 비즈앱 전환 후 '카카오계정(이메일)'이 설정되어있는지 확인해주세요.

 

- 로그인하면 소셜회원으로 로그인 정보가 저장되는 것을 볼 수 있습니다.

반응형