로그인 하지 않은 사용자가, 로그인 이후 접근 가능한 경로로 접속했을때는 splash 화면으로 이동 후 로그인 페이지로 가는 흐름
✔ 도입한 기술
이번 로그인 흐름 개선에서는 React Router 기반의 라우팅 시스템을 구축하면서, protected route
와 public route
를 명확히 분리하는 구조를 도입했다. 이를 통해 로그인 상태에 따라 접근 가능한 경로를 엄격히 제어하고자 했다. 인증 상태 확인과 사용자 정보를 효율적으로 관리하기 위해 tanstack-query
를 활용하여 사용자 상태를 서버에서 조회하는 useAuth
커스텀 훅을 만들었고, 인증 흐름 제어는 AuthGuard
컴포넌트로 구현했다. 또한, 카카오 소셜 로그인 연동 시 발생하는 인가 코드를 받아 서버에 전달해 로그인 처리를 하는 LoginCallback
컴포넌트가 있다. 로그인 과정 중 401 Unauthorized 상태가 발생하면 인터셉터로 이를 감지해 자동으로 로그인 페이지로 리다이렉트하는 로직도 함께 구성되었다.
✔ 문제 요약
초기에는 로그인 필요 페이지에 로그인하지 않은 사용자가 접근할 경우, 적절한 보호 및 리다이렉트 처리가 체계적으로 이뤄지지 않아 사용자 경험이 일관되지 않았다. 특히, 카카오 로그인 버튼 클릭 후 콜백에서 토큰 발급 및 사용자 정보 조회 후 화면 전환까지의 흐름이 명확하지 않았고, 인증 상태를 판단하는 useAuth
훅과 AuthGuard
의 역할 분리가 애매해 로직이 복잡하게 얽혀 있었다. 이로 인해 로그인 성공 여부와 회원 가입 여부 판단 후 올바른 화면으로 자연스럽게 이동시키는 부분에서 예외 상황이 발생하거나 불필요한 재렌더링이 많았다. 더불어 interceptor에서 발생하는 401 에러 처리와 인증 흐름이 명확히 연결되지 않아 중복된 인증 검사와 비효율적인 네비게이션이 발생했다.
추가적으로 인증되지 않은 사용자가 홈 같은 인증 필요 경로에 접근할 경우, Tanstack Query를 통한 API 요청이 먼저 발생해 서버로부터 401 Unauthorized 에러가 반환된다. 이때 인증 상태 판단 전에 API 요청이 먼저 실행되고, 인증 실패(Hi developers… .. ㅋㅋ) 후 스플래시 화면으로 리다이렉트되면서 화면 깜빡임 현상이 발생해 사용자 경험이 떨어졌다.
✔ 원인 분석
가장 큰 원인은 인증 흐름의 단계별 역할과 경계가 명확히 정의되어 있지 않은 데 있었다. 카카오 로그인 콜백에서 인가 코드를 받아 서버에 전달하고, 서버로부터 로그인 성공 응답을 받은 후 클라이언트가 사용자 정보를 조회해 로그인 상태를 판단하는 부분이 분리되어 있었고, 이 사이의 상태 관리가 일관적이지 않았다. 또한, useAuth
훅이 사용자 상태를 조회하지만 이 결과를 기반으로 AuthGuard
가 경로 접근을 제어하는 역할이 뚜렷하게 구분되지 않아 책임이 분산되었다. interceptor는 401 상태 발생 시 로그아웃 혹은 로그인 페이지 이동을 처리하지만, 그 흐름이 useAuth
나 라우터와 조화롭게 연결되지 못해 중복 검사와 예외 처리가 반복됐다. 결과적으로 로그인 전, 로그인 후 화면 전환과 상태 반영이 비동기적으로 꼬여 흐름 제어가 어려웠다.까깜
깜빡임 관련 현상은, 라우터에서 인증 보호 기능(AuthGuard
)이 자식 컴포넌트 렌더링 전에 선행되지 않아, 인증 검증 전 API 요청이 발생하는 문제가 있었다. 또한 라우터에 에러 처리용 errorElement
가 없어서 401 에러로 인한 예외 상황이 자연스럽게 핸들링되지 않았다. 결과적으로 사용자는 인증 상태 확인 이전에 불필요한 API 호출과 깜빡임 현상을 경험했다.
✔ 해결 방법
라우터 구조 재설계: React Router의 createBrowserRouter를 활용해, 로그인 필요 경로를 AuthGuard 컴포넌트로 감싸고, 로그인 전용 경로는 publicRoutes로 분리해 두었다. 이로써 인증 여부에 따라 접근 가능한 경로가 엄격히 구분되도록 했다.
useAuth 훅 개선: 서버에서 사용자 상태를 조회해 닉네임 존재 여부(isAuthenticated)와 가입 조건(isNotMatched) 등을 명확히 반환하도록 하여, 로그인 여부 및 추가 매칭 필요 여부를 판별하는 로직을 일원화했다. 캐시 무효화 기능을 활용해 사용자 상태 갱신도 쉽게 할 수 있도록 설계했다.
AuthGuard 컴포넌트 역할 명확화: useAuth에서 반환된 로그인 상태와 로딩 상태를 토대로 로그인되지 않은 경우 Navigate 컴포넌트를 이용해 로그인 페이지로 리다이렉트시키고, 인증 중이면 로딩 상태를 보여주도록 하여 접근 제어를 엄격하게 구현했다.
깜빡임 관련 해결 방법으로는 , 라우터에서
AuthGuard
를 최상위 레벨로 배치해, 인증 여부 확인이 먼저 이루어지고 자식 라우트들이 렌더링 되도록 변경했다. 이를 통해 인증이 안 된 경우 자식 컴포넌트들의 API 요청 자체를 막았다. 또, 라우터에errorElement
를 빈 컴포넌트 또는 별도 에러 UI로 추가해 예외 상황을 자연스럽게 처리하도록 함으로써, 예기치 않은 에러 발생 시 사용자에게 불필요한 깜빡임을 보여주지 않도록 했다.AuthGuard
컴포넌트에서 인증 상태 로딩 중엔 스플래시 화면을 렌더링하고, 인증 실패 시 로그인 페이지로 즉시 리다이렉트하도록 개선해 사용자 경험을 부드럽게 만들었다.코드 일부…
tsx// router.tsx import { createBrowserRouter } from 'react-router-dom'; import AuthGuard from '@routes/auth-guard'; import Layout from '@routes/layout'; import Splash from '@pages/login/components/splash'; import ErrorView from '@pages/error/error-view'; import { protectedRoutes } from '@routes/protected-routes'; import { publicRoutes } from '@routes/public-routes'; import { ROUTES } from '@routes/routes-config'; export const router = createBrowserRouter([ { path: ROUTES.SPLASH, element: <Splash />, }, ...publicRoutes, { path: '/', element: <AuthGuard />, // 최상위에 AuthGuard 배치 errorElement: <></>, // 빈 컴포넌트나 별도의 에러 UI로 깜빡임 방지 children: [ { element: <Layout />, children: [ ...protectedRoutes, { path: '/error', element: <ErrorView />, }, { path: '*', element: ( <ErrorView message={`존재하지 않는 페이지입니다.\nURL을 다시 확인해 주세요.`} /> ), }, ], }, ], }, ]);
✔ 회고 및 개선 방향
이번 로그인 흐름 설계 도전은 protected route와 public route를 명확히 분리하여, 인증 상태에 따른 사용자 경험을 체계적으로 관리하는 데 큰 도움이 되었다. 하지만 카카오 로그인 콜백 이후 인가 코드 처리부터 사용자 상태 조회 및 화면 전환까지 이어지는 비동기 흐름이 복잡하여, interceptor, useAuth, AuthGuard 등 여러 컴포넌트가 인증 흐름의 일부를 분담하는 과정에서 상태 변화가 즉시 반영되지 않아 로직 꼬임과 디버깅 어려움이 있었다.
앞으로는 인증 흐름 내 각 역할별 책임과 상태 변화를 더욱 명확히 구분하는 동시에, 전역 상태 관리 솔루션(Recoil, Zustand 등)을 도입해 인증 상태 변화를 일관성 있게 처리하는 방안을 고민할 예정이다. 또한 네트워크 오류, 토큰 만료 등 다양한 예외 처리 케이스를 세밀하게 테스트하여 사용자 이탈을 방지하는 UX 개선에도 주력할 계획이다. 이를 통해 로그인과 인증 로직을 더욱 견고하고 확장성 있게 다듬는 것이 목표다.
이번 개선 작업을 통해 인증 상태가 완전히 확인된 후에만 protected route 내부 컴포넌트가 렌더링되도록 하여, 불필요한 API 호출과 401 에러로 인한 화면 깜빡임 현상을 원천 차단할 수 있었다. 덕분에 스플래시 화면이 자연스럽게 노출되어 사용자 경험이 크게 향상되었다. 앞으로도 인증과 관련된 비동기 상태 관리는 라우터 수준에서 관리하여 페이지 렌더링 타이밍과 API 호출 흐름을 최대한 일치시키는 방향으로 설계할 계획이다. 또한, 에러 핸들링 UI도 일관성 있게 구성해 사용자 이탈을 최소화하는 데 집중할 예정이다.