쿠키 로그인은 사용자의 로그인 정보를 클라이언트의 브라우저에 저장하는 방식입니다. 클라이언트가 서버에 요청을 보낼 때마다 저장된 쿠키가 함께 전송됩니다. 이를 통해 사용자의 인증 상태를 유지할 수 있습니다.
특징
구성 요소: 쿠키는 키-값 쌍으로 구성되어 있으며, 사용자 식별 정보를 포함합니다.
저장 위치: 클라이언트 브라우저에 저장됩니다.
보안 문제:
쿠키는 클라이언트 측에 저장되므로 탈취될 위험이 있습니다.
XSS(Cross-Site Scripting) 공격에 취약할 수 있습니다.
민감한 정보를 암호화하지 않으면 정보 유출 가능성이 높습니다.
예시 코드
// 쿠키 생성 및 설정
Cookie cookie = new Cookie("authToken", "userTokenValue");
cookie.setHttpOnly(true); // XSS 방지
cookie.setMaxAge(7 * 24 * 60 * 60); // 7일간 유효
response.addCookie(cookie);
// 쿠키 읽기
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie c : cookies) {
if ("authToken".equals(c.getName())) {
String token = c.getValue();
// 토큰 처리 로직
}
}
}
장점
간단한 구현과 관리.
서버의 메모리나 저장소를 사용하지 않음.
단점
보안에 취약하며, 쿠키 크기 제한(일반적으로 4KB)이 있습니다.
클라이언트 측에서 쿠키 삭제 시 인증 상태가 무효화됩니다.
세션 로그인은 사용자 인증 정보를 서버에 저장하고, 클라이언트는 세션 ID만 쿠키에 저장하여 전송하는 방식입니다. 서버는 클라이언트로부터 받은 세션 ID를 기준으로 인증 상태를 확인합니다.
특징
구성 요소: 세션 ID는 서버에서 생성되며 클라이언트의 요청마다 쿠키를 통해 서버로 전달됩니다.
저장 위치: 서버 메모리나 데이터베이스.
보안:
쿠키에 민감한 정보를 저장하지 않으므로 비교적 안전합니다.
세션 탈취(Session Hijacking) 공격에 주의해야 합니다.
// 세션 생성
HttpSession session = request.getSession();
session.setAttribute("user", "loggedInUser");
// 세션 읽기
String user = (String) session.getAttribute("user");
if (user != null) {
// 인증된 사용자 처리
}
// 세션 무효화
session.invalidate();
장점
민감한 정보를 클라이언트에 저장하지 않아 보안성이 높음.
클라이언트 측에서 쿠키 삭제해도 서버에 세션 정보가 유지됨.
단점
서버 메모리 사용량이 증가합니다.
확장성이 낮아 서버 간 세션 동기화가 필요할 수 있습니다.
Spring Security는 스프링 기반 애플리케이션의 보안을 강화하는 프레임워크입니다. JWT를 사용하면 인증 정보를 토큰 형태로 클라이언트에 저장하고 서버는 이를 검증하여 인증을 처리합니다.
특징
구성 요소:
JWT는 Header, Payload, Signature로 구성됩니다.
클라이언트는 JWT를 HTTP 헤더의 Authorization 필드에 포함하여 요청합니다.
저장 위치: 브라우저의 로컬 스토리지나 세션 스토리지.
보안:
JWT 자체에 인증 정보를 포함하므로, 서버의 저장소를 사용하지 않습니다.
JWT는 서명을 통해 변조를 방지하지만, 탈취 시 악용될 수 있으므로 만료 시간을 설정해야 합니다.
// JWT 생성
String token = Jwts.builder()
.setSubject("userId")
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1시간 유효
.signWith(SignatureAlgorithm.HS256, "secretKey")
.compact();
// JWT 검증
Claims claims = Jwts.parser()
.setSigningKey("secretKey")
.parseClaimsJws(token)
.getBody();
String userId = claims.getSubject();
장점
서버 확장성과 성능이 우수.
상태 비저장(stateless) 방식으로 서버 부하가 적음.
클라이언트에서 인증 상태를 쉽게 확인할 수 있음.
단점
토큰 탈취 시 재발급 전까지 악용 가능.
만료된 토큰을 처리하기 위한 별도 메커니즘이 필요.
토큰 크기가 크면 네트워크 부하가 증가할 수 있음.
| 구분 | 쿠키 로그인 | 세션 로그인 | Spring Security + JWT |
|---|---|---|---|
| 저장 위치 | 클라이언트 브라우저 | 서버 | 클라이언트 로컬/세션 스토리지 |
| 확장성 | 높음 | 낮음 | 매우 높음 |
| 보안 | 낮음 | 비교적 높음 | 중간~높음 |
| 상태 관리 | 클라이언트에서 관리 | 서버에서 관리 | 상태 비저장 |
| 구현 복잡도 | 낮음 | 중간 | 높음 |
💡 그렇다면 어떤 방식을 사용하는 것이 적합할까?
쿠키 로그인이 적합합니다. 구현이 간단하며 서버 자원을 많이 사용하지 않습니다.
세션 로그인이 적합합니다. 보안성이 높고, 서버 측에서 세션 정보를 효율적으로 관리할 수 있습니다.
Spring Security와 JWT를 사용하는 것이 적합합니다. 서버 확장이 용이하며, 클라이언트와 서버 간의 통신 부하를 줄일 수 있습니다.