You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
쿠키를 발급하는 로직을 RoomMemberCookieEncryptor와 같은 필드로 컨트롤러에 가지고 있고, 쿠키를 설정하고 지우는 작업을 컨트롤러가 가지고 있는 것은 책임 분리 측면에서 부적절하다고 판단하였다. 이에 따라, 쿠키 설정 및 삭제 로직을 컨트롤러에서 분리하여 관리할 필요성을 느끼게 되었다.
TODO ✅
ArgumentResolver를 활용한 memberId 캐스팅 구현
AOP를 활용한 쿠키 발급 구현
해당 기능들에 대한 테스트 구현
기존 레거시 코드 삭제
API 문서 테스트 수정
Reference 🔎
배경
방 참여 및 방 생성 작업 시 쿠키를 발급하여 유저 정보를 세션 관리하고 있었다.
(방 참여 API에서 쿠키를 저장하는 로직을 호출한다.)
하지만, 쿠키를 발급하는 로직을 RoomMemberCookieEncryptor와 같은 필드로 컨트롤러에 가지고 있고, 쿠키를 설정하고 지우는 작업을 컨트롤러가 가지고 있는 것은 책임 분리 측면에서 부적절하다고 판단하였다. 이에 따라, 쿠키 설정 및 삭제 로직을 컨트롤러에서 분리하여 관리할 필요성을 느끼게 되었다.
(RoomController에서 쿠키를 설정하고 삭제하는 로직이 구현되어 있다)
이를 해결하기 위해 다음 세 가지 방안을 고려하였다.
대안
1. Filter
필터는 J2EE 표준 스펙으로, 디스패처 서블릿에 전달되기 전후에 URL 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공하였다.
필터를 사용하면, 컨트롤러로 요청이 전달되기 이전에 HTTP 요청에서 쿠키를 확인하거나 요청 처리 이후에 쿠키를 발급하는 로직을 구현할 수 있었다.
[필터를 활용하면 스프링 예외 처리를 사용할 수 없다.]
필터 내에서 발생하는 예외는 스프링의 ControllerAdvice나 ExceptionHandler를 통해 처리할 수 없었다. 이는 예외가 서블릿에게 전달되기 전에 발생하기 때문이었다. [참고](https://mangkyu.tistory.com/204)
❓
필터를 사용하면 빈을 사용하지 못하는거 아니야?
필터는 스프링 이전의 서블릿 영역에서 관리된다. 따라서 스프링에서 관리하는 빈을 사용하지 못할 것이라고 생각할 수 있다. 예전에는 그랬었다. 하지만 현재 스브링 빈으로 등록이 가능하며, 다른 곳에서 주입되거나 다른 빈을 주입받을 수 있다.
인터셉터
인터셉터는 Spring이 제공하는 기술로, 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다. 즉, 스프링 컨텍스트 내에서 동작한다.
[스프링 예외 처리를 사용할 수 있다.]
스프링 컨텍스트에서 동작하기 때문에 ControllerAdvice나 ExceptionHandler와 같은 스프링 예외 처리를 활용할 수 있다.
[인터셉터를 활용하면 요청 / 응답 객체를 교체할 수 없다.]
인터셉터는 필터와 다르게 인터셉터 목록을 가지고 있고, for문을 순차적으로 돌면서 실행시킨다. 인터셉터가 하나씩 실행되고 true를 반환해야 다음 인터셉터가 실행된다. 만약 중간에 하나의 인터셉터라고 false를 반환하게 되면 요청이 중단된다.
즉, 인터셉터는 요청과 응답 객체를 완전히 교체할 수 없으며, 단순히 참조하거나 조작할 수 있다.
publicclassMyInterceptorimplementsHandlerInterceptor {
defaultbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler) {
// Request/Response를 교체할 수 없고 boolean 값만 반환할 수 있다.returntrue;
}
}
Description 💭
쿠키를 발급하는 로직을 RoomMemberCookieEncryptor와 같은 필드로 컨트롤러에 가지고 있고, 쿠키를 설정하고 지우는 작업을 컨트롤러가 가지고 있는 것은 책임 분리 측면에서 부적절하다고 판단하였다. 이에 따라, 쿠키 설정 및 삭제 로직을 컨트롤러에서 분리하여 관리할 필요성을 느끼게 되었다.
TODO ✅
Reference 🔎
배경
방 참여
및방 생성
작업 시 쿠키를 발급하여 유저 정보를 세션 관리하고 있었다.(방 참여 API에서 쿠키를 저장하는 로직을 호출한다.)
하지만, 쿠키를 발급하는 로직을
RoomMemberCookieEncryptor
와 같은 필드로 컨트롤러에 가지고 있고, 쿠키를 설정하고 지우는 작업을 컨트롤러가 가지고 있는 것은 책임 분리 측면에서 부적절하다고 판단하였다. 이에 따라, 쿠키 설정 및 삭제 로직을 컨트롤러에서 분리하여 관리할 필요성을 느끼게 되었다.(RoomController에서 쿠키를 설정하고 삭제하는 로직이 구현되어 있다)
이를 해결하기 위해 다음 세 가지 방안을 고려하였다.
대안
1. Filter
필터는 J2EE 표준 스펙으로, 디스패처 서블릿에 전달되기 전후에 URL 패턴에 맞는 모든 요청에 대해 부가 작업을 처리할 수 있는 기능을 제공하였다.
필터를 사용하면, 컨트롤러로 요청이 전달되기 이전에 HTTP 요청에서 쿠키를 확인하거나 요청 처리 이후에 쿠키를 발급하는 로직을 구현할 수 있었다.
[필터를 활용하면 스프링 예외 처리를 사용할 수 없다.]
필터 내에서 발생하는 예외는 스프링의 ControllerAdvice나 ExceptionHandler를 통해 처리할 수 없었다. 이는 예외가 서블릿에게 전달되기 전에 발생하기 때문이었다. [참고](https://mangkyu.tistory.com/204)
❓필터를 사용하면 빈을 사용하지 못하는거 아니야?
필터는 스프링 이전의 서블릿 영역에서 관리된다. 따라서 스프링에서 관리하는 빈을 사용하지 못할 것이라고 생각할 수 있다. 예전에는 그랬었다. 하지만 현재 스브링 빈으로 등록이 가능하며, 다른 곳에서 주입되거나 다른 빈을 주입받을 수 있다.
인터셉터
인터셉터는 Spring이 제공하는 기술로, 디스패처 서블릿이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다. 즉, 스프링 컨텍스트 내에서 동작한다.
[스프링 예외 처리를 사용할 수 있다.]
스프링 컨텍스트에서 동작하기 때문에 ControllerAdvice나 ExceptionHandler와 같은 스프링 예외 처리를 활용할 수 있다.
[인터셉터를 활용하면 요청 / 응답 객체를 교체할 수 없다.]
인터셉터는 필터와 다르게 인터셉터 목록을 가지고 있고, for문을 순차적으로 돌면서 실행시킨다. 인터셉터가 하나씩 실행되고 true를 반환해야 다음 인터셉터가 실행된다. 만약 중간에 하나의 인터셉터라고 false를 반환하게 되면 요청이 중단된다.
즉, 인터셉터는 요청과 응답 객체를 완전히 교체할 수 없으며, 단순히 참조하거나 조작할 수 있다.
[Path 패턴 단위로만 필터를 설정할 수 있다.]
인터셉터를 등록할 때 적용될 범위를 설정해줄 수 있다. 이때는 Path의 패턴으로만 설정할 수 있다.
즉, 특정 HTTP Method만 인터셉터가 적용되게 하려면 아래와 같이 별도의 방법을 사용해야한다.
인터셉터를 정의하는 객체에서 request 객체에서 method를 추출하여 검증을 해주는 방법을 활용할 수 있다.
하지만 인터셉터의 적용 범위를 설정하는 곳이 두 곳으로 나뉘게 된다.
설정의 범위가 분산되어 있는 것은 유지보수에 좋은 영향을 끼치지 않는다.
AOP
AOP는 관점 지향 프로그래밍 패러다임으로, 여러 모듈에서 공통적으로 사용되는 관점을 분리하는 프로그래밍 패턴이다. Spring AOP는 메서드 호출, 예외 발생 등 특정 이벤트에 대해 공통 기능(로깅, 트랜잭션 처리 등)을 적용할 수 있게 도와준다.
[확장성 및 재사용성]
메서드 호출 전후, 예외 발생 시 등 다양한 시점에 로직을 삽입할 수 있으며, 특정 패턴이나 애노테이션에 따라 공통 로직을 재사용할 수 있다.
[메서드 단위로 설정 범위를 설정할 수 있다.]
인터셉터보다 더 세부적인 범위를 설정할 수 있다.
예) GET 요청에만 인터셉터 적용
[코드의 복잡성이 올라간다]
커스텀 애노테이션 추가 및 AOP 설정이 필요하여 코드의 복잡성이 증가할 수 있었다.
[성능 오버헤드]
프록시 생성 등으로 인해 약간의 성능 저하가 발생할 수 있다.
결론
필터, 인터셉터, AOP 세 가지 방안을 검토한 결과, AOP를 활용하는 방식이 가장 적합하다고 판단한다. 그 이유는 다음과 같다.
필터는 스프링 예외 처리를 활용하기 어려운 점이 큰 단점으로 작용하며, 인터셉터를 활용하면 관리 영역이 분산된다고 판단했다. 따라서, AOP를 활용하여 쿠키 설정 및 삭제 로직을 분리하는 방안을 채택하기로 결정했다.
참조
[[Spring] 필터(Filter) vs 인터셉터(Interceptor) 차이 및 용도 - (1)](https://mangkyu.tistory.com/173)
[[Java Spring] Filter, Interceptor, AOP의 차이](https://kimdirector1090.tistory.com/129)
The text was updated successfully, but these errors were encountered: