모의 면접 한 번 - 질문 30개 실전 연습
이 장에서 배우는 것
앞 장에서 면접을 마무리하는 질문과 태도를 다뤘다. 이제는 따로 준비한 답변을 하나의 면접 흐름으로 연결할 차례다. 질문 목록을 읽을 때는 알고 있던 내용도, 앞선 답변의 긴장감이 남아 있는 상태에서 들으면 쉽게 정리되지 않는다. 마지막 연습에서는 지식의 양뿐 아니라 답변을 시작하는 속도, 근거를 설명하는 방식, 모르는 내용을 구분하는 태도까지 확인한다.
이 장에서는 가상의 중고 거래 서비스 팀에 지원한 지원자가 기술 질문 20개, 경험 질문 6개, 역질문 4개를 연습한다. 실제 면접의 문항 수나 시간을 예측하는 구성이 아니라, 자신의 준비 상태를 같은 조건에서 비교하기 위한 연습 틀이다.
- 30문항 진행표를 이용해 기술 설명, 경험 설명, 역질문을 이어서 연습한다.
- 답변을 녹음하고 관찰 가능한 기준으로 셀프 채점한다.
- 점수와 오답 원인을 함께 보고 다시 연습할 질문을 고른다.
- 영역별 문항 수와 고정 시드를 사용하는 질문 추출 프로그램을 실행한다.
- 2주 동안 첫 녹음, 보완, 재녹음을 반복하는 준비 계획을 세운다.
문제 상황
지원자는 중고 거래 프로젝트에서 상품 목록, 관심 상품, 거래 완료 기능을 구현했다. 각 기능은 설명할 수 있지만 모의 면접에서는 문제가 생겼다. 인덱스 질문에 테이블 구조부터 길게 설명했고, 장애 경험을 묻자 팀 전체가 한 일을 자신의 행동과 섞어서 말했다. 마지막에는 준비한 역질문을 모두 꺼내느라 이미 들은 내용을 다시 물었다.
녹음을 들은 지원자는 “말을 잘 못한다”라고 평가했다. 그러나 이 평가는 다음 행동을 정해 주지 못한다. 결론이 늦었는지, 기술 설명이 틀렸는지, 경험의 근거가 없었는지를 구분해야 연습 방법이 달라진다. 결론이 늦었다면 첫 두 문장을 고치고, 기술 설명이 틀렸다면 작은 예제로 개념을 다시 확인해야 한다.
또 매번 떠오르는 질문만 골라 연습하면 익숙한 영역이 반복된다. 자료구조 설명은 좋아지는데 운영 질문은 계속 빠질 수 있다. 이번 프로그램은 영역별 문항 수를 먼저 정하고 질문을 선택한다. 같은 시드(seed)에서는 같은 질문과 순서가 나오므로, 첫 녹음과 두 번째 녹음의 답변을 비교할 수 있다.
30문항을 하나의 면접으로 연결한다
30문항은 모두 같은 방식으로 답하지 않는다. 기술 질문은 판단과 근거를 설명하고, 경험 질문은 실제 행동과 결과를 구분한다. 역질문은 지원자가 팀에 묻는 차례다. 실제 면접에서는 시간이 부족하면 준비한 역질문 중 우선순위가 높은 것만 사용한다. 연습에서는 네 개를 모두 말해 보되, 각각 무엇을 확인하려는 질문인지 덧붙인다.
| 순서 | 문항 구성 | 연습 시간 | 진행 원칙 |
|---|---|---|---|
| 시작 | 녹음 설정과 조건 확인 | 3분 | 프로젝트와 역할을 한 문장으로 적는다. |
| 01~20 | 기술 5개 영역, 각 4문항 | 40분 | 문항마다 첫 답변 90초, 추가 확인 30초를 쓴다. |
| 21~26 | 경험 6문항 | 18분 | 상황 설명보다 자신의 판단과 행동에 시간을 쓴다. |
| 27~30 | 역질문 4문항 | 8분 | 질문과 확인 목적을 말하고 예상 답변을 메모한다. |
| 종료 | 녹음 재생과 채점 | 별도 30분 | 기억이 아니라 실제로 말한 내용을 평가한다. |
다음 열 가지는 진행 중 점검할 대표 질문이다. 새로운 지식을 정리하는 목록이 아니라, 앞에서 익힌 설명을 면접 상황에서 꺼낼 수 있는지 확인하는 목록이다. 꼬리 질문은 외운 정의 다음에 판단의 근거가 이어지는지 확인한다.
| 질문 | 의도 | 답변 핵심 | 꼬리 질문 |
|---|---|---|---|
| 관심 상품 중복을 어떻게 막겠는가? | 자료구조 선택의 근거를 확인한다. | 식별자와 집합의 역할을 설명한다. | 서로 다른 요청이 동시에 오면 어떻게 되는가? |
| 상품 목록이 느리면 무엇부터 확인하는가? | 추측과 측정을 구분한다. | 느린 구간과 실행 계획을 확인한다. | 인덱스를 추가했는데도 느리면 무엇을 보는가? |
| 거래 완료 요청이 두 번 오면 어떻게 하는가? | 중복 요청의 결과를 생각하는지 본다. | 허용할 상태 변화와 중복 결과를 정한다. | 응답을 받기 전에 연결이 끊기면 어떻게 되는가? |
| 공유 데이터에 여러 스레드가 접근하면 어떤 문제가 있는가? | 실행 순서에 따른 결과 차이를 이해하는지 본다. | 읽기와 갱신 사이의 경쟁을 예로 든다. | 잠금 범위가 넓으면 어떤 비용이 생기는가? |
| 목록 화면이 느리다는 제보를 어떻게 좁히는가? | 사용자 증상과 원인을 연결하는지 본다. | 재현 조건과 구간별 시간을 확인한다. | 자신의 환경에서 재현되지 않으면 어떻게 하는가? |
| 장애 로그에 무엇을 남기겠는가? | 추적 가능성과 정보 보호를 함께 본다. | 요청 식별자와 실패 지점을 남긴다. | 인증 토큰이 필요해 보이면 어떻게 하는가? |
| 팀원과 의견이 달랐던 일을 설명하라. | 합의 과정에서의 행동을 확인한다. | 쟁점, 비교 기준, 자신의 행동을 말한다. | 본인 제안이 채택되지 않았다면 어떻게 했는가? |
| 모르는 질문을 받으면 어떻게 하겠는가? | 지식의 경계를 다루는 태도를 본다. | 아는 범위와 확인할 내용을 구분한다. | 지금 아는 범위에서 가설을 세워 보라. |
| 입사 후 처음 맡게 될 일은 무엇인지 묻겠는가? | 업무 기대를 확인하려는지 본다. | 업무 범위와 초기 완료 기준을 묻는다. | 이미 설명을 들었다면 무엇을 더 묻겠는가? |
| 배포 전 검증 과정은 어떻게 묻겠는가? | 팀의 작업 방식을 이해하려는지 본다. | 검증 책임과 되돌리는 판단 기준을 묻는다. | 그 답을 듣고 무엇을 판단하려는가? |
혼자 연습할 때는 질문을 읽은 직후부터 시간을 잰다. 답이 생각나지 않아도 녹음을 중단하지 않는다. “현재 아는 범위는 여기까지다”라고 정리하고 다음으로 넘어간다. 둘이 연습한다면 면접관 역할은 답변을 대신 완성해 주지 않고, 근거가 빠진 곳에 꼬리 질문 하나를 덧붙인다.
답변의 구조를 듣고 점수를 매긴다
답변은 “결론 먼저 → 근거 → 내 경험·예시 → 한계와 대안”으로 구성한다. 모든 답변에 네 문단을 강제로 붙일 필요는 없다. 짧은 정의 질문이라면 두세 문장 안에 들어갈 수 있다. 중요한 점은 듣는 사람이 첫 부분에서 답의 방향을 알고, 뒤에서 그 판단을 검토할 수 있어야 한다는 것이다.
상품 목록이 느리면 무엇부터 확인하는가
| 수준 | 답변 | 평가 근거 |
|---|---|---|
| 나쁜 답 | 인덱스를 만들면 빨라진다. | 원인을 확인하지 않고 해결책부터 고른다. |
| 보통 답 | 느린 쿼리를 찾아 실행 계획을 보겠다. | 측정 방향은 있지만 요청 전체에서 어느 구간이 느린지 빠져 있다. |
| 좋은 답 | 요청을 재현하고 구간별 시간을 확인한 뒤, 데이터 조회가 병목이면 실행 계획과 조회 조건을 보겠다. | 관찰에서 판단으로 이어지며 조치의 조건이 드러난다. |
먼저 같은 조건으로 요청을 재현하고 서버 처리, 데이터 조회, 응답 이후 화면 처리 중 어디에 시간이 쓰이는지 확인하겠다. 목록이 느리다는 증상만으로 인덱스가 원인이라고 판단하기 어렵기 때문이다. 제 프로젝트에서 같은 증상을 확인한다면 상품 수, 검색 조건, 페이지 위치를 고정하고 구간별 시간을 기록하겠다. 데이터 조회가 병목이면 실행 계획과 반환 행 수를 보고 인덱스나 조회 방식을 검토하겠다. 다만 평균 시간만 보면 일부 느린 요청을 놓칠 수 있으므로 느린 사례의 조건도 따로 비교하겠다.
이 답변의 예시는 앞으로 확인할 절차다. 실제로 측정한 경험처럼 말하지 않는다. “인덱스를 추가해도 느리다면”이라는 꼬리 질문에는 반환 데이터 양, 깊은 페이지 탐색, 외부 호출, 화면 처리 등 앞서 측정한 구간으로 돌아가 답한다. 원인 후보를 많이 나열하는 것보다 다음에 확인할 항목과 이유를 하나 연결하는 편이 분명하다.
팀원과 의견이 달랐던 일을 설명하라
| 수준 | 답변 | 평가 근거 |
|---|---|---|
| 나쁜 답 | 팀원이 고집을 부려서 제가 설득했다. | 상대 평가만 있고 쟁점과 행동이 없다. |
| 보통 답 | 일정과 품질에 대한 의견이 달라 회의로 합의했다. | 합의했다는 결과는 있으나 과정이 보이지 않는다. |
| 좋은 답 | 검색 기능의 범위를 두고 의견이 달라 사용 시나리오와 남은 작업을 비교했고, 필수 조건부터 구현하기로 합의했다. | 쟁점, 기준, 행동, 결과를 추가로 확인할 수 있다. |
의견이 다를 때는 먼저 같은 기준으로 선택지를 비교하려고 했다. 중고 거래 프로젝트에서 검색 기능을 넓히자는 의견과 일정 안에 끝내자는 의견이 나뉜 적이 있다. 저는 필요한 검색 조건과 각 작업의 완료 기준을 표로 정리하고, 남은 기간에 검증할 수 있는 범위를 함께 확인했다. 그 결과 필수 조건을 먼저 구현하고 나머지는 후속 작업으로 남겼다. 다만 당시 작업량 추정은 실제 기록이 부족해 거칠었다. 다음에는 작업을 더 작게 나누고 예상과 실제 소요를 비교하겠다.
이 경험은 가상 지원자의 예시다. 독자는 자신의 실제 사건으로 바꿔야 한다. “본인 제안이 채택되지 않았다면”이라는 질문에는 상대 의견에 따랐다는 사실만 말하지 않는다. 합의한 기준을 받아들인 이유, 실행 과정에서 맡은 일, 이후 확인한 결과를 설명한다. 팀의 결과와 자신의 기여도 분리한다.
모르는 질문을 받으면 어떻게 하겠는가
나쁜 답은 “잘 모르지만 아마 그렇다”라며 추측을 사실처럼 이어 가는 답이다. 보통 답은 “모른다. 공부하겠다”에서 멈춘다. 좋은 답은 알고 있는 범위를 밝힌 뒤 가정에 따른 추론과 확인 방법을 구분한다.
정확히 모르는 부분은 먼저 밝히고, 아는 범위 안에서 조건을 확인하며 답하겠다. 추측을 사실처럼 말하면 뒤의 판단도 검토하기 어려워지기 때문이다. 예를 들어 특정 실행 환경에서 스레드가 어떻게 동작하는지 확신이 없다면, 공유 상태를 갱신하는 과정에서 경쟁이 생길 수 있다는 일반 원리까지 설명하고 해당 환경의 세부 동작은 확인이 필요하다고 말하겠다. 이후 작은 재현 코드와 공식 문서로 확인하겠다. 다만 실행 결과 한 번만으로 모든 실행 순서를 확인했다고 결론짓지는 않겠다.
면접관이 “지금 가설을 세워 보라”고 하면 가정을 먼저 붙인다. “두 실행 흐름이 읽기와 쓰기 사이에서 교차할 수 있다고 가정하면 갱신이 누락될 수 있다”처럼 말한다. 모른다는 선언은 답변의 끝이 아니라, 확실한 사실과 가설의 경계를 표시하는 시작점이다.
입사 후 처음 맡을 일을 어떻게 묻겠는가
나쁜 질문은 이미 설명받은 내용을 그대로 다시 묻는 질문이다. 보통 질문은 “처음에 어떤 일을 하는가”처럼 범위가 넓다. 좋은 질문은 들은 내용을 바탕으로 아직 확인하지 못한 업무 범위나 완료 기준을 좁힌다.
초기에 맡을 업무의 범위와 완료 기준을 확인하고 싶다. 준비 방향을 구체적으로 잡는 데 도움이 되기 때문이다. 앞서 상품 목록 개선 업무를 맡을 수 있다고 설명해 주셨는데, 처음에는 기존 문제를 재현하고 테스트를 보완하는 일부터 시작하는지, 작은 기능 변경까지 기대하는지 묻겠다. 제 프로젝트에서는 구현 완료와 검증 완료를 다르게 이해해 일정이 어긋난 적이 있어 이 기준을 확인하고 싶다. 다만 배정은 상황에 따라 바뀔 수 있으므로 확정된 약속보다는 현재의 기대를 듣는 질문으로 사용하겠다.
“이미 설명했다면”이라는 꼬리 질문에는 질문을 생략하거나 남은 불확실성만 묻겠다고 답한다. 역질문의 점수는 어려운 용어의 개수가 아니라, 면접 중 들은 내용을 반영하고 실제 판단에 필요한 정보를 얻는지로 매긴다.
| 항목 | 0점 | 1점 | 2점 |
|---|---|---|---|
| 결론 | 질문에 답하지 못한다. | 답은 있으나 뒤늦게 드러난다. | 첫 두 문장에 답의 방향이 드러난다. |
| 근거 | 핵심 오류가 있거나 근거가 없다. | 방향은 맞지만 조건이나 이유가 빠진다. | 이유와 적용 조건이 정확히 연결된다. |
| 적용 | 예시나 확인 목적이 없다. | 관련 예시는 있으나 연결이 약하다. | 기술은 예시, 경험은 행동, 역질문은 확인 목적이 구체적이다. |
| 한계 | 불확실성을 숨기거나 과도하게 단정한다. | 제약은 말하지만 후속 판단이 없다. | 제약과 확인 방법 또는 대안을 설명한다. |
문항당 8점이지만 총점만으로 준비 상태를 판단하지 않는다. 근거가 0점인 기술 답변은 결론을 빠르게 말했다고 통과 처리하지 않는다. 반대로 짧은 역질문에 억지로 긴 사례를 붙이지도 않는다. 위 기준은 채용 결과를 예측하는 척도가 아니라, 같은 질문의 답변을 고치기 위한 연습 도구다.
녹음은 자신이 관리할 수 있는 기기에 저장하고 실제 이용자의 이름이나 연락처는 예시에서 제외한다. 파일 이름은 회차와 날짜 정도로 정한다. 재생할 때는 첫 결론이 나온 시점, 근거가 끊긴 문장, 다시 말하고 싶은 문장을 적는다. 모든 발화를 받아쓰기하기보다 수정에 필요한 구간의 시각을 남긴다.
다시 연습할 질문과 2주 계획을 정한다
재연습 목록은 세 단계로 고른다. 먼저 사실 오류나 근거 0점이 있는 질문을 넣는다. 다음으로 총점 4점 이하인 질문을 넣는다. 마지막으로 영역별 최저점 질문을 확인해 빠진 영역을 보충한다. 같은 질문이 여러 조건에 걸려도 한 번만 넣고, 동점이면 문항 번호가 빠른 것을 먼저 고른다. 첫 보완 목록은 여섯 개 정도로 제한해 실제로 다시 말할 시간을 확보한다.
총점이 높아도 근거가 부정확하면 우선 보완 대상이다. 반대로 말이 잠깐 끊겼더라도 판단과 근거가 정확하다면 표현 연습으로 분류할 수 있다. 오답 원인을 지식 부족, 구조 부족, 경험 근거 부족으로 적고 각각 작은 실험, 첫 두 문장 수정, 실제 작업 기록 확인으로 연결한다.
| 기간 | 주요 작업 | 남길 결과 | 완료 기준 |
|---|---|---|---|
| 1일 | 프로그램 실행과 30문항 첫 녹음 | 질문 목록과 녹음 | 막힌 질문도 건너뛴 표시를 남긴다. |
| 2일 | 녹음 채점과 우선순위 선정 | 항목별 점수와 보완 6문항 | 낮은 점수마다 원인을 한 줄로 적는다. |
| 3~5일 | 기술 오류 확인과 작은 재현 | 실행 결과와 수정한 설명 | 결과가 판단을 어떻게 뒷받침하는지 말한다. |
| 6일 | 경험 답변의 사실과 역할 점검 | 사건별 행동·결과 메모 | 팀 결과와 자신의 행동을 구분한다. |
| 7일 | 보완 질문 재녹음 | 같은 질문의 두 답변 | 개선한 문장과 남은 문제를 찾는다. |
| 8~9일 | 꼬리 질문과 시간 제한 연습 | 문항별 추가 질문 한 개 | 가정이 바뀌면 답도 조정한다. |
| 10일 | 역질문 선택과 목적 설명 | 우선순위가 있는 역질문 4개 | 이미 들은 내용은 생략할 수 있다. |
| 11일 | 같은 시드로 전체 재녹음 | 두 번째 전체 채점표 | 같은 기준으로 변화한 항목을 비교한다. |
| 12일 | 남은 오류 보완 | 오류별 확인 근거 | 표현 수정과 지식 수정을 구분한다. |
| 13일 | 다른 시드로 새 조합 연습 | 새 질문의 답변 기록 | 질문 순서가 달라도 구조를 유지한다. |
| 14일 | 회고와 마지막 점검 | 핵심 경험과 재확인 목록 | 새 답안을 늘리기보다 남은 오류를 정리한다. |
아래 프로그램의 기본 시드는 바꾸지 않은 채 비교용 출력을 보관한다. 새 조합을 연습하는 날에만 복사본에서 시드를 바꾼다. 질문 은행이 작으므로 다른 시드에서도 문항이 겹칠 수 있다. 겹치지 않는 문항 수를 늘리는 것보다, 질문 표현이나 조건이 달라졌을 때도 같은 개념을 설명할 수 있는지 확인한다.
완성 코드
다음 내용을 main.py로 저장한다. Python 3.12 이상에서 외부 패키지 없이 실행된다. 기술 다섯 영역에서 각각 4개, 경험에서 6개, 역질문에서 4개를 뽑는다. 각 질문 은행은 필요한 수보다 크게 구성했다.
선택 과정을 손으로도 확인할 수 있도록 작은 선형 합동 생성기를 사용한다. 상태를 갱신해 시작 위치를 정하고, 그 위치부터 원형으로 연속된 문항을 고른다. 이는 각 부분집합을 같은 확률로 뽑는 추출 방식이 아니다. 영역별 수량과 재현성을 확인하는 교육용 선택기이며, 보안 목적에는 사용하지 않는다. 실행 날짜는 읽지 않고 고정 회차만 출력한다.
SEED = 42
SESSION = "연습-01"
# 이름, 유형, 선택 수, 질문 은행
BANKS = (
("자료구조", "기술", 4, (
"배열과 연결 리스트를 언제 선택하는가?",
"해시 충돌을 어떻게 설명하겠는가?",
"관심 상품 중복을 어떻게 막겠는가?",
"가격순 상위 상품을 어떻게 유지하겠는가?",
"트리 탐색 비용은 무엇에 좌우되는가?",
)),
("실행과 통신", "기술", 4, (
"프로세스와 스레드를 어떻게 구분하는가?",
"공유 데이터 갱신에서 어떤 경쟁이 생기는가?",
"상품 요청의 통신 경로를 설명하라.",
"응답 대기 시간은 어디에서 생기는가?",
"연결 실패 뒤 재시도는 언제 가능한가?",
)),
("데이터와 API", "기술", 4, (
"인덱스의 비용과 이점은 무엇인가?",
"거래 상태 변경을 어떻게 묶겠는가?",
"상품 수정 권한을 어디서 확인하는가?",
"상품 목록이 느리면 무엇부터 확인하는가?",
"거래 완료 요청이 두 번 오면 어떻게 하는가?",
)),
("화면과 품질", "기술", 4, (
"목록 화면이 느리면 어떻게 좁히는가?",
"비동기 검색 응답의 순서가 바뀌면 어떻게 하는가?",
"상품 등록의 실패 경로를 어떻게 테스트하는가?",
"키보드로 상품을 탐색할 수 있는지 어떻게 확인하는가?",
"화면 상태를 어디에 둘지 어떻게 정하는가?",
)),
("설계와 운영", "기술", 4, (
"요청이 늘면 무엇을 먼저 측정하는가?",
"캐시 데이터가 오래되면 어떻게 하는가?",
"배포 뒤 오류가 늘면 어떻게 대응하는가?",
"장애 로그에 무엇을 남기겠는가?",
"실패한 외부 호출을 어떻게 제한하겠는가?",
)),
("경험", "경험", 6, (
"가장 설명하고 싶은 기능은 무엇인가?",
"팀원과 의견이 달랐던 일을 설명하라.",
"일정이 어긋났을 때 무엇을 바꿨는가?",
"실패한 시도에서 무엇을 배웠는가?",
"피드백을 반영한 사례를 설명하라.",
"모르는 질문을 받으면 어떻게 하겠는가?",
"자신이 맡은 범위를 어떻게 증명하겠는가?",
)),
("역질문", "역질문", 4, (
"입사 후 첫 업무의 범위와 완료 기준을 묻는다.",
"코드 검토에서 주로 확인하는 기준을 묻는다.",
"배포 전 검증과 되돌리는 기준을 묻는다.",
"신입이 질문하고 피드백받는 방식을 묻는다.",
"팀이 현재 개선하려는 사용자 문제를 묻는다.",
)),
)
def make_session(seed):
state = seed % 97
selected = []
for area, kind, quota, questions in BANKS:
if not 0 < quota <= len(questions):
raise ValueError(f"문항 수 확인 필요: {area}")
if len(set(questions)) != len(questions):
raise ValueError(f"중복 질문 확인 필요: {area}")
state = (state * 5 + 1) % 97
start = state % len(questions)
chosen = [
questions[(start + offset) % len(questions)]
for offset in range(quota)
]
for question in chosen:
selected.append((kind, area, question))
return selected
def validate(rows):
expected = {"기술": 20, "경험": 6, "역질문": 4}
actual = {kind: 0 for kind in expected}
area_counts = {}
seen = set()
for kind, area, question in rows:
actual[kind] += 1
area_counts[area] = area_counts.get(area, 0) + 1
if question in seen:
raise ValueError("전체 목록에 중복 질문이 있다.")
seen.add(question)
if actual != expected or len(rows) != 30:
raise ValueError("유형별 문항 수가 맞지 않는다.")
for area, _, quota, _ in BANKS:
if area_counts.get(area, 0) != quota:
raise ValueError(f"영역별 문항 수 오류: {area}")
def main():
rows = make_session(SEED)
validate(rows)
if rows != make_session(SEED):
raise RuntimeError("같은 시드의 결과가 다르다.")
print(f"모의 면접 {SESSION} | seed={SEED}")
print("검증: 기술 20 / 경험 6 / 역질문 4 / 합계 30 / 중복 0")
print("점수 칸: 결론/근거/적용/한계, 각각 0~2점")
for number, (kind, area, question) in enumerate(rows, start=1):
print(f"{number:02d} [{kind}/{area}] {question} | __/__/__/__")
print("재연습 번호: ______")
print("오류 원인과 다음 행동: ______")
if __name__ == "__main__":
main()
줄별 해설
첫 두 줄의 SEED와 SESSION은 비교 조건이다. SEED는 문항 선택에 쓰고 SESSION은 출력 제목에만 쓴다. 현재 시각을 읽는 함수가 없으므로 실행 시점이 출력에 영향을 주지 않는다. 시각이 필요한 기록은 프로그램 밖의 녹음 파일에 남긴다.
BANKS의 각 항목은 영역 이름, 질문 유형, 선택할 수, 질문 묶음 순서다. 기술은 다섯 영역으로 나눴지만 이 분류가 모든 지식을 빠짐없이 대표하지는 않는다. 실제 준비에서는 취약한 주제를 질문 은행에 보태되 비교 중인 두 녹음 사이에는 은행을 바꾸지 않는다.
make_session의 첫 줄은 입력 시드를 0부터 96까지의 상태로 바꾼다. 각 영역에 들어갈 때 상태를 한 번 갱신한다. 기본 시드에서 갱신되는 상태는 17, 86, 43, 22, 14, 71, 65다. 첫 영역의 질문은 다섯 개이므로 시작 위치는 17을 5로 나눈 나머지인 2다. 인덱스 2, 3, 4, 0의 질문 네 개가 선택된다.
quota 검사는 은행 크기보다 많은 문항을 요구해 같은 영역의 질문이 되풀이되는 것을 막는다. set으로 질문 수를 비교하는 부분은 은행 안에 같은 문자열이 두 번 들어간 편집 오류를 잡는다. chosen을 만드는 식의 나머지 연산은 마지막 질문 다음에 첫 질문으로 돌아오게 한다.
validate는 실제 선택 결과를 별도로 센다. 유형별 20·6·4뿐 아니라 기술의 각 영역이 4개인지도 검사한다. 전체 질문 문자열의 중복도 확인하므로, 서로 다른 영역에 같은 문장을 넣은 경우도 실행을 중단한다. 문자열이 다르지만 의미가 같은 질문까지 판별하는 검사는 아니다.
main은 결과를 검증하고 같은 시드로 한 번 더 만든 목록과 비교한다. 이 검사는 현재 코드에서 재현 조건이 유지되는지 확인하는 작은 실험이다. 선택 방식의 공정성이나 질문의 교육적 품질을 증명하지는 않는다. 마지막 반복문은 질문과 빈 점수 칸을 함께 출력한다. 프로그램은 말의 정확성을 자동 평가하지 않으며, 점수는 녹음을 들은 사람이 채운다.
실행 결과
macOS나 Linux 터미널에서 다음 명령으로 실행한다.
python3 main.py
기본 코드를 그대로 저장했을 때의 출력은 다음과 같다.
모의 면접 연습-01 | seed=42
검증: 기술 20 / 경험 6 / 역질문 4 / 합계 30 / 중복 0
점수 칸: 결론/근거/적용/한계, 각각 0~2점
01 [기술/자료구조] 관심 상품 중복을 어떻게 막겠는가? | __/__/__/__
02 [기술/자료구조] 가격순 상위 상품을 어떻게 유지하겠는가? | __/__/__/__
03 [기술/자료구조] 트리 탐색 비용은 무엇에 좌우되는가? | __/__/__/__
04 [기술/자료구조] 배열과 연결 리스트를 언제 선택하는가? | __/__/__/__
05 [기술/실행과 통신] 공유 데이터 갱신에서 어떤 경쟁이 생기는가? | __/__/__/__
06 [기술/실행과 통신] 상품 요청의 통신 경로를 설명하라. | __/__/__/__
07 [기술/실행과 통신] 응답 대기 시간은 어디에서 생기는가? | __/__/__/__
08 [기술/실행과 통신] 연결 실패 뒤 재시도는 언제 가능한가? | __/__/__/__
09 [기술/데이터와 API] 상품 목록이 느리면 무엇부터 확인하는가? | __/__/__/__
10 [기술/데이터와 API] 거래 완료 요청이 두 번 오면 어떻게 하는가? | __/__/__/__
11 [기술/데이터와 API] 인덱스의 비용과 이점은 무엇인가? | __/__/__/__
12 [기술/데이터와 API] 거래 상태 변경을 어떻게 묶겠는가? | __/__/__/__
13 [기술/화면과 품질] 상품 등록의 실패 경로를 어떻게 테스트하는가? | __/__/__/__
14 [기술/화면과 품질] 키보드로 상품을 탐색할 수 있는지 어떻게 확인하는가? | __/__/__/__
15 [기술/화면과 품질] 화면 상태를 어디에 둘지 어떻게 정하는가? | __/__/__/__
16 [기술/화면과 품질] 목록 화면이 느리면 어떻게 좁히는가? | __/__/__/__
17 [기술/설계와 운영] 실패한 외부 호출을 어떻게 제한하겠는가? | __/__/__/__
18 [기술/설계와 운영] 요청이 늘면 무엇을 먼저 측정하는가? | __/__/__/__
19 [기술/설계와 운영] 캐시 데이터가 오래되면 어떻게 하는가? | __/__/__/__
20 [기술/설계와 운영] 배포 뒤 오류가 늘면 어떻게 대응하는가? | __/__/__/__
21 [경험/경험] 팀원과 의견이 달랐던 일을 설명하라. | __/__/__/__
22 [경험/경험] 일정이 어긋났을 때 무엇을 바꿨는가? | __/__/__/__
23 [경험/경험] 실패한 시도에서 무엇을 배웠는가? | __/__/__/__
24 [경험/경험] 피드백을 반영한 사례를 설명하라. | __/__/__/__
25 [경험/경험] 모르는 질문을 받으면 어떻게 하겠는가? | __/__/__/__
26 [경험/경험] 자신이 맡은 범위를 어떻게 증명하겠는가? | __/__/__/__
27 [역질문/역질문] 입사 후 첫 업무의 범위와 완료 기준을 묻는다. | __/__/__/__
28 [역질문/역질문] 코드 검토에서 주로 확인하는 기준을 묻는다. | __/__/__/__
29 [역질문/역질문] 배포 전 검증과 되돌리는 기준을 묻는다. | __/__/__/__
30 [역질문/역질문] 신입이 질문하고 피드백받는 방식을 묻는다. | __/__/__/__
재연습 번호: ______
오류 원인과 다음 행동: ______
실무에서 자주 틀리는 것
전체 은행에서 30개만 뽑는다
전체 질문 수만 맞으면 영역별 비율이 유지된다고 생각하기 쉽다. 한 번에 추출하면 특정 영역이 빠질 수 있다. 다음은 잘못된 구성 방식이다.
import random
all_questions = [
question
for _, _, _, questions in BANKS
for question in questions
]
rows = random.Random(42).sample(all_questions, 30)
고친 코드는 영역별로 먼저 선택하고 결과를 검증한다. 전체 30개라는 조건과 영역별 할당은 별도로 확인해야 한다.
rows = make_session(SEED)
validate(rows)
시드가 같으면 입력 순서와 무관하다고 생각한다
시드는 실행 조건의 일부다. 질문을 집합으로 바꾸면 원래 순서를 잃고 실행 환경에 따라 다른 순서가 될 수 있다. 다음 코드는 비교용 질문 은행을 만드는 방식으로 적절하지 않다.
questions = tuple(set(questions))
원래 순서를 유지하고 중복을 오류로 처리한다. 질문 은행의 내용이나 순서를 바꿨다면 기존 녹음과 질문 번호가 같다고 가정하지 않는다.
if len(set(questions)) != len(questions):
raise ValueError("질문 은행의 중복을 수정해야 한다.")
높은 총점이 사실 오류를 가리게 한다
결론 2점, 근거 0점, 적용 2점, 한계 2점이면 총점은 6점이다. 다음 코드는 이 답변의 핵심 오류를 우선 보완 대상으로 잡지 못한다.
needs_review = sum(scores) <= 4
고친 코드는 근거 점수와 사실 오류를 따로 본다. scores는 결론, 근거, 적용, 한계 순서의 네 점수이며 factual_error는 채점자가 표시한 값이다.
needs_review = (
factual_error
or scores[1] == 0
or sum(scores) <= 4
)
다른 질문의 점수를 그대로 비교한다
첫 녹음과 재녹음의 시드를 다르게 설정하면 질문 난도와 답변 변화가 섞인다. 다음 방식은 같은 질문에서 무엇이 개선됐는지 확인하기 어렵다.
first = make_session(42)
second = make_session(43)
같은 질문의 개선 여부를 확인할 때는 시드와 질문 은행을 유지한다. 새로운 조합에 대응하는 연습은 별도 기록으로 남긴다.
first = make_session(42)
second = make_session(42)
new_combination = make_session(43)
한눈에 보기
| 대상 | 핵심 기준 | 남길 기록 | 다음 행동 |
|---|---|---|---|
| 질문 구성 | 기술 20·경험 6·역질문 4 | 시드와 질문 은행 버전 | 영역별 수량과 중복을 검사한다. |
| 답변 | 결론·근거·적용·한계 | 녹음과 문장별 수정 지점 | 빠진 요소를 보완한다. |
| 채점 | 항목별 0~2점 | 점수를 준 이유 | 사실 오류를 총점보다 먼저 다룬다. |
| 재연습 | 오류, 낮은 점수, 영역 누락 | 우선 보완할 질문 번호 | 실험·구조 수정·경험 확인으로 나눈다. |
| 비교 | 같은 질문과 같은 시간 제한 | 첫 녹음과 재녹음 | 어느 항목이 변했는지 설명한다. |
이 책의 마지막에 남길 결과물은 외운 답안 묶음보다 작아도 된다. 자신의 판단을 근거와 연결한 녹음, 아직 확인하지 못한 내용을 적은 목록, 실제 경험을 구분한 메모가 있으면 다음 연습을 시작할 수 있다. 면접에서 질문의 표현이 달라져도 이 자료를 바탕으로 답을 다시 구성한다.
연습 문제
- 자료구조 영역의 선택 수를 6으로 바꾸면 어떤 검사가 먼저 실패하는지 설명하라. 질문 은행을 6개로 늘리기만 하면 전체 구성이 맞는지도 판단하라.
- 총점은 같지만 점수가 각각 2·0·2·2와 1·2·2·1인 답변이 있다. 어느 답변을 먼저 보완할지 정하고 녹음에서 확인할 내용을 적어라.
- 프로그램의 질문 하나에 90초 이내로 답하고 녹음하라. 네 기준으로 채점한 뒤 첫 두 문장을 수정하고 다시 녹음하라. 말하지 않은 경험을 추가하지 말라.
- 선택 방식이 모든 조합을 만들 수 있는지 자료구조 은행을 기준으로 검토하라. 질문 다섯 개 중 두 개를 선택하도록 바꿨을 때 가능한 조합과 빠지는 조합의 예를 들어라.
정답과 해설
- 현재 은행에는 다섯 문항이 있으므로 make_session의 선택 수 검사가 먼저 실패한다. 은행을 여섯 문항으로 늘리면 그 검사는 통과하지만 기술 문항이 22개, 전체가 32개가 되어 validate에서 실패한다. 현재 구성에서는 기술 다섯 영역에서 각각 네 개를 고른다는 조건도 유지해야 한다.
- 2·0·2·2인 답변을 먼저 보완한다. 총점은 둘 다 6점이지만 첫 답변은 핵심 오류가 있거나 근거가 없다. 녹음에서 어떤 주장에 이유가 없었는지 확인하고, 사실 오류인지 설명 누락인지 나눈다. 두 번째 답변은 결론을 앞당기고 제약과 후속 판단을 연결하는 연습을 한다.
- 정해진 답안은 없다. 첫 녹음과 두 번째 녹음에서 결론이 나오는 위치, 근거의 정확성, 예시와 질문의 연결, 한계의 명시를 비교하면 된다. 새 경험을 꾸며 답변을 풍부하게 만들었다면 개선으로 보지 않는다. 실제 경험이 없으면 확인할 절차나 가상 예시임을 밝힌다.
- 현재 선택기는 시작 위치부터 연속된 문항을 고르므로 모든 부분집합을 만들지 못한다. 위치를 0부터 4로 표시하면 두 문항 선택 시 0·1이나 4·0은 가능하지만 0·2는 불가능하다. 현재 네 문항 선택에서는 다섯 개 중 하나를 제외하는 형태가 모두 가능해 이 제약이 덜 드러난다. 다양한 부분집합을 고르게 뽑는 것이 목표라면 표준 라이브러리 random의 독립된 생성기와 sample을 영역마다 사용하도록 바꾸고, 고정 시드와 입력 순서를 함께 보관한다.