슬기로운 개발생활

[Spring] PSA(Portable Service Abstraction)란?

by coco3o
반응형

Spring은 Spring Triangle이라고 부르는 핵심 3대요소를 제공해준다. 이는 각각 IoC , AOP , PSA를 일컫는다.

Spring Triangle

[Spring] POJO(Plain Old Java Object)란?

[Spring] IoC 컨테이너 (Inversion of Control) 란?
[Spring] 스프링 빈을 등록하는 두 가지 방법(@Component, @Bean)
[Spring] 의존성 주입 3가지 방법 - (생성자 주입, Field 주입, Setter 주입)

[Spring] AOP(Aspect Oriented Programming)란?

참고


PSA(Portable Service Abstraction)

PSA란 환경의 변화와 관계없이 일관된 방식의 기술로의 접근 환경을 제공하는 추상화 구조를 말합니다.
이는 POJO 원칙을 철저히 따른 Spring의 기능으로 Spring에서 동작할 수 있는Library들은
POJO원칙을 지키게끔 PSA형태의 추상화가 되어있음을 의미합니다.

"잘 만든 인터페이스 하나가 열 클래스 부럽지 않다"

PSA = 잘 만든 인터페이스

PSA가 적용된 코드라면 나의 코드가 바뀌지 않고, 다른 기술로 간편하게 바꿀 수 있도록 확장성이 좋고,
기술에 특화되어 있지 않는 코드를 의미합니다.
Spring은 Spring Web MVC, Spring Transaction, Spring Cache 등의 다양한 PSA를 제공합니다.


1. Spring Web MVC

일반적인 서블릿의 형태

Servlet을 사용하려면 HttpServlet을 상속받고 doGet(), doPost() 등 오버라이딩하여 사용해야 한다.
public class CocoServlet extends HttpServlet {

	// GET
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.doGet(req, resp);
	}
	
	// POST
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		super.doPost(req, resp);
	}
}

Spring Web MVC의 형태

@Controller
class OwnerController {

 do something..

@GetMapping("/owners/new")
@LogExecutionTime
public String initCreationForm(Map<String, Object> model) {
	Owner owner = new Owner();
	model.put("owner", owner);
	return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
}

@PostMapping("/owners/new")
@LogExecutionTime
public String processCreationForm(@Valid Owner owner, BindingResult result) {
	if (result.hasErrors()) {
		return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
	}
	else {
		this.owners.save(owner);
		return "redirect:/owners/" + owner.getId();
	}
}

do something..

} // end OwnerController

일반 클래스에 @Controller 어노테이션을 사용하면 요청을 매핑할 수 있는 컨트롤러 역할을 수행하는 클래스가 됩니다.
그 클래스에서는 @GetMapping@PostMapping 어노테이션을 사용해서 요청을 매핑할 수 있습니다.

  • 서블릿을 Low level 로 개발하지 않고도, Spring Web MVC를 사용하면 이렇게 서블릿을 간편하게 개발할 수 있습니다. 그 이유는 뒷단에 spring이 제공해주는 여러 기능들이 숨겨져 있기 때문입니다.
  • 즉, HttpServlet을 상속받고 doGet(), doPost()를 구현하는 등의 작업을 하지 않아도 되는 것입니다.

Service Abstraction(서비스 추상화)의 목적 중 하나가 이러한 편의성을 제공하는 것입니다.

  • 또한, Spring Web MVC는 코드를 거의 그대로 둔 상태에서 톰캣이 아닌 다른 서버로 실행하는 것도 가능합니다.
    • 프로젝트의 spring-boot-starter-web 의존성 대신 spring-boot-starter-webflux 의존성을 받도록 바꿔주기만 하면 Tomcat이 아닌 netty 기반으로 실행하게 할 수 있습니다.

이렇게 Spring Web MVC는 @Controller, @RequestMapping 과 같은 어노테이션과 뒷단의 여러가지 복잡한 인터페이스들
그리고 기술들을 기반으로 하여 사용자가 기존 코드를 거의 변경하지 않고, 웹 기술 스택을 간편하게 바꿀 수 있도록 해줍니다.


2. Spring Transaction

트랜잭션이란?
Low level로 트랜잭션 처리를 하는 간단한 예제 코드를 보겠습니다.

 try (Connection conn = DriverManager.getConnection(
             "jdbc:coco://127.0.0.1:5432/test", "coco", "password");
             Statement statement = conn.createStatement();
             ) {
             
             //start transaction block
             conn.setAutoCommit(false); //default true
             
             String SQL = "INSERT INTO Employees " +
             			  "VALUES (101, 20, 'Rita', 'Tez')";
             stmt.executeUpdate(SQL);
             
             String SQL = "INSERTED INT Employees " +
             			  "VALUES (107, 22, 'Kita', 'Tez')";
             stmt.executeUpdate(SQL);
             
             // end transaction block, commit changes
             conn.commit();
             
             // good practice to set it back to default true
             conn.setAutoCommit(true);
             
             } catch(SQLException e) {
             	
                System.out.println(e.getMessage());
                conn.rollback();
             }

conn.setAutoCommit(false);을 하여 자동커밋을 막아주고, 오류 없이 진행된다면 conn.commit();으로 커밋 될 것 입니다.
하지만, 2번째 SQL문에 INSERTED INT 의 오타로 인해 커밋 되지 않고 catch문으로 가게되어
conn.rollback();으로 롤백 하는 코드입니다.

위의 코드와 같이 Low level로 트랜잭션 처리를 하려면 명시적으로 setAutoCommit()과 commit(), rollback()을 호출해야 합니다.

하지만 Spring이 제공하는 @Transactional 어노테이션을 사용하면 단순하게 메소드에 어노테이션을 붙여줌으로써
트랜잭션 처리가 간단하게 이루어집니다.

@Transactional(readOnly = true)
Employees findById(Integer id);

이 또한 PSA로써 다양한 기술 스택으로 구현체를 바꿀 수 있습니다.

예를들어, JDBC를 사용하는 DatasourceTransactionManager, JPA를 사용하는 JpaTransactionManager,
Hibernate를 사용하는 HibernateTransactionManager를 유연하게 바꿔서 사용할 수 있습니다.

즉, 기존 코드는 변경하지 않은 채로 트랜잭션을 실제로 처리하는 구현체를 사용 기술에 따라 바꿀 수 있는 것입니다.


3. Spring Cache

Cache도 마찬가지로 JCacheManager, ConcurrentMapCacheManager, EhCacheCacheManager와 같은
여러가지 구현체를 사용할 수 있습니다.

@Transactional
@Cacheable("users")
List<User> findAllUser();

사용자는 @Cacheable 어노테이션을 붙여줌으로써 구현체를 크게 신경쓰지 않아도 필요에 따라 바꿔 쓸 수 있습니다.

Spring은 이렇게 특정 기술에 직접적 영향을 받지 않게끔 객체를 POJO 기반으로 한번씩 더 추상화한 Layer를 갖고 있으며,
이를통해 일관성있는 Service Abstraction(서비스 추상화)를 만들어 냅니다.
덕분에 코드는 더 견고해지고 기술이 바뀌어도 유연하게 대처할 수 있게 됩니다.

반응형

블로그의 정보

슬기로운 개발생활

coco3o

활동하기