목적 : WebSocket 연결을 최초로 맺는 과정. 일반적인 HTTP/HTTPS 프로토콜을 사용.
헤더 : Authorization, Cookie 등 표준 HTTP 헤더
인터셉터 : 주된 역할은 HTTP 헤더에 담긴 토큰(예:JWT)을 검증하여 사용자를 인증하고, 인증된 사용자 정보(Principal)를 WebSocket 세션 속성(attributes)에 저장. 해당 과정은 연결을 맺을 때 단 한번만 일어남.
목적 : WebSocket 연결이 이뤄지면, 통로(Channel)을 통해 STOMP 프로토콜에 맞는 메세지(프레임)을 주고 받음.
헤더 : STOMP 헤더. 클라이언트가 stompClient.connect(stompHeaders, ...) 나 stompClient.subscribe(..., stompHeaders) 호출시 넘겨주는 값들.
인터셉터 : ChannelInter 가 메시지를 가로채고, StompHeaderAccessor 를 통해 STOMP 메시지에 담긴 헤더를 읽거나 수정할 수 있다.
사용 이유: 핸드세이크 이후에 STOMP 메시지 헤더의 정보를 사용하고 싶다면, ChannelInterceptor 의 preSend 메소드 내에서 StompHeaderAccessor 를 사용하여 명시적으로 STOMP 헤더 값을 읽고 처리하는 로직을 구현하고자 할 때, 예를 들어 SUBSCRIBE 요청 시 특정 권한이 있는지 STOMP 헤더를 통해 추가로 검사하는 등의 로직을 구현할 수 있다.
(어디에선가 "STOMP의 헤더정보는 WebSocket의 캐싱된 HTTP 헤더를 재사용한다"는 글을 본 거 같아서 확인해 봤다.)
1. 최초 인증 : HandshakeInterceptor 가 HTTP 헤더의 토큰으로 사용자를 인증하고, 그 결과(UserPrincipal)를 WebSocket 세션에 저장.
2. 인증 정보 재사용 : 이 후 ChannelInterceptor에서는 STOMP 메시지를 처리할 때, STOMP헤더에 새로운 토큰이 있는지 확인하기 보다는 이미 WebSocket 세션에 저장된 사용자 인증 정보를 우선적으로 신뢰하는 경우가 많음.
3. 오해 : ChannelInterceptor 가 STOMP 헤더에 담긴 새로운 토큰을 보지 않고 세션에 저장된 초기 인증 정보를 계속 사용하기 때문에, 마치 핸드세이크의 정보가 "캐싱"되어 이후의 헤더 변경을 무시하는 것처럼 보인다.
=> 핸드세이크 단계에서 완료된 "인증결과"가 WebSocket 세션동안 유지되고 재사용된다.