백엔드 면접 용어 사전
시스템 설계OptimisticLockException · 재시도 로직

낙관적 재시도

충돌 시 되돌리고 다시 시도하는 방식. 선착순·재고 차감 같은 짧은 경쟁에 쓰인다.

낙관적 락 충돌로 실패한 작업을 트랜잭션을 새로 열어 다시 시도하는 처리 방식.

왜 필요한가

낙관적 락은 충돌을 감지만 한다. 감지 후 무엇을 할지는 애플리케이션 몫이다.

  • UPDATE stock SET qty = 9, version = 4 WHERE id = 1 AND version = 3;
  • 0행 영향 → OptimisticLockException

여기서 그냥 사용자에게 에러를 던지면? "다른 사용자가 먼저 수정했습니다. 다시 시도해 주세요."

  • 사용자가 직접 새로고침하고 다시 눌러야 한다

재고 차감처럼 사용자가 개입할 필요 없는 작업은 서버가 알아서 재시도해야 한다.

반드시 트랜잭션 밖에서 재시도해야 한다 — 가장 중요한 지점

// ❌ 잘못된 방법 — 같은 트랜잭션 안에서 반복
@Transactional
public void order(Long id) {
    for (int i = 0; i < 3; i++) {
        try {
            Stock s = repo.findById(id).get();
            s.decrease();
            return;
        } catch (OptimisticLockException e) { /* 재시도 */ }
    }
}

왜 안 되나 — 두 가지 이유

  1. 영속성 컨텍스트가 오염된 상태로 남는다. 1차 캐시에 이전 버전의 엔티티가 그대로 있어, 다시 조회해도 DB가 아닌 캐시에서 옛 값을 반환한다. → 몇 번을 재시도해도 같은 버전으로 실패한다.
  2. 예외가 발생하면 트랜잭션이 rollback-only로 표시되어, 이후 무엇을 해도 커밋 시점에 UnexpectedRollbackException이 난다.
// ✅ 올바른 방법 — 트랜잭션 자체를 새로 연다
@Retryable(
    retryFor = { OptimisticLockingFailureException.class },
    maxAttempts = 3,
    backoff = @Backoff(delay = 50, multiplier = 2, random = true)
)
@Transactional
public void order(Long id) {
    Stock s = repo.findById(id).get();
    s.decrease();
}

@Retryable메서드 전체를 다시 호출하므로 트랜잭션도, 영속성 컨텍스트도 새로 만들어진다.

주의 — 스프링 AOP는 프록시 기반이라 같은 클래스 안에서 호출하면 재시도가 걸리지 않는다. 외부에서 호출되는 진입점에 붙여야 한다.

백오프와 지터

backoff = @Backoff(delay = 50, multiplier = 2, random = true)

충돌한 요청들이 동시에 재시도하면 또 충돌한다. 무작위 지연으로 흩어야 한다. 지수 백오프에서 본 thundering herd와 같은 문제다.

언제 재시도가 답이 아닌가

① 경쟁이 극심할 때 동시 요청 100건 → 1건 성공, 99건 재시도 → 1건 성공, 98건 재시도 … 총 시도 5000회. 대부분이 낭비 → 비관적 락이나 Redis 원자 연산(DECR)으로 바꾼다.

② 사용자의 판단이 필요할 때

  • 게시글을 두 사람이 동시에 편집
  • 자동으로 재시도하면 뒤에 저장한 사람이 앞사람 내용을 덮어쓴다
  • "다른 사람이 수정했습니다. 변경 내용을 확인하세요"가 옳다

자동 재시도는 "다시 해도 결과가 같아야 하는" 작업에만 쓴다.

재시도 횟수를 초과하면

@Recover
public void recover(OptimisticLockingFailureException e, Long id) {
    log.warn("재고 차감 최종 실패: {}", id);
    throw new OrderFailedException("주문이 몰려 처리하지 못했습니다");
}

조용히 삼키면 주문이 사라진 것처럼 보인다. 명확히 실패시키고 기록해야 한다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 시스템 설계·분산 — CAP·복제·샤딩·Saga·서킷브레이커