컨텍스트와 DI우리가 @Transactional을 붙이는 순간, 스프링 내부에서는 보이지 않는 두가지 역할을 합니다. 첫번째로는 트랜잭션 컨텍스트를 생성하는데 이 컨텍스트는 커넥션 획득 -> 트랜잭션 시작 -> 커밋 또는 롤백 -> 리소스 정리 등의 변하지 않는 행위를 하는 흐름이 저희의 코드를 감쌉니다. 이 컨텍스트가 실행되기 위해서는 PlatformTransactionManager을 구현한 구현체가 필요한데 이는 DI를 통해DataSourceTransactionManager 주입할 지 JpaTransactionManager를 주입할 지는 설정에 따라 달라지지만 비즈니스 로직은 그 차이를 알 수 없습니다. 컨텍스트는 반복되는 흐름을 추상화시킴으로써 반복되는 흐름을 재사용가능하도록 구현한 개념입니다. 이..
1. 초난감 주문 메서드@Service@RequiredArgsConstructorpublic class OrderService { private final RedissonClient redissonClient; private final StockRepository stockRepository; public void decreaseStock(Long productId, int quantity) { RLock lock = redissonClient.getLock("stock:" + productId); try { boolean acquired = lock.tryLock(5, 10, TimeUnit.SECONDS); if (!a..
테스트 코드를 왜 작성하는 것일까?테스트를 하는 이유는 우리가 작성한 코드에 대해 의도한대로 동작하는지 테스트하기 위함입니다. 테스트 코드를 작성은 여러 팀원들과 함께 일할 때 빛을 발하는데 예를들어 우리가 모든 팀원들이 올린 PR을 모두가 전부 리뷰를 할 수 있을까요? 불가능할 것입니다. 그럼 이런 상황에서 어떻게 안정적으로 우리가 만든 어플리케이션이 동작하는지 보장할 수 있을까요? 바로 그것이 테스트 코드입니다. 스프링은 어플리케이션을 개발하는 것 뿐만 아니라 어플리케이션을 테스트하는데도 다양한 기능을 제공해주는데 그 기능들을 알아봅시다.좋은 단위 테스트는 무엇일까?단위 테스트에서 가져야할 특징을 이야기하면 회귀 방지, 리팩토링 내성, 빠른 피드백, 유지보수성을 이야기합니다. 좀 더 쉽게 예를들면 단..
1. 테스트의 가치와 필요성스프링이 개발자에게 제공하는 가장 중요한 가치 중 하나는 객체지향과 테스트입니다. 테스트는 코드가 예상대로 정확히 동작하는지 확인하여 개발자에게 의도한대로 동작한다는 확신을 주며, 디버깅 시간을 단축시켜 줍니다. 테스트하기 좋은 코드는 해당 코드가 어떤 역활을 하는지 명확하게 보이고 반대로 테스트하기 불편하게 설계된 코드는 상당히 많은 책임과 역활을 가지고 있습니다. 거짓 신호(잘 동작하지 않는데 잘 동작한다고 신호를 주는 코드)를 주는 테스트는 없는 것보다 나쁘므로, 부정적인 상황을 먼저 테스트하는 단위 테스트를 작성하는 습관이 중요합니다. 2. UserDaoTest 다시 보기와 단위 테스트기존의 웹을 통한 테스트 방식은 모든 레이어를 다 만든 후에나 가능하며, 서버 설..
객체 생성의 역전 - 팩토리 패턴토비의 스프링에 나오고 있는 내용에서 나오는 패턴 중 팩토리 패턴이라는 개념은 객체의 생성의 책임을 팩토리라는 클래스에 위임함으로 전략 패턴과 템플릿 메소드 패턴 등으로 분산되는 객체를 한 곳에서 관리할 수 있게 해줍니다. 왜 이전에 역활과 책임에 따라 분리해두었던 객체를 다시 한 곳에 모아두는 이유가 무엇일까요?팩토리 패턴의 예시이전에 설명했던 알림 모듈을 예시로 들자면 유저에게 알림을 발송할 때 알림톡으로 알림을 보낼 때와 앱 푸시로 알림을 보낼 때 그리고 이메일로 알림을 보낼 때에는 주입받아야 하는 객체가 전부 다릅니다. 아래의 코드를 보면 쉽게 이해할 수 있을 것입니다.// 전략 인터페이스public interface NotificationSender { vo..
중복된 코드의 문제토비의 스프링 1장에서는 DAO의 관심사를 분리하고, 중복된 코드를 한 곳에 모아 상속을 통해 구현하는 방식을 설명합니다. 오래된 개념이지만 현재까지도 자주 사용되는 패턴입니다.예를 들어 알림 발송 모듈을 만든다고 가정해봅시다. 아래 코드에서 사용자 조회와 로그 저장 로직이 각 메서드마다 반복됩니다.만약 사용자 조회가 다른 마이크로서비스 호출로 변경되거나, 로그 저장소가 RDB에서 NoSQL로 바뀐다면 모든 메서드를 수정해야 합니다. 이것이 관심사가 분리되지 않았을 때 발생하는 문제입니다.// 중복이 많은 초기 코드public class NotificationService { public void sendKakaoAlimtalk(String userId, String message..