
기간: 2026.04.13 - 2026.04.17
커리큘럼: 최종 프로젝트 (HR 인사시스템 SaaS 플랫폼) - 평가 관리 도메인 설계 및 구현
< 평가 관리 모듈 도메인 설계 및 핵심 로직 구현 >
evaluation_season → evaluation_group → evaluation_design → evaluation_response → calibration_history 흐름으로 이어지는 평가 전체 라이프사이클을 설계하고 구현했다.EvaluationSeason을 DRAFT → ACTIVE → CLOSED 상태로 관리하고, 결과 공개는 resultsPublishedAt 타임스탬프로 별도 제어하는 구조를 만들었다. 시즌 상태와 결과 공개를 분리함으로써 종결 후 결과 공개, 또는 공개 없이 행정 종결하는 시나리오를 모두 지원하도록 설계했다.EvaluationGroup에 평가 대상자 목록과 평가자-대상자 매핑(evaluatorMapsJson)을 설계해, 자기평가(SELF), 하향(DOWNWARD), 상향(UPWARD), 동료(PEER) 등 다면평가 유형을 하나의 그룹 구조로 수용했다.EvaluationDesign에 평가 항목(sectionsJson)과 등급 설정(gradeConfigJson)을 분리 저장해, 평가 양식 자체를 데이터로 관리하고 그룹별로 다른 설계를 할당할 수 있도록 구성했다.EvaluationResponse에 answersJson, calibrationJson, normalizedScore를 두고, 평가 응답 저장 → 제출 → 캘리브레이션 등급 조정 → 결과 공개 흐름을 구현했다.startSeason()) 시점에 피평가자의 ACTIVE/COMPLETED 목표를 goalSnapshotJson으로 캡처해 각 EvaluationResponse에 저장하는 구조를 만들었다. 나중에 목표가 수정·삭제되더라도 평가 당시 목표 기준을 재현할 수 있도록 설계했다.CalibrationHistory로 등급 조정 이력을 별도 테이블에 추적해, 누가 언제 어떤 이유로 등급을 바꿨는지 감사 가능한 구조를 갖췄다.meeting_record)이 생성되는 흐름을 publishResults()에 연결했다.status(DRAFT/ACTIVE/CLOSED)와 resultsPublishedAt을 별도로 관리한 것처럼, "시스템 내부 진행 상태"와 "외부에 노출되는 공개 상태"는 독립적으로 제어할 수 있어야 다양한 운영 시나리오를 수용할 수 있다.evaluatorMapsJson을 서비스에서 objectMapper.readValue()로 직접 파싱하고 map.get("targetMemberId")처럼 문자열 키로 접근하는 구조는, 오타가 있어도 컴파일 타임에 잡히지 않고 런타임 NPE나 예외로만 발견된다. KpiDefinition처럼 전용 값 객체와 AttributeConverter를 사용하는 패턴이 일관되게 적용되어야 한다.goalSnapshotJson은 평가 당시 목표를 보여주는 데는 충분하지만, 평가 점수 계산에 achievementPct를 연산 입력으로 쓰려면 스냅샷에 achievementPctAtSnapshot, weightPct 같은 연산 가능한 수치가 명시적으로 포함되어야 한다. 목적이 다르면 저장 구조도 달라야 했다.achievementPct)이 EvaluationDesign의 KPI 섹션에 자동으로 반영되지 않으면, 정량적 성과 데이터를 쌓는 의미가 사라진다.CalibrationHistory 설계를 통해 체득했다. 현재값을 덮어쓰는 것과, 변경 전·후를 모두 보존하는 것은 완전히 다른 요구사항이며, HR 시스템처럼 책임 추적이 중요한 도메인에서는 이력 테이블이 필수다.EvaluationDesign의 섹션 구조에 SectionType(MANUAL / KPI_SCORE / PEER_FEEDBACK)을 도입해, KPI 섹션은 achievementPct를 자동 집계하고 수동 섹션만 평가자가 직접 입력하는 혼합 채점 구조로 개선할 계획이다.GoalSnapshotDto에 achievementPctAtSnapshot과 weightPct를 추가해, 스냅샷이 화면 표시뿐 아니라 점수 계산의 입력값으로도 사용 가능한 구조로 확장할 예정이다.evaluatorMapsJson을 EvaluatorMapping 값 객체와 컨버터로 타입화해, 서비스 내 수동 파싱 코드와 중복 로직을 제거할 계획이다.EvaluationResponse의 targetGoalIdsJson 필드는 goalSnapshotJson에서 ID를 추출하면 대체 가능하므로 제거해 중복 저장 문제를 해소할 예정이다.KpiTemplate → Goal → achievementPct → EvaluationResponse.score 로 이어지는 성과와 평가가 실질적으로 연결된 단일 파이프라인을 완성하는 것을 목표로 한다."평가 시스템을 만들며 깨달은 것 - 점수를 저장하는 건 쉽지만, 그 점수가 어디서 왔는지 추적 가능하고 성과 데이터와 실제로 연결되어야 비로소 의미 있는 평가 시스템이 된다."