web.xml는 서블릿 컨테이너에 대한 전반적인 설정을 담당한다.
1. DispatcherServlet 정의
2. URL 패턴과 DispatcherServlet 매핑
3. Spring 설정 파일 위치 지정
4. ContextLoaderListener 등록 (필요한 경우)
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
dispatcher-servlet.xml은 Spring MVC의 구체적인 설정을 담당한다.
1. 컴포넌트 스캔 범위 지정
2. MVC 관련 어노테이션 활성화
3. ViewResolver 설정
4. 정적 리소스 처리 방법 정의
5. 기타 MVC 관련 설정 (인터셉터, 메시지 소스 등)
<context:component-scan base-package="com.myapp"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/"/>
DispatcherServlet
긍께..
- 모든 요청이 앞단의 DispatcherServlet으로 들어옴.
(web.xml에서 <url-pattern>을 "/"로 설정했기 때문에 모든 요청이 DispatcherServlet으로 전달됨)
- DispatcherServlet은 HandlerMapping을 사용하여 요청 url에 맞는 Controller(핸들러)를 찾음
주로 @RequestMapping 기반으로 매핑 이루어짐
- 매핑된 Controller의 메서드가 실행 --> Service 호출 --> repository 호출..
- Controller는 비즈니스 로직 실행 결과를 Model 객체에 담고,
적절한 뷰 이름을 반환함.
- DispatcherServlet은 ViewResolver를 사용해 Controller가 반환한 뷰 이름에 해당하는 실제 View(예 : .jsp)를 찾음
View(.jsp)는 Model 데이터를 사용해 렌더링됨.
- 렌더링된 최종 응답은 DispatcherServlet을 통해 클라이언트로 전달되고
클라이언트(브라우저)는 해당 응답을 화면에 뿌림
인터셉터
인터셉터는 DispatcherServlet과 Controller 사이에서 동작하는 컴포넌트임
여러 개 등록할 수 있으며, 순서대로 실행됨.
주로
- PreHandler(컨트롤러 실행 전 호출),
- PostHandler(컨트롤러 실행 후, 뷰 렌더링 전 호출 (=응답 생성 전)),
- afterCompletion(뷰 렌더링 완료 후 호출 (=응답 전송 후))
등 메서드를 구현하여 사용한다.
로깅(요청/응답 정보 기록), 인증 및 권한 검사(사용자 권한 확인), 공통 데이터 설정(여러 컨트롤러에서 공통으로 사용할 데이터 준비), 성능 측정(API 호출 시간 측정), 언어 설정 처리.. 등을 용도로 주로 사용된다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/admin/**");
}
}
특정 URL 패턴에 대해서만 동작하도록 설정할 수 있다.
public class ApiInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// API 요청 전 처리 (예: 인증 토큰 검증)
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
// API 응답 생성 전 처리 (예: 응답 헤더 추가)
// modelAndView는 null일 가능성이 높음 (RESTful API에서는 거의 사용하지 않음)
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
// API 응답 완료 후 처리 (예: 로깅, 리소스 정리)
}
}
※ 인터셉터는 웹 계층, 특히 컨트롤러 수준에서 작동하도록 설계되어 있어
서비스 계층의 메소드 실행을 직접 가로채거나 그 전후에 로직을 삽입하는 것은 불가능하다.
반면에 AOP는 애플리케이션의 어느 계층에서든 사용할 수 있으므로,
서비스 계층의 메소드 실행을 가로채고 그 전후에 로직을 삽입하는 데 적합하다.
예를 들어, 서비스 계층의 모든 메소드에 대해 로깅을 하고 싶다면 AOP를 사용하여 다음과 같이 구현하면 된다....
@Aspect
@Component
public class ServiceLoggingAspect {
private static final Logger logger = LoggerFactory.getLogger(ServiceLoggingAspect.class);
@Around("execution(* com.yourcompany.*.service.*.*(..))")
public Object logServiceMethod(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
logger.info("Starting execution of service method: {}", methodName);
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
logger.info("Service method: {} executed in {} ms", methodName, executionTime);
return result;
}
}
// AOP 설정은 com.yourcompany.*.service 패키지 내의 모든 클래스의 모든 메소드에 대해 로깅을 수행.
// 메소드 실행 전후에 로그를 남기고 실행 시간도 측정
따라서 서비스 계층에서 인터셉터와 같은 기능(로깅, 성능 측정 등)을 구현하고 싶을 때는 AOP를 사용하는 것이 맞다.
AOP는 인터셉터보다 더 넓은 범위에서, 더 세밀한 제어를 가능하게 해준다.....고 한다....
∴ HTTP 요청 처리 과정에서 controller 계층의 전/후 등 특정 지점에 끼어들어 추가적인 처리를 수행하는 !!!
놈이 바로 인터샙터 라고 할 수 있다~~~
'Spring' 카테고리의 다른 글
ServletResponse.isComitted(), FilterChain (with GPT) (2) | 2024.12.19 |
---|---|
(지피티 선생님의) 람다와 일급 객체, FP 특강 (0) | 2024.12.12 |
WebFlux 첨들어봄 (1) | 2024.12.10 |
Spirng AOP (3) | 2024.09.03 |
ModelAndView vs @ResponseBody (0) | 2024.09.02 |