React와 OAuth2 인증 연동 구현
React 앱에서 OAuth2 인증 흐름, Authorization Code(PKCE) 적용 예시, 토큰 저장과 갱신 전략, 보안 고려사항을 초심자도 이해하기 쉬운 설명
목차
개요
React 애플리케이션에 OAuth2를 연동하는 과정은 사용자 인증과 토큰 관리를 포함한다. 잘 설계하면 보안 사고를 줄이고 사용자 경험을 개선할 수 있다. 이 글은 react oauth2 연동 관점에서 인증 흐름, 코드 예시, 토큰 처리 방법과 보안 포인트를 실무 중심으로 설명한다.
OAuth2 흐름 요약
가장 권장되는 방식은 Authorization Code 플로우에 PKCE를 더한 방법이다. 클라이언트는 인증 서버로 리디렉션해 권한을 얻고, 발급된 코드를 백엔드 또는 클라이언트에서 교환해 액세스 토큰을 얻는다.
주요 단계
- 클라이언트: 인증 서버에 인증 요청(코드 + PKCE)
- 사용자 인증: 인증 서버에서 사용자 로그인
- 리디렉션: 인증 서버가 리다이렉트로 코드 전달
- 토큰 교환: 코드 → 액세스 토큰(+리프레시 토큰) 교환
- API 호출: 액세스 토큰으로 보호된 리소스 접근
왜 PKCE를 쓰나
PKCE는 공개 클라이언트(스파, 모바일)가 보안 토큰 교환 과정에서 코드 탈취를 방지하도록 고안되었다. 브라우저 환경에서는 Authorization Code + PKCE를 기본으로 고려한다.
토큰 저장과 보안
토큰 저장 위치는 보안과 편의성 사이의 균형이다. 로컬 스토리지에 저장하면 XSS에 취약하고, 세션 스토리지는 탭 간 공유에 제약이 있다. 가장 안전한 방법은 서버에서 httpOnly 쿠키로 관리하는 방식이다.
추천 전략
- 가능하면 백엔드에서 토큰 교환을 수행하고 httpOnly, Secure, SameSite 쿠키로 토큰 전달
- 클라이언트 단에서 직접 토큰을 받아야 할 경우 메모리 저장(리프레시 토큰 사용은 주의)
- 토큰 갱신은 리프레시 토큰 또는 재인증으로 처리
React 구현 예시
아래 코드는 간단한 흐름을 보여준다. 실제 환경에서는 CORS, 상태 검증(state), PKCE 코드 검증, 에러 처리 등 추가 작업이 필요하다.
1) 인증 시작 함수
const startAuth = () => {
const clientId = 'YOUR_CLIENT_ID';
const redirectUri = encodeURIComponent('https://your.app/callback');
const scope = encodeURIComponent('openid profile email');
const state = encodeURIComponent(Date.now().toString());
const codeChallenge = 'GENERATED_CODE_CHALLENGE'; // PKCE 처리 필요
const url = `https://auth.server/authorize?response_type=code&client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}&state=${state}&code_challenge=${codeChallenge}&code_challenge_method=S256`;
window.location.href = url;
};
2) 콜백에서 코드 처리
React 라우트 컴포넌트에서 쿼리 파라미터를 읽고 토큰 교환 요청을 수행한다. 아래 예시는 클라이언트에서 직접 교환하는 경우이다.
const Callback = () => {
useEffect(() => {
const params = new URLSearchParams(window.location.search);
const code = params.get('code');
const state = params.get('state');
if (code) {
fetch('/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ code, redirect_uri: 'https://your.app/callback', code_verifier: 'SAVED_VERIFIER' })
})
.then(res => res.json())
.then(data => {
// 액세스 토큰 처리: 권장 방식은 서버가 httpOnly 쿠키로 응답
sessionStorage.setItem('access_token', data.access_token);
});
}
}, []);
return <div>인증 처리 중...</div>;
};
백엔드 중계의 장점
백엔드가 토큰 교환을 맡으면 클라이언트에는 httpOnly 쿠키만 전달된다. 토큰 탈취 위험이 크게 줄고, 리프레시 토큰을 안전하게 보관할 수 있다. 또한 API 호출 시 서버가 토큰을 붙여 프록시 형태로 처리하면 CORS 문제도 줄어든다.
토큰 갱신 시나리오
- 리프레시 토큰 사용: 서버에서 관리하고 만료 시 재로그인 유도
- 무상태 접근: 짧은 만료 시간을 두고 자주 재인증
- Silent Refresh: iframe 또는 백그라운드 요청으로 토큰 갱신(보안 고려 필요)
보안 체크리스트
- 항상 PKCE 사용
- state 파라미터로 CSRF 방지
- 토큰은 가능하면 httpOnly 쿠키로 저장
- HTTPS 적용
- 클라이언트에서 민감 정보 저장 금지
마무리
react oauth2 연동은 설계 단계에서 토큰 보관과 갱신 전략을 명확히 해야 안정적인 서비스가 된다. oauth react example을 통해 인증 흐름을 이해하고, 리액트 인증 토큰 처리 시 보안 원칙을 우선 고려하면 운영 위험을 줄일 수 있다. 추가적으로 사용 사례에 따라 백엔드 중계나 토큰 암호화 등 보안 강화를 검토하는 것이 권장된다.