[BE-66] 교차 회사 목록에 추천도 노출 · 추천도 정렬 (FR-78 + FR-96 연결)
작업 내용 (설계 의도)
근거 TDD: 20260808-지원관리-확장-tdd.md — “API 계약 1단계 교차 회사 공고 목록(recommendation 필드)”, “단계별 점진 노출”
변경 사항
- BE-52가 만든
CrossCompanyJobPostingItem.recommendation필드를 실제 값으로 채웁니다. 1단계 배포 시점에는 항상null이었고(하위 호환), 2단계에서 recommendation 컨텍스트가 생기면서 채울 수 있게 됩니다. - id 집합 배치 조회 1회로 가져옵니다 — 페이지 항목의
jobPostingId집합으로RecommendationDomainService.findAllBy(ids)한 번. 항목마다 조회하지 않습니다. - 정렬 옵션
RECOMMENDATION_DESC추가 — 총점 내림차순, 미평가·평가 불가는 마지막, 동순위는 마감일 오름차순 →id오름차순. 총점은job_posting_recommendations조인으로 SQL 정렬합니다(메모리 정렬 금지 — 페이지네이션과 결합 불가). recommendationGrade필터 추가 —grade=RECOMMENDED&grade=STRONGLY_RECOMMENDED형태 OR 필터. PRD Success Metrics “등급별 저장률” 측정의 조회 수단이 됩니다.- 하위 호환 — 기존 파라미터·필드는 변경하지 않고 추가만 합니다. 추천도가 없는 공고는
recommendation: null로 계속 내려갑니다.
파일 소유: ListAllJobPostingsUseCase.kt·CrossCompanyPostingResponseMapper.kt·JobPostingSearchRepositoryImpl.kt를 수정합니다. 같은 wave(BE-65)와 파일이 겹치지 않습니다 — BE-65는 application/recommendation·presentation/recommendation만 건드립니다.
의존
- BE-52 (교차 목록 API — 1단계)
- BE-63 (추천도 결과 저장)
다이어그램
처리 흐름
sequenceDiagram participant FE as web(SPA) participant C as JobPostingApiController participant U as ListAllJobPostingsUseCase participant S as JobPostingSearchDomainService participant R as RecommendationDomainService FE->>C: GET /api/job-postings?sort=RECOMMENDATION_DESC&grade=RECOMMENDED C->>U: execute(command) U->>S: search(criteria + 추천도 정렬·등급 필터) S-->>U: 페이지 (SQL 정렬) U->>R: findAllBy(jobPostingIds) 배치 1회 U->>U: recommendation 필드 채움 U-->>C: PageResponse C-->>FE: 200
클래스 의존
flowchart LR subgraph Application["application/posting"] UC[ListAllJobPostingsUseCase] Mapper[CrossCompanyPostingResponseMapper] end subgraph Domain["domain"] SDS[JobPostingSearchDomainService] RDS[RecommendationDomainService] end subgraph Infra["infrastructure/posting"] Impl[JobPostingSearchRepositoryImpl] end UC --> Mapper UC --> SDS UC --> RDS SDS --> Impl
테스트 케이스
- 평가된 공고의
recommendation에 점수·등급·상한 여부가 채워진다 - 미평가 공고의
recommendation이 null이다 (하위 호환) NOT_EVALUABLE공고는totalScore=null+notEvaluableReason이 채워진다- 20건 페이지에 대해 추천도 조회가 1회만 발생한다 (N+1 방지)
sort=RECOMMENDATION_DESC에서 총점 내림차순으로 정렬된다sort=RECOMMENDATION_DESC에서 미평가 공고가 마지막에 온다sort=RECOMMENDATION_DESC동점 시 마감일 오름차순, 그다음 id 오름차순이다grade=RECOMMENDED필터로 해당 등급만 조회된다grade를 2개 지정하면 OR로 조회된다- 추천도 정렬 시 페이지 1·2 사이 항목 중복·누락이 0건이다
- 기존 파라미터(
watchStatus·platform등) 동작이 변경되지 않는다 (회귀) - 상한이 적용된 공고의
capApplied=true, 해제된 공고의capReleased=true가 노출된다