Blog
Anki
ohks 면접질문

Retry 로직 개발 시 고려해야할 사항

꼬리 질문
  • Retry가 불가능한 로직이란 구체적으로 어떤 경우들인가요? 그리고 이런 케이스들을 어떻게 구분해서 처리하셨나요?
  • 낙관적 락 외에 네트워크 호출(외부 API, DB 연결 등)에서 retry를 적용한다면, 어떤 예외나 응답 코드에 대해서만 retry를 수행해야 할지 기준이 있으실까요?
  • API Rate Limit의 경우 429 Too Many Requests 응답이 오는데, 이때 응답 헤더에 Retry-After가 포함되어 있을 수 있어요. 이런 동적 대기 시간은 어떻게 처리하실 건가요?
  • HTTP Timeout의 경우도 Connection TimeoutRead Timeout이 다른데, 둘 다 retry 대상으로 보시나요? 특히 Read Timeout은 서버에서 처리가 완료되었을 수도 있는 상황인데, 이때 멱등성이 보장되지 않는 요청(POST로 데이터 생성 등)은 어떻게 처리하시겠어요?
  • 멱등성(Idempotency)에 대해서는 어떻게 생각하시나요? 예를 들어, 결제 API를 호출했는데 Read Timeout이 발생했다면, 실제로는 결제가 성공했을 수도 있잖아요. 이런 상황에서 안전하게 retry를 구현하려면 어떤 방법들이 있을까요?
  • 멱등키를 지원하지 않는 레거시 API나 외부 시스템과 연동해야 하는 상황이라면 어떻게 하시겠어요? 예를 들어, 이메일 발송 API나 SMS 발송 같은 경우 말이죠?
  • 멱등키를 사용할 때 키 생성 전략도 중요한데, 보통 어떤 방식으로 생성하시나요? UUID를 쓸지, 요청 내용의 해시값을 쓸지, 아니면 다른 방법이 있을지요?
  • "응답이 올 때까지 재시도"라고 하셨는데, 만약 정말 오랫동안 응답이 안 온다면? 최대 대기 시간이나 총 retry 시간에 대한 제한도 필요할 것 같은데 어떻게 생각하시나요?

답변 보기
  • ✅ 실무 경험: 낙관적 락 적용 시 CAS 연산 실패로 인한 Exception 발생 상황에서 Retry 로직을 구현했습니다 🔄

  • ✅ 핵심 고려사항:

    • 백오프 전략: 동시 트래픽 몰림 시 Retry 시간을 랜덤하게 줘서 재충돌 방지
    • 최대 재시도 횟수 제한: 무한 반복 방지를 위한 필수 요소
  • ✅ 꼬리질문: Retry가 불가능한 로직이란 구체적으로 어떤 경우들인가요?

    • DB가 완전히 다운된 상황
    • API Rate Limit에 걸린 상황
    • 화이트리스트 방식 채택: Retry 가능한 에러들만 명시적으로 관리하는 것이 안전
      • HTTP Timeout
      • Resource Exhausted
      • CAS로 인한 Update Fail
    • 예상치 못한 에러에 대한 무분별한 retry 방지 가능
  • ✅ 꼬리질문: API Rate Limit 상황에서 Retry-After 헤더가 있을 때 동적 대기 시간 처리 방법

    • Circuit Breaker 패턴 활용이 적절 🔌
    • 429 Too Many Requests 응답 시 Circuit Breaker를 열고, Retry-After 헤더의 시간만큼 대기 후 Half-Open 상태로 전환
    • 단순 retry보다 서버 부하를 줄이는 효과적인 방법
  • ❌ 꼬리질문: Connection Timeout vs Read Timeout 처리 방식

    • ❌ Connection Timeout은 단순히 연결 실패만이 아닙니다 🔌

      • DNS 해석 실패: 완전히 안전, retry 가능
      • TCP 3-way handshake 실패: 안전, retry 가능
      • SSL/TLS handshake 실패: 안전, retry 가능
      • HTTP 요청 전송 중 실패: ⚠️ 위험할 수 있음
    • ❌ Read Timeout은 가장 복잡한 상황입니다 ⏰

      • 서버에서 처리가 완료되었을 수도, 진행 중일 수도 있는 상태
      • 단순 retry는 위험할 수 있음
        • Connection Timeout: 서버 연결 자체 실패, 안전하게 retry 가능
        • Read Timeout: 요청은 전송되었으나 응답 지연, 서버에서 처리 중일 가능성
  • ✅ 꼬리질문: 멱등성을 활용한 안전한 retry 구현

    • 멱등키(Idempotency Key) 활용: 동일한 키로 여러 번 호출해도 한 번만 실행되도록 보장 🔑
    • 결제 API 같은 중요한 작업에서 필수적
    • 응답이 올 때까지 재시도해서 확실한 결과를 클라이언트에 전달
  • ✅ 꼬리질문: 멱등키 생성 전략

    • 기본적으로 UUID 사용
    • User-specific한 경우: User ID를 prefix로 붙여서 사용자별 구분 👤
      • 동시 처리 시 유용하고 중복 생성 감지 가능
  • ❌ 꼬리질문: 멱등키 미지원 시스템 대응 방안 (이메일/SMS 발송 등)

    • 애플리케이션 레벨 중복 방지:
      • 데이터베이스에 발송 이력 테이블 생성
      • (user_id, message_type, content_hash, created_at) 조합으로 중복 체크 📧
    • 상태 조회 API 활용:
      • 요청 ID나 transaction ID를 저장 후 상태 조회로 결과 확인
      • 예: SMS 발송 후 message_id로 delivery status 조회
    • 보상 트랜잭션 패턴:
      • 중복 발송 시 롤백 메커니즘 준비 (사과 메일 발송 등)
  • ❌ 꼬리질문: 총 retry 시간 및 대기 시간 제한 전략

    • 총 실행 시간 제한 (Total Timeout):
      • 전체 retry 프로세스가 30초를 넘지 않도록 제한 ⏰
      • 개별 재시도 간격이 늘어나더라도 총 시간 초과 시 중단
    • 단계별 백오프 + 최대 대기 시간:
      • 1회: 100ms, 2회: 200ms, 3회: 400ms...
      • 최대 5초까지만 대기, 그 이후는 5초 고정
    • Dead Letter Queue 활용:
      • 최종 실패 요청들을 별도 큐에 저장
      • 수동 처리 또는 배치 재처리 📥
    • 모니터링 및 알람:
      • retry 실패율 임계치 초과 시 즉시 알람
      • 시스템 전체 장애 가능성 빠른 감지

자바 synchronized의 락 범위와 종류

꼬리 질문
  • static synchronized method와 인스턴스 synchronized method의 락 범위 차이는?
  • synchronized method와 synchronized block의 락 객체 차이는?
  • 서로 다른 락 객체를 사용하는 synchronized block들의 동시 실행 가능성은?

답변 보기
  • ✅ 인스턴스 synchronized method들은 같은 인스턴스에서 서로 블로킹됨
  • ❌ 꼬리질문: static synchronized method와 인스턴스 synchronized method의 락 범위 차이는?
    • static synchronized method는 Class 객체를 락으로 사용 (클래스 레벨 락)
    • 인스턴스 synchronized method는 this 객체를 락으로 사용 (인스턴스 레벨 락)
    • 따라서 static과 인스턴스 메서드는 서로 다른 락이므로 동시 실행 가능 🔄
  • ❌ 꼬리질문: synchronized method와 synchronized block의 락 객체 차이는?
    • synchronized method: 자동으로 this(인스턴스) 또는 Class(static) 객체를 락으로 사용
    • synchronized block: 개발자가 명시적으로 지정한 객체를 락으로 사용
    • synchronized(lock1), synchronized(lock2)처럼 다른 객체 사용 시 동시 실행 가능 ⚡
  • ❌ 꼬리질문: 서로 다른 락 객체를 사용하는 synchronized block들의 동시 실행 가능성은?
    • 서로 다른 락 객체를 사용하면 동시 실행 가능
    • 각 락 객체는 독립적인 모니터를 가지므로 상호 간섭하지 않음

ReentrantLock의 고급 기능과 활용

꼬리 질문
  • tryLock(timeout) 기능이 언제 유용한가?
  • ReentrantLock이 synchronized보다 유리한 상황들은?

답변 보기
  • ✅ 큐 방식은 락 대기 스레드들이 대기큐에서 순서대로 대기하는 방식
  • ❌ 꼬리질문: tryLock(timeout) 기능이 언제 유용한가?
    • 데드락 방지: 일정 시간 후 락 획득을 포기하고 다른 로직 수행 🚫
    • 응답성 향상: 사용자 요청이 무한정 대기하지 않도록 타임아웃 설정
    • 장애 격리: 특정 리소스 문제가 전체 시스템을 멈추지 않도록 방어
  • ❌ 꼬리질문: ReentrantLock이 synchronized보다 유리한 상황들은?
    • 타임아웃이 필요한 경우 (tryLock)
    • 락 획득을 중단해야 하는 경우 (lockInterruptibly)
    • 공정성이 중요한 경우 (fair lock 옵션)
    • 조건 변수가 필요한 경우 (Condition 객체 활용)
    • 락 상태를 확인해야 하는 경우 (isLocked, getQueueLength 등)

Atomic 클래스의 CAS 연산 처리

꼬리 질문
  • CAS 연산이 실패했을 때 어떻게 처리되는가?

답변 보기
  • ✅ Atomic 클래스는 CAS 연산을 통해 동시성 보장
  • ✅ volatile을 활용해 메모리 가시성 문제 해결
  • ❌ 꼬리질문: CAS 연산이 실패했을 때 어떻게 처리되는가?
    • CAS 실패 시 스핀 루프(spin loop)를 통해 재시도 🔄
    • 현재 값을 다시 읽어와서 새로운 값을 계산하고 CAS 재시도
    • 성공할 때까지 반복하는 lock-free 알고리즘
    • 예: AtomicInteger.incrementAndGet()은 내부적으로 CAS 루프 사용