TIL - 20250904

juni·2025년 9월 4일

TIL

목록 보기
115/316

0904 Full-Stack 인증: JWT 로그인 및 인증 기반 라우팅


✅ 1. 백엔드(BE): JWT 기반의 안전한 인증 시스템 구축

  • 이메일 인증을 마친 사용자의 회원가입을 최종 완료하고, 이후 서비스 접근을 위한 로그인 및 인증 유지 시스템을 구축했습니다.

➕ 주요 개념

  1. 비밀번호 암호화 및 회원가입 완료:

    • 사용자로부터 받은 비밀번호를 절대 평문으로 저장하지 않습니다. Spring Security의 PasswordEncoder (e.g., BCryptPasswordEncoder)를 사용하여 비밀번호를 단방향으로 해시(Hash)한 후, 암호화된 값을 데이터베이스에 저장합니다.
    • 회원가입 완료 API는 이메일 인증을 통과한 사용자인지 확인한 후, 암호화된 비밀번호와 함께 최종 사용자 정보를 DB에 저장합니다.
  2. JWT(JSON Web Token) 기반 로그인:

    • 로그인 API: 사용자가 이메일과 비밀번호를 제출하면, 서버는 DB에 저장된 암호화된 비밀번호와 사용자가 입력한 비밀번호를 PasswordEncodermatches() 메서드를 통해 비교합니다.
    • 토큰 발급: 인증에 성공하면, 서버는 사용자를 식별할 수 있는 정보(e.g., 사용자 ID, 이메일)와 만료 시간을 담은 JWT를 생성하여 클라이언트에게 발급합니다. 이 토큰은 서버가 사용자를 기억하는 "인증서" 역할을 합니다.
  3. 토큰 검증 필터 (JWT Authentication Filter):

    • 로그인이 필요한 모든 API 요청에 대해, 클라이언트는 발급받은 JWT를 HTTP 헤더(Authorization: Bearer ...)에 담아 보냅니다.
    • 서버에서는 커스텀 필터를 Spring Security 설정에 추가하여, API가 실행되기 전에 이 토큰을 먼저 가로채 검증합니다.
    • 토큰이 유효하면, 필터는 토큰에서 사용자 정보를 추출하여 현재 요청의 인증 컨텍스트(Security Context)에 저장합니다. 이를 통해 해당 요청은 "인증된 사용자의 요청"으로 처리됩니다.
  4. 인증 기반 데이터 처리:

    • 이벤트 생성과 같은 API에서, 이제 어떤 사용자가 이벤트를 생성했는지 알아야 합니다.
    • 토큰 검증 필터를 통해 인증 컨텍스트에 저장된 사용자 정보를 컨트롤러에서 주입받아, 이벤트 엔티티와 사용자 엔티티를 연관(Mapping)시켜 저장합니다.

✅ 2. 프론트엔드(FE): 인증 상태에 따른 동적 UI 및 라우트 제어

  • 백엔드에서 구현한 인증 시스템과 연동하여, 사용자의 로그인 상태에 따라 다른 UI를 보여주고 특정 페이지에 대한 접근을 제어하는 로직을 구현했습니다.

➕ 주요 개념

  1. 회원가입 및 로그인 플로우 완성:

    • 이메일 인증 후, 비밀번호 입력 및 유효성 검증(e.g., 최소 길이, 특수문자 포함) 로직을 추가하여 회원가입 버튼을 조건부로 활성화했습니다.
    • 로그인 폼에서 action 함수를 사용하여 서버에 로그인 요청을 보내고, 성공 시 발급받은 JWT를 브라우저의 안전한 저장소(localStorage)에 저장합니다. 실패 시에는 서버로부터 받은 에러 메시지를 사용자에게 피드백합니다.
  2. loader를 활용한 라우트 가드 (Route Guard):

    • 개념: loader는 컴포넌트가 렌더링되기 전에 실행되므로, 이 단계에서 사용자의 인증 상태를 확인하여 특정 라우트에 대한 접근을 제어할 수 있습니다.
    • 구현: 로그인이 필요한 페이지의 loader 함수에서, 브라우저에 저장된 토큰의 유효성을 확인합니다. 토큰이 없거나 유효하지 않으면, redirect() 함수를 반환하여 사용자를 로그인 페이지로 강제 이동시킵니다.
  3. 전역 상태 관리 및 데이터 전파:

    • 루트 loader: 최상위(Root) 라우트의 loader에서 사용자의 로그인 상태(토큰 유무)를 확인하고, 그 결과를 반환합니다.
    • useRouteLoaderData Hook: 자식 컴포넌트들은 useRouteLoaderData Hook을 사용하여 부모(루트) 라우트의 loader가 반환한 데이터를 쉽게 조회할 수 있습니다. 이를 통해 앱 전반에서 "현재 로그인된 상태인가?"를 쉽게 파악하고, 조건부로 UI(e.g., 로그인/로그아웃 버튼)를 렌더링할 수 있습니다.
  4. 로그아웃 처리:

    • 로그아웃 action 함수는 브라우저에 저장된 토큰을 삭제하고, 사용자를 홈이나 로그인 페이지로 redirect 시키는 역할을 합니다.
  5. 인증된 API 요청:

    • 이벤트 생성과 같이 인증이 필요한 API를 호출할 때는, 저장해 둔 JWT를 HTTP 요청 헤더에 포함하여 전송합니다. 이를 통해 서버는 해당 요청이 어떤 사용자의 요청인지 식별할 수 있습니다.

📌 요약

  • 백엔드비밀번호 암호화로 회원가입을 안전하게 마무리하고, 로그인 성공 시 JWT를 발급하며, 들어오는 모든 요청을 토큰 검증 필터를 통해 인증 처리하는 시스템을 구축했습니다.
  • 프론트엔드action 함수를 통해 로그인/로그아웃 로직을 처리하고, 발급받은 JWT를 브라우저에 저장하여 인증 상태를 유지합니다.
  • React Router의 loader라우트 가드로 활용하여, 인증되지 않은 사용자의 페이지 접근을 사전에 차단했습니다.
  • 루트 loaderuseRouteLoaderData Hook을 통해 앱 전반에서 전역적인 인증 상태를 효율적으로 공유하고, 이에 따라 동적인 UI를 제공하는 구조를 완성했습니다.

0개의 댓글