https://jakarta.ee/specifications/servlet/5.0/apidocs/jakarta/servlet/http/httpsession
1. 세션(Session) 개념
- 세션(Session)은 서버 측에서 사용자 정보를 유지하는 방법입니다.
- 클라이언트가 서버와 상호작용하는 동안(특히 로그인 상태) 서버는 세션을 사용하여 사용자를 식별하고 데이터를 유지합니다.
- 클라이언트는 세션 ID를 통해 서버와 연결됩니다.
2. 세션의 특징
| 특징 | 설명 |
|---|
| 저장 위치 | 서버 메모리 또는 외부 저장소(Redis, DB 등). |
| 데이터 수명 | 세션 타임아웃(일정 시간 동안 활동이 없으면 만료). |
| 식별 방식 | 클라이언트는 세션 ID를 쿠키 또는 URL 파라미터를 통해 서버에 전달. |
| 보안 | 세션 데이터는 서버에서 관리되므로 클라이언트는 데이터에 직접 접근할 수 없음. |
| 사용 사례 | 로그인 상태 유지, 장바구니, 폼 데이터 유지 등. |
3. 세션 동작 원리
3.1 데이터 흐름
- 클라이언트가 서버에 요청.
- 서버가 세션 생성:
- 고유한 세션 ID를 생성하여 클라이언트에 반환.
- 세션 데이터를 서버 메모리나 외부 저장소에 저장.
- 클라이언트가 세션 ID 전송:
- 쿠키 또는 URL 파라미터에 세션 ID를 포함하여 요청.
- 서버가 세션 확인:
- 세션 ID를 바탕으로 클라이언트를 식별하고 데이터를 처리.
sequenceDiagram
participant Client as 클라이언트 (브라우저)
participant Server as 서버
Client->>Server: HTTP 요청 (로그인)
Server-->>Client: HTTP 응답 + 세션 ID 발급 (JSESSIONID=abc123)
Client->>Server: HTTP 요청 + JSESSIONID=abc123
Server-->>Client: 사용자 상태 확인 및 응답
4. Spring MVC에서 세션 사용
4.1 세션 생성 및 설정
세션에 데이터 저장
@GetMapping("/set-session")
public ResponseEntity<String> setSession(HttpSession session) {
session.setAttribute("user", "홍길동");
session.setAttribute("role", "admin");
return ResponseEntity.ok("Session data set!");
}
HttpSession 객체를 통해 세션 데이터를 설정.
setAttribute(String key, Object value)로 데이터 저장.
세션 데이터 읽기
@GetMapping("/get-session")
public ResponseEntity<String> getSession(HttpSession session) {
String user = (String) session.getAttribute("user");
String role = (String) session.getAttribute("role");
if (user == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("No active session found.");
}
return ResponseEntity.ok("User: " + user + ", Role: " + role);
}
getAttribute(String key)로 세션 데이터 읽기.
- 세션 데이터가 없으면
null 반환.
세션 무효화 (로그아웃)
@PostMapping("/invalidate-session")
public ResponseEntity<String> invalidateSession(HttpSession session) {
session.invalidate();
return ResponseEntity.ok("Session invalidated!");
}
invalidate()로 세션 데이터를 삭제하고 세션 자체를 무효화.
4.2 세션의 주요 메서드
| 메서드 | 설명 |
|---|
setAttribute(String, Object) | 세션에 데이터를 저장. |
getAttribute(String) | 세션에서 데이터를 가져옴. |
removeAttribute(String) | 세션에서 특정 데이터를 제거. |
invalidate() | 세션 무효화(모든 데이터 삭제 및 세션 종료). |
getId() | 현재 세션의 고유 ID를 반환. |
getCreationTime() | 세션 생성 시간을 반환. |
getLastAccessedTime() | 마지막으로 세션에 접근한 시간을 반환. |
4.3 세션 타임아웃 설정
Spring Boot 기본 설정
application.properties에서 세션 타임아웃을 설정할 수 있습니다.
server.servlet.session.timeout=30m # 30분
프로그램으로 설정
@Bean
public ServletContextInitializer initializer() {
return servletContext -> {
servletContext.setSessionTimeout(1800);
};
}
5. 세션 관리 전략
5.1 세션 스토리지
- 메모리 기반(Default):
- 서버의 메모리에 세션 데이터를 저장.
- 단점: 서버가 재시작되면 데이터 손실.
- 데이터베이스 기반:
- 외부 DB에 세션 데이터를 저장.
- 서버 재시작 시 데이터 유지 가능.
- Redis 기반:
- Redis와 같은 인메모리 데이터베이스를 사용.
- 고성능, 다중 서버 환경에서 유용.
5.2 세션 고정 공격(Session Fixation) 방지
- 세션 ID 재발급:
- 로그인 성공 시 기존 세션 ID를 무효화하고 새 세션 ID를 발급.
@PostMapping("/login")
public ResponseEntity<String> login(HttpServletRequest request) {
HttpSession oldSession = request.getSession(false);
if (oldSession != null) {
oldSession.invalidate();
}
HttpSession newSession = request.getSession(true);
newSession.setAttribute("user", "홍길동");
return ResponseEntity.ok("Login successful!");
}
6. 세션의 장단점
| 장점 | 단점 |
|---|
| 사용자 상태 정보를 서버에서 관리하므로 보안이 강화됨 | 서버 리소스(메모리, 스토리지) 소모 증가 |
| 클라이언트의 데이터 손상 가능성이 낮음 | 서버가 재시작되면 세션 데이터 손실 가능 |
| 상태 정보가 서버에 집중되어 관리가 용이 | 다중 서버 환경에서 세션 동기화 필요 (예: Redis 사용) |
| 유효 기간을 설정하여 자동 만료 가능 | 세션 고정 공격 방지 필요 |
7. 쿠키와 세션 비교
| 특징 | 쿠키(Cookie) | 세션(Session) |
|---|
| 저장 위치 | 클라이언트(브라우저) | 서버 |
| 보안 | 클라이언트에 저장되므로 데이터 조작 가능 | 서버에서 관리하므로 보안이 강함 |
| 데이터 용량 | 최대 4KB 제한 | 제한 없음 |
| 유효 기간 | 만료 시간 설정 가능 | 서버 타임아웃 설정 가능 |
| 속도 | 빠름 (클라이언트에서 관리) | 요청마다 서버 확인 필요 |
| 사용 사례 | 로그인 유지, 환경 설정 | 사용자 인증, 민감한 데이터 관리 |
8. 보안 강화 전략
- HTTPS 사용:
- 세션 타임아웃 설정:
- 비활동 시간이 일정 시간 초과하면 자동으로 세션 만료.
- 세션 ID 재발급:
- 로그인 또는 중요한 작업 이후 세션 ID를 변경.
- CSRF 방지:
- 서버 간 세션 동기화:
- 다중 서버 환경에서는 Redis 등을 활용해 세션 동기화.