AI 면접관에게 면접 본 후기…3번째 꼬리질문에 막혀
AI 면접관을 일대일로 붙여 꼬리질문을 받은 실전 후기와 10가지 추궁 질문 목록을 정리했다.
중국어 원문을 AI로 번역했습니다. 고유명사와 수치는 원문 표기를 우선하며, 중요한 판단에는 아래 출처 원문을 함께 확인하세요.
나 자신에게 꽤 잔인한 짓을 했다. 이력서의 하이라이트를 AI 대화 세션에 넘기고 면접관 역할을 시킨 것이다. 한 번에 한 질문만, 같은 주제는 연속해서 파고들 것, 숫자와 증거만 인정할 것, 사교적 인사 금지. 총 9개 질문, 그중 잡담성 질문은 하나도 없었고, 나는 매 라운드 즉석에서 답했다. 리허설은 없었다.
결과는 진짜 면접보다 더 혹독했다. 첫 번째 주제가 채 끝나기도 전에, 세 번째 질문에서 나는 "이 데이터는 없습니다"를 내놓고 말았다. 이 글에서는 세 차례 심문의 실록 일부와 내가 무릎 꿇은 지점을 완전히 복기해 준다. 글 끝에는 10개追问 리스트가 있다. 면접 전에 이걸로 자기 자신을 한 번 면접해 보길 권한다.
이 면접은 어떻게 진행됐나
면접관 페르소나: 경력 12년의 시니어 프런트엔드, 수백 번의 면접을 봤고, 이력서 전공(戰功) 속의 수분을 전문적으로 찔러대는 사람. 후보자는 내 이력: 프런트엔드 5년, 컴포넌트 라이브러리와 중·백오피스 방향, 이력서의 주력은 "성능 최적화를 주도했다"와 "React 상태 관리 리팩터링".
규칙은 딱 세 가지: 한 번에 하나만 질문할 것; 같은 주제는 최소 두 층까지 파고든 뒤에야 문제를 바꿀 것; 매 라운드 "평가 + 추가 질문"을 출력하되, 평가는 직전 답변의 수분만 지적할 것. 나는 스스로 한 가지 최저선을 정했다: 데이터를 지어내지 않고, 답을 못 하면 그 자리에서 인정할 것.
그러고는 칼을 대기 시작했다.
주제 1: 성능 최적화——숫자가 단단한지, 몇 층의 추궁을 견디는지 보라
내가 처음 보고한 숫자: 운영 설정 페이지의 LCP를 p75 4.2초에서 2초 안팝으로 압축했다. 조치는 레이지 로딩, 차트 온디맨드, 인터페이스 집계 세 가지였다. 첫 라운드 평가에서 바로 현행범을 잡혔다. 내가 처음에는 "첫 화면에 큰 테이블과 차트 두 개를 렌더링한다"고 말했다가, 뒤에서는 "첫 화면에 필요 없는 차트 두 개를 옮겼다"고 말한 것——앞뒤가 맞지 않았다.
진짜로 수분을 짜낸 것은 두 번째 라운드였다:
레이지 로딩, 온디맨드 도입, 인터페이스 집계 이 세 칼을 각각 분리해서, p75에서 각각 몇 밀리초를 기여했는지, 무슨 데이터로 그것을 분리해냈는가? 그리고 이런 가능성은 어떻게 배제하는가: 4.2초가 2초로 떨어진 것이 단지 LCP 요소가 차트에서 더 작은 테이블로 바뀐 것 때문이고, 너는 한 번의 측정 기준 변화를 전공(戰功)으로 기록한 것 아닌가?
이 두 질문 모두 나는 받아내지 못했다. 당시 우리에게는 총계——프리프로덕션 단일 변수 비교와 운영 그레이 분할 버킷——와 "번들 크기, 메인 스레드 점유" 같은 중간 지표만 있었고, 밀리초 단위 분해는 하지 않았다. LCP 요소가 바뀌었는가? 바뀌었다. 차트의 canvas에서 테이블 첫 화면 행으로 바뀌었다. 실제 속도 향상과 측정 기준 변화가 뒤섞여 있어서 나는 깔끔하게 분리할 수 없었고, 그 자리에서 첫 번째 의문 항목을 인정했다.
세 번째 질문이 가장 혹독했다:
LCP는 이제 쓰지 마라. 그것과 완전히 무관한 지표를 하나 다오——TBT, 총 롱태스크 시간, INP 모두 괜찮다. 반드시 중저가 기기와 약한 네트워크 데이터를 포함해야 한다.
Lab 기준의 TBT는 나에게 있었다: 800여 밀리초에서 400 안팝으로 떨어졌다. 하지만 실제 기기, 실제 약한 네트워크는 없었다, 측정한 적이 없었다——우리는 throttle 환경에서만 시뮬레이션했다. 면접관은 그때 한마디를 던졌다: "이 빚은 저가 기기에서 스크롤할 때 롱태스크의 형태로 되돌아올 것이다."
이 부분의 교훈은 아주 소박하다: 숫자의 단단함 = 단일 변수 분해 정도 × 측정 기준 무관성 정도. 둘 다 안 되면, 네 '최적화'는 세 층의 추궁을 견디지 못하고, 그저 하나의 이야기로만 남는다.
주제 2: 상태 관리——3000건 데이터 × 60페이지가 내 가장 매끄러운 그 한마디를 지워버렸다
이 주제는 내가 가장 매끄럽게 답했다: 필터, 페이지네이션, 선택 행, 유일한 데이터 원천은 URL query에 두고, 모든 컴포넌트는 URL에서 파생하며, 쓰기 작업은 URL만 바꾼다; 그리고 세 가지 기준선을 붙였다——세션을 넘어설 때만 store로, URL에서 재구성 가능하면 URL에, 서버 데이터의 투영은 요청 캐시 계층에 맡긴다.
첫 라운드 추가 질문에서 그것은 시나리오를 못 박았다: 필터로 3000건을 뽑고 페이지당 50건, 사용자가 먼저 "현재 페이지 전체 선택"을 누른 뒤 페이지별로 추가해 60페이지를 다 채운다. 그동안 한 번 체크할 때마다 내 주장대로 "URL만 바꾼다".
이 3000개 id를 query에 써넣으면 URL이 대략 얼마나 길어지고, history에는 몇 개의 레코드가 쌓이며, 그가 뒤로 가기를 한 번 누르면 어느 단계로 돌아가는가?
그 자리에서 계산: id마다 구분자를 더하면 약 11자, 3000개면 3.3만 자의 query로, 브라우저 안전선(약 2000자)을 한 자릿수 넘는다; history는 push로 계산하면 3000여 개, 뒤로 가기 키를 수천 번 눌러야 한다. 결론은 등급을 낮출 수밖에 없었다: 선택 행을 URL에서 회수해 페이지 레벨 store로 옮기고, "전체 선택 + 제외 집합"의 규칙화 모델링으로 바꾼다. 나는 그 자리에서 인정했다——"선택 행 = URL 유일 원천이라는 말, 절반을 회수한다."
하지만 나는 용량 이 한 건만 계산했고, 두 번째 칼이 있었다: 시간.
사용자가 3000건 전체 선택, 5건 제외, "선택됨 2995"를 표시; 그는 아무것도 누르지 않았고, 그 사이 새로 20건이 조건에 맞고 38건이 무효화됐다(그중 3건은 그의 제외 집합에 있다). 그런데 그가 내보내기를 누른다: 2982−5=2977과 2982−2=2980, 너는 어느 수를 내놓는가?
답: 2980. 제외 집합은 집합 연산으로 빼야지, 단순 뺄셈으로 빼는 게 아니다——이미 조건 집합에 없는 그 3건의 제외 항목은 두 번째로 빼면 안 된다. 하지만 더 값진 것은 강제로 끌어낸 그 질문이었다: "전체 선택"은 도대체 체크한 그 순간의 스냅샷인가, 내보내기 그 순간의 술어인가? 내가 마지막에 낸 것은 세 번째 길이었다——술어는 편집기를 관장하고, 스냅샷은 제출기를 관장한다: 내보내기를 누를 때 서버가 술어를 한 번 평가해 스냅샷으로 얼리고, 확인 상자가 숫자와 변화 내역을 펼쳐 보여주며, 사용자가 보고 확인하고 내보내는 것이 반드시 같은 한 번의 평가 결과여야 한다.
이 라운드를 한마디로 정리하면: 결과가 있는 동작이라면, 사용자가 보는 수, 백엔드가 계산하는 수, 실제로 일어나는 수는 반드시 같은 한 번의 평가여야 한다. 상태를 어디에 두는가는 그저 첫 번째 층의 문제일 뿐이다; 진짜 어려운 것은 그것이 언제 평가되는가다.
주제 3: 컴포넌트 라이브러리——상반된 두 건의 불만, 하나의 근본 원인
이 라운드에서 그것이 낸 것은 즉석 문제였다: 네 컴포넌트 라이브러리가 3년간 배포되고 40여 개 중·백오피스 프로젝트에 소비됐다고 가정하자, 산출물은 ESM/CJS 두 벌, 메인 엔트리 barrel이 120개 컴포넌트를 커버하고, 각 컴포넌트 엔트리 상단에 import './style/index.less', 빌드 시 독립 CSS로 추출되고, package.json에 "sideEffects": false가 적혀 있다. 오늘 책상 위에 두 건의 불만이 있다:
webpack5 도입 측: "나는 DatePicker만 import했는데 산출물에 400KB가 들어앉아 있다. source map을 보니 라이브러리 전체다."
Vite 도입 측: "dev에서는 모든 게 정상인데, 빌드 산출물에서 스타일이 전부 사라진다."
하나는 많고 하나는 적고, 증상은 반대지만 근본 원인은 같은 한 가지다: package.json이 패키지에 대한 설명과 산출물의 실제 구조가 맞지 않는다.
Vite 쪽이 특히 전형적이다. "sideEffects": false는 번들러에게 "이 패키지 전체에 부작용이 없다"고 약속하는 것인데, import './style/index.less'는 바로 아무것도 바인딩하지 않는 순수 부작용 import다——Rollup이 빌드 시 삭제 가능 항목으로 트리 셰이킹해 버린다; dev는 트리 셰이킹을 돌리지 않으므로 모든 게 정상이다. "dev는 좋고 build는 나쁘다"는 이 조합은 기본적으로 하나의 해석밖에 없다.
webpack 쪽은 해석이 셰이킹 불가능한 엔트리로 떨어진 것이다: CJS의 barrel은 런타임 속성 내보내기라 정적 분석으로 셰이킹할 수 없고, 라이브러리 전체가 패키지에 들어간다. 여기 놓치기 쉬운 점이 하나 있다——sideEffects는 이 사슬에서 도움이 안 된다, 그것은 약속이지 메커니즘이 아니다.
그러고는 SSR에 칼을 한 번 더 댔고, "모니터링은 전부 초록인데 사용자는 벗고 뛰는" 함정을 끌어냈다: SSR 첫 화면 HTML에 클래스명은 있지만 스타일은 클라이언트 chunk에 있고 600밀리초 후에 주입된다. 클래스명은 컴포넌트 JS가 생성한 문자열이라, 브라우저에 CSS 1바이트가 존재함을 증명하지 못한다——내가 원래 준비한 "HTML에 클래스명이 있다"는 단언은 빈 단언으로 판정됐다. 사용자는 그 600밀리초 동안 "구조는 있고 껍질은 없는" 페이지를 보는데, 모니터링에서는 모든 게 정상이다.
이 라운드의 교훈 한마디: 번들러를 넘나드는 공공 계약(온디맨드 도입 + 스타일 주입)은 문서에 적는 것으로 검증되지 않고, 소비 측 매트릭스에 들어가야 검증된다.
면접관이 마지막으로 내게 준 판정
위로는 없었다, 곧바로 원문을 인용했다:
- 성능 주제 프로필: "동작은 맞게 할 수 있지만, 결과를 변호하지는 못한다."
- 상태 관리 주제: "경험은 진짜, 추상화는 강함, 경계 의식은 한 박자 느림."
- 컴포넌트 라이브러리 주제: "잘 알고, 두루 생각하지만, 출하를 못 한다——이 맥락에서는 출하를 못 하면 물건이 없는 것이다."
- 전장에서 가장 자주 나온 한마디: "메커니즘은 도출할 수 있는데 검증은 나에게 없다"——네 번 나왔다: 실제 기기 약한 네트워크, 소비 측 매트릭스, SSR 스타일 목록, 컴포넌트 라이브러리 마이그레이션 툴체인.
- 가장 아픈 마무리: "네가 한 등급 위와 차이나는 것은 인식이 아니라 증거다."
이 면접을 건강검진으로 본다면, 보고서는 한 문장이다: 방법은 부족하지 않고, 클로즈드 루프가 부족하다. 모든 메커니즘을 나는 도출할 수 있지만, 모든 메커니즘이 "검증은 돌려본 적 없다"에서 멈춘다.
10개 추가 질문 리스트: 면접 전에, 이걸로 자기 자신을 한 번 면접하라
전체 추궁을 10개의 범용 질문으로 압축했다. 면접 준비, 프로젝트 정리, 사고 복기 때 모두 쓸 수 있다:
추궁 템플릿 그것이 검증하는 것 나의 결말 1 이 숫자는 어떻게 측정했나? 온라인과 오프라인 측정 기준은 각각 무엇인가? 데이터 변호 가능성 통과 2 몇 가지 일을 분리했을 때 각각 얼마나 기여했나? 측정 기준 변화가 전공으로 계산되는 것을 어떻게 배제하나? 귀인 능력 반무릎: 총계만 있음 3 그것과 무관한 지표로 바꿔라, 반드시 실제 기기, 약한 네트워크 데이터를 포함할 것 두 번째 측정 기준이 있는가 무릎: TBT는 있고, 실제 기기는 없음 4 같은 상태가 시스템에 몇 개의 복사본으로, 각각 어디에 있나? 네가 밟았던 사고는 무엇인가? 상태 단일 귀속 통과 5 극단적 규모 계산: 3000건 × 60페이지, URL은 얼마나 길고, history는 몇 개, 뒤로 가기 키는 어디로 돌아가나? 용량 경계 반무릎: 절반 회수 6 이 수는 체크한 그 순간의 스냅샷인가 내보낸 그 순간의 술어인가? 삼자가 어떻게 같은 한 번의 평가를 보장하나? 시간 일관성 통과(즉석에서 도출) 7 증상이 반대인 두 건의 불만, 무엇을 먼저 보고, 어떻게 검증하며, 근본 원인이 한 가지인가? 진단 방법 통과 8 너의 단언은 "터지지 않았다"를 증명하는가 아니면 "제대로 됐다"를 증명하는가? 빈 단언 식별 무릎: 클래스명 단언이 빈 것으로 판정됨 9 제약을 더한 뒤, 옛 사용법 중 어느 것이 하드 실패하고 어느 것이 조용히 해석 대상을 바꾸는가? 훑어봤나? 호환 면 통과 10 마이그레이션 비용은 누가 지불하나? "업그레이드 후 아무도 안 터진다"를 너는 무엇으로 증명하나? 마무리 능력 종이 위 통과
자기 자신에게 같은 심문을 배치하는 법
아래 문단을 자주 쓰는 AI 대화에 보내면 면접을 시작할 수 있다. 규칙이 페르소나보다 중요하다:
너는 지금부터 엄격한 프런트엔드 면접관이다: 경력 12년, 수백 번 면접을 봤고, 이력서 속 수분을 전문적으로 찌른다. 후보자 배경: <두 줄 이력서 하이라이트>. 규칙: 1. 한 번에 한 문제만 질문한다; 같은 주제는 최소 두 층 연속 추궁하고, 숫자를 못 내면 계속 추궁한다; 2. 숫자, 측정 기준, 트레이드오프만 인정하고, 프로세스와 형용사는 인정하지 않는다; 3. 매 라운드 두 부분만 출력한다: 【평가】 직전 답변의 수분; 【추가 질문】 다음 질문, 구체적 시나리오와 숫자를 요구할 것; 4. 전장에서 사교적 인사 금지. 끝까지 추궁한 뒤, 전체 평가를 하나 주고, 어느 몇 가지가 사람을 설득하지 못하는지 직설적으로 말하라.
두 가지 사용 제안. 첫째, 답하기 전에 "이 문제가 세 번째 층까지 추궁당하면 나에게 무엇이 남는가"를 먼저 생각하라, 답을 못 하면 다른 경험을 꺼내라; 둘째, 그것의 【추가 질문】을 전부 모아둬라——그것은 오직 너만을 겨냥한 개인 문제 은행이며, 어떤 범용 면접 후기보다도 정확하다.
마지막으로
이 10문제, 너는 몇 라운드까지 통과할 수 있나? 댓글로 번호를 알려달라, 어느 것이 가장 어려운지 보겠다.
만약 너도 한 판 열고 싶다면, 내 교훈을 기억하라: "어떻게 답할까"를 준비하는 데만 매달리지 말고, 먼저 각 답이 세 층 추궁당한 뒤에도 얼마나 검증 가능한 것이 남는지 확인하라. 네가 다음 등급과 차이나는 그 조금은, 아마 인식이 아니라 증거일 것이다.