Spring Boot 트랜잭션 동기화 하기

김건우·2026년 2월 26일

개발 이야기

목록 보기
12/14

기존 구조와 문제점

AI서버에서 작업된 결과를 반환 받는 API는 아래와 같은 구조로 작동 중이었다.

위 구조처럼 커밋이 완료되기 전에 FCM과 SSE이 먼저 전송되면서 그것을 수신한 클라이언트에서 커밋이 반영되지 못한 결과를 조회하게 되는 Premature Event Publishing(조기 이벤트 발행)가 발생했다.

그렇기에 클라이언트에서는 분명 작업 완료라는 알림을 받았음에도 불구하고 바로 조회를 하면 결과를 조회할 수 없는 괴현상이 발생했다.

구조 파악

기존에 유스케이스 코드 구조는 아래와 같은 플로우로 이루어져 있었다. 코드를 전부 공개할 수 없어서 매우 많이 압축하고 또 의역해서 적었으니 참고 바란다.

@Transactional
public void editJobStatus(Request request) {
    if (request.jobStatus() == JobStatus.DONE) {
        AiService.done(request.jobId(), ...); // DB 변경 (아직 커밋 안 됨)
		try {
        	sseService.send(userId, ...); // SSE 즉시 전송
        	fcmService.sendAlarm(userId, ...); // FCM 즉시 전송
        } catch (Exception e) {
        	// ...
		}
    }
}
  1. AiService.done() → DB에 jobStatus=DONE으로 변경 (아직 커밋 전)
  2. sseService.send() / fcmService.sendAlarm() → 클라이언트에 "DONE" 알림 전송
  3. 클라이언트가 SSE 받고 즉시 조회 API 호출
  4. 조회 API는 다른 트랜잭션이므로 아직 커밋되지 않은 데이터를 읽음 → 이전 상태(RUNNING)가 조회됨
  5. 메서드 종료 후 트랜잭션 커밋 → DB에 DONE 반영

위 플로우와 코드를 보면 하나의 트랜잭션에서 모든 작업이 이루어지고 있으며 커밋은 위 트랜잭션 안에 있는 작업이 모두 끝난 뒤에 이루어지기에 DB에 작업 사항이 커밋되기 전에 외부로 알림을 전송하는 구조가 된 것이다.

해결

DB 작업이 실제로 모두 반영된 뒤에, 즉 커밋이 모두 이루어진 뒤에 클라이언트로 알림을 전송할 수 있도록 하는 Post-Commit Hook 작업을 하였다. 이를 위해 스프링 부트에서 지원하는 TransactionSynchronizationManager를 사용해서 트랜잭션 동기화를 적용했다.

@Transactional
public void editJobStatus(Request request) {
    if (request.jobStatus() == JobStatus.DONE) {
        AiService.done(request.jobId(), ...);      // DB 변경 (아직 커밋 안 됨)
        registerAfterCommit(() -> {
            try {
              sseService.send(userId, ...); // 트랜잭션 커밋 후 SSE 전송
              fcmService.sendAlarm(userId, ...); // 트랜잭션 커밋 후 FCM 전송
            } catch (Exception e) {
                // ...
            }
        });
    }
}
  1. AiService.done() → DB에 jobStatus=DONE으로 변경
  2. 메서드 종료 → 트랜잭션 커밋 → DB에 DONE 반영
  3. afterCommit() 콜백 실행 → SSE/FCM 전송
  4. 클라이언트가 알림 받고 조회 → 커밋된 최신 데이터(DONE) 조회

이렇게 하여 DB 반영 → 알림 전송 순서를 보장하여 클라이언트가 항상 올바르게 반영된 최신 상태를 조회할 수 있도록 하였다.

결과

이것도 처음 써보는 방식이어서 신선했고 오늘도 새로운 지식이 늘어난 기분이다. 작업 순서를 보장한다는 것이 얼마나 중요한지 알게 되었다.

profile
백엔드 개발자, 김건우입니다.

0개의 댓글