프론트엔드 개발을 하다 보면 로그인 구현과 관련된 개념이 복잡하게 느껴진다. 이번 글에서는 프론트엔드 관점에서 필요한 로그인 관련 개념을 정리하고, 실제 SPA에서 어떻게 구현되는지 알아본다.
인증과 인가
프론트엔드 개발자는 인증
과 인가
의 결과를 기반으로 사용자에게 맞춤형 경험을 제공한다.
인증 (Authentication) = 누구인가?
- 사용자가 실제로 본인인지 확인하는 과정이다.
- 이메일 로그인이나 구글, 카카오 같은 소셜 로그인이 이 인증에 해당한다.
- 프론트엔드에서는 이 인증에 성공하면 로그인 상태라는 것을 인지하고, 로그인 버튼을 마이페이지 버튼으로 바꾸는 등 UI 변화를 주게 된다.
인가 (Authorization) = 무엇을 할 수 있는가?
- 인증이 완료된 후, 해당 사용자가 무엇을 할 수 있는지를 결정하는 과정이다.
- 예를 들어, 일반 사용자는 게시글을 읽고 쓸 수 있지만, 관리자는 사용자 정보를 삭제할 수 있는 권한을 가질 수 있다.
- 프론트엔드에서는 인가된 권한에 따라 특정 버튼을 숨기거나, 관리자 페이지로 이동하는 라우팅을 제어하는 기능을 구현한다.
세션과 토큰: 로그인 상태를 유지하는 방법
로그인 상태를 유지하는 방식에는 크게 세션
기반과 토큰
기반이 있다. 프론트엔드 개발에서는 토큰 기반 방식이 더 보편적으로 사용된다.
세션 (Session)
- 서버가 로그인 상태를 메모리나 DB에 저장하고, 클라이언트에는 세션 ID가 담긴 쿠키를 발급하는 방식이다.
- 클라이언트는 이후 모든 요청에 이 쿠키를 함께 보내고, 서버는 쿠키의 세션 ID를 확인하고 사용자의 로그인 상태를 검증한다.
- 하지만 세션은 서버의 상태를 유지해야 하기 때문에, 서버를 여러 대 사용하는 환경에서는 관리가 복잡해진다.
토큰 (Token)
토큰
은 사용자의 인증 정보를 담고 있는 문자열이다.
- 서버는 사용자를 인증한 후 토큰을 생성하고, 클라이언트에 보낸다.
- 이때, 더 이상 사용자 상태를 서버에 저장하지 않는다.
- 클라이언트는 토큰을 로컬에 저장해두었다가, 요청할 때 토큰을 함께 보내면 서버는 토큰 자체의 유효성만 검사해서 로그인 상태를 확인한다.
토큰 기반 로그인 더 자세히 알기: Access Token과 Refresh Token
토큰 기반 로그인에서는 주로 두 가지 토큰이 사용된다
Access Token
- 실제로 인증 및 인가 권한을 부여하는 토큰이다.
- 만료 시간이 짧아서 보안에 강하다.
- 클라이언트는 이 토큰을 매 요청마다 헤더에 포함해서 서버로 보낸다.
- 만료 시간이 지나면 사용자가 다시 로그인해야 하는 불편함이 있다.
Refresh Token
- 액세스 토큰을 재발급받기 위한 토큰이다.
- 긴 만료 시간을 가진다.
- 액세스 토큰이 만료되면, 프론트엔드는 저장된 리프레시 토큰을 서버로 보내 새로운 액세스 토큰을 요청한다.
- 로그아웃 없이도 계속해서 서비스를 이용할 수 있는 편리함이 있다.
프론트엔드에서 토큰을 어디에 저장할까?
토큰은 사용자의 정보가 담겨 있으므로 안전하게 저장해야 한다. 이 때, 크게 세 가지 저장소가 사용된다.
보안과 편의성을 모두 고려할 때, 액세스 토큰과 리프레시 토큰을 모두 HttpOnly 쿠키에 저장하는 방식이 가장 안전하다고 알려져 있다.
쿠키 (Cookie)
- 서버에서 설정한 HttpOnly 옵션을 통해 자바스크립트의 접근을 막을 수 있어 XSS(Cross-Site Scripting) 공격으로부터 안전하다.
로컬 스토리지 (Local)
- 만료 기한이 없어서 사용자가 직접 지우지 않는 한 계속 유지된다.
- XSS 공격에 매우 취약하다. 자바스크립트 코드로 쉽게 접근하고 수정할 수 있기 때문에, 토큰 탈취 위험이 크다.
세션 스토리지 (Session)
- 브라우저 세션(탭)이 닫히면 데이터가 자동으로 삭제된다.
- 로컬 스토리지와 마찬가지로 XSS 공격에 취약하다.