ReactAuthenticationOAuthRedux

QASTUDIO: 소셜 로그인 쿠키가 저장되지 않던 문제를 추적한 과정

Kim Yeon Jin

1. 문제는 로그인 화면이 아니라 로그인 이후 흐름이었다

QASTUDIO는 QA 시나리오를 만들고, 실행 결과를 확인하는 QA 자동화 서비스였습니다.
저는 이 프로젝트에서 로그인, 회원가입, 소셜 로그인, 사용자 프로필 설정, 시나리오 조회 페이지의 상태 관리를 맡았습니다.

처음에는 인증 기능을 일반적인 로그인 구현으로 생각했습니다.
이메일 로그인은 요청을 보내고, 소셜 로그인은 OAuth 흐름을 연결하고, 로그인 이후에는 메인 화면으로 보내면 된다고 봤습니다.

하지만 실제로 붙여보니 문제가 그렇게 단순하지 않았습니다.

  • 일반 로그인에서는 CORS 문제가 발생했다
  • 소셜 로그인에서는 응답에는 쿠키가 있는 것처럼 보이는데 브라우저에 저장되지 않았다
  • 로그인 성공 이후 신규 사용자와 기존 사용자의 이동 경로가 달라야 했다
  • 시나리오 조회 페이지는 사용자, 프로젝트, 역할, 시나리오 상태가 함께 필요했다

결국 이 문제는 "로그인 버튼이 동작하느냐"가 아니라,
인증 이후 서비스 상태를 어디서부터 믿고 이어갈 수 있느냐의 문제였습니다.

QASTUDIO 서비스 화면

2. 처음에는 쿠키 설정 문제라고 생각했다

QASTUDIO는 보안을 고려해 쿠키 기반 인증을 사용했습니다.
토큰을 프론트에서 직접 들고 있는 방식보다 안전하다고 판단했기 때문입니다.

문제는 쿠키 기반 인증이 브라우저 조건에 민감하다는 점이었습니다.
특히 로컬 개발 환경에서는 다음 설정들이 계속 의심 대상이 됐습니다.

  • SameSite
  • Secure
  • HttpOnly
  • CORS credentials 설정
  • 로컬 HTTPS 여부

그래서 처음에는 프론트엔드 개발 서버를 HTTPS로 띄우고, 요청 옵션과 백엔드 쿠키 속성을 함께 확인했습니다.
일부 문제는 이 과정에서 정리됐지만, 소셜 로그인은 여전히 깔끔하게 해결되지 않았습니다.

응답을 보면 인증이 된 것 같고, 리다이렉트도 일어나는 것 같은데,
브라우저에는 기대한 상태가 남지 않았습니다.

3. 진짜 원인은 OAuth URI 충돌이었다

쿠키 옵션만 계속 보면 답이 나오지 않았습니다.
그래서 요청이 어느 경로로 들어가고, 백엔드에서 어떤 핸들러를 타는지 다시 추적했습니다.

그 과정에서 Spring Security OAuth2 Client의 기본 로그인 경로와 팀 서버에서 사용하던 로그인 처리 URI가 충돌하고 있다는 것을 확인했습니다.

겉으로는 쿠키 저장 문제처럼 보였지만 실제 흐름은 달랐습니다.

text
소셜 로그인 클릭
  ↓
의도한 로그인 처리 경로로 이동한다고 생각
  ↓
Spring Security 기본 OAuth2 경로와 충돌
  ↓
provider 매칭이 꼬임
  ↓
없는 provider 요청처럼 처리되거나 에러 흐름으로 빠짐

즉, 브라우저가 쿠키를 못 저장한 것이 핵심이 아니었습니다.
인증이 끝났다고 믿을 수 있는 경로까지 정상적으로 도달하지 못하고 있었습니다.

4. 경로를 정리하고 성공 이후 흐름을 다시 만들었다

해결은 크게 두 가지였습니다.

첫 번째는 소셜 로그인 진입 경로를 Spring Security가 기대하는 형태로 정리하는 것이었습니다.

text
/oauth2/authorization/{provider}

이렇게 바꾸면서 OAuth provider를 명확하게 넘기고, 프레임워크 기본 매핑과 팀 서버의 로그인 처리 경로가 애매하게 겹치지 않도록 했습니다.

두 번째는 로그인 성공 이후를 단순 리다이렉트로 끝내지 않는 것이었습니다.
/login/success에서 사용자 정보를 조회하고, 그 결과를 기준으로 다음 화면을 결정하도록 바꿨습니다.

text
로그인 성공
  ↓
/login/success
  ↓
사용자 정보 조회
  ├─ nickname 있음: 메인 화면
  └─ nickname 없음: /userSetting

이 구조로 바꾸고 나서야 로그인 이후 흐름이 명확해졌습니다.
쿠키가 저장됐는지 감으로 판단하는 대신, 현재 사용자 정보를 조회할 수 있는지를 기준으로 다음 상태를 결정할 수 있었기 때문입니다.

QASTUDIO 로그인 이후 화면
로그인 이후 화면. 인증 성공 여부만이 아니라 사용자 상태에 따른 다음 흐름이 필요했습니다.
QASTUDIO 사용자 상태 기반 화면
사용자 상태 기반 화면. 신규 사용자와 기존 사용자의 이동 경로를 분리했습니다.

5. 인증 API는 역할별로 나눠서 관리했다

인증 문제를 겪고 나니 API를 한 파일에 계속 쌓아두는 방식도 불편했습니다.
문제가 생겼을 때 회원가입, 로그인, 토큰 재발급, 프로필 설정이 섞여 있으면 원인을 찾는 데 시간이 더 걸렸습니다.

그래서 인증 관련 API를 역할별로 나눠 관리했습니다.

  • 회원가입
  • 이메일 인증
  • 일반 로그인
  • 소셜 로그인
  • 토큰 재발급
  • 로그아웃
  • 비밀번호 변경
  • 프로필 설정

큰 구조를 만든다기보다, 디버깅할 때 바로 찾을 수 있게 책임을 나눈 정도였습니다.
인증처럼 실패 원인이 여러 층에 걸쳐 있는 기능에서는 이 정도 분리만으로도 추적 시간이 줄었습니다.

6. 시나리오 조회 페이지는 Redux로 상태를 묶었다

QASTUDIO에서 인증 다음으로 복잡했던 부분은 시나리오 조회 페이지였습니다.
이 화면은 단순 목록이 아니라 사용자, 프로젝트, 역할, 시나리오가 함께 움직이는 구조였습니다.

예를 들어 사용자가 특정 프로젝트에 들어가면 프로젝트 정보만 필요한 것이 아니었습니다.

  • 현재 사용자 정보
  • 프로젝트 목록
  • 프로젝트 내 역할 목록
  • 시나리오 목록
  • 시나리오 생성, 수정, 삭제 상태
  • 실행 결과와 성공/실패 비율

이 값들이 한 화면에서 연결됐기 때문에 Redux Toolkit으로 전역 상태를 관리했습니다.
인증 상태와 프로젝트/시나리오 상태를 분리해두니, 로그인 이후 사용자 상태가 바뀌어도 시나리오 조회 흐름을 비교적 안정적으로 이어갈 수 있었습니다.

QASTUDIO 시나리오 조회 화면
시나리오 조회 화면. 사용자, 프로젝트, 역할, 시나리오 상태가 함께 필요한 화면이었습니다.
QASTUDIO 시나리오 실행 결과 화면
실행 결과 화면. 목록 상태와 실행 결과를 같은 흐름 안에서 관리해야 했습니다.

7. 이 프로젝트에서 배운 점

QASTUDIO에서 가장 크게 배운 것은 인증 문제를 프론트엔드 코드 안에서만 보면 해결이 늦어진다는 점이었습니다.

처음에는 쿠키 옵션, HTTPS, CORS만 계속 봤습니다.
하지만 실제 원인은 OAuth 경로와 백엔드 프레임워크의 기본 매핑까지 같이 봐야 드러났습니다.

이 경험 이후 인증을 볼 때 기준이 바뀌었습니다.

  • 응답에 쿠키가 보이는지보다 브라우저가 신뢰할 수 있는 흐름으로 저장했는지를 봐야 한다
  • OAuth는 프론트 URL만 맞추는 문제가 아니라 백엔드 프레임워크의 기본 경로와도 맞아야 한다
  • 로그인 성공 이후에는 사용자 상태를 다시 확인하고 화면을 분기해야 한다
  • API와 상태는 기능 이름보다 디버깅 가능한 책임 단위로 나눠야 한다

QASTUDIO는 단순히 로그인과 시나리오 화면을 구현한 프로젝트가 아니었습니다.
프론트엔드가 인증 흐름을 제대로 다루려면 브라우저, 백엔드 라우팅, 사용자 상태를 한 흐름으로 봐야 한다는 것을 배운 프로젝트였습니다.

Enjoyed this article? Check out more projects and posts on my portfolio.

Explore this project