본문 바로가기
✨FRONTEND/📍Next.js

카카오 간편 로그인 구현하기

by 짱돌보리 2024. 8. 24.
728x90

카카오 간편 로그인 구현하기

소셜 로그인 기능을 구현하기 위해 카카오 OAuth 로그인을 적용했다.

카카오 로그인은 OAuth 2.0 방식으로 동작하며 전체 흐름은 다음과 같다.

✅ 카카오 로그인 절차

1️⃣ 인가 코드 발급

사용자가 카카오 로그인 버튼을 클릭하면 카카오 인증 서버로 이동한다.
사용자가 로그인 및 동의를 완료하면 인가 코드(code)가 발급되고, 설정한 redirectUri로 리다이렉트된다.

 

2️⃣ 토큰 발급

서비스 서버는 전달받은 인가 코드를 이용해 카카오 서버에 토큰 발급 요청을 보낸다.
카카오는 요청이 정상일 경우 사용자 토큰을 반환한다.

 

3️⃣ 회원 확인 및 등록

서비스는 발급받은 토큰을 이용해 사용자 정보를 조회하고
기존 회원 여부를 확인한다.

  • 회원이 있다면 → 로그인 처리
  • 회원이 없다면 → 회원가입 진행

4️⃣ 서비스 로그인

로그인 성공 시 서비스에서 세션 또는 토큰을 발급하고
사용자는 로그인된 상태로 서비스 화면으로 이동한다.

위를 바탕으로 카카오 소셜 로그인을 구현해보자.

1. 앱 등록하기

아래 링크로 들어가 애플리케이션을 추가한다. 애플리케이션을 생성하면 REST API 키를 확인할 수 있다.

https://developers.kakao.com/console/app

2. REST API 키 저장하기

 

프로젝트에서 카카오 API를 사용하기 위해 REST API 키를 환경 변수로 설정했다.

 

3. redirectUri 설정하기

redirectUri 설정해야 하는 이유

OAuth 로그인에서는 로그인 완료 후 사용자를 다시 돌려보낼 URL이 필요하다.

 

예시) http://localhost:3000/oauth/callback

 

카카오 로그인 인증이 완료되면 인가 코드가 포함된 상태로 이 URL로 리다이렉트된다.

4. env 설정

로그인과 회원가입을 분리하기 위해 redirect URI를 각각 설정했다.

NEXT_PUBLIC_KAKAO_REST_API_KEY=위에서 설정했던 REST API KEY
NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI=http://localhost:3000/signup/oauth/kakao
NEXT_PUBLIC_KAKAO_LOGIN_REDIRECT_URI=http://localhost:3000/login/oauth/kakao

5. URL 생성하기

위에서 설정했던 env를 통해 아래의 URL 을 설정해준다.

 

로그인 URL 맨 뒤에 &prompt=login을 붙이면 로그인할 때마다 카카오톡 로그인 창이 뜸!

export const KAKAO_SIGNUP_URL = `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY}&redirect_uri=${process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI}&scope=profile_nickname,account_email`;
export const KAKAO_LOGIN_URL = `https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${process.env.NEXT_PUBLIC_KAKAO_REST_API_KEY}&redirect_uri=${process.env.NEXT_PUBLIC_KAKAO_LOGIN_REDIRECT_URI}&scope=profile_nickname,account_email&prompt=login`;

6. 간편 회원가입 구현

카카오 로그인 후 리다이렉트되면 URL에 인가 코드(code)가 포함된다.

 

이 값을 이용해 회원가입 요청을 보낸다.

const KAKAO_SIGNUP_REDIRECT_URI =
  process.env.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URI;

export default function Kakao() {
  const router = useRouter();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const handleOAuthCallback = async () => {
      const { code } = router.query;

      if (code) {
        try {
          const signUpData: SignUpRequest = {
            nickname: randomNickname(),
            redirectUri: KAKAO_SIGNUP_REDIRECT_URI,
            token: code as string,
          };

          const signInResponse: SignInResponse = await SignUpUser(
            'kakao',
            signUpData,
          );

          console.log('회원가입 성공:', signInResponse);
          notify('success', '회원가입 성공!');

          router.push('/activities');
        } catch (error) {
          console.error('회원가입 오류:', error);
          if (axios.isAxiosError(error) && error.response) {
            notify('error', error.response.data.message);
            if (error.response.data.message === '이미 등록된 사용자입니다.')
              router.push('/login');
          } else {
            notify('error', '회원가입 중 알 수 없는 오류가 발생했습니다.');
          }
        } finally {
          setLoading(false);
        }
      }
    };

    handleOAuthCallback();
  }, [router.query]);

  return <div>{loading && <Loading />}</div>;
}

 

⚠️ 참고

 

카카오에서 닉네임을 받아오려 했지만 API로 해당 값을 전달할 경우 잘못된 인가 코드 오류가 발생했다.

그래서 회원가입 시 랜덤 닉네임을 생성하도록 처리했다.

7. 간편 로그인 구현

로그인 로직도 동일하게 인가 코드(code)를 이용해 진행된다.

로그인이 성공하면 서버에서 발급한 토큰을 쿠키에 저장한다.

 
const KAKAO_LOGIN_REDIRECT_URI =
  process.env.NEXT_PUBLIC_KAKAO_LOGIN_REDIRECT_URI || '';

export default function Kakao() {
  const router = useRouter();
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const handleOAuthCallback = async () => {
      const { code } = router.query;

      if (code) {
        try {
          const signInData: SignInRequest = {
            redirectUri: KAKAO_LOGIN_REDIRECT_URI,
            token: code as string,
          };

          const signInResponse: SignInResponse = await signInUser(
            'kakao',
            signInData,
          );
          console.log('로그인 성공:', signInResponse);
          notify('success', '로그인 성공!');

          setCookie('accessToken', signInResponse.accessToken, {
            path: '/',
            secure: true,
            sameSite: 'strict',
          });
          setCookie('refreshToken', signInResponse.refreshToken, {
            path: '/',
            secure: true,
            sameSite: 'strict',
          });
          setCookie('isSocialUser', true, {
            path: '/',
            secure: true,
            sameSite: 'strict',
          });

          router.push('/activities');
        } catch (error) {
          if (
            axios.isAxiosError(error) &&
            error.response &&
            error.response.status === 401
          ) {
            notify('warning', '계정이 없는 경우 회원가입을 진행해 주세요.');
            router.push('/signup');
          }
          console.error('로그인 오류:', error);
          notify('error', '로그인 중 알 수 없는 오류가 발생했습니다.');
        } finally {
          setLoading(false);
        }
      }
    };

    handleOAuthCallback();
  }, [router.query]);

  return <div>{loading && <Loading />}</div>;
}

구현 끝!

이렇게 해서 카카오 OAuth 기반 간편 로그인 / 회원가입 기능을 구현했다.

 

전체 흐름은 다음과 같다.

카카오 로그인 요청
→ 인가 코드 발급
→ redirectUri로 이동
→ 인가 코드 서버 전달
→ 로그인 또는 회원가입 처리
→ 서비스 로그인 완료

 

참고: 개인 개발자 비즈 앱 전환 방법

https://developers.kakao.com/docs/latest/ko/getting-started/app#biz-app-for-individual

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-token

https://developers.kakao.com/docs/latest/ko/kakaologin/common