Repository navigation
feat: 직군을 개발 4종 → 개발 8종 + 비개발 12종으로 확장 - #266
Merged
Merged
Conversation
서비스 대상은 IT 직군이 아니라 **취준생 전반**인데, 면접 시작 화면의 직군
선택지가 프론트엔드·백엔드·인프라·DBA 넷뿐이었다. 개발자가 아닌 지원자는
고를 수 있는 게 없었다.
## 직군
개발 FRONTEND BACKEND INFRA DBA + MOBILE DATA_AI SECURITY QA
비개발 PLANNING MARKETING SALES HR FINANCE DESIGN
MANUFACTURING RND CUSTOMER_SERVICE LOGISTICS LEGAL PUBLIC
개발은 세부 직무, 비개발은 대분류 단위다. 입도가 섞이지만 기존 4개를 그대로
둬야 이미 쌓인 세션·통계가 유지된다(enum 이름이 DB 에 문자열로 저장된다).
더 좁은 직무는 **직무 맞춤 모드**(회사명 + 채용공고)가 받는다 — 자유 입력 창구는
이미 있다.
## 평가 관점을 직군의 언어로 썼다
이게 이름만 늘리는 것과의 차이다. 기본 fallback 이 "기술 정확성, 깊이,
trade-off" 였는데, 영업·인사 지원자에게 그 기준을 들이대면 **점수의 근거가
통째로 헛돈다.** 기본 문구를 "직무 이해도, 판단의 근거, 경험의 구체성" 으로
바꾸고, 20개 직군마다 실무 관점을 따로 썼다.
영업 고객 문제 파악과 제안 논리, 거절·이견 대응, 파이프라인 관리
인사 채용·평가 기준의 공정성, 노동 관계 법규, 비밀 유지 감각
법무 계약·규정 해석, 법적 위험 식별, 사업 요구와 준법의 조율
## 목록이 네 군데에 흩어져 있다
enum · Flyway CHECK · Pydantic Literal · 프론트 선택지. 하나만 빠뜨리면 그
직군 세션이 **INSERT 에서 터지거나**(CHECK) 메시지 검증에서 튕겨 조용히 DLQ 로
간다. 사람이 네 곳을 동시에 맞추는 일을 믿지 않는다:
- AI: 5곳에 복사돼 있던 Literal 을 `model/messages/job_category.py` 하나로
- 프론트: 선택 화면과 히스토리 카드가 각자 들고 있던 라벨 맵을 하나로
(한쪽만 고치면 히스토리에 영어 코드가 그대로 뜬다)
- Java 테스트: enum ↔ 마이그레이션 CHECK 대조
- Python 테스트: Literal ↔ 같은 마이그레이션 파일 대조
가드가 실제로 잡는지 확인했다 — 마이그레이션에서 SALES 를 빼니 양쪽 다 실패했다.
## 검증
- `JobCategoryPersistenceTest`(@PostgresRepositoryTest): **20개 직군 전부**
실제 PostgreSQL 에 INSERT 되는지 + 개발/비개발 다중 선택이
session_job_categories 까지 저장되는지. CHECK 가 두 곳이라 한 곳만 고쳐도
절반은 통과하기 때문에 둘 다 건드린다.
- 백엔드 338건 / AI 431건 / 프론트 201건 통과
## UI·카피
선택지를 개발/비개발로 나눴다 — 20개를 한 덩어리로 늘어놓으면 비개발 지원자가
자기 직군을 찾기 전에 개발 직무만 훑고 나간다.
"IT 면접 시뮬레이터" → "AI 모의면접 시뮬레이터"(타이틀·OG·트위터·히어로),
README·docs·루트 CLAUDE.md 도 같이. GitHub 레포 분석은 그대로 두고 개발 직군용
자료로 남긴다(`isEngineering()` / `isEngineeringJob()` 추가).
## 남은 것
점수 축 이름이 `technical_accuracy`("기술 정확도")다. 비개발 직군에는 어울리지
않지만 DB 컬럼·API 필드·프론트 표시가 묶여 있어 별도 PR 로 다룬다.
This was referenced Sep 29, 2026
i3months
added a commit
to i3months/stackup
that referenced
this pull request
Oct 6, 2026
Team-StackUp#266 으로 직군을 20종으로 늘렸지만 두 가지가 남았다. 1. 면접을 만들 때마다 직군을 다시 고르게 한다. 대부분 매번 같은 값이다. 2. 직군만으로는 질문 맥락이 얇다. **같은 '생산·품질' 이라도 반도체 공정과 건설 현장은 묻는 것이 전혀 다르다.** ## 산업은 열거하지 않는다 직군은 평가 관점(_DOMAIN_TECH_GUIDE)을 큐레이션해야 해서 유한 집합이 맞지만, 산업은 프롬프트 맥락으로만 쓰인다. 열거하면 "IT 직군만 있던" 문제가 그대로 반복된다 — 반도체·건설·토목을 넣어도 조선·방산·바이오·수직농업은 빠지고, 빠진 사람은 또 고를 게 없다. 자유 입력 + datalist 제안으로 둔다. CHECK 제약도, Literal 도, 4곳 동기화도 필요 없다. 경력 수준만 CHECK 로 막는다 — 질문 난이도를 가르는 값이라 오타가 조용히 흘러가면 안 된다. ## profile 슬라이스를 따로 둔 이유 처음엔 User 에 필드를 붙였다. ArchUnit 이 막았다: Cycle between top-level domains found: user -> session -> user User 가 JobCategory(session 슬라이스)를 참조하면 순환이다. OAuthProvider 를 user.domain 에 둔 것과 같은 함정이다. profile 이 user·session 을 의존하고 역방향이 없으므로 순환이 없다. users 테이블을 부풀리지 않는 부수 효과도 있다. ## 프로필 → 세션은 프론트 프리필로 SessionService 가 프로필을 읽으면 session→profile 이 되어 다시 순환이다. 프론트가 프로필을 읽어 기본값을 채우고 사용자가 그 자리에서 바꿀 수 있으며, 세션은 **실제로 쓰인 값**만 interview_sessions.industry 에 기록한다. 프로필은 나중에 바뀌므로 "이 면접이 어떤 맥락이었는지" 는 세션이 스스로 남겨야 한다 (직군을 세션에 복사해 두는 것과 같은 이유). 사용자가 이미 건드린 값은 덮지 않는다 — 프로필은 기본값이지 강제값이 아니다. ## null 과 빈 값의 의미가 다르다 null 은 "그대로 두기", 빈 목록/빈 문자열은 "지우기". 계정 화면이 일부 항목만 보내도 나머지가 날아가면 안 되는데, 그러면 비우는 수단이 사라지기 때문이다. ## 프롬프트 산업이 있으면 그 현장의 언어로 묻게 하되, **"산업은 질문의 맥락이지 새로운 근거가 아니다 — 자료에 없는 산업 지식을 지어내 묻지 않는다"** 를 명시했다. 비어 있으면 "(지정 없음)" 이 들어가 지침이 무시된다. 빈 값을 그대로 흘리면 프롬프트에 None 이 박혀 LLM 이 산업 이름으로 읽을 수 있다. ## 검증 - UserJobProfilePersistenceTest(@PostgresRepositoryTest): 실제 PostgreSQL 에서 저장·조회, **제안 목록에 없는 산업("수직농업 스마트팜")도 그대로 저장**, 개발+비개발 혼합, 모든 경력 수준이 CHECK 통과 - AI: 산업이 프롬프트 입력까지 실제로 도달하는지 + 빈 값 3종이 모두 "(지정 없음)" 이 되는지 + 프롬프트에 슬롯과 지침이 둘 다 있는지 - 백엔드 353 / AI 434 / 프론트 201 통과
i3months
added a commit
to i3months/stackup
that referenced
this pull request
Oct 6, 2026
Team-StackUp#266 에서 남겨 둔 것. 영업 지원자의 피드백이 이렇게 나오고 있었다: 페르소나 "영업·영업관리 직군 시니어 **기술** 면접관" 평가 축 이름 "**기술** 정확도·깊이" 화면 표시 "기술 정확도" **표시 문제가 아니다.** 페르소나와 축 이름은 프롬프트에 들어가 평가의 틀을 정한다 — 기술 면접관에게 기술 정확도를 매기라고 시키면 영업 지원자의 점수 근거가 그쪽으로 끌려간다. 직군별 실제 관점(_DOMAIN_TECH_GUIDE)은 이미 구분돼 있는데 그 위에 덮인 이름이 그걸 되돌리고 있었다. persona "{직군} 직군 시니어 실무 면접관" dimension_name "직무 역량·깊이" 화면 표시 "직무 역량" DB 컬럼(technical_accuracy)·API 필드는 그대로 둔다. 값의 의미는 처음부터 "직군 패널이 매긴 직무 역량" 이었고 틀린 건 이름뿐이라, 스키마를 흔들 이유가 없다. 용어집에 대응을 적어 뒀다. ## 곁가지 — 단일 직군 평가위원 라벨 "기술" 이던 라벨이 직군명("백엔드")이 된다. 다직군 경로는 원래 직군명을 썼으므로 이제 단일/다직군이 일관되고, 요약의 "[백엔드] 설계 깊이" 가 "[기술] 설계 깊이" 보다 구체적이다. ## 회귀 테스트 - 20개 직군 **전부** 에 대해 페르소나에 "기술 면접관" 이, 축 이름에 "기술" 이 들어가지 않는지 - 영업 스펙이 자연스럽게 읽히고 **평가 관점은 여전히 영업의 것**인지 ("고객 문제 파악") - 중립화가 개발 직군의 관점까지 뭉개지 않았는지 (백엔드에 "트랜잭션") AI 437 / 백엔드 353 / 프론트 201 통과.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
서비스 대상은 IT 직군이 아니라 취준생 전반인데, 면접 시작 화면의 직군 선택지가
프론트엔드·백엔드·인프라·DBA 넷뿐이었다. 개발자가 아닌 지원자는 고를 수 있는 게 없었다.
직군
개발은 세부 직무, 비개발은 대분류 단위다. 입도가 섞이지만 기존 4개를 그대로 둬야 이미 쌓인
세션·통계가 유지된다(enum 이름이 DB 에 문자열로 저장된다). 더 좁은 직무는 직무 맞춤
모드(회사명 + 채용공고)가 받는다 — 자유 입력 창구는 이미 있다.
이름만 늘리는 것과의 차이 — 평가 관점
기본 fallback 이 이랬다:
영업·인사 지원자에게 이 기준을 들이대면 점수의 근거가 통째로 헛돈다. 기본 문구를
"직무 이해도, 판단의 근거, 경험의 구체성"으로 바꾸고 20개 직군마다 실무 관점을 따로 썼다:
목록이 네 군데에 흩어져 있다
enum· FlywayCHECK· PydanticLiteral· 프론트 선택지. 하나만 빠뜨리면 그 직군 세션이INSERT 에서 터지거나(CHECK) 메시지 검증에서 튕겨 조용히 DLQ 로 간다.
사람이 네 곳을 동시에 맞추는 일을 믿지 않는다:
model/messages/job_category.py하나로(한쪽만 고치면 히스토리에 영어 코드가 그대로 뜬다)
가드가 실제로 잡는지 확인했다 — 마이그레이션에서
SALES를 빼니 양쪽 다 실패했다.검증 — "저장된다"를 실제로 본다
JobCategoryPersistenceTest(@PostgresRepositoryTest, 실제 PostgreSQL):session_job_categories까지 저장되는지(CHECK 가 두 곳이라 한 곳만 고쳐도 절반은 통과한다)
enum 만 늘리고 마이그레이션을 빠뜨리면 그 실패는 사용자가 면접을 시작하는 순간에만
드러난다. 그래서 여기서 막는다.
UI·카피
선택지를 개발/비개발로 나눴다 — 20개를 한 덩어리로 늘어놓으면 비개발 지원자가 자기 직군을
찾기 전에 개발 직무만 훑고 "여긴 개발자용이구나" 하고 나간다.
IT 면접 시뮬레이터→AI 모의면접 시뮬레이터(타이틀·OG·트위터·히어로), README·docs·루트CLAUDE.md 도 같이. GitHub 레포 분석은 그대로 두고 개발 직군용 자료로 남긴다
(
isEngineering()/isEngineeringJob()추가).남은 것 (별도 PR)
점수 축 이름이
technical_accuracy("기술 정확도")다. 비개발 직군에는 어울리지 않지만DB 컬럼·API 필드·프론트 표시가 묶여 있어 따로 다루는 게 맞다.