작성
·
76
1
13. jpa reader,writer 까지만 보고 질문드립니다.JpaPagingItemReader
, JpaItemWriter
를 사용해서 JPA 기반으로 DB에 직접 접근해 처리할때, Writer나 Processor에서 복잡한 비즈니스 로직이 필요한 경우에는 어떻게 설계하는 것이 좋은지 궁금합니다.
만약 주문을 처리하는 배치가 있다고 했을 때
배치 작업에서 주문을 조회 (JpaPagingItemReader
-Entity 리턴)
writer에서
주문 상태 변경
주문 내역 추가
배송 테이블에 적재 등 여러 도메인을 걸치는 비즈니스 로직 수행 필요
이렇게 되면 reader에서 조회한 것을 processor에서 command와 같은 객체로 변환해서 writer에서는 service 로직을 호출하는 것이 좋을까요?
답변 2
2
> KILL-9@/batch/architecture:~$ systemctl status design_decision
● design_decision.service - loaded and active
Active: active (running) since 11:33
Main PID: 666 (pragmatic-approach)
Status: "Flexibility over purity - mission accomplished"
Batch integrity: MAINTAINED
Business logic: PRESERVED 💀
비즈니스 로직이 복잡해서 기존 Service 로직을 재사용하고 싶은 것 같다.(내가 이해한게 맞았나?) (사실 청크 지향 처리 구조에 복잡한 비즈니스 로직을 억지로 끼워맞추려다 보면, 이런 고민에 빠질 수밖에 없다. 정해진 답은 없다.)
실제 로직을 봐야 말을 할 수 있는 부분이라 정확한 답변이 될 수 없겠지만...
기존에 동일한 Service 로직이 존재하고 비즈니스 로직이 매우 복잡해 기존 Service 로직을 그대로 사용해야겠다고 판단한다면, 너 말대로 ItemWriter 단에서 호출하는 것도 방법이 될 수 있다.
(ItemWriterAdapter라는 것도 있으니 참고해보길 바란다)
하지만 먼저 복잡한 비즈니스 로직을 쪼갤 수만 있는지부터 판단해보길 바란다. 쪼갤 수만 있다면 Step을 여러 개로 나누는 것도 방법이 될 수 있다.
예를 들어:
Step 1: 주문 상태 변경
Step 2: 배송 테이블 적재
이렇게 Step별로 책임을 분리하면 각 Step의 Processor나 Writer가 단순해져서 관리하기 훨씬 편해진다.
만약 각 Step간 공유해야할 정보가 필요하다면 ExecutionContext를 활용하거나 redis cache / file / 하다 못해 DB 저장과 같이 중간 상태를 저장해놓아야 한다.
1) 하나의 큰 비즈니스로직이 Transaction으로 감싸져있다는것은 oltp에 최적화된 비즈니스로직이아닐까싶다(그럴 경향이 크다는것이지) 따라서 배치처리에서 이런 로직을 그대로 사용하지않을 가능성이 크다는 것이다. 물론 필요하다면 앞서말한것처럼 ItemWriter에서 호출하는 방법도 있을 것이다. 재처리와 정합성이라.. 그렇다 이 방법이 훨씬 복잡도를 낮춘다. 단 각 배치잡이 멱등해야 재처리가 편할것이다.
2) 결국 담당하는 비즈니스 로직에 따라 달라지겠지만 일반적으로 웹이나 다른 모듈에서와 완전히 동일한 비즈니스 로직을 배치에서 공유할 일은 많지 않다. 특히 비즈니스로직이 복잡할수록 이를 그대로 배치에서 사용하긴 어렵지. 오히려 배치 로직자체를 하나의 비즈니스 로직으로 봐야할 것이다.
0
안녕하세요, 인프런 AI 인턴입니다.
기린그린그림님, Spring Batch에서 비즈니스 로직을 어떻게 효과적으로 처리할 수 있는지에 대해 질문 주셨네요. 복잡한 비즈니스 로직은 잘못 설계하면 유지보수나 성능 저하의 원인이 될 수 있기 때문에 신중한 접근이 필요합니다.
Separation of Concerns:
ItemReader: 단순히 데이터를 조회하여 이동시키는 역할을 담당하도록 설계합니다. 조회한 데이터를 그대로 ItemProcessor
로 전달합니다.
ItemProcessor: 필요한 경우 데이터를 변환하거나 비즈니스 로직의 주안을 처리합니다. 일반적으로 여기서 비즈니스 로직의 변환이나 결합이 가능합니다. 여기서의 작업은 특히 로직 복잡성을 분리하는 데 유용할 수 있습니다.
ItemWriter: 비즈니스의 핵심적인 데이터 변경 작업을 수행합니다. 여기에 서비스 레이어를 통해 데이터베이스 변경을 수행하는 것이 일반적입니다.
Command Pattern 사용:
ItemProcessor
내부에서 주로 처리합니다. 이 방식은 각 커맨드 객체가 특정 비즈니스 작업을 독립적으로 처리할 수 있도록 설계하며, ItemWriter
는 이를 호출하는 방식으로 설계합니다.Service Layer 활용:
ItemWriter
에서 직접 EntityManager를 사용하기보다는, 서비스 레이어를 통해 비즈니스 로직을 수행하도록 연결합니다. 이렇게 하면 비즈니스 로직을 보다 유연하게 관리할 수 있으며, 테스트가 용이해집니다.ItemReader
: 주문 정보를 조회합니다.ItemProcessor
: 주문을 처리하기 위해 필요한 추가적인 비즈니스 로딕을 수행하거나, 데이터를 변환합니다.ItemWriter
: 서비스 레이어를 통해 상태 수정, 내역 추가 및 배송 데이터 적재 등의 작업을 수행합니다.이와 관련해서, 유사한 질문에 대한 논의를 참고하시면 도움이 될 것 같습니다:
- Spring Batch에서 Reader, Writer 설계에 대한 고민
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
질문이 추가로 더 생겼습니다..ㅎㅎ
1. step을 별도로 나누지 않고, 기존 서비스를 사용하려고 하는 이유가 같은 트랜잭션에 묶였으면 하는 생각으로 기존 로직을 사용하고 싶었습니다.
step을 나누게 되면 트랜잭션에 묶이지 않게 되는데 실패 되는 경우 배치 재처리나 이런 걸 통해서 정합성을 맞추는 걸까요?(아직 뒷부분을 못 보고 있어서 질문 먼저 드립니다.)
2. 보통 실무에서는 비즈니스 로직으로 판단되어도 배치모듈에 작성을 하는 편인지 궁금합니다.
api 모듈이나 다른 모듈에서 재사용할 수 있는 비즈니스 로직들도 있을 것이라 생각이 들어서요.