Companies
Stripe Data Engineer Interview Questions & Process (2026)
— docs/Stripe Data Engineer Interview Questions & Process (2026).pdf
Stripe의 Data Engineer 채용 프로세스는 리크루터 스크린부터 오퍼까지 보통 3~4주가 걸리는, 업계에서 가장 빠른 축에 속하는 루프다. 가장 큰 특징은 알고리즘 문제(LeetCode)를 의도적으로 배제하고 대신 'SQL Bug Squash'라는 전용 라운드와 48시간짜리 실전형 테이크홈 프로젝트로 대체했다는 점이다. 모든 질문이 결제(payments) 도메인 맥락 위에서 출제되며, idempotency·reconciliation·exactly-once 같은 개념을 얼마나 깊이 이해하는지가 통과 여부를 가른다.
| # | 단계 | 형식 | 소요 시간 | 평가 항목 |
|---|---|---|---|---|
| 1 | Recruiter Screen | Phone call | 30 min | Role fit, comp expectations, payments interest signal |
| 2 | Take-Home Project | Async | 48 hours window | Data modeling, code quality, tests, documentation |
| 3 | Technical Phone Screen | Video call | 60 min | Take-home walkthrough + extra technical questions |
| 4 | Onsite Loop | 3-4 rounds, 45-60 min each | 1일(분산 가능) | SQL Bug Squash, Data Modeling, Coding, Values |
| 5 | Debrief & Decision | Internal | 영업일 2~4일 | Hiring committee sync, decision, offer call |
결제 프로세서의 데이터를 나타내는 4개의 CSV 파일(charges, refunds, disputes, customers)이 주어진다. 이 파일들을 인제스트하고, 깔끔한 분석 스키마로 모델링하며, 고객 세그먼트별로 나눈 일별 매출 리포트를 생성하는 데이터 파이프라인을 만들라. 테스트, 문서화, 설계 선택에 대한 간단한 서술을 포함하라.
README.md에 데이터 모델과 그 이유, 시간이 더 있었다면 무엇을 다르게 했을지를 설명하고, src/·tests/·data/·output/로 나뉜 깔끔한 디렉터리 구조를 갖추며, 모든 변환 함수에 단위 테스트와 엔드투엔드 통합 테스트를 작성한다. 의사결정 지점마다 "이건 함수입니다"가 아니라 "환불 없는 charge도 리포트에 나타나야 하므로 여기서는 left join을 선택했습니다"처럼 이유가 담긴 주석을 남기고, README에 처리한 엣지 케이스와 시간이 더 있었다면 처리했을 엣지 케이스를 정직하게 적는다.
결제 API가 초당 5만 건의 이벤트를 인제스트한다고 할 때, idempotency를 어떻게 설계할지 코드 없이 설계와 트레이드오프만 말로 설명하라.
인터뷰어는 기억력이 아니라 판단력을 시험한다. 정직하게 답하는 것이 핵심이다. 예를 들어 "고객 테이블에 SCD Type 2를 쓸까 고민했지만 이 스코프에서는 단순 스냅샷으로 충분했다. 시간이 더 있었다면 고객 세그먼트가 시간에 따라 변하므로 SCD Type 2를 추가했을 것이다"처럼 답한다.
테이크홈에서 내린 결정을 정직하게 방어한다. "고객 테이블에 SCD Type 2를 쓸까 고민했지만 이 스코프에서는 단순 스냅샷으로 충분했습니다. 시간이 더 있었다면 SCD Type 2를 추가했을 것입니다."
성공한 charge에서 환불 금액을 제외한 월별 매출(USD)을 계산하도록 되어 있는 쿼리인데 결과가 틀렸다. SELECT DATE_TRUNC('month', c.created_at) AS month, SUM(c.amount - COALESCE(r.amount, 0)) AS revenue_usd FROM charges c LEFT JOIN refunds r ON r.charge_id = c.id WHERE c.status = 'succeeded' GROUP BY 1 — 왜 틀렸는가?
버그가 최소 두 개 있다. 통화 변환이 없어서 EUR charge가 USD인 것처럼 합산된다. 그리고 한 charge에 환불이 여러 건이면 join이 charge 행을 여러 번 복제해 금액 차감이 부풀려진다. 깔끔한 수정은 charge별로 환불을 먼저 집계하는 CTE를 만든 뒤 단일 charge 행에 join하고, rates 테이블로 통화를 변환하는 것이다.
생각의 흐름을 소리 내어 말한다. "쿼리를 위에서 아래로 읽어볼게요. LEFT JOIN은 맞는 것 같고, WHERE 절이 succeeded charge만 필터링하는 것도 괜찮아 보이네요. 잠깐, 통화 변환이 없네요. amount 컬럼이 항상 USD인가요?"
"그냥 처음부터 다시 짤게요" — 핵심을 놓친 답이다. Bug Squash는 남의 코드를 읽고 문제를 찾아 외과적으로 고칠 수 있는지를 시험한다. 재작성은 탈락 시그널이며 실제 프로덕션 디버깅 방식과도 다르다.
"Stripe의 charges API 뒤에 있는 데이터 모델을 설계하라. charge는 생성, 캡처, 환불, 부분 환불, 분쟁(dispute) 상태를 거칠 수 있으며 임의 시점의 charge 전체 상태를 재구성할 수 있어야 한다" / "우리의 내부 결제 기록을 은행에서 받는 일일 정산 리포트와 매칭하는 reconciliation 파이프라인을 설계하라. 불일치는 24시간 내에 사람이 검토하도록 표면화되어야 한다" / "초당 5만 건이 들어오고 200ms 내에 판단이 내려져야 하는 실시간 사기 탐지 시그널 파이프라인을 설계하라"
요구사항 확인(5~7분, 처리량·지연시간·일관성 요구사항과 exactly-once 여부를 명시적으로 질문) → 결제 특화 제약 명시(3~5분, idempotency·audit trail·다중 통화·exactly-once를 먼저 선언) → 상위 아키텍처(10~15분, Ingestion→Processing→Storage→Serving을 기술 이름과 함께) → 심화(15~20분, 장애 처리·백필·reconciliation·지연 도착 데이터) → 트레이드오프(5분) 순서로 진행한다. idempotency(재시도되어도 같은 응답을 내는 idempotency key + TTL 저장·중복 제거), reconciliation, exactly-once, append-only/event-sourced 모델(금융 데이터는 제자리 수정 대신 새 이벤트가 이전 상태를 대체하고 현재 상태는 계산됨), audit trail을 핵심 개념으로 삼는다. Stripe는 데이터 레이크에 Apache Iceberg를, 상태 기반 스트리밍에 Apache Flink를(idempotency와 exactly-once 요구 때문에 Flink가 기본 선택), 이벤트 전송에 Kafka를, 배치 오케스트레이션에 Airflow를 무겁게 쓰는 회사라는 점을 언급하면 좋다.
항상 도메인부터 시작한다. "결제는 exactly-once 시맨틱스를 요구합니다. 아키텍처를 건드리기 전에 이게 설계를 어떻게 제약하는지부터 생각해보겠습니다."
"at-least-once로 전달하고 다운스트림에서 dedupe하겠습니다" — 기술적으로 맞을 때도 있지만 Stripe에서는 exactly-once를 진지하게 여기지 않는 사람으로 읽힌다. 기본값은 exactly-once 설계로 잡고, 그다음에 트레이드오프를 논의해야 한다.
charge_created, charge_captured, charge_refunded, charge_disputed로 구성된 charge 이벤트 스트림을 받는다. 각 이벤트는 charge_id, event_type, amount_cents, currency, timestamp를 가진다. 일부 이벤트는 중복이고 일부는 순서가 뒤바뀌어 도착한다. 각 charge의 현재 상태(total_captured, total_refunded, total_disputed, current_status, last_updated)를 반환하는 함수를 작성하라.
이 문제는 idempotency(중복 처리), 상태 관리(이벤트 로그로부터 현재 상태 계산), 순서 뒤바뀜 처리(더 이른 타임스탬프의 이벤트가 이후 상태를 덮어쓰면 안 됨), 통화 인식(통화 간 단순 합산 금지)을 동시에 시험하는 실제 Stripe형 문제다.
코딩 전에 먼저 명확화 질문을 한다. "금액은 환불에서도 항상 양수인가요? 어떤 통화 변환을 가정해야 하나요? 중복의 정의는 무엇인가요 — 같은 event_id인가요, 아니면 같은 (charge_id, event_type, timestamp) 조합인가요?"
"먼저 시간 복잡도부터 생각해보겠습니다" — Stripe는 이런 문제에서 Big-O를 신경 쓰지 않으며, 이를 신경 쓴다는 것 자체가 과제를 잘못 이해했다는 시그널이다.
"단순한 이해관계자 요청이 아니라 실제 사용자 시그널에 기반해 데이터 파이프라인을 재설계했던 경험을 말해달라" / "불확실한 상황에서 기술적 결정을 어떻게 내리는가? 구체적인 사례로 설명해달라" / "시간을 더 쓰고 싶었지만 빠르게 출시해야 했던 경험을 말해달라. 그 트레이드오프를 어떻게 조율했는가"
구체적인 스토리와 수치화된 결과, 처음부터 끝까지 설명할 수 있는 의사결정이 핵심이다. 인터뷰어는 지원자가 실제로 Stripe가 일하는 방식대로 일하는지 증거를 찾는다. 일반적인 행동 답변은 통과하지 못한다.
"내부 사용자들이 매일 raw 이벤트 테이블에 같은 다섯 개 쿼리를 반복 실행하고 있다는 걸 발견했습니다. 일별 집계 테이블을 만들어 쿼리 시간을 4분에서 6초로 줄였고, 한 분기 만에 채택 팀이 0개에서 12개 팀으로 늘었습니다."
"저는 항상 속도와 품질의 균형을 맞추려고 합니다" — 일반론적인 답은 실패한다. 원칙이 아니라 스토리로 답해야 한다.
Stripe의 문화는 인프라 빌더답고 엄격하며 사용자 중심적이라는 것이 저자의 평가다. 행동 인터뷰(Values/Culture 라운드)뿐 아니라 다른 라운드 전반에서도 이 다섯 가지 패턴이 반복적으로 관찰된다고 한다. 인터뷰어는 원칙을 말로만 아는지가 아니라 실제로 그렇게 일해왔는지 구체적 증거(무엇이 신호였는지, 어떤 대안을 검토하고 왜 기각했는지, 성공을 어떻게 측정했는지, 지금이라면 무엇을 다르게 할지, 누가 관여했고 이견은 없었는지)를 후속 질문으로 파고들어 확인한다.