문서

복합 스코어링

복잡한 판단을 원자적 점수로 나누고, 코드에서 직접 제어하는 가중치로 결합합니다.

여러 기준을 한꺼번에 사용해 항목 집합의 순위를 매기고 싶을 때가 자주 있습니다. 복합 스코어링은 이를 생각하는 쉬운 방법입니다. 판단을 독립적인 차원으로 나누고, 각 차원을 따로 점수 매기고, 코드에서 직접 제어하는 가중치로 결합하는 것입니다.

예: 이력서 심사

엔지니어링 직무의 이력서를 처리하고 있다고 상상해 봅시다. 여러 기준에 따라 후보의 순위를 매기고, 최종적으로 상위 X명의 후보를 추가 검토 대상으로 선정하려고 합니다.

%%{init: {"fontFamily": "Inter, sans-serif", "flowchart": {"rankSpacing": 35, "wrappingWidth": 300, "subGraphTitleMargin": {"top": 12, "bottom": 36}}}}%%
flowchart LR
    resume["candidate resume"]

    subgraph req["TypeSafe evaluates questions<br/>in parallel"]
        direction TB
        py["<b>Score:</b> Python depth"]
        lead["<b>Score:</b> team leadership"]
        arch["<b>Score:</b> system design"]
        general["<b>Score:</b> generalist"]
        %% Invisible links stack the questions; they are answered in parallel.
        py ~~~ lead ~~~ arch ~~~ general
    end

    resume -- "one request<br/>resume + 4 questions" --> req
    req -- "one response<br/>4 score answers" --> normalize["<b>normalize scores to 0–1</b><br/>divide each by 4 in your code"]
    normalize --> ic["<b>senior IC weights</b><br/>40% Python + 10% leadership<br/>40% design + 10% generalist"]
    normalize --> em["<b>engineering manager weights</b><br/>15% Python + 40% leadership<br/>20% design + 25% generalist"]
    ic --> rank["rank candidates<br/>for each role"]
    em --> rank

1단계: 각 차원을 독립적으로 점수 매기기

questions
{
  "python_depth": {
    "type": "score",
    "instructions": "How much depth of python experience does this candidate have, based on the supplied resume?",
    "criteria": [
      "No Python experience mentioned",
      "Mentioned but no detail",
      "Used in projects, some specifics",
      "Primary language, multiple projects",
      "Deep expertise: architecture, performance, libraries"
    ]
  },
  "team_leadership": {
    "type": "score",
    "instructions": "How much experience does this candidate have managing or leading engineering teams?",
    "criteria": [
      "No management experience mentioned",
      "Informal mentorship or tech lead role",
      "Led a small team or project",
      "Managed a team with direct reports",
      "Managed multiple teams or an engineering org"
    ]
  },
  "system_design": {
    "type": "score",
    "instructions": "How much experience does this candidate have designing large-scale or distributed systems?",
    "criteria": [
      "No architecture work mentioned",
      "Contributed to design discussions",
      "Designed components of a larger system",
      "Owned architecture of a significant system",
      "Designed systems at scale across multiple domains"
    ]
  },
  "generalist": {
    "type": "score",
    "instructions": "How much evidence is there that this candidate picks up unfamiliar tools, roles, or domains outside their core specialty?",
    "criteria": [
      "Only one domain or role mentioned",
      "Some variety but within a narrow field",
      "Worked across a few different areas or tech stacks",
      "Regularly moved between domains, wore many hats",
      "Track record of ramping up in unfamiliar areas and delivering"
    ]
  }
}

2단계: 가중치로 결합하기

각 차원은 0–1로 정규화되고 가중치가 부여됩니다. 가중치는 개별 점수의 뉘앙스를 하나도 잃지 않으면서 각 차원의 상대적 중요도를 조정하는 쉬운 방법을 제공합니다.

scoring.py

py      = response.answers["python_depth"].score / 4
lead    = response.answers["team_leadership"].score / 4
arch    = response.answers["system_design"].score / 4
general = response.answers["generalist"].score / 4

# Senior IC
ic_score = (0.40 * py) + (0.10 * lead) + (0.40 * arch) + (0.10 * general)

# Engineering Manager
em_score = (0.15 * py) + (0.40 * lead) + (0.20 * arch) + (0.25 * general)

이를 통해 복합 점수를 기준으로 후보의 순위를 매길 수 있습니다. 하지만 더 중요한 것은, 최종 점수가 정확히 어떻게 계산되는지에 대한 가시성을 준다는 점입니다. 가장 높은 순위의 후보가 기대와 맞지 않으면, 가중치를 조정해 올바른 균형을 찾을 수 있습니다.