OAuth 로그인 — 환경별 redirect URI 관리하기
소셜 로그인이 운영 환경에서는 잘 되는데 로컬이나 스테이징에서는 에러가 나나요? Redirect URI 하드코딩의 문제점과 이를 동적으로 해결하는 방법을 알아봅니다.
아키텍처 구조도
OAuth 리다이렉트 흐름 복습
카카오, 네이버, 구글 등 소셜 로그인은 모두 비슷한 "Auth Code Flow"를 따릅니다. 사용자가 로그인을 마치면 카카오 서버가 우리 사이트로 다시 돌려보내 주는데, 이때 도착하는 주소가 바로 Redirect URI입니다.
로그인 버튼 클릭
우리 사이트에서 로그인 버튼을 누릅니다.
소셜 로그인 창
카카오/네이버 로그인 창으로 이동해 아이디/비밀번호를 입력합니다.
인증 완료 및 리다이렉트
소셜 서버가 인증을 확인한 뒤, 사전에 등록된 Redirect URI로 사용자를 돌려보냅니다. (이때 url에 인증 코드 ?code=... 가 붙어옵니다)
우리 서버 로그인 처리
우리 서버가 그 코드를 받아 진짜 토큰으로 교환하고 로그인을 완료합니다.
보안의 핵심: Redirect URI 검증
소셜 서버는 아무 주소로나 사용자를 돌려보내지 않습니다. 해커의 사이트로 인증 코드가 유출되는 것을 막기 위해, 우리가 "개발자 콘솔"에 미리 등록해둔 URI와 **정확히 일치할 때만** 리다이렉트를 허용합니다.
왜 하드코딩하면 안 되는가
✕하드코딩 (위험)
- ✕const redirectUri = 'https://8282100.xyz/login';
- ✕로컬(localhost:3000)에서 테스트할 수 없음
- ✕스테이징(staging.8282100.xyz)에서 로그인하면 갑자기 운영 서버로 튕김
✓동적 할당 (안전)
- ✓const redirectUri = `${window.location.origin}/login`;
- ✓로컬에서는 http://localhost:3000/login 이 됨
- ✓스테이징에서는 https://staging.8282100.xyz/login 이 됨
- ✓현재 접속한 환경에 맞춰 자동으로 변환됨
스테이징에서 로그인했는데 운영(prod) 사이트로 이동하는 이유는 뭔가요?
코드에 Redirect URI가 운영 도메인(https://8282100.xyz)으로 고정되어 있었기 때문입니다. 카카오 서버 입장에서는 요청받은 주소로 충실히 돌려보냈을 뿐입니다.
동적 Redirect URI 구현하기
// 카카오 로그인 호출 함수
const kakaoLogin = () => {
const clientId = process.env.NEXT_PUBLIC_KAKAO_CLIENT_ID;
// 현재 브라우저의 도메인을 가져옴
const redirectUri = `${window.location.origin}/login`;
const authUrl = `https://kauth.kakao.com/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&response_type=code`;
window.location.href = authUrl;
};위와 같이 코드를 수정했다면, 카카오와 네이버 개발자 콘솔(Developer Center)에 접속해 모든 환경의 URI를 전부 등록해야 합니다.
- http://localhost:3000/login
- https://staging.8282100.xyz/login
- https://8282100.xyz/login주의사항 및 팁
Q.localhost도 등록이 가능한가요?
네, 대부분의 OAuth 제공자(카카오, 네이버, 구글)는 개발 편의를 위해 localhost를 등록할 수 있게 허용합니다.
Q.http와 https를 구별하나요?
네, 완전히 다른 주소로 인식합니다. localhost는 예외적으로 http를 허용하지만, 실제 도메인은 반드시 https로 등록해야 동작합니다.
Q.마지막 슬래시(/) 유무도 중요한가요?
매우 중요합니다. https://8282100.xyz/login 과 https://8282100.xyz/login/ 은 다른 주소입니다. 코드에 작성한 주소와 콘솔에 등록한 주소가 토씨 하나 틀리지 않고 똑같아야 합니다.
