[BE-15] 면접 회차 기록 API

작업 내용 (설계 의도)

근거 TDD: 20260722-타깃-공고-알림-및-지원-히스토리-tdd.md — “API 계약”, “클래스 역할 정의”

변경 사항

한 지원 건에 여러 면접 회차를 추가·수정하는 API입니다(FR-46).

핵심 설계 의도:

  • 면접 회차는 지원 상태값이 아니라 별도 기록입니다. INTERVIEWING이라는 단일 상태 아래에 1차·2차·3차가 각각 독립 레코드로 존재합니다. 회차를 상태값으로 만들면(INTERVIEWING_1, INTERVIEWING_2…) 전이 표가 회차 수만큼 폭발하고, 회차 수가 회사마다 다르다는 현실을 표현할 수 없습니다.
  • 레이블은 사용자 지정 문자열입니다(“1차 기술면접”, “임원면접”, “컬처핏”). 회사마다 부르는 이름이 달라 enum으로 고정할 수 없습니다.
  • 면접 결과 기록이 지원 상태를 자동 전이시키지 않습니다. 1차 합격이 곧 다음 단계 진입은 아니며(대기 기간 존재), 사용자가 명시적으로 상태를 전이합니다(BE-14). 두 개념을 자동 연결하면 사용자 의도와 어긋난 이력이 쌓입니다.
  • unique(application_id, round_number)로 같은 회차 중복 등록을 막습니다.
  • 일정 변경(reschedule)과 결과 기록(recordResult)을 PATCH 하나로 받되, 도메인에서는 별개 행위 메서드로 분리합니다.
  • 종료된 지원(종료 상태)에도 면접 회차 조회는 가능하지만 신규 추가는 거부합니다 — 이미 끝난 지원에 면접이 추가되는 건 데이터 오류입니다.

범위: InterviewApiController, AddInterviewUseCase, UpdateInterviewUseCase, InterviewDomainService.

의존

  • BE-04

다이어그램

처리 흐름

sequenceDiagram
    participant U as 사용자
    participant C as InterviewApiController
    participant UC as AddInterviewUseCase
    participant D as InterviewDomainService
    participant A as Application
    participant I as Interview
    participant R as InterviewRepository
    U->>C: POST /api/applications/{id}/interviews
    C->>UC: execute(command)
    UC->>D: add(applicationId, round, label, scheduledAt)
    D->>A: isTerminal()
    alt 종료된 지원
        A-->>D: true → 도메인 예외
        C-->>U: 409 Conflict
    else 진행 중
        D->>I: create(round, label, scheduledAt)
        D->>R: save(interview)
        C-->>U: 201 {interviewId}
    end

클래스 의존

flowchart LR
    subgraph Presentation["presentation/application"]
        Api[InterviewApiController]
    end
    subgraph Application["application/application"]
        UC1[AddInterviewUseCase]
        UC2[UpdateInterviewUseCase]
    end
    subgraph Domain["domain/application"]
        DS[InterviewDomainService]
        Interview[Interview]
        Result[InterviewResult]
        Repo[InterviewRepository]
    end
    Api --> UC1
    Api --> UC2
    UC1 --> DS
    UC2 --> DS
    DS --> Interview
    Interview --> Result
    DS --> Repo

테스트 케이스

  • 1차 면접 회차를 추가하면 201과 함께 회차가 저장된다
  • 같은 지원에 1차·2차를 추가하면 2건이 회차 순으로 조회된다
  • 같은 회차 번호를 중복 등록하면 409를 반환한다
  • 사용자 지정 레이블(“임원면접”)이 그대로 저장·조회된다
  • 면접 결과를 PASSED로 기록해도 지원 상태는 전이되지 않는다
  • 일정 변경 PATCH가 scheduledAt만 갱신하고 결과를 덮어쓰지 않는다
  • 일정 없이(scheduledAt=null) 회차를 먼저 추가할 수 있다
  • 종료 상태(REJECTED)인 지원에 면접 회차를 추가하면 409를 반환한다
  • 종료 상태인 지원의 기존 면접 회차 조회는 정상 동작한다
  • 존재하지 않는 지원 ID로 회차를 추가하면 404를 반환한다
  • 회차 번호가 0 이하이면 400을 반환한다