요즘 많은 웹 애플리케이션에서는 JWT(JSON Web Token)를 사용하여 인증과 권한 부여를 처리하는 것이 일반적입니다. 특히, 쿠키와 세션을 사용하는 전통적인 방식에서 JWT 기반 인증으로 많이 전환하는 추세입니다. 이 방식은 특히 API 기반 애플리케이션(RESTful API, SPA, 모바일 앱)에서 많이 사용됩니다.
JWT(JSON Web Token)란?
JWT는 클라이언트와 서버 간에 JSON 형식의 데이터를 토큰 형태로 주고받는 방법입니다. JWT는 토큰 기반 인증 방식으로, 사용자 인증 후 서버가 세션을 관리하지 않고, 클라이언트에 토큰을 발급하여 이후 요청을 처리하는 방식입니다.
JWT는 세 가지 부분으로 구성된 문자열로, 각 부분은 Base64로 인코딩되어 있습니다.
- Header: 토큰의 타입과 해싱 알고리즘을 포함합니다.
- Payload: 토큰의 본문으로, 사용자 정보나 권한과 같은 데이터를 포함합니다.
- Signature: 토큰의 무결성을 보장하는 서명으로, 헤더와 페이로드를 해싱한 값입니다.
예시:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
JWT와 세션/쿠키 방식의 차이
- 상태 저장 방식(Stateful) vs 상태 비저장 방식(Stateless):
- 세션 방식은 상태 저장 방식으로, 서버가 사용자의 상태(세션 정보)를 관리합니다. 세션 ID를 쿠키에 저장하고, 서버는 이 세션 ID를 통해 사용자의 상태를 유지합니다.
- JWT는 상태 비저장 방식입니다. 서버는 사용자의 상태를 저장하지 않으며, 모든 인증 정보가 JWT에 포함되어 클라이언트와 함께 전송됩니다. 서버는 토큰만 검증하면 되므로, 서버 측에서 세션을 유지할 필요가 없습니다.
- 서버 부담:
- 세션 기반: 각 사용자의 세션 정보를 서버에 저장해야 하므로, 사용자가 많아질수록 서버의 메모리나 데이터베이스에 부담이 될 수 있습니다.
- JWT 기반: 서버에 세션을 저장하지 않기 때문에, 서버는 무상태(Stateless)로 동작하며, 확장성과 성능 측면에서 더 유리합니다.
- 토큰 전달:
- 세션 기반: 세션 ID는 주로 쿠키를 통해 클라이언트와 서버 간에 전송됩니다.
- JWT 기반: JWT는 HTTP 헤더(주로 Authorization 헤더)를 통해 전송됩니다. 브라우저, 모바일 앱, API 클라이언트 등 다양한 환경에서 사용하기 유리합니다.
- 확장성:
- 세션 기반: 사용자가 늘어나면 세션을 저장하고 관리해야 하므로 서버의 확장성이 제한될 수 있습니다.
- JWT 기반: 서버는 상태를 관리하지 않기 때문에, 서버 간 상태 공유가 필요 없으며, 마이크로서비스 아키텍처나 로드 밸런싱 환경에서 유리합니다.
JWT의 동작 원리
- 로그인: 사용자가 아이디와 비밀번호를 입력하여 서버에 로그인 요청을 보냅니다.
- 서버에서 토큰 발급: 서버는 사용자가 인증되면, 사용자 정보를 담은 JWT를 생성하여 클라이언트에 반환합니다.
- 클라이언트는 토큰 저장: 클라이언트는 JWT를 브라우저의 로컬 스토리지, 세션 스토리지, 또는 쿠키에 저장할 수 있습니다.
- 인증된 요청: 클라이언트는 이후 요청을 보낼 때 JWT를 HTTP 헤더(Authorization: Bearer )에 포함하여 서버에 전송합니다.
- 서버에서 JWT 검증: 서버는 JWT의 서명을 확인하여, 토큰이 유효한지, 위변조되지 않았는지 확인한 후 요청을 처리합니다.
JWT의 장점
- 상태 비저장(Stateless):
- JWT는 서버가 사용자의 상태를 저장하지 않기 때문에 확장성이 뛰어납니다. 서버는 클라이언트로부터 받은 JWT만 검증하면 되므로, 로드 밸런싱이나 마이크로서비스 아키텍처에서 특히 유리합니다.
- 유연성:
- JWT는 JSON 형식의 데이터를 담을 수 있어, 사용자 정보뿐만 아니라 권한(Role), 만료 시간(Expiration) 등의 정보를 함께 담을 수 있습니다.
- 보안성:
- JWT는 서명(Signature)을 포함하여 위변조를 방지할 수 있습니다. 서버는 서명을 검증하여 토큰이 변경되지 않았음을 확인할 수 있습니다.
- HTTPS와 함께 사용하면 JWT의 안전성이 더욱 강화됩니다.
- 다양한 환경에서 사용 가능:
- JWT는 API 기반 애플리케이션, 모바일 앱, SPA(Single Page Application) 등 다양한 환경에서 사용할 수 있으며, 클라이언트 측에서 상태를 유지하기에 유리합니다.
JWT의 단점
- 만료된 토큰 처리:
- JWT는 상태 비저장 방식이므로, 서버에서 토큰을 즉시 무효화하는 것이 어렵습니다. 예를 들어, 사용자가 로그아웃했거나 권한이 변경되었을 때, 서버는 해당 토큰을 즉시 무효화할 수 없습니다. 따라서 일반적으로 짧은 유효 기간을 설정하고, 리프레시 토큰(Refresh Token)을 사용해 이 문제를 해결합니다.
- 토큰 크기:
- JWT는 사용자의 정보를 포함하므로 토큰의 크기가 클 수 있습니다. 세션 ID에 비해 상대적으로 크기 때문에, 네트워크 대역폭에 영향을 미칠 수 있습니다.
- 보안 관리:
- 클라이언트 측에 토큰을 저장하므로, 보안적으로 매우 신경을 써야 합니다. JWT는 브라우저의 로컬 스토리지에 저장될 경우, XSS(Cross-Site Scripting) 공격에 취약할 수 있습니다. 이런 경우 쿠키의 HttpOnly 속성을 사용하는 것이 더 안전할 수 있습니다.
JWT 사용 예시
스프링 보안(Spring Security)과 JWT를 함께 사용한 예시입니다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // CSRF 비활성화
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager())) // JWT 인증 필터 추가
.addFilter(new JWTAuthorizationFilter(authenticationManager())); // JWT 인가 필터 추가
}
}
JWT의 동작 흐름
- 사용자가 로그인 요청: 클라이언트가 서버에 로그인 요청을 보냅니다.
- JWT 발급: 서버가 인증을 확인한 후 사용자에게 JWT 토큰을 발급합니다.
- 클라이언트가 토큰 저장: 클라이언트는 JWT를 로컬 스토리지나 쿠키에 저장합니다.
- 인증된 요청: 클라이언트는 이후 요청 시 JWT를 Authorization 헤더에 포함시켜 서버로 전송합니다.
- 서버가 토큰 검증: 서버는 받은 JWT의 서명을 검증하고, 사용자 요청을 처리합니다.
요약
- JWT(JSON Web Token)는 쿠키나 세션 대신 상태 비저장(Stateless) 방식으로 사용자 인증을 처리하는 방법으로, 특히 API 기반 애플리케이션에서 많이 사용됩니다.
- JWT는 서버가 클라이언트 상태를 저장할 필요가 없으며, 확장성과 유연성이 뛰어납니다.
- 세션/쿠키 방식은 서버에서 상태를 저장하는 방식(상태 저장)이고, JWT 방식은 클라이언트가 토큰을 저장하여 서버와 통신하는 방식(상태 비저장)입니다.
- JWT는 보안 관리에 신경 써야 하며, HTTPS와 함께 사용하고, 토큰의 만료 시간과 저장 위치에 대한 신중한 선택이 필요합니다.
최근에는 마이크로서비스 아키텍처나 **
API 중심의 애플리케이션**에서 JWT가 많이 사용되고 있으며, 세션과 쿠키에 비해 확장성과 유연성이 더 좋다는 점에서 인기를 얻고 있습니다.
'Network Study' 카테고리의 다른 글
마샬링(Marshalling)과 시리얼라이제이션(Serialization) (1) | 2024.10.14 |
---|---|
TCP (HTTP/1.1, HTTP/2, Head-of-Line Blocking, 파이프라이닝 vs 멀티플렉싱) (1) | 2024.10.10 |
로그인(Authentication) - 쿠키(Cookie), 세션(Session) (0) | 2024.10.10 |
세션 어트리부트 - 서블릿 컨테이너에서 세션 관리, HTTP는 무상태 프로토콜 (0) | 2024.10.10 |
RESTful API (OPEN API) (0) | 2024.10.08 |