spring28 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. 스프링 AOP - 프록시와 내부 호출 대안(2) 지연 조회 자기 자신을 생성하면서 주입해야해서 실패한다. 수정자 주입이나 지연 조회 사용 스프링 빈 지연해서 조회 → ObjectProvider(Provider), ApplicationContext 사용 @Slf4j @Component public class CallServiceV2 { private final ApplicationContext applicationContext; public CallServiceV2(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public void external() { log.info("call external"); CallServiceV2 callServiceV2 .. Tech/Spring 2023. 11. 10. 스프링 AOP - 프록시와 내부 호출 대안(1) 자기 자신 주입 내부 호출을 해결하는 가장 간단한 방법은 자기 자신을 의존관계 주입받는 것이다. @Autowired public void setCallServiceV1(CallServiceV1 callServiceV1) { this.callServiceV1 = callServiceV1; } 수정자를 통해 주입을 받는 것을 확인할 수 있다. 스프링에서 AOP가 적용된 대상을 의존관계 주입 받으면 주입 받은 대상은 실제 자신이 아니라 프록시 객체이다. /** * 참고: 생성자 주입은 순환 사이클을 만들기 때문에 실패함 */ @Slf4j @Component public class CallServiceV1 { private CallServiceV1 callServiceV1; @Autowired public void setCal.. Tech/Spring 2023. 11. 7. 스프링 AOP - this VS target this: 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트 target: Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트 둘 다 적용 타입 하나를 정확하게 지정해야 한다. 같은 패턴 사용 불가 부모 타입 허용 this vs target 단순히 타입 하나를 정하면 되는데, this와 target은 어떤 차이가 있을까? 스프링에서 AOP 적용하면 실제 target 객체 대신 프록시 객체가 스프링 빈으로 등록된다. this는 스프링 빈으로 등록되어있는 프록시 객체를 대상으로 포인트컷을 매칭한다. target은 실제 target 객체를 대상으로 포인트컷을 매칭한다. 프록시 생성 방식에 따른 차이 스프링은 프록시를 생성할 때 JDK 동적 프록시와 CG.. Tech/Spring 2023. 10. 27. 스프링 AOP - 매개변수 전달 매개변수 전달 포인트컷 표현식을 사용해서 어드바이스에 매개변수 전달할 수 있다. this., target, args, @target, @within, @annotation, @args 포인트컷 이름과 매개변수의 이름을 맞춰야한다. 추가로 타입이 메서드에 지정한 타입으로 제한된다. 1. 가장 기본적인 방식 @Around("allMember()") public Object logArgs1(ProceedingJoinPoint joinPoint) throws Throwable { Object arg1 = joinPoint.getArgs()[0]; log.info("[logArgs1]{}, arg={}", joinPoint.getSignature(), arg1); return joinPoint.proceed();.. Tech/Spring 2023. 10. 25. AOP 용어 정리 조인 포인트(Join point) 어드바이스가 적용될 수 있는 위치, 메소드 실행, 생성자 호출, 필드 값 접근, static 메서드 접근 같은 프로그램 실행 중 지점 조인 포인트는 추상적인 개념이다. AOP를 적용할 수 있는 모든 지점이라 생각하면 된다. 스프링 AOP는 프록시 방식을 사용하므로 조인 포인트는 항상 메소드 실행 지점으로 제한된다. 포인트컷(Pointcut) 조인 포인트 중에서 어드바이스가 적용될 위치를 선별하는 기능 주로 AspectJ 표현식을 사용해서 지정 프록시를 사용하는 스프링 AOP는 메서드 실행 지점만 포인트컷으로 선별 가능 타켓(Target) 어드바이스를 받는 객체, 포인트컷으로 결정 어드바이스(Advice) 부가 기능 특정 조인 포인트에서 Aspect에 의해 취해지는 조치 .. Tech/Spring 2023. 10. 18. 이전 1 2 3 다음 728x90 반응형