자바에서는 표준 스펙, 상용, 오픈소스를 합해서 사용방식과 형식은 다르지만 목적과 기능이 비슷한 제품이 존재하는데 특정한 환경과 상황에 따라 접근가능한 기술이 달라진다면 실제로 개발하는 데 있어서 문제가 발생할 것이다.
PSA(Portable Service Abstraction)
스프링의 3대 요소 중 하나로 일관성 있는 추상화를 의미하는데 환경과 세부 기술의 변화와 관계없이 일관된 방식으로 기술에 접근할 수 있게 해 주겠다는 것을 의미한다.
스프링에서는 어떻게 성격이 비슷한 여러 종류의 기술을 추상화하고 이를 일관된 방법으로 사용할 수 있게 지원해 주는지 한번 알아보자.
서비스 추상화의 개념에 맞추어서 리팩터링 한 기능에는 아래와 같은 장점을 가지게 된다.
- 각 메서드가 자신의 작업에만 충실하게 작동한다.
- 다른 기능을 포함하지 않기 때문에 코드의 복잡성이 떨어지고 코드를 이해하기 쉽다
- 코드를 이해하기 쉽기 때문에 유지보수성이 향상된다.
- 예외처리를 하기가 쉬워지고 또 테스트 코드 작성이 용이하다.
결론적으로 말하자면 코드를 더 이해하기 쉽고 변화에 대응하기 편하게 설계할 수 있게 되었다. 객체지향적 특징에 더욱 가까워질 수 있었다.
스프링과 서비스추상화
스프링에서는 그렇다면 서비스 추상화를 어떻게 사용하고 있을까?
트랜잭션을 통해서 스프링이 어떻게 제공해주고 있는지 알아보자
트랜잭션(Transaction)
데이터베이스의 상태를 변환시키는 더 이상 쪼갤 수 없는 업무 처리의 최소 단위를 의미한다.
트랜잭션의 처리가 정상적으로 완료된다면 커밋(Commit)을 정상적으로 완료되지 못했다면 롤백(Rollback) 작업을 수행한다.
트랜잭션의 성질
트랜잭션이 정상적으로 안전하게 수행되게 위해서는 4가지의 필수적인 성질 "ACID" 조건을 충족해야 한다.
- Atomicity(원자성): 트랜잭션은 작업이 모두 정상적으로 반영되는것을 보장한다 100개 로직으로 이루어진 작업에서 단 하나라도 실패한다면 무조건 실패로 간주하고 트랜잭션의 시작 전 상태로 되돌린다.
- Consistency(일관성): 트랜잭션의 작업처리 결과가 항상 일관성이 있어야 한다는 것으로 작업중에 데이터베이스가 변경되더라도 처음 트랜잭션이 시작될 때 참조한 데이터베이스로 작업이 진행되어야 한다.
- Isolation(고립성): 하나의 트랜잭션 작업이 수행될때는 다른 트랜잭션의 작업이 끼어들수 없는데 이는 트랜잭션끼리 서로 간섭할 수 없다는 것을 의미한다. 또 다른 말로는 격리성이라 하는데 한 트랜잭션에서 변경된 데이터는 커밋되기 전까지 어떠한 다른 트랜잭션과도 작업을 수행할 수 없게 된다.
- Durability(지속성): 트랜잭션이 정상적으로 완료됬다면 그 결과값은 데이터베이스에 영구적으로 저장되어야 한다는 의미로 정상적으로 완료되거나 또는 부분적으로 완료된 데이터를 데이터베이스가 책임지고 저장하는 성질을 의미한다. 영속성이라고도 표현하기도 한다.
비즈니스 로직에 프레임워크의 도움 없이 직접 트랜잭션 코드를 넣게 된다면 코드가 복잡해지게 된다 객체지향적인 코드를 작성할 수 없게 되는데 이를 해결하기 위해서 스프링에서 제공하는 JdbcTemplate를 사용해 볼 것이다.
JdbcTemplate
스프링에서 복잡한 Jdbc의 사용을 단순화하고 일반적인 오류를 방지하기 위해 만들어진 클래스로
인터페이스를 통해서 JDBC 핵심 워크플로우를 이용해 반복작업을 줄여준다.
간편한 Save 구현
@Override
public Item dbSave(Item item) {
String sql = "insert into item(item_name, price, quantity) values (?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, new String[]{"id"});
ps.setString(1, item.getItemName());
ps.setInt(2, item.getPrice());
ps.setInt(3, item.getQuantity());
return ps;
}, keyHolder);
long key = keyHolder.getKey().longValue();
item.setId(key);
return item;
}
[참고]
토비의 스프링 Vol.01
https://frtt0608.tistory.com/136
https://dev-coco.tistory.com/83