본문 바로가기
Java/Spring 기초

[Spring 기초] Spring 3대 요소 (3) Portable Service Abstraction

by 개미는뚠뚠딴 2021. 9. 22.
반응형

2021.09.22 - [Java/Spring 기초] - [Spring 기초] Spring 3대 요소 (2) Aspect Oriented Programming

이전 글에 이어 이번에는 Spring 3대 요소 중 세 번째인 PSA (Portable Service Abstraction) 에 대해서 알아보고자 한다. 
(이번 글도 백기선님의 강의 를 참고해서 정리했다.)

 

PSA 란 무엇인가 ?


PSA 란 백기선 님의 말을 빌리자면 '잘 만든 인터페이스' 라고 한다. (처음에는 좀 잘 안 와닿았는데 몇 가지 예시를 보니 이해가 갔다.)

내 이해로는 추상화가 굉장히 잘 된  인터페이스라고 이해했다.
작업 환경이나 기술이 변화더라도 일관된 방식의 접근 방식을 제공하여 의존성을 크게 고려하지 않아도 되는 구조라고 이해했다.

저번 글에서 어노테이션이 있으면 해당 어노테이션이 붙은 클래스에 부가 기능을 붙일 수 있는 AOP 에 대해서 알아보았다.

그의 예시로 트랜젝션 어노테이션을 들었는데 이 트랜젝션 어노테이션이 붙은 Class 는 자동적으로 try catch 가 붙게 된다. 
그러나 만약 JPA 를 이용해 JpaTransacionManager 를 사용하고 있었는데 JDBC 로 기술을 바꾸어 DatesourceTransactionManager 를 사용해야 한다고 가정하자. 

이때 코드는 거의 변경할 필요가 없다. (추상화가 잘된 인터페이스이기 때문이다.)

이러한 트랜젝션 어노테이션도 PSA 가 적용된 예시이다. 

또 다른 예시로는 Controller 어노테이션과 RequestMapping 어노테이션이 있다.

오늘도 역시 예시 코드 를 이용했다.

Controller 어노테이션 예시

Controller 어노테이션이 붙으면 요청을 매핑할 수 있는 컨트롤러 역할의 클래스가 되는데 이 클래스 내부에서 GetMapping 또는 PostMapping 의 어노테이션이 붙으면 뒤의 붙은 url 로 요청이 들어왔을 때 해당 어노테이션이 붙은 클래스에서 요청을 처리해준다.

GetMapping 예시

여기서 쓰인 GetMapping 함수를 조금 뜯어보면 

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(
    method = {RequestMethod.GET}
)
public @interface GetMapping {
    @AliasFor(
        annotation = RequestMapping.class
    )
    String name() default "";

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] value() default {};

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] path() default {};

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] params() default {};

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] headers() default {};

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] consumes() default {};

    @AliasFor(
        annotation = RequestMapping.class
    )
    String[] produces() default {};
}

name, value, path, params 등등 이렇게 많은 속성을 가지고 있다는 것을 볼 수 있다. 
이 속성들은 전부 요청과 관련이 있는데 요청이 들어오는 경로, 헤더, 파라미터 등이 있을 때
매핑되는 요청이 있다면 해당 어노테이션이 붙은 컨트롤러 함수가 실행되는 것이다.

해당 컨트롤러 함수 내부에서 Model 을 객체에 담아 View 에 전달해 리턴해주는 것을 볼 수 있다.

이것이 spring 에서 제공해주는 MVC 추상화 계층인데 이것 역시 PSA 의 예시이다.

원래 톰캣 환경의 Java 에서 Client 의 요청을 받아오기 위해서 HttpServelet 을 이용해야 하는데
Spring 의 @Controller 와 @RequestMapping 에노테이션을 사용하면 HttpServelet Class 가 없어도 Http 통신을 할 수 있다.(Spring 이 다 알아서 해주기 때문이다.)

low level 까지 신경 쓰지 않아도 클라이언트와 요청을 주고받을 수 있는 추상화가 잘 된 예시이다.
(사용자에게 편의성을 제공해준다.)

기본적으로 spring boot 기반의 애플리케이션을 실행하면 톰캣 기반으로 실행이 되는 것을 확인할 수 있는데 그럼 톰캣이 아닌 네티나 제티, 언더토우 기반으로 실행하고 싶다면 어떻게 하면 좋을까 ?? 

애플리케이션 실행시 Tomcat 기반 실행되는 것을 볼 수 있다.

PSA 가 적용되었기 때문에 코드는 거의 변경하지 않은 상태로 손쉽게 다른 기술 스택으로 갈아 끼울 수 있다. 

pom.xml 파일에 들어가서 dependency 를 수정해주는데

기존의 web 으로 되어 있던 부분을 webflux 로 수정해준다.

<!--    기존 코드 주석 -->
<!--    <dependency>-->
<!--      <groupId>org.springframework.boot</groupId>-->
<!--      <artifactId>spring-boot-starter-web</artifactId>-->
<!--    </dependency>-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

대신 위처럼 바꾸면 더 이상 ModelAndView 를 사용할 수 없게 되므로
OwnerController 의 ModelAndView 를 사용한 코드도 주석처리해준다. (맨 마지막 함수)

ModelAndView 주석처리
ModelAndView 사용한 코드도 주석처리

그리고 다시 애플리케이션을 실행해보면 Netty 기반으로 실행된 것을 볼 수 있다.

톰캣 환경의 코드를 거의 변경하지 않고 네티 기반으로 바꾼 것이다 ! 

이것이 바로 PSA 의 예시이다.

 

이렇게 Spring 의 3대 주요 개념 (IoC/DI, AOP, PSA) 중 마지막으로 PSA 에 대해서 알아보았다. 

이 3대 개념은 스프링의 철학에 대한 것이며 이를 통해 스프링이 지향하는 것과 그 가치에 대해서 알 수 있었다. (잊지 말자 !!)

스프링을 이제 막 입문했지만 벌써 친구가 된 기분이다. (물론 기분 탓이겠지만 ...)

반응형

댓글