스프링 애플리케이션을 환경이나 서버, 특정 기술에 종속되지 않고 이식성이 뛰어나며 유연한 애플리케이션으로 만들 수 있게 해준다.
일반 클래스에 @Controller 애노테이션을 사용하면 요청을 매핑할 수 있는 컨트롤러 역할을 수행하는 클래스가 된다. 그 클래스에서는 @GetMapping과 @PostMapping 애노테이션을 사용해서 요청을 매핑한다.
Spring Web MVC를 사용하면 이렇게 서블릿을 간편하게 개발할 수 있는데, 뒷단에 spring이 제공해주는 여러 기능들이 숨겨져 있기 때문이다. 그래서 우리는 서블릿을 low level로 개발하지 않아도 된다. (즉 HttpServlet을 상속받고 doGet(), doPost()를 구현하는 등의 작업을 직접 하지 않아도 된다.)
그런데 여기서 Spring Web MVC는 코드를 거의 그대로 둔 상태에서 톰캣, netty 기반으로 실행할 수 있다. 예를 들어 프로젝트가 spring-boot-starter-web 의존성 대신 spring-boot-starter-webflux 의존성을 받도록 바꿔주기만 하면 톰캣이 아닌 netty 기반으로 실행하게 할수도 있다.
원래 기존에 톰캣으로 실행하던 프로젝트를 netty 기반으로 실행하게 하려면 더 복잡한 과정이 필요하지만 spring이 제공해주는 Spring Web MVC 추상화 계층을 사용해서 간단히 netty로 실행할 수 있는 것이다.
이렇게 Spring Web MVC는 @Controller, @RequestMapping과 같은 애노테이션과 뒷단의 여러가지 복잡한 인터페이스들 그리고 기술들을 기반으로 하여 사용자가 웹 기술 스택을 간편하게 바꿀 수 있도록 해준다.
중요한 것은 이런 것들이 기존 코드를 거의 변경하지 않고도 가능하다는 것이다.
Low level로 트랜잭션 처리를 하려면 setAutoCommit()과 commit(), rollback()을 명시적으로 호출해야 한다. 그러나 Spring 이 제공하는 @Transactional 애노테이션을 사용하면 간단하게 트랜잭션 처리가 이루어진다.
예를 들어 JDBC를 사용하는 DatasourceTransactionManager, JPA를 사용하는 JpaTransactionManager, Hibernate를 사용하는 HibernateTransactionManager를 유연하게 바꿔서 사용할 수 있다.
즉 기존 코드는 변경하지 않은 채로 트랜잭션을 실제로 처리하는 구현체를 상황에 따라 바꿔 쓸 수 있다.
Cache도 마찬가지로 JCacheManager, ConcurrentMapCacheManager, EhCacheCacheManager와 같은 여러가지 구현체를 사용할 수 있다.
사용자는 @Cacheable 애노테이션을 붙여줌으로써 구현체를 크게 신경쓰지 않아도 필요에 따라 바꿔 쓸 수 있는 것이다.
@Transactional로 예를 들자면, DB와 Connection을 맺고 쿼리를 실행하고 commit, rollback 하는 코드는 사용하는 구현체(JDBC, JPA, Hibernate)에 따라 구현 코드가 달라질 것이다. 따라서 Spring의 @Transactional은 각 구현체의 TransactionManager을 각각 구현하는 대신에 최상위 PlatformTransactionManager를 이용하고 필요한 TransactionManager를 DI로 주입받아 사용하도록 한다.
출처