LLM WikiAccess-protected knowledge portal

WIKI

리멤버 1차 면접 2일 압축본

리멤버 1차 면접 2일 압축본 작성일 2026 08 10 D 2 면접 2026 08 12 · Data Engineer 팀장 1명, 팀원 1명 전제 일과 병행. 총 학습시간 4시간으로 끝내는 것을 목표로 한다. 원본 면접 준비 가이드 전체판 2026 08 05 remember data engineer interview prep.md · 스터디 지도 2026 08 07 remember interview study map.md ·

경로human/reports/2026-08-10-remember-interview-2day-cram.md
카테고리Reports
태그#2day #airflow #cram #infra #interview #portfolio #remember #report #reports #study

작성일 2026-08-10 (D-2) 면접 2026-08-12 · Data Engineer 팀장 1명, 팀원 1명 전제 일과 병행. 총 학습시간 4시간으로 끝내는 것을 목표로 한다. 원본 면접 준비 가이드(전체판) · 스터디 지도 · 과제 아키텍처 페이지

이 문서의 원칙은 하나다. 어려운 말로 정확하게 말하는 것보다, 쉬운 말로 정확하게 말하는 것이 어렵다. 그래서 모든 항목을 초등학생 설명 → 정확한 정의 → 내 사례 연결 3단으로 적었다. 면접장에서는 1단으로 시작해 상대가 더 파면 2단, 3단으로 내려간다.


0. 시간표 — 4시간 안에 끝내기

언제시간무엇
D-2 밤 (8/10)90분2장 과제 + 3장 A그룹(과제에 쓴 기술)가장 많이 물어볼 곳. 여기만 되면 절반은 넘긴다
D-1 밤 (8/11)90분4장 리멤버 스택 + 6장 안 해본 것 스크립트남의 집 지도와 경계선. 외우는 게 아니라 개념만
D-1 밤30분2-2·2-3을 소리 내어 5회30초 설명은 입으로 외워야 현장에서 나온다
당일 아침30분8장 치트시트 1장만숫자와 첫 문장만 다시 본다

하지 말 것: 전체판 가이드(755줄)를 처음부터 다시 읽는 것. 이미 만든 답변 스크립트는 지금 단계에서 도움이 안 된다. 문장을 외우면 질문이 살짝만 비틀려도 무너진다. 구조와 숫자만 잡는다.

5장 포트폴리오는 읽지 않는다. 본인이 직접 한 일이라 이미 알고 있다. 표에 적은 것은 "물어보면 이 각도로 꺼내라"는 앵커 한 줄씩이다. 훑기만 한다.


1. 팀장이 5년차에게 확인하려는 것 6가지

경력 5년차 데이터 엔지니어 면접에서 실제로 판정되는 건 지식의 양이 아니다. 아래 6개 신호다. 답변마다 이 중 하나는 반드시 태우고 지나간다.

신호팀장이 속으로 하는 질문내가 태울 재료
① 데이터를 먼저 봤나요구사항만 읽고 코딩부터 시작하는 사람인가구현 전 두 CSV 전수 조사 → 1 vs 1.0, 전남 vs 전라남도 210건 발견
② 되돌릴 수 있게 만들었나사고 나면 이 사람 코드는 복구 가능한가RAW 선보존, 컬럼별 변경 이력, 한 트랜잭션 커밋, 멱등 재실행
③ 모르는 값을 함부로 고치지 않나데이터를 오염시킬 사람인가9자리 사업자번호에 0을 채우지 않고 격리, checksum 불일치 9건은 WARN만
④ 자기 설계의 한계를 아나자기 코드를 과대평가하는가"실행 메타데이터까지 exactly-once는 아니다", "동시 backfill은 지금 안전하다고 말 못 한다"
⑤ 안 해본 걸 안 해봤다고 하나같이 일할 때 믿을 수 있는가Spark·Kafka 프로덕션 없음, AWS는 EC2만, 개인정보 운영 없음
⑥ 혼자 결정했나 팀을 통했나영향 범위 큰 변경을 혼자 지르는가인덱스 224개 삭제 전 95개 쿼리 실행계획 확인, 팀장·CTO 리뷰

③④⑤가 5년차와 3년차를 가르는 지점이다. 신입은 "했습니다"를 말하고, 5년차는 "여기까지 했고 여기부터는 안 했습니다"를 말한다.


2. 과제 — 여기가 면접의 절반

2-1. 10초 버전

2022년 회사 명단과 2023년 회사 명단을 사업자번호로 맞춰서, 새로 생긴 곳·바뀐 곳·그대로인 곳·이번에 안 보이는 곳을 나누고, 그 판단 근거를 전부 남기는 파이프라인입니다.

2-2. 초등학생 버전 (30초) — 이걸 먼저 말한다

작년 반 명단이랑 올해 반 명단을 들고 비교한다고 해보세요. 이름·주소·전화번호가 적혀 있고요.

그냥 눈으로 비교하면 실수가 납니다. 작년에는 "1명"이라고 썼는데 올해는 "1.0명"이라고 썼으면 사람은 같다고 보지만 컴퓨터는 다르다고 봐요. 주소도 작년엔 "전남", 올해는 "전라남도"라고 쓰면 이사 간 것처럼 보이고요.

그래서 저는 세 칸으로 나눠서 일했습니다. 첫째 칸에 받은 종이를 원본 그대로 붙여두고, 둘째 칸에서 글씨체를 통일해서 옮겨 적고, 셋째 칸에서 작년 명단이랑 한 줄씩 맞췄습니다. 나중에 "이거 왜 바뀐 거예요?" 물으면 셋째 칸만 보면 안 되니까, 원본을 첫째 칸에 남겨둔 거예요.

그리고 "올해 명단에 없다"고 지우지 않았습니다. 전학 간 건지, 명단 만드는 사람이 빠뜨린 건지 저는 모르거든요. 그래서 지우는 대신 "올해는 안 보였음"이라고 표시만 해뒀습니다.

세 칸 = RAW / STG / MASTER. 이 비유 하나로 계층 설계·재처리·soft delete가 한 번에 설명된다. 면접에서 용어를 먼저 꺼내지 말고 비유를 먼저 던진 뒤, 상대가 고개를 끄덕이면 "이걸 RAW/STG/MASTER라고 부릅니다"로 붙인다.

2-3. 면접용 버전 (30초)

2022 초기 적재와 2023 동기화를 DAG 하나로 처리했습니다. 연도만 파라미터로 받아서 같은 코드가 두 회차를 돌립니다.

입력 파일을 RAW로 원문 보존하고, STG에서 사업자번호·주소·근로자수·날짜를 같은 형식으로 정규화하면서 품질을 판정합니다. 그다음 사업자번호로 조인해서 신규·변경·no-op를 나누고, 마스터 반영 + 변경 이력 + 부재 표시 + 정합성 검사 8종을 한 트랜잭션으로 커밋합니다. 하나라도 실패하면 이력까지 롤백하고 회차를 FAILED로 마감합니다.

DuckDB 파일에 동시에 쓰지 않도록 태스크를 직렬로 두고 max_active_runs=1로 제한했습니다.

2-4. 데이터 흐름 (이 그림을 머리에 넣는다)

flowchart LR
  CSV["연도별 CSV<br/>2022 · 2023"] --> RAW
  subgraph RAW["RAW · 원문 보존"]
    R1["raw_workplace<br/>규칙 바뀌면 파일 재수신 없이 여기서 재계산"]
  end
  RAW --> STG
  subgraph STG["STAGING · 정규화 + 품질 판정"]
    S1["stg_workplace<br/>has_valid_key / is_valid 분리"]
    S2["ops_quarantine<br/>격리 · 확인 필요"]
  end
  S1 --> MERGE{"사업자번호 조인<br/>IS DISTINCT FROM"}
  MERGE -->|없던 키| INS["신규 2,174"]
  MERGE -->|5속성 중 1개라도 다름| UPD["변경 4,000"]
  MERGE -->|전부 동일| NOP["no-op 17,087"]
  MERGE -->|소스에 없음| ABS["is_active=false 9,426"]
  INS --> TX
  UPD --> TX
  NOP --> TX
  ABS --> TX
  subgraph TX["단일 트랜잭션 — 전부 성공 or 전부 롤백"]
    M1["master_workplace<br/>사업장당 1행 (과제 결과물)"]
    M2["master_change_log<br/>컬럼별 전·후 값"]
    CHK["정합성 검사 8종"]
  end
  TX --> OPS["ops_sync_run<br/>회차별 입력·정책·건수·검증결과"]

이 그림에서 반드시 말할 3가지

  1. RAW가 앞에 있는 이유 — 규칙이 바뀌어도 원본 파일을 다시 받지 않는다
  2. 네모 하나(TX)로 묶인 이유 — 절반만 반영된 상태를 남기지 않는다
  3. ops_sync_run이 밖에 있는 이유 — 여기가 exactly-once가 아닌 지점이다 (2-9 참고)

2-5. 실행 구조

flowchart TB
  subgraph IMG["Airflow 이미지 (빌드 시 굽는다)"]
    CODE["DAG · 파이프라인 코드"]
    DATA["입력 CSV (NFC 정규화)"]
  end
  subgraph RUN["docker compose"]
    AF["Airflow scheduler + webserver<br/>max_active_runs=1 · 태스크 직렬"]
    PG[("PostgreSQL<br/>Airflow 메타데이터 전용")]
    VOL[("named volume<br/>DuckDB 작업 파일")]
  end
  IMG --> AF
  AF <--> PG
  AF <--> VOL
  VOL -->|두 회차 SUCCESS 이후에만| OUT["warehouse/employment_insurance.duckdb"]
  UP["./up.sh<br/>검토자는 Docker만 있으면 됨"] --> RUN

왜 바인드 마운트를 안 했나 (물어보면 강한 답): 호스트 경로를 그대로 붙이면 한글 파일명과 Drive 동기화 폴더에서 파일 접근이 실패했다. 실제로 OSError: Resource deadlock avoided를 봤고, macOS는 한글을 NFD로 저장하는데 리눅스 컨테이너 안에서는 바이트 단위 조회가 어긋났다. 그래서 입력과 코드를 이미지에 굽고 CSV 이름을 NFC로 정규화했다. 재현성 문제를 실제 실패로 겪고 고쳤다는 점이 이 답변의 값이다.

2-6. 테이블 6개 — 왜 마스터 하나로 안 끝냈나

이 질문은 거의 확실히 나온다. "과제는 마스터 테이블 하나만 요구했는데 왜 6개죠?"

마스터만 만들면, Update가 규칙대로 됐는지 확인할 방법이 없습니다.

계층테이블한 줄 역할없으면 못 하는 것
RAWraw_workplace받은 원문 그대로규칙 바꿀 때 파일 재수신 필요
STGstg_workplace정규화 + 품질 판정무엇이 왜 제외됐는지 설명 불가
MASTERmaster_workplace사업장당 1행 최신 상태 (과제 결과물)
MASTERmaster_change_log컬럼별 전·후 값"무엇이 바뀌었나" 답변 불가
OPSops_quarantine격리·확인 필요 기록버린 데이터가 사라짐
OPSops_sync_run회차별 입력·정책·건수·검증결과"어느 회차가 이걸 했나" 추적 불가

변경 이력은 SCD2 대신 컬럼 단위 로그로 갔다. 비교 컬럼이 5개뿐이고 "무엇이 바뀌었나"가 검증의 핵심이었기 때문이다.

2-7. 설계 결정 7개 — 각 1줄 + 되받아치는 말

압박 질문이 오면 먼저 "그 지적 맞습니다"를 인정하고, 왜 그럼에도 이 선택인지로 간다.

#결정한 줄 근거반론이 오면
1데이터 먼저 전수 조사1 vs 1.0, 전남 vs 전라남도 210건. 정규화 없었으면 변경 건수가 5천 건 넘게 부풀었다"샘플만 봐도 되지 않나요?" → 3만 행이라 전수가 가능했고, 표기 차이는 샘플에 안 걸린다
2키는 고치지 않는다9자리 사업자번호에 0을 채우면 실재하는 다른 사업장과 충돌한다. 되돌릴 수 없는 오염"그럼 그 행은 버리나요?" → 마스터에서만 제외하고 격리 테이블에 남긴다. 버리지 않는다
32023 빈 값 → NULL 갱신이 기본과제가 "최신 파일 값으로 갱신"이라고 정의했으니 literal 적용. 보존은 SYNC_PRESERVE_EXISTING_ON_NULL 옵션"그건 데이터 손실 아닌가요?" → 맞다. 주소 결측 2,249건 중 2,093건은 2022에 값이 있어 추출 누락 가능성이 있다. 그래서 옵션을 만들고 두 정책 모두 검증을 통과시켰다. 운영이면 데이터 소유자와 먼저 합의할 문제
42023에 없는 9,426건 삭제 안 함폐업·추출 누락·공개 범위 변경을 구분할 수 없다. 과제 동작도 Insert·Update뿐"그건 과제가 요구 안 한 확장 아닌가요?" → 맞다. 해석이 들어간 확장이다. 그래서 부재를 무시하는 옵션도 뒀고, 5개 업무 속성 결과는 그대로 재현된다
5테이블 6개2-6 표
6한 트랜잭션마스터·이력·부재·검증 8종을 묶고, 하나라도 실패하면 이력까지 롤백"성능은요?" → 3만 행 규모라 문제 없었다. 수백만 행이면 청크와 publish pointer로 나눈다
7DuckDB연도별 CSV 전체 읽기 + 집합 조인 + 전수 검증이라 컬럼 지향이 맞았다. read_csv, IS DISTINCT FROM"SQLite는요?" → 행 단위 OLTP에 맞는 엔진이다. 약 3만 행에서 성능 자랑하려는 선택은 아니었다. 동시 writer가 필요해지면 중앙 DB로 옮긴다

2-8. 외울 숫자 — 7개면 충분

덧셈으로 외운다. 개별 숫자를 외우지 말고 을 외운다.

30,513 + 2,174 = 32,687     초기 마스터 + 신규 = 최종 마스터
21,087 = 4,000 + 17,087     공통 키 = 변경 + no-op
23,261 + 9,426 = 32,687     활성 + 최근 소스 부재
5,196 = 2,876 + 1,972 + 310 + 30 + 8    주소·근로자수·이름·날짜·업종
8/8, 불일치 0               연도별 정합성 + 2023 최종 대조

함정 질문 대비: "변경된 사업장이 4,000인데 이력이 5,196이면 계산이 안 맞는데요?" → 한 사업장에서 주소와 근로자수가 함께 바뀔 수 있다. 이력을 컬럼별로 한 건씩 남겼기 때문이다.

품질 판정 결과: 실제 파일 ERROR 0건, 2023 WARN 29건, INFO 2,249건(주소 결측). 테스트: 제출 시점 컨테이너 107개, 현재 동일 소스 재검증 108개 (기록 시점을 나눠 말한다).

2-9. 먼저 인정할 한계 3개 — 지적당하기 전에 내가 말한다

이게 신호 ④다. 순서를 바꾸면 방어가 되고, 내가 먼저 말하면 판단력이 된다.

  1. exactly-once는 업무 데이터까지다. 마스터·이력·부재·검증 8종은 한 트랜잭션이지만, 성공 상태와 건수(ops_sync_run)는 그 커밋 뒤에 따로 기록된다. 두 단계 사이에서 죽으면 데이터는 반영됐는데 상태는 RUNNING으로 남을 수 있다. → 운영이면 같은 DB일 때 한 트랜잭션으로 묶고, 저장소가 갈리면 outbox와 오래된 RUNNING 재대조로 복구한다.
  2. 동시 backfill은 지금 안전하다고 주장하지 않는다. max_active_runs=1 + 직렬 태스크라는 단일 회차 가정에 기대고 있고, 일부 조회가 run_id 대신 source_year 범위를 쓴다. → 병렬을 허용하려면 모든 접근을 run_id 또는 immutable snapshot으로 격리하고 (run_id, key) 유일성, lease, publish pointer를 둔다.
  3. 메모리에 한 해 분량을 올린다. stage()가 그렇게 동작하므로 수백만 행에서는 청크 처리가 먼저다.

문서·구현 차이 3건도 먼저 말한다 (이건 진짜 점수가 된다):

말하는 법: "제출 이후에 문서를 실행 산출물과 다시 대조했는데 세 군데 어긋난 부분을 찾았습니다. 먼저 정정하고 시작하겠습니다."

2-10. "코드리뷰 해보세요" 대본 — 두 방향 다 준비한다

(A) 내 과제 코드를 셀프 리뷰하라고 하면 — 잘한 점 자랑이 아니라, 한계를 심각한 순서로 + 조건과 함께. 2-9의 한계 3개가 그대로 재료다.

"제가 리뷰어라면 세 가지를 지적하겠습니다. 심각한 순서로 — ① stage()가 한 연도를 메모리에 올립니다. 3만 행이면 20MB라 지금은 문제없지만 수백만 행에서 첫 번째로 무너지는 지점이고, 그때는 정규화를 DuckDB SQL로 내리거나 청크 처리로 바꿔야 합니다. ② 성립일자가 과거로 이동한 17건을 WARN으로만 남기고 판정하지 않았습니다. 소급 정정인지 추출 오류인지 데이터만으로 알 수 없어서인데, 운영이라면 이 WARN이 사람에게 도달하는 경로와 원천 정정 요청 절차까지 있어야 '기록'이 '처리'가 됩니다. ③ 품질 규칙 12종이 코드에 있어 규칙 변경마다 배포가 필요합니다. 12개 규모에선 리뷰·테스트를 타는 지금이 안전하고, 수십 개로 늘면 선언적 정의로 분리하겠습니다."

닫는 말: "실제로 제출 전 재리뷰에서 테스트 헬퍼가 운영 경로(apply_master 한 트랜잭션)와 다른 경로를 검증하던 결함을 찾아 고쳤습니다. 테스트가 통과하는 것보다 무엇을 통과하는지가 중요하다는 걸 다시 배웠습니다."

(B) 남의 코드를 리뷰하라고 하면 — 평가 대상은 버그 개수가 아니라 접근 순서와 화법이다.

  1. 맥락 먼저 (30초): "목적과 호출 주체가 뭔가요? 가장 걱정되는 부분이 있으신가요? 신규인가요, 수정인가요?" — 바로 코드로 뛰어들지 않는 것 자체가 점수.
  2. 읽는 순서를 소리 내어 선언: "입출력 계약 → 정확성 → 경계 조건 → 실패 시나리오 → 테스트 순으로 보고, 스타일은 마지막에 몰아 말씀드리겠습니다."
  3. 파이프라인 코드 체크리스트 6개: 정확성(유실·중복 경로, NULL을 =로 비교하나) → 멱등성(두 번 돌리면 중복 적재되나) → 트랜잭션 경계(중간에 죽으면 절반 반영이 남나) → 경계값(빈 파일·0건·중복 키) → 조용한 실패(예외 삼키기, 실패해도 0 반환) → 테스트(운영 경로를 타나).
  4. 화법 = 심각도 라벨 + 질문형: blocker "이 UPDATE에 WHERE가 없는데 의도된 건가요?" / major "재실행하면 중복 적재될 것 같은데 UPSERT가 앞에 있어야 하지 않을까요?" / nit "취향 차이일 수 있는데 매직 넘버는 상수로." 좋은 점 하나는 꼭 언급.
  5. 요약으로 마감: "blocker 1, major 1, 나머지 nit — blocker만 고치면 머지해도 된다고 생각합니다."

하지 말 것: 스타일부터 지적, "다 다시 짜야 해요", 확신 없는 단정. A→B로 이어지면 "체크리스트 6개는 제 과제의 검증 8종과 같은 관점입니다"로 연결한다.


3. 기술 용어 — 초등학생 설명 카드

각 카드는 쉬운 말 / 정확히 / 내 연결 3줄이다. 면접에서는 1줄로 시작한다.

A그룹 — 과제에서 직접 쓴 것 (여기는 확실히 알아야 함)

멱등성 (idempotency)

트랜잭션

RAW / STG / MASTER

IS DISTINCT FROM

soft delete

backfill / catchup / max_active_runs

데이터 품질(DQ)과 차단선

reconciliation (대조)

B그룹 — 리멤버 스택 (개념만. 운영 경험처럼 말하지 않는다)

CDC (Change Data Capture)

Kafka / MSK

Spark

Iceberg / S3 Tables

compaction / snapshot 만료 / orphan file

StarRocks (OLAP)

Lake Formation

Glue PySpark Full Load

C그룹 — 내 포트폴리오 용어 (물어보면 파고들 곳)

collation

실행계획 (EXPLAIN)

backpressure / 429 + Retry-After

OLTP vs OLAP


4. 리멤버 스택 — 남의 집 지도

말하기 전 안전 문구: "공개된 AWS 기술 블로그와 채용 공고에서 본 구조입니다. 내부 규칙이나 임계값은 모르고, 제가 운영해 본 스택도 아닙니다."

이 경계를 먼저 긋고 들어가면 그다음 설명은 전부 가산점이 된다. 안 긋고 아는 척하면 한 번에 무너진다.

flowchart LR
  subgraph OLTP["운영 (OLTP)"]
    AUR[("Aurora MySQL<br/>writer")]
    REP[("Full Load 전용<br/>replica")]
  end
  AUR -->|binlog| DBZ["Debezium<br/>변경 이벤트 추출"]
  DBZ --> MSK["Amazon MSK (Kafka)<br/>topic · partition"]
  AUR -.복제.-> REP
  REP -->|"JDBC 병렬 스캔"| GLUE["AWS Glue PySpark<br/>Full Load"]
  MSK -->|"PK upsert"| S3T
  GLUE -->|"초기 적재"| S3T
  subgraph LAKE["레이크하우스"]
    S3T[("S3 Tables · Iceberg<br/>Parquet + metadata")]
    MAINT["compaction · snapshot 만료<br/>orphan file 정리"]
    OBS["PyIceberg 자체 수집기<br/>file count · size · partition"]
  end
  S3T --- MAINT
  S3T --- OBS
  S3T --> SR["StarRocks on EKS<br/>저지연 OLAP"]
  S3T --> ATH["Athena · BI"]
  SR --> APP["대시보드 · API"]
  LF["Lake Formation<br/>DB·table·column·row 권한"] -.권한 판정.-> S3T
  LF -.-> ATH

이 그림에서 내가 꺼낼 수 있는 질문 3개 (역질문으로 써도 좋다):

  1. Full Load와 CDC의 접속점을 어떻게 잡으셨나요? (아래 그림)
  2. S3 Tables의 관리형 maintenance 실행 여부를 무엇으로 확인하시나요? (PyIceberg 관측)
  3. StarRocks와 Athena의 책임 경계는 freshness 기준으로 나누시나요?

Full Load ↔ CDC 접속점 — 가장 물어보기 좋은 지점

sequenceDiagram
  participant DB as Aurora replica
  participant FL as Glue Full Load
  participant CDC as Debezium/Kafka
  participant T as S3 Tables
  Note over DB,CDC: ① 기준점 먼저 고정 (binlog position / GTID)
  DB->>CDC: 이 위치부터 이벤트 수집 시작
  DB->>FL: 스냅샷 읽기 (기준점 시각 기준)
  FL->>T: 초기 전량 적재
  Note over CDC: 그동안 발생한 변경은 버퍼에 쌓임
  CDC->>T: ② 기준점 이후 이벤트를 PK upsert로 재적용
  Note over T: ③ 키 · 건수 · 핵심 속성 대조

왜 이게 어려운가 (초등학생 버전): 책을 통째로 베끼는 동안에도 원본은 계속 고쳐진다. 그래서 "몇 시 몇 분까지의 내용을 베낀 건지" 시각을 먼저 못 박고, 그 이후 고쳐진 부분만 따로 모았다가 나중에 덧칠한다. 덧칠할 때는 같은 줄을 두 번 덧칠해도 결과가 같도록 "줄 번호(PK) 기준으로 덮어쓰기"를 쓴다.

내 과제와의 연결: 여기서 PK upsert가 하는 역할이 내 과제의 IS DISTINCT FROM 비교 + 사업자번호 기준 merge와 같은 문제다. 재적용해도 결과가 같아야 한다는 요구가 동일하다. 이 연결을 말할 수 있으면 "과제만 한 사람"에서 "구조를 이해한 사람"으로 올라간다.


5. 포트폴리오 8개 — 앵커 한 줄씩 (읽기만, 외우지 않음)

본인이 한 일이므로 내용은 이미 안다. 각 항목에서 "면접에서 꺼낼 각도" 하나씩만 정리했다.

#항목꺼낼 각도 한 줄숫자 1개
01OS 패키지 취약점 수집 정확도CVE ID만 맞아서는 부족하다. 어느 버전에서 고쳐졌는지까지 맞아야 스캐너가 신뢰된다12종 배포판 × 4가지 제공 방식(API·OVAL·Tracker·Git)
02라이브러리 컴포넌트 테이블 재설계CPU 부하를 보고 서버를 키우는 대신 슬로우 쿼리→실행계획으로 내려가니 원인이 collation·식별자 정책이었다실행계획 예상 스캔 행 130만 → 6,000
03인덱스 최적화 & 용량 절감지워도 되는 근거를 먼저 만들고 지웠다 (95개 쿼리 실행계획 전수 확인)인덱스 311개 중 224개 삭제 · 9.6TB→4TB · 고객사 DB 생성 12h→6h
04RAW 보존·재파싱 ETL외부에서 다시 받아야만 재처리되던 구조를 원본 선보존으로 바꿨다 → 과제 설계의 원형적용 소스의 재처리 외부 요청 0건 (2일→5분은 설계 산정 예시, 실측 아님)
05K8s·Airflow 운영노드 증설과 pool·backoff·resource request를 함께 조정했다. 최초 클러스터 설계자라고 말하지 않는다Pod 할당 실패 주 70~100건 → 주 1~5건
06DML Broker80개 크롤러가 각자 재시도를 관리하던 걸 공통 운영 규칙 하나로 모았다. 각 담당자가 자기 크롤러를 이관lock·connection 오류 하루 3~4건 → 적용 후 4개월 0건
07AWS→IDC 이전장비가 없어서 먼저 수집 시간 분산으로 버티고, 준비된 뒤 DB 역할을 분리했다 (임시복구→구조개선 순서)월 10~20건 → 5건 미만 → 전환 후 1~2건
08Grafana 모니터링서버 자원·DB·수집 누락·고객사 동기화를 같은 시간축에서 봤다10~20대 서버 (탐지시간 감소율은 미확인)

추가 카드: MySQL 8.4 최대 약 30억 행 사전 검증에서 HDD 쓰기 회귀를 보고 innodb_flush_method 기본값 변화로 원인을 좁혔다. 하드웨어별 기준을 나누고 단계적으로 적용했다.

단위 방어 3개 (과장으로 오해받기 쉬운 지점):


6. 안 해본 것 스크립트 — 5년차의 가장 강한 무기

각 항목은 없다대신 있는 것어떻게 채울지 3박자. 미안해하지 않고 담백하게.

질문없다대신 있는 것채우는 법
Spark·Kafka프로덕션 운영 경험 없음Python·SQL·Airflow·Kubernetes·MySQL로 수십억 행 DB와 80개 크롤러의 스케줄링·pool/backoff·재처리·동시성·backpressure팀의 실제 데이터량과 지연 요구 기준으로 실행 모델부터
OLAP DB (StarRocks·ClickHouse)프로덕션 없음과제의 DuckDB 전수 검증, 실무의 MySQL 실행계획과 대규모 배치소비 쿼리·동시 사용자·freshness·비용 확인 후 판단
AWSRDS·S3·EFS 운영 경험 없음. 제출 자료의 관련 태그는 최종 검수에서 놓친 잘못된 표기EC2에서 self-managed MySQL과 애플리케이션 운영. 온프레미스 SeaweedFS 설계·단계적 이관질문받으면 바로 정정. SeaweedFS 경험을 S3 운영이라고 말하지 않는다
개인정보 데이터 운영리멤버 수준의 개인정보 운영 경험 없음 (내 경력은 보안 메타데이터 중심)최소 권한·마스킹·보존/삭제·재처리 산출물 동일 정책·접근 로그라는 설계 원리수집 목적·접근 주체·보존 삭제 규칙·감사 경계를 먼저 확인
MDM 전용 조직 운영없음식별자 정책 재설계, 원천 레지스트리 전수 대조, RAW·이력·재처리 구조자동 연결 / 사람 검토 / 보류로 나누고 false merge·false split 비율을 표본 검사

AWS 태그 오기는 면접 초반에 내가 먼저 꺼낸다. 지적당하면 실수지만, 먼저 말하면 검수 태도가 된다.

답변 만들면 안 되는 3개 — 확인된 사건이 없으므로 그럴듯하게 지어내지 않는다:

실패 경험을 물으면: "직장 실패 대신 최근 제출 과제에서 사전 발견한 near-miss로 답해도 될까요?"로 먼저 묻는다. → 독립 재리뷰에서 README 필수 항목 누락, production에서 안 쓰는 경로를 검증한 테스트, 재패키징 후 실행 권한 문제를 발견했다. 제출물 소유자의 검수 실패로 받아들이고 README 복구, production-path 테스트, 파일 모드·인코딩 검사, 한글 경로 clean extraction E2E를 추가했다. 제출 전 Airflow 두 회차 성공과 source-master 불일치 0을 확인했다. (AI 도구도 썼지만, 지적 내용을 요구사항과 실행 결과로 확인하고 제출을 결정한 책임은 나에게 있다.)


7. 역질문 3개 — 하나만 골라도 됨

과제 얘기가 끝날 때쯤 던지면 대화가 이어진다. 회사 복지 말고 팀의 실제 판단 기준을 묻는다.

  1. "Full Load와 CDC의 접속점을 어떻게 잡으셨는지 궁금합니다. 공개 자료로는 전용 replica를 쓰신 것까지 봤는데, 기준점 이후 이벤트 재적용에서 어려웠던 부분이 있으셨을까요?"
  2. "식별·매핑에서 자동 연결과 사람 검토를 나누는 기준이 있으신가요? false merge와 false split 중 어느 쪽 비용을 더 크게 보시는지 궁금합니다."
  3. "데이터 품질 규칙 중 파이프라인을 멈추는 것과 경고만 남기는 것을 나누는 기준이 팀에 정해져 있나요?"

8. 당일 아침 30분 치트시트

이 페이지만 보고 들어간다.

첫 90초

여러 곳에서 다른 이름으로 들어오는 데이터를 '결국 같은 대상인지' 판단해 연결해 온 데이터 엔지니어입니다. 5년간 오픈소스 제품과 버전, 취약점, 12종 Linux 배포판의 보안 정보를 맞춰 왔습니다. 잘못 연결되거나 빠진 데이터는 식별 규칙부터 저장 구조와 재처리 방법까지 고쳤습니다. 리멤버에서는 명함·프로필·회사 데이터를 오래 믿을 수 있게 만들고 싶습니다.

과제 30초 (2-3 그대로) RAW 보존 → STG 정규화·품질판정 → 사업자번호 조인으로 신규/변경/no-op → 마스터·이력·부재·검증 8종을 한 트랜잭션 → DuckDB 단일 writer라 직렬 + max_active_runs=1.

숫자

30,513 + 2,174 = 32,687
21,087 = 4,000 + 17,087
23,261 + 9,426 = 32,687
5,196 = 2,876 + 1,972 + 310 + 30 + 8
8/8 · 불일치 0 · ERROR 0 · 테스트 107(제출)/108(현재)

먼저 말할 정정 2개

먼저 인정할 한계 3개 exactly-once는 업무 데이터까지(실행 기록은 별도 커밋) · 동시 backfill 미보장 · stage() 메모리 적재.

답변 길이 규칙 상황 1문장 → 선택 2문장 → 검증 1문장 → 한계 1문장. 길어지면 여기로 되돌아온다.

말하기 순서 규칙 비유 먼저 → 용어는 나중. 상대가 끄덕이면 그때 RAW/STG/MASTER, 멱등성, IS DISTINCT FROM을 붙인다.

마지막 한 줄 확인한 것과 확인 못 한 것을 같은 문장 안에서 구분하면, 나머지 답변의 신뢰도가 같이 올라간다.


출처 ai/repo-notes/remember-data-engineer-assignment-claude.md · human/reports/2026-08-05-remember-data-engineer-interview-prep.md · human/reports/2026-08-07-remember-interview-study-map.md · human/study/content/remember-data-engineering/01~07 · human/career/remember-interview/assignment.html · 기준일 2026-08-10

연결 문서