Spring MVC vs WebFlux 선택 가이드

← 기술 결정 목록

결정: Spring MVC + Virtual Threads 상태: 승인됨


목차


1. 핵심 차이점

1.1 Spring MVC (서블릿 스택)

특징:

의존성:

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

코드 예시:

1
2
3
4
5
6
7
@RestController
public class UserController {
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id); // 블로킹 호출
    }
}

1.2 Spring WebFlux (리액티브 스택)

특징:

의존성:

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

코드 예시:

1
2
3
4
5
6
7
@RestController
public class UserController {
    @GetMapping("/users/{id}")
    public Mono<User> getUser(@PathVariable Long id) {
        return userService.findById(id); // 리액티브 반환
    }
}

2. 성능 비교 (시대별)

2.1 Virtual Threads 이전 시대 (Java 17 이하)

Spring MVC (전통)

문제점:

성능:

Spring WebFlux

장점:

성능:

결론: Virtual Threads 이전에는 WebFlux가 확실히 유리했음

2.2 Virtual Threads 이후 시대 (Java 21+)

Spring MVC + Virtual Threads

혁신:

성능:

결론: WebFlux와 성능 차이가 거의 없어짐

2.3 현재 상황 (Java 25)

Spring MVC + Virtual Threads vs Spring WebFlux

성능 비교:

차이점:

결론:

설정:

1
2
# application.properties
spring.threads.virtual.enabled=true

3. Co-Talk 프로젝트 선택

3.1 최종 결정: Spring MVC + Virtual Threads

선택 이유:

  1. Java 25 Virtual Threads 활용
    • Virtual Threads로 WebFlux 수준의 동시성 확보
    • 기존 코드 패턴 유지 가능
  2. 개발 생산성
    • 명령형 코드 (기존 방식)
    • 학습 곡선 낮음
    • 디버깅 용이
  3. 생태계 호환성
    • Spring Data JPA (블로킹) 사용 가능
    • 기존 라이브러리 모두 호환
    • WebFlux는 리액티브 라이브러리 필요
  4. 실제 성능
    • Virtual Threads로 충분한 성능
    • 대부분의 경우 WebFlux와 유사한 처리량

3.2 WebFlux를 고려할 경우

언제 WebFlux가 유리한가:

  1. 완전한 리액티브 스택
    • R2DBC (리액티브 데이터베이스 드라이버)
    • 리액티브 Redis 클라이언트
    • 모든 라이브러리가 리액티브
  2. 초고성능이 필수
    • WebFlux가 약간 더 효율적 (하지만 차이 미미)
  3. 기존 리액티브 코드베이스
    • 이미 리액티브로 구축된 경우

단점:


4. 성능 비교 (대규모 트래픽)

4.1 시대별 동시 연결 처리 능력

Virtual Threads 이전 (Java 17 이하)

방식 동시 연결 메모리 사용 코드 복잡도 평가
Spring MVC (전통) ~500 높음 낮음 ❌ 제약 많음
Spring WebFlux 수십만 매우 낮음 높음 ✅ 유리

결론: WebFlux가 확실히 유리했음

Virtual Threads 이후 (Java 21+)

방식 동시 연결 메모리 사용 코드 복잡도 평가
Spring MVC + Virtual Threads 수백만 낮음 낮음 ✅ 권장
Spring WebFlux 수백만 매우 낮음 높음 ⚠️ 선택적

결론: 성능 차이가 거의 없어짐

4.2 실제 벤치마크 (참고)

10,000 TPS 처리:

성능 차이:

결론:


5. 구현 전략

5.1 Spring MVC + Virtual Threads 설정

의존성:

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

설정:

1
2
# application.properties
spring.threads.virtual.enabled=true

코드:

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class ChatController {
    @Autowired
    private ChatService chatService;
    
    @GetMapping("/chats")
    public List<ChatRoom> getChatRooms() {
        // 기존 코드 그대로 사용
        // Virtual Thread에서 자동 실행
        return chatService.findAll();
    }
}

5.2 WebSocket은 별도 처리

WebSocket 서버:

이유:


6. 마이그레이션 전략

6.1 초기 단계

6.2 성능 문제 발생 시

  1. 먼저 확인:
    • Virtual Threads 활성화 확인
    • 데이터베이스 쿼리 최적화
    • 캐싱 전략
  2. 그래도 부족하면:
    • WebFlux 고려
    • 또는 Netty 직접 사용

7. 최종 권장사항

✅ Spring MVC + Virtual Threads (강력 권장)

이유:

핵심:

⚠️ Spring WebFlux (선택적, 비권장)

고려 시점:

단점:


8. 결론

핵심 요약

Virtual Threads 이전 (Java 17 이하):

Virtual Threads 이후 (Java 21+):

Co-Talk 프로젝트 선택

REST API: Spring MVC + Virtual Threads ✅ WebSocket: Netty 기반 독립 서버 ✅

이유:

문서 작성일: 2024년 최종 수정일: 2024년