UMC

[UMC] 미션 2. Servlet vs Spring MVC | AOP

hyomee2 2025. 9. 24. 22:18

Servlet vs Spring MVC

Q1.

전통적인 서블릿(Servlet) 기반 개발과 Spring MVC의 차이를 조사하고,

  • HttpServlet, doGet(), doPost() 방식과
  • @Controller, @RequestMapping, DispatcherServlet 구조를 비교

A1.

웹 애플리케이션을 개발할 때, 과거에는 servlet을 직접 작성해서 요청과 응답을 처리했지만, 

요즘은 Spring MVC 같은 프레임워크를 사용해서 훨씬 편리하게 개발할 수 있다.

전통적인 서블릿(Servlet) 기반 개발

Servlet 기반의 웹 개발은 클라이언트의 모든 요청을 HttpServlet 클래스를 상속받는 servlet이 직접 처리하는 방식이다.

마치 모든 손님(요청)을 한 명의 직원이 직접 응대하는 것과 같다.

1. 구조

  • HttpServlet 클래스 상속: 모든 servlet 클래스는 HttpServlet을 상속받아야 한다.
  • goGet()/doPost() 메서드: HTTP GET 요청은 doGet() 메서드가, POST 요청은 doPost() 메서드가 처리한다. 

 

  • servlet은 요청과 응답을 다루기 위해 HttpServletRequest와 HttpServletResponse 객체를 직접 다루기 때문에 코드의 재사용성이 떨어지고 테스트하기 어렵다는 단점이 있다.

 

Spring MVC

servlet의 비효율성을 개선하기 위해 등장한 MVC(Model - View - Controller) 디자인 패턴 기반의 프레임워크이다.

이 방식은 손님(요청)을 복잡하게 처리하는 대신, 모든 요청을 일단 DistpatcherServlet이라는 Front Controller가 받아서 적절한 담당자에게 전달한다.

1. 구조

  • DispatcherServlet: Spring MVC의 핵심 엔트리 포인트. 모든 요청의 관문 역할을 하는 서블릿으로, 클라이언트의 요청이 들어오면 적절한 controller로 요청을 전달한다.
  • @Controller: 요청을 처리하는 controller 역할을 하는 클래스이다. 비즈니스 로직을 포함하지 않고, 요청을 받아 서비스로 전달하고 view로 데이터를 반환한다.
  • @RequestMapping: 요청 URL과 controller 멤서드를 매핑하며, GET, POST 등 HTTP 메서드별 매핑도 지원 가능하다. (@GetMapping, @PostMapping 등)

Q2.

Spring MVC가 왜 서블릿보다 편할까? (프레임워크의 역할과 함께 정리해보기)

A2.

1. 반복 코드의 제거 -> 개발의 생산성 향상

  • @Controller, @RequestMapping 과 같은 어노테이션을 사용하므로 서블릿을 직접 등록하거나 web.xml 파일을 수정할 필요가 없다. 개발자는 클래스나 메서드 위에 어노테이션을 붙여 URL 매핑이나 요청 처리를 쉽게 할 수 있다.

2. MVC 패턴 강제 -> 관심사의 분리

  • 서블릿 기반 개발은 한 클래스 내에서 요청 처리, 데이터베이스 접근, HTML 응답 생성 코드가 뒤섞여 관심사가 혼재되고 했다.
  • Spring MVC는 model-view-controller 패턴을 기반으로 역할을 명확하게 분리하고, 이 덕분에 각 역할의 코드가 독립적으로 존재하며, 특정 부분을 수정하거나 개선해도 다른 부분에 영향을 최소화할 수 있다. -> 재사용성 높이고 유지보수 용이

 

Q3.

DispatcherServlet이 내부적으로 요청을 처리하는 방식 단계별 분석하고, (키워드: HandlerMapping, HandlerAdpater, Intercepter) 다이어그램을 그려서 단계별로 설명하기

A2.

 

AOP(Aespect-Oriented Programming) 원리 탐구

Q1.

AOP가 무엇인지, 그리고 왜 필요한지 개념적으로 정리한 내용을 블로그 내용에 정의하기

  • OOP와 AOP의 차이점 분석.
  • AOP의 핵심 개념(Advice, JoinPoint, Pointcut, Aspect, Weaving) 정리.
  • AOP가 적용되는 런타임 위빙 vs 컴파일 타임 위빙의 차이점 조사.
  • 어노테이션이 작동되는 방식을 Spring AOP를 중심으로 조사.

A1.

OOP vs AOP

구분 OOP (객체 지향 프로그래밍) AOP (관점 지향 프로그래밍)
모듈화 단위 클래스 (class) 에스펙트 (aspect)
주요 초점 핵심 비즈니스 로직을 객체 단위로 구조화 횡단 관심사(Cross-cutting concern)를 모듈화
강점 캡슐화, 상속, 다형성을 통한 코드 재사용 공통 기능(트랜젝션, 로깅 보안 등) 분리로 중복 제거
한계 공통 기능이 여러 클래스에 중복 삽입됨 프록시 기반 동작 -> 약간의 성능 오버헤드 가능
스프링에서의 역할 IoC/DI 컨테이너 기반으로 객체 관리 IoC를 보완하여 트랜젝션, 보안 등 선언적 서비스 제공
구현 예시 UserService, OrderService 같은 도메인 클래스 TransactionAspect, LoggingAspect 같은 횡단 기능 모듈
비유 건물의 구조(설계도와 방의 배치) 건물 전체에 공통으로 깔린 전기, 수도 배관

 

AOP의 핵심 개념(Advice, JoinPoint, Pointcut, Aspect, Weaving)

개념 설명
Advice - 특정 joinpoint에서 실행되는 부가 기능 동작
JoinPoint - 프로그램 실행 도중 특정 지점 
ex) 메서드 실행, 예외 처리 시점
- Spring AOP에서의 joinpoint는 항상 메서드 실행 시점을 의미
Pointcut - 어떤 JoinPoint에 Advice를 적용할지를 지정하는 표현식
ex) execution(* com.example.service.*.*(..))
       -> com.example.service 패키지의 모든 메소드에 대해 advice를 적용하겠다는 의미
Aspect - 여러 클래스에 걸쳐 반복되는 "횡단 관심사(Cross-cutting concern)"를 모듈화한 것
- Spring AOP에서는 일반 클래스에 @Aspect 어노테이션을 붙이거나 XML 기반 설정으로 구현 가능
Weaving - Aspect를 애플리케이션 코드와 결합해 "부가기능이 적용된 객체(Advised Object)"를 만드는 과정
* 위빙 시점에 따라 아래와 같이 구분
1. 컴파일 타임 위빙
2. 로드 타임 위빙
3. 런타임 위빙

 

위빙(Weaving) 방식: 런타임 vs 컴파일타임

1. 런타임 위빙

  • 프로그램 실행 중에 프록시(proxy) 객체를 생성하여 부가기능을 삽입
  • Spring AOP가 주로 사용하는 방식
  • 장점: 유연하고 기존 코드 수정이 필요없다.
  • 단점: 프록시 오버헤드 존재

2. 컴파일타임 위빙

  • 소스코드를 컴파일할 때(.java를 컴파일러를 통해 .class로 만드는 시점) 부가기능 삽입
  • AspectJ 같은 AOP 전용 컴파일러가  필요
  • 장점: 빠르고, 명확한 코드 변환
  • 단점: 복잡한 빌드 과정

 

어노테이션이 작동되는 방식 (Spring AOP를 중심으로)

어노테이션이 작동되는 방식을 알기 전 어노테이션과 Spring AOP에 대해 먼저 알아보자.

 

어노테이션과 Spring AOP

어노테이션 자체는 단순한 메타데이터이다.

즉, @Transactional을 붙인다고 해서 이 자체로 트랜젝션이 동작하는 것은 아니고,

"이 메서드는 데이터베이스 트랜젝션으로 보호돼야해!" 라는 신호를 보낸다.

 

그러면 이것을 보고 Spring AOP가 일을 하게 된다.

Spring은 횡단 관심사(여러 모듈에 걸쳐 반복적으로 나타나는 기능)를 처리하기 위해

프록시(proxy, 실체 객체를 대신해서 요청을 받는 대리인 객체) 기술을 사용한다.

 

그럼 이제 작동되는 방식을 알아보자.

 

어노테이션의 작동 방식

1. 어노테이션 부착

- 개발자가 서비스 메서드(여기선 saveUser()라고 하자)에 @Transactional 어노테이션을 붙인다.

2. Spring 컨테이너의 감지

- Spring IoC 컨테이너가 애플리케이션을 초기화할 때, @Transactional 같은 AOP 관련 어노테이션이 붙은 빈(Bean)을 발견한다.

3. 프록시 생성

- Spring은 감지된 메서드(saveUser())에 대해 동적으로 프록시 객체를 만들고, 이 프록시는 실제 서비스 메서드(saveUser())를 감싸는 역할을 한다.

4. 호출 가로채기 (Joinpoint)

- 클라이언트가 서비스 메서드(saveUser())를 호출하면 실제로는 프록시 객체의 메서드가 호출된다. 프록시가 호출을 가로채는 지점을 AOP에서는 joinpoint라고 한다.

5. 부가 기능 실행(Advice)

- 프록시는 호출을 가로챈 후, 어노테이션에 정의된 advice(언제, 무엇을 할지에 대한 로직을 담음)를 실행한다.

- ex) @Transactional의 경우, 서비스 메서드(saveUser()) 실행 전에 트랜젝션을 시작하고, 실행 후에 성공 여부에 따라 커밋 또는 롤백하는 로직이 advice이다.

6. 실제 메서드 실행

- Advice를 처리한 후, 프록시는 실제 서비스 메서드 saveUser()을 호출하여 핵심 비즈니스 로직을 수행하도록 한다.

 

위와 같이 Spring AOP와 어노테이션 덕분에 개발자는 핵심 비즈니스 로직에만 집중할 수 있고,

트랜젝션, 로깅, 보안 등 횡단 관심사 코드를 일일이 작성할 필요없이, 어노테이션만 붙이면 Spring이 알아서 처리해준다.

이러한 방식은 코드를 더 깔끔하게 만들고, 기능의 재사용성을 높여 유지보수를 훨씬 쉽게 만들어준다.

'UMC' 카테고리의 다른 글

[UMC] 미션 0. DB 정규화, 요청 지연 해결법  (0) 2025.09.18