이번 포스트에서는 카카오/구글 로그인 기능 구현에 대해 작성해보고자 한다.
카카오
카카오 디벨로퍼 사이트에서 애플리케이션을 등록해 관련 키를 발급 받는다
이러한 키를 .env 파일로 관리하여 원격 저장소에서 노출되지 않도록 하였다..
VITE_KAKAO_REST_API = ''
VITE_GOOGLE_CLIENT_ID = ''
VITE_GOOGLE_CLIENT_SECRET = ''
VITE_YOUTUBE_CLIENT_ID = ''
VITE_YOUTUBE_CLIENT_SECRET= ''
VITE_API_URL= ''
VITE_CALLBACK_URL = ''
VITE_OAUTH_API_URL = ''
VITE_OAUTH_CALLBACK_URL = ''
카카오 로그인 요청을 보냈을 때의 리턴 값 타입은 다음과 같다.
이때 닉네임, 프로필 사진, 카카오계정 요청에 대한 허가를 받으려면 비즈니스 등록을 해야하는데,
이때 사업자 등록번호가 필요한데, 카카오에서는 비즈니스 정보 심사를 간단하게 목적만 알려주어
허가가 되면 아래의 닉네임, 프로필 사진, 카카오계정에 대한 값을 받아올 수 있다.
ID값을 토대로 타입을 정의하면 다음과 같다.
export type OAuthProvider = {
name: string;
authUrl: string;
tokenUrl: string;
clientId: string;
clientSecret?: string;
redirectUri: string;
scope: string;
};
실제로 요청하는 함수는 다음과 같이 작성한다.
이때 scope를 입력하여 내가 원하는 값을 받을 수 있도록 하였다.
export const kakaoOAuth: OAuthProvider = {
name: 'kakao',
authUrl: 'https://kauth.kakao.com/oauth/authorize',
tokenUrl: 'https://kauth.kakao.com/oauth/token',
clientId: import.meta.env.VITE_KAKAO_REST_API, // REST API 키
redirectUri: import.meta.env.VITE_CALLBACK_URL + '',
scope: 'profile_nickname profile_image account_email',
};
위의 kakaoOAuth함수를 사용하여 카카오 서버에 요청을해서 authUrl과 code의 값을 가지는 URL을 생성하여
미리 설정한 Redirect URL로 보내는데, 카카오 디벨로퍼 홈페이지에서 추가하면 된다.
URL 생성함수는 다음과 같다.
// 로그인 URL 생성
export const getAuthorizationUrl = (
provider: OAuthProvider,
state?: string
): string => {
const params = new URLSearchParams({
client_id: provider.clientId,
redirect_uri: provider.redirectUri,
response_type: 'code',
scope: provider.scope,
});
if (state) {
params.append('state', state);
} else {
state = '';
}
return `${provider.authUrl}?${params.toString()}`;
};
위에서 설정한 Redirect URL에 맞게 route 경로를 설정하고,
export const Route = createFileRoute('/auth/callback/kakao/')({
component: RouteComponent,
});
아래의 코드를 실행하여 백엔드에 카카오로부터 받은 authUrl의 값과 code 값을 보낸다
이때 현재 kakao에서는 state에 대한 값이 URL에 존재하지 않기 때문에, cryptoUUID나 랜덤 함수를 사용하여 임의의 값을 만들고 백엔드에 보낸다.
useEffect(() => {
const processKakaoLogin = async () => {
try {
const params = new URLSearchParams(location.search);
const code = params.get('code');
const state = params.get('state');
if (!code) {
setError('인증 코드가 없습니다.');
setLoading(false);
return;
}
const response = await axios.post(import.meta.env.VITE_OAUTH_API_URL, {
provider: 'kakao',
code: code,
state: state,
});
if (response.data) {
const { accessToken } = response.data;
setTokens(accessToken);
}
navigate({ to: '/auth/sign-up/sns' });
} catch {
setError('로그인 처리 중 오류가 발생했습니다.');
setLoading(false);
}
};
processKakaoLogin();
}, [location.search, navigate]);
state를 사용하는 이유는 CSRF(Cross-Site Request Forgery) 공격에 대비하기 위해서인데,
절차는 다음과 같다.
- 인증 요청 시 무작위로 생성한 고유한 state 값을 포함
- 이 state 값을 서버 세션에 저장
- 카카오에서 리다이렉트될 때 반환되는 state 값과 세션에 저장된 값을 비교
- 두 값이 일치하면 정상적인 인증 흐름으로 판단하고, 일치하지 않으면 CSRF 공격 시도로 간주하여 처리를 중단
그리고 위 코드에서보면, accessToken으로 관리하고 있는데, 이것은 다음 포스트에서 다루겠다.
if (response.data) {
const { accessToken } = response.data;
setTokens(accessToken);
}
'패스트캠퍼스 데브캠프' 카테고리의 다른 글
파이널 프로젝트 - 내 프로젝트 (7) - Tanstack-Query useInfinity (0) | 2025.04.04 |
---|---|
파이널 프로젝트 - 회원가입 (6) - 로그인 (0) | 2025.04.04 |
파이널 프로젝트 - 회원가입 (5) - 이메일 인증 (0) | 2025.04.03 |
파이널 프로젝트 - 회원가입 (4) - 회원정보 입력 (0) | 2025.04.03 |
파이널 프로젝트 - 회원가입(3) - 전화번호 인증 (0) | 2025.04.03 |