Tech/Spring40 @Transactional의 타입 : readOnly readOnly 트랜잭션은 기본적으로 읽기 쓰기 모두 가능한 트랜잭션이 생성된다. readOnly=true 옵션을 사용하면 읽기 전용 트랜잭션이 생성된다. 이 경우 등록, 수정, 삭제가 안되고 읽기 기능만 작동한다. readOnly 옵션을 사용하면 읽기에서 다양한 최적화가 발생할 수 있다. [readOnly 옵션이 적용되는 3곳] 프레임워크 JdbcTemplate은 읽기 전용 트랜잭션 안에서 변경 기능을 실행하면 예외를 던진다. JPA(하이버네이트)는 읽기 전용 트랜잭션의 경우 커밋 시점에 플러시를 호출하지 않는다. 읽기 전용이니 변경에 사용되는 플러시를 호출할 필요가 없다. 추가로 변경이 필요 없으니 변경 감지를 위한 스냅샷 객체도 생성하지 않는다. 이렇게 JPA에서는 다양한 최적화가 발생한다. JDB.. Tech/Spring 2023. 12. 27. 스프링 트랜잭션 이해 스프링 트랜잭션 추상화 각각의 데이터 접근 기술들은 트랜잭션을 처리하는 방식에 차이가 있다. JDBC 기술과 JPA 기술은 트랜잭션을 사용하는 코드 자체가 다르다 따라서 JDBC 기술을 사용하다가 JPA 기술로 변경하게 되면 트랜잭션을 사용하는 코드도 모두 함께 변경해야 한다. 스프링은 이런 문제를 해결하기 위해 트랜잭션 추상화를 제공한다. 트랜잭션을 사용하는 입장에서는 스프링 트랜잭션 추상화를 통해 둘을 동일한 방식으로 사용할 수 있게 되는 것이다. 스프링은 PlatformTransactionManager라는 인터페이스를 통해 트랜잭션을 추상화한다. PlatformTransactionManager 인터페이스 트랜잭션은 트랜잭션 시작(획득), 커밋, 롤백으로 단순하게 추상화 할 수 있다. 스프링은 트랜잭.. Tech/Spring 2023. 12. 25. 어떤 데이터 접근 기술을 선택하는 것이 좋을까? 비즈니스 상황과 현재 프로젝트 구성원의 역량에 따라서 결정하는 것이 맞다고 생각한다. JdbcTemplate이나 MyBatis같은 기술들은 SQL을 직접 작성해야하는 단점이 있지만 기술이 단순하기 때문에 SQL에 익숙한 개발자라면 금방 적응할 수 있음 JPA, 스프링 데이터 JPA, Querydsl 같은 기술들은 개발 생산성을 혁신할 수 있지만, 학습 곡선이 높기 때문에, 이런 부분을 감안해야 한다. 그리고 매우 복잡한 통계 쿼리를 주로 작성하는 경우에는 잘 맞지 않는다. 개인적으로 추천하는 방향은 JPA, 스프링 데이터 JPA, Querydsl을 기본으로 사용하고, 만약 복잡한 쿼리를 써야 하는데, 해결이 잘 안되면 해당 부분에는 JdbcTemplate이나 MyBatis를 함께 사용하는 것이다. 트랜잭.. Tech/Spring 2023. 12. 22. 스프링 데이터 JPA와 트레이드 오프 스프링 데이터 JPA 구조를 맞추기 위해, 중간에 어댑터가 들어가면서 전체 구조가 너무 복잡해지고 사용하는 클래스도 많아지는 단점이 생겼다. 유지보수 관점에서 ItemRepository의 구현체를 변경할 수 있는 장점이 있다. DI, OCP 원칙을 지킬 수 있다는 좋은 점이 분명히 있다. 반대로 구조가 복잡해지면서 어댑터 코드와 실제 코드까지 함께 유지보수 해야하는 어려움도 발생한다. 다른 선택 직접 스프링 데이터 JPA를 사용하는 방법 DI, OCP 원칙을 포기하는 대신, 복잡한 어댑터를 제거하고, 구조를 단순하게 가져갈 수 있는 장점이 있다. 클래스 의존 관계 런타임 객체 의존 관계 트레이드 오프 DI, OCP를 지키기 위해 어댑터를 도입하고, 더 많은 코드를 유지함 어댑터를 제거하고 구조를 단순하게.. Tech/Spring 2023. 12. 20. SpringBootTest : 임베디드 모드 DB H2 데이터베이스는 자바로 개발되어 있고, JVM안에서 메모리 모드로 동작하는 특별한 기능을 제공한다. 그래서 애플리케이션을 실행할 때 H2 데이터베이스도 해당 JVM 메모리에 포함해서 함께 실행할 수 있다. DB를 애플리케이션에 내장해서 함께 실행한다고 해서 임베디드 모드(Embedded mode)라 한다. 물론 애플리케이션이 종료되면 임베디드 모드로 동작하는 H2 데이터베이스도 함께 종료되고, 데이터도 모두 사라진다. 쉽게 이야기해서 애플리케이션에서 자바 메모리를 함께 사용하는 라이브러리처럼 동작하는 것이다. jdbc:h2:mem:db : 이 부분이 중요하다. 데이터소스를 만들때 이렇게만 적으면 임베디드 모드(메모리 모드)로 동작하는 H2 데이터베이스를 사용할 수 있다. DB_CLOSE_DELAY=-.. Tech/Spring 2023. 12. 18. SpringBootTest : @Transactional 스프링은 테스트 데이터 초기화를 위해 트랜잭션을 적용하고 롤백하는 방식을 @Transactional 애노테이션 하나로 깔끔하게 해결해준다. 다시 테스트를 실행해도 실패되지 않고 모두 성공한다 마치 롤백되는 것처럼!! @Transactional 원리 스프링이 제공하는 @Transactional 애노테이션은 로직이 성공적으로 수행되면 커밋되도록 동작한다. 그런데 @Transactioanl 애노테이션을 테스트에서 사용하면 아주 특별하게 동작한다. 테스트에서는 스프링은 테스트를 트랜잭션 안에서 실행하고, 테스트가 끝나면 트랜잭션을 자동으로 롤백시켜 버린다. @Transactional이 적용된 테스트 동작 방식 테스트에 @Transactional 애노테이션이 테스트 메서드나 클래스에 있으면 먼저 트랜잭션을 시작한.. Tech/Spring 2023. 12. 15. SpringBootTest : 데이터 롤백 테스트가 끝나고 나서 트랜잭션을 강제로 롤백해버리면 데이터가 깔끔하게 제거됨 테스트 순서 트랜잭션 시작 테스트 A 실행 트랜잭션 롤백 트랜잭션 시작 테스트 B 실행 트랜잭션 롤백 → @BeforeEach , @AfterEach 트랜잭션 관리자는 PlatformTransactionManager 를 주입 받아서 사용하면 된다. 참고로 스프링 부트는 자동으로 적절한 트랜잭션 매니저를 스프링 빈으로 등록해준다. @BeforeEach : 각각의 테스트 케이스를 실행하기 직전에 호출된다. 따라서 여기서 트랜잭션을 시작하면 된다. 그러면 각각의 테스트를 트랜잭션 범위 안에서 실행할 수 있다. transactionManager.getTransaction(new DefaultTransactionDefinition()) .. Tech/Spring 2023. 12. 13. SpringBootTest : 데이터베이스 분리 로컬에서 사용하는 애플리케이션 서버와 테스트에서 같은 데이터베이스를 사용하고 있으니 테스트에서 문제가 발생함 테스트를 다른 환경과 철저하게 분히해야 함 테스트 전용 데이터베이스를 별도로 운영하는 것임 현재 JdbcTemplate를 사용해서 findItems를 구현한 상태이다. (추후 업로드 예정) findItems: 전체 아이템 조회 쿼리 이후에 다른 테스트와 함께 실행하면 이렇게 에러가 발생한다. 처음 테스트를 실행할 때 저장한 데이터가 계속 남아있기 때문에 두번째 테스트에 영향을 준 것임 save()에서도 동일한 문제가 발생할 것이다. 이 문제를 해결하려면 각 테스트가 끝날 때마다 해당 테스트에서 추가한 데이터를 삭제해야 한다. 💡 테스트는 다른 테스트와 격리해야 한다. 💡 테스트는 반복해서 실행할 .. Tech/Spring 2023. 12. 11. JdbcTemplate : SimpleJdbcInsert private final SimpleJdbcInsert jdbcInsert; public JdbcTemplateItemRepositoryV3(DataSource dataSource) { this.template = new NamedParameterJdbcTemplate(dataSource); this.jdbcInsert = new SimpleJdbcInsert(dataSource) .withTableName("item") .usingGeneratedKeyColumns("id"); // 메타 데이터로 자동 인지 // .usingColumns("item_name", "price", "quantity"); // 생략 가능 } @Override public Item save(Item item) { SqlPara.. Tech/Spring 2023. 12. 7. JdbcTemplate : 이름 지정 파라미터 이름 지정 파라미터 map 처럼 key-value 데이터 구조 만들어서 전달해야 한다. Map SqlParameterSource MapSqlParameterSource BeanPropertySqlParameterSource 1. Map Map param = Map.of("id", id); Item item = template.queryForObject(sql, param, itemRowMapper()); 2. MapSqlParameterSource Map 과 유사한데, SQL 타입을 지정할 수 있는 등 SQL에 좀 더 특화된 기능을 제공 SqlParameterSource 인터페이스의 구현체이다.ㄴ MapSqlParameterSource 는 메서드 체인을 통해 편리한 사용법도 제공한다. SqlParamet.. Tech/Spring 2023. 12. 5. 스프링 예외 추상화 이해 스프링은 데이터 접근 계층에 대한 수십 가지 예외를 정리해서 일관된 예외 계층을 제공한다. 특정 기술에 종속적이지 않게 설계되어 있다. 서비스 계층에서도 스프링이 제공하는 예외를 사용하면 된다. 예를 들어서 JDBC 기술을 사용하든, JPA 기술을 사용하든 스프링이 제공하는 예외 를 사용하면 된다. JDBC나 JPA를 사용할 때 발생하는 예외를 스프링이 제공하는 예외로 변환해주는 역할도 스프링이 제공한다. DataAccessException 은 크게 2가지로 구분하는데 NonTransient 예외와 Transient 예외이다. Transient 는 일시적이라는 뜻이다. Transient 하위 예외는 동일한 SQL을 다시 시도했을 때 성공할 가능성이 있다. 예를 들어서 쿼리 타임아웃, 락과 관련된 오류들이.. Tech/Spring 2023. 11. 23. 스프링 AOP - 프록시와 내부 호출 대안(3) 구조 변경 스프링에서 가장 권장하는 방법 clienct → external() client → internal() 클라이언트에서 둘 다 호출하는 것 물론 external()에서 internal을 내부 호출하지 않도록 코드를 변경해야 한다. 클라이언트가 모두 호출하도록 구조를 변경 하면 된다. (가능한 경우에) 💡 참고) aop는 주요 트랜잭션 적용이나 주요 컴포넌트의 로그 출력 기능에 사용된다. 인터페이스에 메서드가 나올 정도의 규모에 aop 적용하느 것이 적당하다. aop는 public 메서드만 적용한다. private 메서드처럼 작은 단위에는 AOP를 적용하지 않는다. AOP 적용을 위해 private 메서드를 외부 클래스로 변경하고 public 으로 변경하는 일은 거의 없다. 그러나 위 예제와 같이 publi.. Tech/Spring 2023. 11. 14. 이전 1 2 3 4 다음 728x90 반응형