지원 전략 - 직무 고르기·지원 기록·불합격에서 배우기
이 장에서 배우는 것
지원은 준비가 끝났음을 증명하는 마지막 시험이 아니다. 내가 해 온 일과 채용하는 쪽이 맡기려는 일이 얼마나 맞는지 확인하는 과정이다. 짧은 기간에 팀으로 서비스를 완성하고, 역할을 나누고, 일정 안에 결과를 만든 경험은 지원할 때 꺼낼 수 있는 근거다. 여기에 이전 직장에서 익힌 업무 지식과 협업 경험이 더해질 수도 있다. 다만 같은 경험도 어떤 직무에 지원하느냐에 따라 설명할 지점이 달라진다.
앞 장에서 질문에 답하는 구조를 연습했다면, 이제 그 답변을 어느 채용 공고에서 사용할지 정할 차례다. 이 장에서는 직무 이름을 외우기보다 실제 업무를 읽고, 지원 결과를 기록하고, 다음 주 행동 하나를 바꾸는 방법을 다룬다. 기록을 집계하는 작은 Python 도구도 만든다. 도구가 계산하는 통과율은 내 지원 기록을 요약한 값이며, 취업 가능성을 예측하는 점수가 아니다.
- 직무 이름과 사업 형태를 구분하고, 공고에서 실제 담당 업무를 찾는다.
- 지원 기록에 단계별 결과와 확인 가능한 근거를 남긴다.
- 서류·코딩 테스트·면접의 통과율을 올바른 분모로 계산한다.
- 탈락 원인을 사실과 가설로 나누고, 다음 지원에서 확인할 보완 행동을 고른다.
- 지원과 회복 시간을 함께 배치해 지속할 수 있는 주간 속도를 만든다.
문제 상황
수료 후 네 번째 주다. 팀 프로젝트에서 주문 조회 기능과 관리 화면 일부를 맡았고, 배포까지 마쳤다. 채용 공고를 열어 보니 웹 백엔드, 프런트엔드, 시스템 통합, 솔루션 개발, 품질 보증이라는 말이 한꺼번에 나온다. 익숙한 언어가 적혀 있으면 지원하고, 처음 보는 도구가 많으면 창을 닫는다. 어느새 여러 곳에 지원했지만 무엇을 기준으로 골랐는지 설명하기 어렵다.
받은 결과도 제각각이다. 어떤 곳은 서류 결과를 기다리고 있고, 어떤 곳은 코딩 테스트에서 탈락했다. 코딩 테스트 없이 면접으로 넘어간 곳도 있다. 그런데 메모에는 모두 ‘지원함’과 ‘불합격’만 남아 있다. 이 상태에서는 지원 방향을 바꿔야 하는지, 제출 자료를 고쳐야 하는지, 시험 운영을 연습해야 하는지 판단하기 어렵다.
문제는 노력의 양을 알 수 없다는 데 그치지 않는다. 면접까지 간 지원과 서류에서 끝난 지원이 같은 한 줄로 취급되면 이미 확인한 강점도 사라진다. 반대로 대기 중인 지원을 탈락으로 세면 실제보다 결과가 나쁘게 보인다. 불확실한 결과를 곧바로 자기 능력의 평가로 받아들이기 쉬워진다.
이 장의 도구는 이런 기록을 단계별로 분리한다. 어디까지 진행했는지, 결과가 확정된 지원은 몇 개인지, 내가 적어 둔 보완 가설은 무엇인지 출력한다. 출력 뒤에는 사람이 해야 할 일이 남는다. 기록의 근거를 확인하고, 다음 주에 바꿀 행동을 작게 정하는 일이다.
직무 이름보다 맡을 일을 읽는다
웹 백엔드와 프런트엔드는 주로 담당하는 기술 영역을 나타낸다. 시스템 통합(SI)은 고객의 업무에 맞춰 시스템을 구축하고 연결하는 사업 형태를 가리키는 경우가 많다. 솔루션 역시 제품을 개발하는 일, 고객 환경에 설치하는 일, 기능을 조정하는 일이 함께 쓰일 수 있는 표현이다. 품질 보증(QA)은 품질을 확인하고 개선하는 업무 영역이다. 따라서 이 다섯 이름은 서로 겹치지 않는 선택지가 아니다. 시스템 통합 사업의 백엔드 개발자도 있고, 솔루션 제품의 프런트엔드 개발자도 있다.
| 공고의 표현 | 읽어 볼 업무 | 내 경험과 연결할 근거 | 확인할 질문 |
|---|---|---|---|
| 웹 백엔드 | 서버 기능, 데이터 처리, 서비스 운영 | 요청 처리와 데이터 변경을 맡은 기록 | 신입이 처음 담당하는 기능은 무엇인가 |
| 프런트엔드 | 화면 구성, 사용자 상호작용, 상태 처리 | 입력 오류나 화면 상태를 개선한 기록 | 화면 개발과 운영 업무의 비중은 어떤가 |
| 시스템 통합 | 고객 업무 분석, 구축, 기존 시스템 연결 | 요구 변경을 정리하고 일정에 맞춘 경험 | 배치될 업무와 근무 장소는 어떻게 정하는가 |
| 솔루션 | 제품 개발, 설치, 고객별 조정, 유지보수 | 공통 기능과 개별 요구를 구분한 경험 | 제품 개발과 고객 대응의 범위는 어디까지인가 |
| 품질 보증 | 검증 계획, 오류 재현, 품질 개선 | 재현 절차와 확인 결과를 남긴 기록 | 수동 검증과 자동화 업무는 어떻게 나누는가 |
표의 업무는 공고를 읽기 위한 출발점이다. 실제 범위는 조직마다 다르므로 제목만 보고 확정하지 않는다. 특히 ‘개발 및 운영’처럼 넓은 표현은 하루 동안 하는 일을 떠올릴 수 있을 때까지 풀어 읽는다. 기능 구현, 고객 문의, 데이터 정리, 장애 대응 중 무엇이 포함되는지 확인할 필요가 있다. 공고에 없다면 면접에서 물어볼 항목으로 남긴다.
첫 지원 범위는 주력 직무 하나와 인접 직무 하나 정도로 시작할 수 있다. 예를 들어 서버 기능을 주로 맡았다면 웹 백엔드를 주력으로 두고, 담당 업무가 명확한 솔루션 개발을 함께 살핀다. 화면 개발 경험이 많다면 프런트엔드를 중심에 둘 수 있다. 품질 보증에 관심이 있다면 오류 재현을 좋아한다는 말에서 더 나아가, 어떤 검증 업무를 맡고 싶은지 구체화한다.
직무를 고를 때는 관심, 경험의 근거, 실제 근무 조건을 함께 본다. 통근과 근무 장소, 고객 대응 여부, 배치 방식처럼 계속 일할 수 있는지를 좌우하는 조건도 기록한다. 이전 경력이 물류나 고객 상담이라면 주문 흐름이나 사용자 문의를 이해하는 데 도움이 될 수 있다. 다만 업무 지식이 곧 개발 역량을 대신한다고 주장하기보다, 요구를 이해하고 질문했던 구체적인 장면과 연결한다.
공고를 읽은 뒤에는 ‘지원’, ‘보류’, ‘제외’ 중 하나로 분류하고 이유를 한 문장 남긴다. 필수 업무와 내 경험의 연결이 보이면 지원 후보가 된다. 담당 업무가 불분명하면 확인할 질문과 함께 보류한다. 지속하기 어려운 근무 조건이 명확하다면 제외한다. 모르는 기술이 있다는 이유만으로 모두 제외하지도, 익숙한 언어 하나가 있다는 이유만으로 모두 지원하지도 않는다.
지원 기록은 결과와 해석을 나눠 남긴다
지원 기록표에는 적어도 지원 식별자, 직무 범위, 지원일, 현재 단계, 단계별 결과, 다음 확인일이 필요하다. 제출한 이력서와 포트폴리오의 버전도 연결해 둔다. 그래야 어떤 자료를 보낸 지원에서 어떤 결과가 나왔는지 돌아볼 수 있다. 연락처나 면접관의 개인 정보는 집계 도구에 넣을 필요가 없다.
단계별 결과는 통과, 탈락, 대기, 미진행, 면제로 나눈다. 대기는 해당 단계의 결과를 기다리는 상태다. 미진행은 아직 그 단계에 도달하지 않았거나 앞 단계에서 절차가 끝난 상태다. 면제는 그 단계가 생략됐다고 확인한 경우다. 연락이 늦는다는 이유만으로 대기를 탈락으로 바꾸지 않는다. 종료 여부가 확인되지 않았다면 확인일과 함께 대기로 유지한다.
아래 완성 코드는 서류, 코딩 테스트, 면접이라는 공통 단계만 사용한다. 실제 전형에 과제나 여러 차례의 면접이 있다면 원본 기록표에 따로 남긴다. 집계할 때는 단계의 정의를 먼저 정해야 한다. 예를 들어 면접 통과를 ‘모든 면접 절차 통과’로 정했다면 첫 면접 통과만으로 최종 면접 단계까지 통과했다고 입력하면 안 된다.
| 항목 | 기록 예시 | 남기는 이유 |
|---|---|---|
| 지원 식별자와 제출 버전 | A04, 이력서 v3 | 어떤 제출물을 보냈는지 되짚는다 |
| 단계와 상태 | 코딩 테스트 대기 | 탈락과 미확정을 구분한다 |
| 확인한 사실 | 제한 시간 안에 한 문제를 제출하지 못했다 | 기억과 추측이 섞이지 않게 한다 |
| 보완 가설 | 문제별 시간 배분을 바꾸면 도움이 될 수 있다 | 다음 행동으로 검증할 대상을 고른다 |
| 다음 행동과 확인일 | 주말 모의 풀이 후 미제출 문제 수 확인 | 회고를 일정과 연결한다 |
불합격 통지만으로는 원인을 알 수 없다. ‘서류에서 탈락했다’는 사실이고, ‘직무 연결이 약했을 수 있다’는 가설이다. 면접에서 특정 질문에 답하지 못한 사실이 있어도 그것이 탈락의 유일한 이유였다고 단정할 수 없다. 외부에서 받은 피드백, 직접 확인한 수행 기록, 자신의 추정을 구분해서 적는다.
완성 코드의 reason은 확정된 채용 사유가 아니라 지원자가 선택한 보완 가설이다. 예제에서는 이해를 돕기 위해 탈락 건마다 대표 가설 하나를 넣는다. 판단 근거가 없으면 빈 문자열로 둔다. 원인을 모른다는 기록도 유효하다. 근거 없이 모든 탈락에 성격이나 실력을 원인으로 붙이면 회고가 행동 계획으로 이어지기 어렵다.
단계별 회고와 지속할 수 있는 속도
단계별 통과율은 해당 단계에서 결과가 확정된 건만 분모에 넣는다. 계산식은 ‘통과 건수 ÷ 통과와 탈락 건수의 합’이다. 대기, 미진행, 면제는 제외한다. 코딩 테스트를 면제받아 면접으로 간 지원은 코딩 테스트 실력을 확인한 사례가 아니므로 코딩 테스트 통과에 더하지 않는다.
서류 통과율이 낮아 보일 때는 지원한 업무와 제출 자료가 맞았는지부터 살핀다. 코딩 테스트에서 절차가 자주 끝난다면 풀이 기록에서 미제출, 오답, 시간 부족을 나눈다. 면접 단계의 탈락이 반복된다면 실제로 답이 끊겼던 질문과 설명의 빈칸을 확인한다. 이 장에서는 그 문제를 다시 가르치기보다, 어느 학습 자료와 기존 기록으로 돌아갈지 정한다.
숫자는 반드시 건수와 함께 읽는다. 한 번의 면접에서 탈락한 것과 여러 번의 면접에서 같은 답변 문제가 반복된 것은 다르다. 서로 다른 직무를 섞은 전체 통과율만으로 제출 자료의 품질을 판단하기도 어렵다. 처음에는 전체 흐름을 보고, 기록이 쌓이면 직무와 제출 버전이 비슷한 지원끼리 비교한다. 그 비교도 개선 효과의 확정 증거가 아니라 다음 행동을 고르는 참고 자료다.
주간 회고에서는 가장 최근의 탈락 하나를 오래 곱씹기보다 한 주의 기록을 모아 본다. 먼저 상태가 오래 갱신되지 않은 지원을 확인하고, 결과가 확정된 건을 집계한다. 다음으로 반복되는 가설 중 근거가 있는 것 하나를 고른다. 마지막으로 다음 주 행동과 완료 증거를 적는다. 가설이 여러 개여도 한꺼번에 모든 자료와 연습 방식을 바꾸지 않아야 무엇이 도움이 됐는지 살피기 쉽다.
지원 속도는 지원 건수만으로 정하지 않는다. 공고 검토, 자료 조정, 연락 확인, 시험과 면접 준비에 드는 시간을 함께 계산한다. 처음에는 감당할 수 있는 작은 묶음으로 시작하고 실제 소요 시간을 기록한다. 일정이 밀리면 제출 품질과 수면을 계속 줄이기보다 새 지원량을 조정한다. 결과 확인 시간도 하루 중 정해 두면 기다리는 동안 채용 화면을 반복해서 여는 일을 줄일 수 있다.
불합격 통지를 받은 날 바로 전체 계획을 고칠 필요는 없다. 먼저 결과와 확인한 사실만 남기고, 해석은 정해 둔 회고 시간에 한다. 회고가 끝나면 다음 행동 하나를 일정에 넣고 기록표를 닫는다. 지원하지 않는 시간과 회복 시간을 계획에 포함하는 것도 지속할 수 있는 실행 방법이다.
| 확인 | 이번 주에 할 일 | 완료 증거 |
|---|---|---|
| □ | 주력 직무와 인접 직무를 정하고 공고를 분류한다 | 지원·보류·제외 이유가 적힌 공고 검토표 |
| □ | 기존 지원의 단계별 상태와 제출 버전을 정리한다 | 미확정 결과를 구분한 지원 기록표 |
| □ | 확인한 사실과 보완 가설을 분리해 회고한다 | 근거와 다음 행동이 있는 회고 한 건 |
| □ | 집계 도구를 실행하고 보완 행동 하나를 예약한다 | 실행 출력과 달력에 적힌 작업 시간 |
| □ | 지원 작업과 회복 시간을 함께 점검한다 | 실제 소요 시간이 반영된 다음 주 시간표 |
보완 자료도 기록에서 고른다. 코딩 테스트의 풀이 실패를 분류할 때는 《논리로 푸는 알고리즘》과 코드패스를 연결한다. 질문의 개념을 설명하지 못했다면 《개발자를 위한 컴퓨터 사이언스》와 《비전공자를 위한 컴퓨터공학 지도》에서 해당 주제를 찾아 확인한다. 데이터 처리 설명에 빈칸이 있다면 《데이터베이스 개론》과 SQL 연구소로 돌아간다. 구현 결정과 협업 근거를 다시 확인할 때는 《클린 코드 노하우》와 《코드 리뷰 실무》를, 면접 회고의 질문 분류에는 《개발자 실무 면접》을 활용한다. 책 전체를 다시 읽는 계획보다 이번 기록에서 드러난 주제와 남길 증거를 지정한다.
완성 코드
아래 내용을 main.py로 저장한다. 가상 지원 여덟 건을 사용하므로 파일 입력이나 네트워크가 필요 없다. 각 지원의 results는 서류, 코딩 테스트, 면접 순서다. reason도 같은 순서이며 탈락한 단계에만 보완 가설을 기록한다. 이 도구는 집계에 집중하므로 실제 지원의 날짜와 제출 버전은 별도 기록표에서 관리한다.
from collections import Counter
STAGES = ("서류", "코딩 테스트", "면접")
STATES = {"통과", "탈락", "대기", "미진행", "면제"}
TIPS = {
"직무 불일치": "담당 업무와 내 경험의 연결을 다시 확인한다.",
"기여 설명 부족": "제출 자료에 내 담당 범위의 근거를 보완한다.",
"시간 배분": "제한 시간 풀이에서 미제출 이유를 기록한다.",
"결정 근거 부족": "답변에서 선택 이유와 확인 결과를 점검한다.",
}
RECORDS = [
{"id": "A01", "results": ("통과", "통과", "탈락"),
"reason": ("", "", "결정 근거 부족")},
{"id": "A02", "results": ("탈락", "미진행", "미진행"),
"reason": ("직무 불일치", "", "")},
{"id": "A03", "results": ("통과", "탈락", "미진행"),
"reason": ("", "시간 배분", "")},
{"id": "A04", "results": ("통과", "면제", "통과"),
"reason": ("", "", "")},
{"id": "A05", "results": ("대기", "미진행", "미진행"),
"reason": ("", "", "")},
{"id": "A06", "results": ("통과", "대기", "미진행"),
"reason": ("", "", "")},
{"id": "A07", "results": ("통과", "통과", "대기"),
"reason": ("", "", "")},
{"id": "A08", "results": ("탈락", "미진행", "미진행"),
"reason": ("기여 설명 부족", "", "")},
]
def validate(records):
seen = set()
for record in records:
record_id = record["id"]
if not record_id or record_id in seen:
raise ValueError("지원 식별자는 비어 있거나 중복될 수 없다.")
seen.add(record_id)
results = record["results"]
reasons = record["reason"]
if len(results) != len(STAGES) or len(reasons) != len(STAGES):
raise ValueError("단계별 결과와 가설은 각각 세 개여야 한다.")
closed = False
for status, reason in zip(results, reasons):
if status not in STATES:
raise ValueError(f"알 수 없는 상태: {status}")
if closed and status != "미진행":
raise ValueError("종료 또는 대기 단계 뒤에는 미진행만 온다.")
if reason and (status != "탈락" or reason not in TIPS):
raise ValueError("등록한 보완 가설은 탈락 단계에만 쓴다.")
if status in {"탈락", "대기", "미진행"}:
closed = True
def main():
validate(RECORDS)
print(f"지원 기록: {len(RECORDS)}건")
print("통과율 = 통과 / (통과 + 탈락)")
print("보완 가설은 확정된 탈락 사유가 아니다.")
for index, stage in enumerate(STAGES):
counts = Counter(record["results"][index] for record in RECORDS)
decided = counts["통과"] + counts["탈락"]
rate = (
f'{counts["통과"] / decided * 100:.1f}%'
if decided else "계산 보류"
)
print()
print(f"[{stage}]")
print(
f'통과 {counts["통과"]}건 | 탈락 {counts["탈락"]}건 | '
f'대기 {counts["대기"]}건 | 면제 {counts["면제"]}건 | '
f'미진행 {counts["미진행"]}건'
)
print(f"확정 {decided}건 | 통과율 {rate}")
hypotheses = Counter(
record["reason"][index]
for record in RECORDS
if record["results"][index] == "탈락"
and record["reason"][index]
)
if hypotheses:
for reason, count in hypotheses.items():
print(f"보완 가설: {reason} {count}건")
print(f"다음 행동: {TIPS[reason]}")
else:
print("보완 가설: 기록 없음")
if __name__ == "__main__":
main()
줄별 해설
첫 줄은 표준 라이브러리의 Counter를 가져온다. 같은 상태나 가설이 몇 번 나오는지 세는 데 사용한다. Java나 JavaScript에서 키별 개수를 담는 자료구조를 직접 만들었다면 같은 목적이라고 이해하면 된다. 뒤의 STAGES는 출력할 단계 순서를 고정한다. STATES는 입력에서 허용할 상태를 모아 둔다.
TIPS는 가설과 행동을 연결한다. 키인 ‘시간 배분’은 원인을 확정하는 진단명이 아니다. 해당 가설을 선택했다면 어떤 기록을 더 남길지 알려 주는 이름이다. 예를 들어 제한 시간 안에 제출하지 못했다면 다음 풀이에서 문제별 사용 시간과 미제출 이유를 확인하도록 안내한다.
RECORDS의 각 사전은 지원 한 건이다. id는 서로 달라야 한다. results와 reason에는 각각 세 개의 값이 들어간다. 예제의 A04는 코딩 테스트가 면제됐고 면접을 통과했다. A05는 서류 결과를 기다리므로 이후 두 단계는 미진행이다. A07은 면접 결과를 기다리므로 앞선 두 단계의 통과 사실만 확정돼 있다.
validate 함수는 계산 전에 기록의 모양을 확인한다. seen에는 이미 확인한 지원 식별자를 넣는다. 식별자가 비었거나 중복되면 ValueError를 발생시켜 조용히 잘못 집계하는 일을 막는다. 이어서 결과와 가설의 개수가 단계 수와 같은지 검사한다.
closed는 뒤 단계가 진행될 수 없는 상태를 만났는지 기억한다. 탈락, 대기, 미진행 중 하나가 나오면 이후에는 미진행만 허용한다. 반면 통과나 면제 뒤에는 다음 단계가 올 수 있다. 이 규칙은 서류부터 면접까지 순서대로 진행하는 예제의 전형을 전제로 한다. 여러 평가가 동시에 진행되는 절차라면 이 규칙부터 바꿔야 한다.
가설 검사에서는 빈 문자열을 허용한다. 근거가 부족하면 가설을 적지 않을 수 있기 때문이다. 가설을 적었다면 해당 단계가 탈락 상태이고 TIPS에 등록된 이름인지 확인한다. 이 검사는 가설의 형식만 확인한다. 실제 근거가 타당한지는 회고하는 사람이 판단해야 한다.
main 함수는 검증을 마친 다음 전체 건수와 계산 기준을 출력한다. enumerate는 단계의 위치와 이름을 함께 제공한다. index가 0이면 모든 지원의 서류 결과를, 1이면 코딩 테스트 결과를 모은다. Counter에서 존재하지 않는 상태를 조회하면 0이 나오므로 면제가 없는 단계도 같은 출력문을 쓸 수 있다.
decided는 통과와 탈락을 더한 확정 건수다. rate를 만드는 조건식은 확정 건수가 있을 때만 나눗셈을 수행한다. 없으면 ‘계산 보류’를 사용한다. 소수점 한 자리 형식을 지정하므로 같은 기록에는 늘 같은 비율 문자열이 나온다. 확정 결과가 없는 상황을 0.0%로 표시하지 않는 것이 중요하다.
hypotheses는 해당 단계에서 탈락했고 가설도 기록된 건만 모은다. items를 순회하면 예제 기록에서 처음 등장한 가설 순서대로 출력된다. 마지막 조건문은 이 파일을 직접 실행했을 때 main을 호출한다. 입력 대기와 현재 시각 사용이 없으므로 실행은 출력 후 바로 끝난다.
실행 결과
macOS 또는 Linux에서 Python 3.12 이상으로 실행한다. 별도 설치할 패키지는 없다.
python3 main.py
지원 기록: 8건
통과율 = 통과 / (통과 + 탈락)
보완 가설은 확정된 탈락 사유가 아니다.
[서류]
통과 5건 | 탈락 2건 | 대기 1건 | 면제 0건 | 미진행 0건
확정 7건 | 통과율 71.4%
보완 가설: 직무 불일치 1건
다음 행동: 담당 업무와 내 경험의 연결을 다시 확인한다.
보완 가설: 기여 설명 부족 1건
다음 행동: 제출 자료에 내 담당 범위의 근거를 보완한다.
[코딩 테스트]
통과 2건 | 탈락 1건 | 대기 1건 | 면제 1건 | 미진행 3건
확정 3건 | 통과율 66.7%
보완 가설: 시간 배분 1건
다음 행동: 제한 시간 풀이에서 미제출 이유를 기록한다.
[면접]
통과 1건 | 탈락 1건 | 대기 1건 | 면제 0건 | 미진행 5건
확정 2건 | 통과율 50.0%
보완 가설: 결정 근거 부족 1건
다음 행동: 답변에서 선택 이유와 확인 결과를 점검한다.
서류 통과율의 분모는 전체 여덟 건이 아니라 확정된 일곱 건이다. 코딩 테스트의 분모는 세 건이며 면제 한 건은 빠진다. 면접 통과율은 두 건을 바탕으로 계산한 값이다. 이 숫자만으로 면접 준비가 충분한지 부족한지 결론 내리지 않는다. 어떤 답변에서 근거가 부족했는지 기록을 확인하는 출발점으로 쓴다.
예제에서 출력되는 네 가지 가설도 서로 우선순위를 다투는 진단 결과가 아니다. 이번 주에 다룰 수 있는 행동 하나를 선택하기 위한 목록이다. 면접 일정이 가까우며 실제로 선택 이유를 설명하지 못한 기록이 있다면 그 행동을 먼저 배치할 수 있다. 일정과 근거를 함께 보고 결정한다.
실무에서 자주 틀리는 것
전체 지원 수를 모든 단계의 분모로 쓴다
아래 조각에서 counts는 해당 단계의 상태별 개수다. 전체 지원 수로 나누면 그 단계에 도달하지 않은 지원까지 실패처럼 반영된다. 코딩 테스트가 면제된 지원도 결과를 왜곡한다.
틀린 코드다.
rate = counts["통과"] / len(RECORDS) * 100
고친 코드다. 확정 결과가 없을 때도 구분한다.
decided = counts["통과"] + counts["탈락"]
rate = counts["통과"] / decided * 100 if decided else None
None은 계산할 값이 없다는 뜻으로 사용한다. 출력할 때는 ‘계산 보류’로 바꾼다. 통과한 사람이 없어서 0%인 상황과 결과 자체가 없는 상황은 다르다.
통과가 아닌 상태를 모두 탈락으로 센다
대기와 미진행은 탈락이 아니다. 면제 역시 통과 여부를 평가한 결과가 아니다. 아래 조각은 지원 한 건인 record와 단계 위치 index를 사용하는 집계 상황이다.
틀린 코드다.
failed = record["results"][index] != "통과"
고친 코드다.
failed = record["results"][index] == "탈락"
상태를 명시적으로 비교하면 나중에 다른 상태가 추가돼도 뜻이 분명하다. 대기 결과를 확인하는 작업은 탈락 분석과 별도 일정으로 관리한다.
불합격 통지에 자동으로 원인을 붙인다
프로그램은 통지 내용에 없는 원인을 알아낼 수 없다. 서류 탈락을 모두 같은 가설로 채우면 출력은 정돈돼 보여도 행동의 근거가 약해진다.
틀린 코드다.
status = "탈락"
reason = "기여 설명 부족"
고친 코드다. 기록으로 확인하지 못한 가설은 비워 둔다.
status = "탈락"
reason = ""
observed_fact = "서류 탈락 통지만 확인했다."
observed_fact는 원본 회고에 남길 사실을 보여 주는 별도 변수다. 완성 코드의 집계 항목에는 포함되지 않는다. 이후 제출 자료를 검토해 근거를 찾았다면 가설과 그 근거를 함께 기록한다.
서로 모순되는 단계 기록을 그대로 집계한다
이 예제의 순차 전형에서는 서류 결과를 기다리면서 코딩 테스트를 통과했다고 기록할 수 없다. 대기 결과를 갱신하지 않은 채 다음 단계만 적었을 수 있다.
틀린 코드다.
results = ("대기", "통과", "미진행")
서류 통과를 실제로 확인한 경우의 고친 코드다.
results = ("통과", "통과", "미진행")
확인하지 못했다면 통과로 추측해서 바꾸지 않는다. 원본 안내를 확인하거나 실제 전형이 병렬 진행인지 살핀다. 현실의 절차가 다르면 데이터 모델과 검증 규칙을 함께 수정해야 한다.
한눈에 보기
| 살필 대상 | 확인할 근거 | 피할 해석 | 남길 증거 |
|---|---|---|---|
| 지원 범위 | 실제 업무, 경험 연결, 근무 조건 | 직무 이름만 보고 적합성을 확정한다 | 공고별 선택 이유 |
| 서류 탈락 | 공고 요구와 제출 버전 | 통지에 없는 탈락 사유를 단정한다 | 대조한 항목과 보완 가설 |
| 코딩 테스트 탈락 | 제출 여부, 오답, 사용 시간 | 면제와 대기를 실패에 넣는다 | 풀이 결과와 다음 확인 항목 |
| 면접 탈락 | 질문과 실제 답변의 빈칸 | 답변 하나를 유일한 원인으로 본다 | 사실과 가설을 나눈 회고 |
| 주간 속도 | 작업 시간, 예정 전형, 회복 시간 | 지원 건수만 계속 늘린다 | 지속 가능한 다음 주 시간표 |
이번 주의 완료 기준은 지원 건수 하나로 정하지 않는다. 직무 선택 이유가 있고, 제출 버전과 단계 상태를 찾을 수 있으며, 집계 출력에서 보완 행동 하나를 골랐다면 다음 주 판단에 쓸 증거가 남은 것이다. 지원 결과가 바뀌면 기존 기록의 상태를 갱신한다. 같은 지원을 새 행으로 다시 추가하면 전체 건수와 통과율이 부풀려진다.
면접 단계의 통과가 곧 입사 확정이라는 뜻도 아니다. 이후 조건 확인과 합류 일정처럼 별도로 확인할 사항이 있다. 다음 장에서는 합류한 뒤 코드와 업무를 익히는 첫 90일로 범위를 옮긴다. 여기서 익힌 ‘확인한 사실, 모르는 점, 다음 행동’을 나눠 기록하는 습관은 그때도 이어진다.
연습 문제
- 새 지원 A09를 추가한다. 서류는 통과했고 코딩 테스트 결과를 기다리며 면접은 미진행이다. 가설은 모두 빈 문자열로 둔다. 서류와 코딩 테스트의 확정 건수와 통과율이 어떻게 바뀌는지 계산한다.
- RECORDS를 빈 목록으로 바꾸면 각 단계의 통과율이 어떻게 출력되는지 설명한다. ‘0.0%’와 ‘계산 보류’를 구분해야 하는 이유도 쓴다.
- 통과로 기록된 단계의 reason에 ‘시간 배분’을 넣었다. 완성 코드가 어떤 검사에서 이 기록을 거부하는지 설명하고, 근거가 없는 가설을 어떻게 고칠지 쓴다.
- 서류 탈락 통지만 받은 지원 하나를 골랐다고 가정한다. 확인한 사실, 보완 가설, 다음 행동, 완료 증거를 한 문장씩 쓴다. 지원자의 능력을 단정하거나 채용 담당자의 생각을 추측한 문장은 제외한다.
정답과 해설
-
추가할 기록은 다음과 같다.
{"id": "A09", "results": ("통과", "대기", "미진행"), "reason": ("", "", "")}서류는 통과 여섯 건과 탈락 두 건이므로 확정 여덟 건, 통과율 75.0%다. 코딩 테스트는 대기만 한 건 늘어난다. 통과 두 건과 탈락 한 건은 그대로이므로 확정 세 건, 통과율 66.7%다. 전체 지원 수가 늘어도 해당 단계의 확정 결과가 같으면 통과율은 바뀌지 않는다.
-
전체 지원 기록은 0건으로 출력된다. 각 단계의 상태별 건수와 확정 건수도 모두 0이며 통과율은 ‘계산 보류’다. 가설은 ‘기록 없음’으로 출력된다. 확정 결과가 없는 것은 통과에 실패했다는 뜻이 아니다. 0.0%는 확정된 결과가 있으나 통과가 하나도 없을 때 사용한다.
-
validate의 가설 검사에서 거부된다. reason이 비어 있지 않은데 status가 ‘탈락’이 아니므로 ValueError가 발생한다. 근거가 없는 가설은 빈 문자열로 되돌린다. 통과했어도 연습에서 개선할 점이 있을 수 있지만, 이 도구의 reason은 탈락 건의 보완 가설만 집계하도록 정의했다. 통과 후 개선 메모는 별도 회고에 남긴다.
-
가능한 답은 다음과 같다. 확인한 사실은 ‘서류 탈락 통지만 받았고 상세 피드백은 없었다’다. 보완 가설은 ‘공고의 담당 업무와 내 경험의 연결이 제출 자료에서 충분히 드러나지 않았을 수 있다’다. 다음 행동은 ‘공고의 주요 업무와 제출한 자료의 근거를 항목별로 대조한다’다. 완료 증거는 ‘연결된 항목과 근거가 없는 항목을 구분한 대조표 한 장’이다. 가설이 맞다고 미리 결론 내리지 않고 직접 확인할 작업으로 바꾼 점이 핵심이다.