Skip to content

[Fix] 원문 기준 공고명 추출 및 생성 결과 보정 - #218

Merged
whc9999 merged 2 commits into
devfrom
fix/extract-original-job-posting-name
Jul 29, 2026
Merged

[Fix] 원문 기준 공고명 추출 및 생성 결과 보정#218
whc9999 merged 2 commits into
devfrom
fix/extract-original-job-posting-name

Conversation

@whc9999

@whc9999 whc9999 commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

✨ 어떤 이유로 PR를 하셨나요?

  • feature 병합
  • 버그 수정(아래에 issue #를 남겨주세요)
  • 코드 개선
  • 코드 수정
  • 배포
  • 기타(아래에 자세한 내용 기입해주세요)

📋 세부 내용 - 왜 해당 PR이 필요한지 작업 내용을 자세하게 설명해주세요

  • 공고 추출 응답에 postingName 필드 추가
  • 원문에 명시된 공고 제목만 그대로 추출하도록 프롬프트 수정
  • 공고명이 없거나 불확실한 경우 빈 문자열을 유지하도록 처리
  • 생성 단계에서 회사명과 직무명으로 공고명을 임의 생성하지 않도록 수정
  • 기존 요청 DTO 생성자 호환성 유지
  • 원문 공고명 전달 및 빈 공고명 유지 테스트 추가

📸 작업 화면 스크린샷

⚠️ PR하기 전에 확인해주세요

  • 로컬테스트를 진행하셨나요?
  • 머지할 브랜치를 확인하셨나요?
  • 관련 label을 선택하셨나요?

🚨 관련 이슈 번호 [ ]

Summary by CodeRabbit

  • 새로운 기능

    • 채용 공고 생성 및 추출 결과에 공고명이 포함됩니다.
    • 공고명 힌트를 제공하면 생성 결과에 해당 공고명이 우선 반영됩니다.
    • 공고명이 없는 경우에도 빈 값으로 일관되게 처리됩니다.
  • 버그 수정

    • 추출된 공고명이 생성 단계로 올바르게 전달되도록 개선했습니다.

- 공고 추출 응답에 postingName 필드 추가
- 원문에 명시된 공고 제목만 그대로 추출하도록 프롬프트 수정
- 공고명이 없거나 불확실한 경우 빈 문자열을 유지하도록 처리
- 생성 단계에서 회사명과 직무명으로 공고명을 임의 생성하지 않도록 수정
- 기존 요청 DTO 생성자 호환성 유지
- 원문 공고명 전달 및 빈 공고명 유지 테스트 추가
@whc9999 whc9999 self-assigned this Jul 29, 2026
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@whc9999, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 44060aec-9131-4a94-aef7-51167861cf3b

📥 Commits

Reviewing files that changed from the base of the PR and between 1424bf7 and 52a2b60.

📒 Files selected for processing (3)
  • src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java
  • src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiServiceTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestServiceTest.java
📝 Walkthrough

Walkthrough

추출 응답과 생성 요청에 postingNamepostingNameHint를 추가하고, ingest 흐름에서 공고명을 전달하도록 변경했습니다. AI 프롬프트와 응답 정규화·폴백 로직 및 관련 테스트도 갱신했습니다.

Changes

공고명 처리 흐름

Layer / File(s) Summary
공고명 DTO 및 추출 응답 확장
src/main/java/com/jobdri/jobdri_api/domain/jobposting/dto/..., src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java
JobPostingGenerateRequestJobPostingExtractResponse에 공고명 필드를 추가하고, 추출 프롬프트·응답 정규화·폴백에 postingName을 반영합니다.
공고명 힌트 생성 및 정규화
src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java, src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestService.java
추출된 공고명을 생성 요청의 postingNameHint로 전달하며, 생성 결과와 폴백에서 해당 힌트를 우선 사용합니다.
공고명 전파 및 정규화 검증
src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/*Test.java
원문 공고명 유지, 빈 공고명 유지, ingest 요청의 postingNameHint 전달을 검증합니다.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant JobPostingIngestService
  participant JobPostingAiService
  participant OpenAI
  JobPostingIngestService->>JobPostingAiService: postingNameHint 포함 생성 요청
  JobPostingAiService->>OpenAI: postingName 생성 규칙 포함 프롬프트 전송
  OpenAI-->>JobPostingAiService: 생성 응답 반환
  JobPostingAiService->>JobPostingAiService: postingNameHint 우선 정규화
  JobPostingAiService-->>JobPostingIngestService: postingName 포함 결과 반환
Loading

Possibly related PRs

Suggested labels: 🐛 fix, ✨ feat, ♻️ refactor

Suggested reviewers: shinae1023

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed 제목이 공고명 추출과 생성 결과 보정이라는 핵심 변경을 잘 요약합니다.
Description check ✅ Passed 템플릿의 목적, 세부 내용, 사전 확인 항목이 채워져 있어 전반적으로 충분합니다.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/extract-original-job-posting-name

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java (2)

385-410: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

AI가 만든 공고명을 원문 대조 없이 저장하지 마세요.

Line 401은 response.postingName()을 빈 값 여부만 정규화합니다. 따라서 모델이 원문에 없는 "회사명 직무명 채용"을 반환해도 그대로 ingest 단계의 postingNameHint가 되어 저장될 수 있습니다. 프롬프트는 지시일 뿐 보장 장치가 아니므로, 텍스트 원문 또는 이미지 OCR 원문과 정규화된 제목을 대조하고 불일치하면 빈 문자열로 처리해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java`
around lines 385 - 410, Update normalizeResponse so response.postingName() is
validated against rawText (including the OCR source represented by it) before
being used as the postingNameHint; retain it only when the normalized title is
supported by the source text, otherwise pass an empty string. Keep the existing
defaultString normalization and other response fields unchanged.

681-707: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

postingNameHint == null로 공고명 합성을 하지 마세요.

/generate API는 JobPostingGenerateRequestpostingNameHint를 검증 없이 받아 null도 전달하고, 이 상태가 기존 11자 매개 생성자 호출 경로와 똑같이 처리됩니다. 실제 기존 11자 생성자는 postingNameHintnull로 넘기도록 되어 있으니, null"무엇이든"을 같은 “공고명 유지” 신호로 쓰면 빈 공고명 요청이 AI 응답/jobTitleHint로 합성됩니다. 누락/빈 공고명 요청만큼은 빈 문자열을 유지하도록 명시적으로 처리하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java`
around lines 681 - 707, Update normalizeGeneratedResponse so a null
postingNameHint produces an empty posting name instead of falling back to
response.postingName() or request.jobTitleHint(). Preserve every non-null
postingNameHint value, including blank strings, unchanged, and leave the
remaining normalization logic intact.
src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestServiceTest.java (1)

130-138: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

테스트 원문에 공고명을 포함하세요.

Line 131의 postingName은 "2026 해커스 클라우드 엔지니어 공개채용"인데, 테스트 원문인 Line 137의 "채용 공고 원문"에는 해당 제목이 없습니다. 이 fixture는 원문에 없는 공고명도 정상 추출된 것으로 간주하므로, source-only 요구사항을 검증하지 못합니다. rawText에 실제 제목을 포함하거나 이미지 OCR 원문을 별도로 구성하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestServiceTest.java`
around lines 130 - 138, Update the test fixture used by
JobPostingIngestServiceTest so the rawText passed to JobPostingExtractResponse
includes the extracted postingName, “2026 해커스 클라우드 엔지니어 공개채용”; alternatively,
use a separate image-OCR source containing that title. Ensure the fixture
validates source-only extraction rather than accepting a title absent from the
original text.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiServiceTest.java`:
- Around line 274-346: Update the tests around generateJobPosting to exercise
the public failure-recovery path instead of invoking private
normalizeGeneratedResponse directly. Mock or otherwise force the external AI
call to fail, then verify that createFallbackGeneratedResponse preserves the
request hint in postingName for both a non-empty original posting name and an
empty one, using the asynchronous result from generateJobPosting.

---

Outside diff comments:
In
`@src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java`:
- Around line 385-410: Update normalizeResponse so response.postingName() is
validated against rawText (including the OCR source represented by it) before
being used as the postingNameHint; retain it only when the normalized title is
supported by the source text, otherwise pass an empty string. Keep the existing
defaultString normalization and other response fields unchanged.
- Around line 681-707: Update normalizeGeneratedResponse so a null
postingNameHint produces an empty posting name instead of falling back to
response.postingName() or request.jobTitleHint(). Preserve every non-null
postingNameHint value, including blank strings, unchanged, and leave the
remaining normalization logic intact.

In
`@src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestServiceTest.java`:
- Around line 130-138: Update the test fixture used by
JobPostingIngestServiceTest so the rawText passed to JobPostingExtractResponse
includes the extracted postingName, “2026 해커스 클라우드 엔지니어 공개채용”; alternatively,
use a separate image-OCR source containing that title. Ensure the fixture
validates source-only extraction rather than accepting a title absent from the
original text.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b1549408-0e02-4149-9a34-8fd02a56b20a

📥 Commits

Reviewing files that changed from the base of the PR and between 8b51086 and 1424bf7.

📒 Files selected for processing (6)
  • src/main/java/com/jobdri/jobdri_api/domain/jobposting/dto/request/JobPostingGenerateRequest.java
  • src/main/java/com/jobdri/jobdri_api/domain/jobposting/dto/response/JobPostingExtractResponse.java
  • src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiService.java
  • src/main/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestService.java
  • src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiServiceTest.java
  • src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingIngestServiceTest.java

Comment on lines +274 to +346
@Test
@DisplayName("공고 생성 결과는 AI가 바꾼 제목 대신 원문에서 추출한 공고명을 유지한다")
void normalizeGeneratedResponsePreservesExtractedPostingName() {
JobPostingGenerateRequest request = new JobPostingGenerateRequest(
"테스트 기업",
null,
100L,
"채용 요약",
"",
"주요 업무",
"자격 요건",
"우대 사항",
null,
"백엔드 개발자",
"2026 백엔드 개발자 공개채용"
);
JobPostingGenerateResponse generated = new JobPostingGenerateResponse(
"테스트 기업 백엔드 채용",
"테스트 기업",
"백엔드 개발자",
"주요 업무",
"자격 요건",
"우대 사항",
"요약"
);

JobPostingGenerateResponse normalized = ReflectionTestUtils.invokeMethod(
jobPostingAiService,
"normalizeGeneratedResponse",
generated,
request
);

assertThat(normalized).isNotNull();
assertThat(normalized.postingName()).isEqualTo("2026 백엔드 개발자 공개채용");
}

@Test
@DisplayName("원문에 공고명이 없으면 생성 결과의 공고명도 빈 문자열로 유지한다")
void normalizeGeneratedResponseKeepsMissingPostingNameEmpty() {
JobPostingGenerateRequest request = new JobPostingGenerateRequest(
"테스트 기업",
null,
100L,
"채용 요약",
"",
"주요 업무",
"자격 요건",
"우대 사항",
null,
"백엔드 개발자",
""
);
JobPostingGenerateResponse generated = new JobPostingGenerateResponse(
"테스트 기업 백엔드 채용",
"테스트 기업",
"백엔드 개발자",
"주요 업무",
"자격 요건",
"우대 사항",
"요약"
);

JobPostingGenerateResponse normalized = ReflectionTestUtils.invokeMethod(
jobPostingAiService,
"normalizeGeneratedResponse",
generated,
request
);

assertThat(normalized).isNotNull();
assertThat(normalized.postingName()).isEmpty();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

생성 실패 fallback을 공개 메서드 기준으로 검증하세요.

추가된 테스트는 private normalizeGeneratedResponse만 직접 호출하며, generateJobPosting의 외부 호출 실패 후 createFallbackGeneratedResponse로 들어가는 경로는 검증하지 않습니다. 빈 공고명과 원문 공고명이 있는 요청 각각에 대해 생성 실패를 유도하고, 공개 메서드 결과의 postingName이 힌트를 그대로 유지하는지 확인해야 합니다.

As per path instructions, 실패 복구 경로를 포함한 비동기·외부 호출 시나리오를 충분히 검증해야 합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/jobdri/jobdri_api/domain/jobposting/service/JobPostingAiServiceTest.java`
around lines 274 - 346, Update the tests around generateJobPosting to exercise
the public failure-recovery path instead of invoking private
normalizeGeneratedResponse directly. Mock or otherwise force the external AI
call to fail, then verify that createFallbackGeneratedResponse preserves the
request hint in postingName for both a non-empty original posting name and an
empty one, using the asynchronous result from generateJobPosting.

Source: Path instructions

- 추출된 공고명이 원문에 존재하는지 정규화 후 검증
- 원문에서 확인되지 않는 공고명은 빈 문자열로 처리
- 공고명 힌트가 null인 경우 임의 제목 생성을 차단
- AI 호출 실패 시 공고명 힌트 보존 여부를 public API 경로로 검증
- 공고명 추출 테스트 fixture에 원문 근거 추가
@whc9999
whc9999 merged commit 08da0c9 into dev Jul 29, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant