Loading the catalog…
Loading the catalog…
우선, 1차적으로는 기능완성을 우선으로 보고 그냥 한 트랜잭션 범위내에서 모든것을 해결했었다. ( openAi 호출 / DB 에서 대상 조회 / openAi 를 통해서 나온 결과를 DB 에 다시 반영 / 검증들 ... ) Transaction BEGIN ↓ PENDING 게시물 10개 조회 ↓ OpenAI API 호출 ↓ 네트워크 응답 대기 ↓ 번역 결과 DB 반영 ↓ Transaction COMMIT 기능은 정상적으로 잘 돌아가는데, 과연 이 트랜잭션 범위가 적절한 범위일까? 왜냐하면 DB 에서 조회하는거야 ... 트랜잭션이 필요하다고 해도, OpenAI API 를 호출하는거까지 트랜잭션이 필요한가? 라는것부터 시작했다. OpenAi API 를 호출하고서, 번역 결과를 받아오는데까지 시간이 오래걸리는 편이었음. 10건을 가지고오는데도 5초~10초 .. 또, 중간에 실패하면 ? 외부 api 호출에 실패하면 ? 등등 ... 하나의 트랜잭션에서 진행하게되면 Connection 자체를 너무 오래 잡고있는 문제가 발생할 가능성이 매우높았음. 그렇기에, 위와같은 생각을 했었고 ... 결국, DB 와는 아무상관없는 Open AI API 를 호출하는데에있어서, 트랜잭션이 계속해서 유지되고있는게 문제. 예를들어서 다음과 같이 걸린다고 하자. DB 조회 20ms OpenAI 호출 3000ms DB 수정 20ms Transaction ≈ 3040ms 즉, DB 와 관련된거는 40ms 뿐인데, DB 와는 상관없는 즉 Transaction 을 물고있지않아도 되는 작업이 3000ms 인 작업시간의 대부분을 차지. 트랜잭션이 유지되는 동안에는 영속성 컨텍스트 / DB 관련된 자원들이 함께 유지가 되고, 쓰기작업 / 락이 개입하게되면 락 유지시간 역시 길어질것이니 ... 문제가 많음 즉, 불필요하게 긴 트랜잭션은 Connection Pool 에 존재하는 Connection / Lock / 영속성 컨텍스트 등등 ... DB 자원을 더 오래 점유할 가능성을 높임. 그래서, 필요한 트랜잭션 범위를 어떻게 설정 ? 결국, 해당 과정에서 Transaction 이 필요한 것에는 어떤 작업이 ? DB 에서 조회 / DB 에 반영하는 이 두개의 작업이 Transaction 이 필요. [Transaction 1] PENDING 10개 조회 DTO 변환 COMMIT ↓ [Transaction 없음] OpenAI API 호출 네트워크 응답 대기 ↓ [Transaction 2] 번역 결과 조회/반영 COMMIT 그래서, DB 작업이 필요한순간에만 잠깐 Transaction 을 여는식으로 선택. 트랜잭션은 Proxy 를 통해서 호출되어야하므로 ... 내부에서 만들지않았음. 즉, 아래와 같은것처럼 만들지않았음 public void translate() { List<TranslationTarget> targets = findPendingTargets(); TranslationBatchResult result = openAiClient.translate(targets); applyTranslations(result); } @Transactional(readOnly = true) public List<TranslationTarget> findPendingTargets() { ... } @Transactional public void applyTranslations( TranslationBatchResult result ) { ... } 이렇게되면, 외부에있는 Proxy 가 applyTranslations / findPendingTargets 를 호출해서 트랜잭션이 적용이 되는게아니라, 내부인 translate -> 위 두개의 메서드를 호출하므로 위 두개의 메서드는 트랜잭션이 적용이 되지 않음. 그렇기에, 별도의 Spring Bean 으로 트랜잭션 담당 분리. 폴더구조는 더 복잡하지만 대략 다음과같이 ... TransferPostTranslationService │ ├── TransferPostTranslationTxService │ └── DB Transaction 담당 │ └── OpenAiClient └── 외부 HTTP 통신 담당 @Service @RequiredArgsConstructor public class TransferPostTranslationServiceImpl { private final TransferPostTranslationTxService txService; private final OpenAiClient openAiClient; public TranslationBatchResult translate() { List<TranslationTarget> targets = txService.findPendingTargets(); if (targets.isEmpty()) { return TranslationBatchResult.empty(); } TranslationBatchResult result = openAiClient.translate(targets); txService.applyTranslations(result); return result; } } @Service @Transactional @RequiredArgsConstructor public class TransferPostTranslationTxService { private final TransferPostRepository transferPostRepository; @Transactional(readOnly = true) public List<TranslationTarget> findPendingTargets() { return transferPostRepository .findTop10ByTranslateStatusOrderByContentCreatedAtDescIdDesc( TranslateStatus.PENDING ) .stream() .map(post -> new TranslationTarget( post.getId(), post.getContent() ) ) .toList(); } public void applyTranslations( TranslationBatchResult result ) { // 번역 결과 DB 반영 } } 그래서, 이전에는 아래와 같은 방식이였다면 ... @Transactional ────────────────────────────────────────── DB 조회 ↓ OpenAI API ──── 네트워크 대기 ──── ↓ DB 수정 ────────────────────────────────────────── COMMIT 이후에는, @Transactional(readOnly = true) ────────────── DB 조회 DTO 변환 ────────────── COMMIT ↓ OpenAI API ────── 네트워크 대기 ────── Transaction 없음 ↓ @Transactional ────────────── DB 수정 ────────────── COMMIT 위처럼, 필요한곳에서만 ... 이번에 해당 과정을 거치면서, 이전에는 그냥 한 범위내에서 모든것을 작성했었는데 실제로 외부 API 를 호출하면서 응답이 느리게오고, 작업이 오래걸리는것은 느끼고 트랜잭션의 범위를 나눠야겠다라고 생각하는게 좋았던거같음. 또한, 트랜잭션이 데이터의 정합성을 보장하는 문제만이 아니라는것을 알게됐음. 그렇기에 앞으로는 DB 작업과 외부 API 호출에 대한것을 분리하고, DB 작업이 필요한 구간에서만 짧게 트랜잭션을 사용하는식으로 변경.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
[Project] OpenAI API 연동 중 발생한 트랜잭션 범위 문제와 해결 과정. 우선, 1차적으로는 기능완성을 우선으로 보고 그냥 한 트랜잭션 범위내에서 모든것을 해결했었다. ( openAi 호출 / DB 에서 대상 조회 / openAi 를 통해서 나온 결과를 DB 에 다시 반영 / 검증들 ... ) Transaction BEGIN ↓ PENDING 게시물 10개 조회 ↓ OpenAI API 호출 ↓ 네트워크 응답 대기 ↓ 번역 결과 DB 반영 ↓ Transaction COMMIT 기능은 정상적으로 잘 돌아가는데, 과연 이 트랜잭션 범위가 적절한 범위일까? 왜냐하면 DB 에서 조회하는거야 ... 트랜잭션이 필요하다고 해도, OpenAI API 를 호출하는거까지 트랜잭션이 필요한가? 라는것부터…
Open source