🍪 Spring Boot Controller 단 - 쿠키 처리 정리
Spring MVC Controller 단에서 쿠키를 생성, 조회, 삭제하는 방법을 정리함.
주로 로그인 유지(JWT/세션 토큰 저장) 및 사용자 환경 설정(언어, 테마 등)에 사용됨.
1️⃣ 쿠키란?
- 클라이언트(브라우저)에 작은 데이터 조각을 저장하여 서버 요청 시 함께 전송하는 메커니즘
- 로그인 상태 유지, 사용자 식별, 설정값 저장 등에 사용
- 단, 민감한 정보(비밀번호, 개인정보) 는 절대 저장하지 않음 (토큰 등만 저장)
2️⃣ 쿠키 생성 및 내려주기
(1) javax.servlet.http.Cookie 사용 예시
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest req, HttpServletResponse res) {
String jwt = tokenService.createToken(req.getEmail());
Cookie cookie = new Cookie("AUTH", jwt);
cookie.setHttpOnly(true);
cookie.setSecure(true);
cookie.setPath("/");
cookie.setMaxAge(60 * 60 * 24);
res.addCookie(cookie);
return ResponseEntity.ok("[로그인 성공] 쿠키 저장 완료");
}
(2) ResponseCookie (Spring Web) 사용 — 추천 방식
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest req) {
String jwt = tokenService.createToken(req.getEmail());
ResponseCookie cookie = ResponseCookie.from("AUTH", jwt)
.httpOnly(true)
.secure(true)
.sameSite("Lax")
.path("/")
.maxAge(Duration.ofDays(1))
.build();
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, cookie.toString())
.body("[로그인 성공] ResponseCookie 방식으로 쿠키 저장");
}
SameSite 옵션 요약
| 옵션 | 설명 |
|---|
Strict | 다른 사이트 요청 시 절대 쿠키 전송 안함 (CSRF 방지 강력) |
Lax | 대부분의 안전한 GET 요청에 한해 쿠키 전송 (기본 권장) |
None | 크로스 도메인 허용 (Secure=true 필수) — SPA 환경에서 사용 |
3️⃣ 쿠키 읽기
(1) @CookieValue 어노테이션 사용
@GetMapping("/me")
public ResponseEntity<?> me(@CookieValue(name = "AUTH", required = false) String token) {
if (token == null) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("로그인 필요");
return ResponseEntity.ok("[인증 성공] Token: " + token);
}
(2) HttpServletRequest 로 쿠키 직접 파싱
@GetMapping("/me2")
public ResponseEntity<?> me2(HttpServletRequest req) {
Cookie[] cookies = req.getCookies();
if (cookies == null) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("쿠키 없음");
String token = Arrays.stream(cookies)
.filter(c -> "AUTH".equals(c.getName()))
.map(Cookie::getValue)
.findFirst()
.orElse(null);
if (token == null) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("인증 실패");
return ResponseEntity.ok("[인증 성공] Token: " + token);
}
4️⃣ 쿠키 삭제 (무효화)
@PostMapping("/logout")
public ResponseEntity<?> logout() {
ResponseCookie expired = ResponseCookie.from("AUTH", "")
.httpOnly(true)
.secure(true)
.sameSite("Lax")
.path("/")
.maxAge(0)
.build();
return ResponseEntity.ok()
.header(HttpHeaders.SET_COOKIE, expired.toString())
.body("[로그아웃 완료] 쿠키 삭제됨");
}
⚠️ 삭제 시 반드시 같은 이름·Path·SameSite 속성을 지정해야 정확히 덮어쓰기 됨.
5️⃣ 쿠키 관련 보안 체크리스트
| 옵션 | 설명 |
|---|
HttpOnly | 자바스크립트 접근 차단 (XSS 방지) |
Secure | HTTPS 환경에서만 전송 |
SameSite | 외부 사이트 요청 시 쿠키 전송 여부 제어 |
Max-Age / Expires | 쿠키의 만료시간 설정 |
| 평문 저장 금지 | 비밀번호나 개인정보는 절대 저장하지 않음 |
| 암호화 | JWT 또는 세션ID 등 식별 토큰만 저장 |
6️⃣ 실무 팁
- JWT + 쿠키 조합 시:
HttpOnly + Secure + SameSite=Lax 권장
- SPA 프런트(React/Vue 등)와 연동 시 CORS와 CSRF 정책을 반드시 함께 고려
- 세션 쿠키는
Max-Age 없이 설정 (브라우저 종료 시 자동 삭제)
- SameSite=None 사용 시 반드시 HTTPS(
secure=true)로 설정
✅ 핵심 요약
| 항목 | 내용 |
|---|
| 쿠키 생성 | Cookie 또는 ResponseCookie 사용 |
| 보안 설정 | HttpOnly / Secure / SameSite 설정 필수 |
| 조회 방식 | @CookieValue, HttpServletRequest.getCookies() |
| 삭제 방식 | 동일한 Path와 이름으로 MaxAge=0 쿠키 반환 |
| 주의점 | 평문 데이터 저장 금지, HTTPS 환경 필수 |