Goal
- 스프링 삼각형에 대해 알아본다
- 스프링이 구현한 PSA에 대해 알아보자
- 샘플코드를 통해 PSA를 이해해본다
스프링 삼각형
스프링을 이해하는 데는 POJO(Plain Old Java Obejct)를 기반으로 스프링 삼각형이라는 애칭을 가진 Ioc/DI, AOP, PSA라고 하는 스프링의 3대 프로그래밍 모델에 대한 이해가 필수다.
이번 포스팅에서는 3대 프로그래밍 중 하나인 PSA에 관해 살펴보자
PSA (Portable Service Abstraction)
이식 가능한 서비스 추상화 => 잘 만든 인터페이스
PSA 적용 전
- 나의 코드
- 확장성이 좋지못한 코드 또는 기술에 특화되어 있는 코드
문제
확장성이 좋지못한 코드 => 테스트가 어렵다
기술에 특화되어 있는 코드 => 어떠한 기술을 바꿀 때마다 나의 코드가 바뀌는 문제
PSA 적용 후
- 나의 코드
- 잘 만든 인터페이스 PSA
- 확장성이 좋지 못한 코드 또는 기술에 특화되어 있는 코드
해결
잘 만든 인터페이스(PSA)를 사용해서 내 코드를 작성하면 테스트가 쉽고, 나의 코드 변경 없이 기술 자체를 바꾸기도 좋다
스프링이 제공하는 PSA
스프링 대부분의 api
Core | IoC Container, Events, Resources, i18n, Validation, Data Binding, Type Conversion, SpEL, AOP, AOT. |
Data Access | Transactions, DAO Support, JDBC, R2DBC, O/R Mapping, XML Marshalling. |
Web Servlet | Spring MVC, WebSocket, SockJS, STOMP Messaging 등.. |
* 추상화(PSA)가 적용된 기술
스프링 PSA의 예
1. Transaction
aop, psa의 예가 되기도 한다. @Transactional이라는 어노테이션이 붙어있으면 트랜잭션을 처리할 aspect가 어딘가에 존재하는데, 그 aspect에서는 트랜잭션 처리를 기술에 독립적인 플랫폼 PlatfromTransactionManager라는 인터페이스를 사용하여 기술을 해놓았다. 그렇기 때문에 PlatfromTransactionManager의 구현체들(JpaTransacionManager, DatasourceTransactionManager, HibernateTransactionManager)이 바뀌더라도 그 트랜잭션 aspect의 코드들은 바뀌지 않는다
@Component
@Aspect
public class LogAspect {
Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Around("@annotation(LogExcutionTime)")
public Object logExcutionTime(ProceedingJoinPoint joinPoint) throws Throwable{
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object ret = joinPoint.proceed();
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
return ret;
}
}
- sping data jpa를 사용하고 있어 스프링부트의 자동설정에 의해서 jpa transaction manager가 기본으로 bean으로 등록이 됨
- 그래서 트랜잭션을 처리하는 aspect는 인터페이스를 사용하였기 때문에 bean이 바뀌어도 (jpa transaction manager -> data source transaction manager) 트랜잭션을 처리하는 aspect코드는 바뀌지 않는다
2. Cache
@Configuration(proxyBeanMethods = false)
@EnableCaching
class CacheConfiguration {
@Bean
public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() {
return cm -> cm.createCache("vets", cacheConfiguration());
}
private javax.cache.configuration.Configuration<Object, Object> cacheConfiguration() {
return new MutableConfiguration<>().setStatisticsEnabled(true);
}
}
- @EnableCaching는 스프링프레임워크에서 온 것으로, 사용하면 캐시관련 기능이 활성화된다.
- 활성화되면 @Cacheable | @CacheEvict | ...와 같은 여러 애노테이션을 사용할 수 있다.
- 그렇게 사용하기 위해서는 CacheManager가 있어야 한다
- @Cacheable | @CacheEvict 을 처리하는 aspect가 어딘가에 있고 그 aspect에서는 CacheManager를 사용한다
3. Web MVC
@GetMapping("/owners/new")
public String initCreationForm(Map<String, Object> model) {
Owner owner = new Owner();
model.put("owner", owner);
return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}
- 나의 코드 - controller와 getmapping을 사용해 webmvc를 구현한다
- /owners/new라는 요청이 들어오면 initCreationForm이라는 메소드가 호출된다
- 뷰 리턴을 하는데, 서블릿일 수도 있고, 리액티브 일 수도 있다.
- 무엇을 사용하는지 위 코드로는 알 수 없고 의존성을 확인해봐야 알 수 있다. => 추상화 (기술에 독립적으로 웹 구현체를 만듦)
- servlet을 로우 레벨로 사용하지 않는다 => 추상화 레이어
참고
스프링입문 강의 by 백기선
https://www.inflearn.com/course/lecture?courseSlug=spring&unitId=15538
코드샘플
https://github.com/spring-projects/spring-petclinic
'Spring > about spring' 카테고리의 다른 글
[IoC 컨테이너와 빈] @Autowired (0) | 2023.07.22 |
---|---|
[IoC 컨테이너와 빈] ApplicationContext (0) | 2023.07.19 |
[스프링 삼각형] AOP 관점 지향 프로그래밍 (0) | 2023.07.11 |
[스프링 삼각형] Inversion of Control 제어의 역전 (0) | 2023.07.11 |
[Transaction] 트랜잭션 전파옵션, 격리수준 (0) | 2023.06.06 |