[Spring] @SessionAttribute는 왜 세션을 직접 만들지 못할까?

joyful·2026년 1월 27일

Java/Spring

목록 보기
33/47

스프링 MVC 강의를 듣던 중 @SessionAttribute에 대해 알게 됐다. 김영한 강사님은 이 기능을 소개하며 한 가지 특징을 명확히 짚어주셨다. "이 어노테이션은 세션을 새로 생성하지 않는다."

단순히 편의성만 생각했다면 생성 기능까지 있어도 좋았을 텐데, 왜 스프링은 이 기능을 굳이 빼놓았을까? 강의를 들으며 바로 꽂혔던 이 '제약 사항' 뒤에 숨겨진 이유와 설계 의도를 정리해 보려 한다.


1. 기술적 팩트: 세션 생성 불가능

@SessionAttribute는 세션이 존재하지 않으면 null을 반환하거나 예외를 던질 뿐, 결코 세션을 새로 생성하지 않는다.

보통 request.getSession()은 세션이 없으면 새로 만들어주는 옵션(true)이 기본이지만, @SessionAttribute는 내부적으로 request.getSession(false)를 고집한다. 즉, 이 어노테이션을 사용하는 순간 스프링은 "이미 있는 세션에서 가져오되, 없으면 새로 만들지 마"라는 스탠스를 취한다.


2. 왜 생성을 못 하게 막아뒀을까?

처음엔 "생성 기능까지 있으면 더 편하지 않나?"라는 생각이 들 수도 있지만, 조금 더 고민해보니 이건 스프링의 철저한 리소스 관리 전략이었다.

  • 불필요한 세션 생성 방지: 로그인이 필요 없는 단순 조회 페이지인데, 실수로 세션 관련 파라미터를 넣었다고 해서 서버 메모리에 세션이 훅 생성되어 버리면 리소스 낭비가 심각해진다.
  • 권한과 책임의 분리: 세션을 생성하고 관리(로그인/로그아웃)하는 것은 시스템에서 매우 무거운 책임이다. 이런 권한을 단순히 파라미터를 주입받는 어노테이션에게까지 주지 않겠다는 의도로 읽힌다.

3. '생성 불가능'이 만든 '조회 전용'이라는 성격

세션을 직접 만들지 못한다는 기술적 제약은 자연스럽게 이 어노테이션을 '조회 전용(Read-Only)' 도구로 정의한다.

이미 생성된 데이터에 접근할 때만 사용 가능하기 때문에, 우리는 이 어노테이션을 보는 것만으로도 "이 메서드는 세션 상태를 변경하지 않고 정보만 참고하겠구나"라는 확신을 가질 수 있다. 기술적 제약이 오히려 코드의 의도를 명확하게 만들어주는 셈이다.

결국 수정이나 삭제 같은 강력한 권한은 HttpSession을 직접 다룰 때만 명시적으로 허용함으로써, 개발자의 실수로 세션 상태가 꼬이는 것을 방지한다.


4. 동작의 비밀: SessionAttributeMethodArgumentResolver

스프링이 파라미터 한 줄로 이 모든 걸 처리해주는 비결은 ArgumentResolver에 있다.

내부를 들여다보면 SessionAttributeMethodArguementResolver가 우리가 수동으로 하던 getAttribute()null 체크, 그리고 타입 캐스팅까지 대신 수행한다. 우리가 반복 작업을 줄이기 위해 커스텀 어노테이션을 만들어 쓰듯, 스프링도 이 리졸버를 통해 "안전하게 세션 값만 꺼내오는 로직"을 표준화해서 제공하고 있다.


💡 마치며

강의에서 배운 "세션을 생성하지 않는다"는 짧은 한 문장이 사실은 가독성 그 이상의 안전최적화를 담고 있다는 걸 알 수 있었다.

  1. 리소스 최적화: 불필요한 세션 생성 방지
  2. 안전성: 조회 전용 접근으로 사이드 이펙트 차단
  3. 추상화: 기술적 상세를 숨기고 도메인 데이터에 집중

직접 어노테이션을 만들어 쓸 때도 마찬가지인 것 같다. 기능을 무조건 꽉꽉 채워 넣는 것보다, 때로는 정확한 제약을 걸어주는 것이 나중에 더 읽기 좋고 안전한 코드를 만드는 길이라는 것을 배웠다.

profile
기쁘게 코딩하고 싶은 백엔드 개발자

0개의 댓글