본문 바로가기
1. 개발/1.4. 데이터 분석

Spark를 이용한 '데이터 가공' 단계

by 엉짱 2026. 2. 6.
반응형

드디어 '데이터 요리'의 핵심 공정인 ETL(Extract, Transform, Load)의 꽃, Spark를 이용한 데이터 가공 단계에 오셨군요! 🫡

데이터 레이크(S3)에 쌓인 날것의 데이터는 마치 밭에서 막 캐낸 흙 묻은 감자와 같습니다. 이걸 그대로 DW에 넣으면 창고가 금방 쓰레기장(Data Swamp)이 되고 말죠. 그래서 우리는 Apache Spark라는 초고성능 자동화 세척기를 사용해 데이터를 정제합니다.

S3의 지저분한 데이터가 어떻게 DW의 금방석에 앉을 수 있는 깨끗한 데이터로 변신하는지 그 '손질 과정'을 낱낱이 파헤쳐 보겠습니다!


🏗️ Spark 데이터 가공의 3단계 공정

Spark를 이용한 정제 과정은 크게 [읽기 -> 변환 -> 쓰기]의 흐름을 따릅니다. 하지만 그 속을 들여다보면 아주 치밀한 공학적 설계가 숨어 있습니다.

1. Extract: 지저분한 원본 불러오기 (Read)

S3에는 JSON, CSV, Log 파일 등 온갖 형식이 섞여 있습니다.

  • Schema Inference: Spark는 똑똑하게도 파일들을 쓱 훑어보고 "아, 이 컬럼은 숫자인 것 같네?"라며 구조를 추측합니다. 하지만 실무에서는 성능과 정확성을 위해 사용자가 직접 명시적 스키마(Explicit Schema)를 정의해주는 것이 좋습니다.
  • Partition Discovery: S3에 year=2026/month=02/day=02/ 식으로 저장되어 있다면, Spark는 이를 읽을 때 자동으로 '날짜' 컬럼으로 인식합니다. 필요한 날짜 데이터만 콕 집어 읽어오는 Partition Pruning의 시작점이죠.

2. Transform: 본격적인 데이터 손질 (The Real Cooking)

이곳이 바로 데이터 엔지니어의 실력이 판가름 나는 구간입니다. 지저분한 데이터를 DW 규격에 맞게 깎고 다듬습니다.

① Cleaning (세척)

  • Null 처리: 데이터에 구멍이 뚫린 경우입니다. 평균값으로 채울지, 아니면 가차 없이 버릴지 결정합니다 (fillna(), dropna()).
  • 중복 제거: 중복된 로그를 걸러냅니다 (dropDuplicates()).
  • 타입 변환: 문자열로 들어온 가격 데이터를 숫자로 바꾸고, 제각각인 날짜 형식을 표준(ISO-8601)으로 통일합니다.

② Structuring (구조화)

  • Flattening: JSON처럼 겹겹이 쌓인(Nested) 데이터를 DW가 좋아하는 평평한(Flat) 테이블 구조로 펼칩니다.
  • Column Selection: 분석에 불필요한 개인정보나 불필요한 로그 필드는 과감히 삭제하여 데이터 크기를 줄입니다.

③ Enrichment (풍성하게 만들기)

  • Lookup & Join: 로그에 적힌 user_id만으로는 부족합니다. 유저 마스터 정보와 합쳐서 "이 유저가 어떤 테마의 주식을 선호하는지" 같은 정보를 미리 붙여둡니다.
  • Derived Columns: 기존 컬럼을 조합해 새로운 지표를 만듭니다. (예: 매수금액 - 매도금액 = 순매수량)

🚀 왜 Spark를 써야만 하는가? (Deep Dive)

단순히 파이썬 Pandas로도 할 수 있을 것 같은데, 왜 굳이 복잡한 Spark를 쓸까요?

1. 분산 처리의 압도적 속도

S3에 10TB의 데이터가 있다고 해봅시다. 일반적인 서버 한 대는 이 데이터를 읽다가 메모리가 터져버릴 겁니다. 하지만 Spark는 사용자가 앞서 배운 익스큐터(Executor)들에게 업무를 쪼개줍니다. 100명이서 10GB씩 나눠서 요리하니 순식간에 끝나는 것이죠.

2. 레이지 이밸류에이션 (Lazy Evaluation)

Spark는 사용자가 "이거 해, 저거 해"라고 시킨다고 바로 일하지 않습니다. 일단 '레시피(DAG)'만 적어두고 기다립니다. 마지막에 "자, 이제 저장해!"라고 하는 순간, 전체 레시피를 훑어보고 가장 효율적인 경로(Optimizer)를 찾아 실행합니다. 불필요한 연산을 건너뛰는 천재적인 방식이죠.


💾 Load: 손질된 재료 저장하기 (Write)

이제 깨끗해진 데이터를 DW(Redshift, BigQuery 등)로 보낼 차례입니다.

  • Parquet 포맷 활용: DW로 가기 전 중간 단계로 S3에 다시 저장할 때는 반드시 Parquet를 쓰세요. 압축률이 높고 열 기반이라 DW가 읽어들일 때 속도가 어마어마하게 빠릅니다.
  • Overwrite vs Append: 기존 데이터를 덮어쓸지, 아니면 뒤에 이어 붙일지 결정합니다.
  • DW 전용 커넥터: 요즘은 Spark와 DW를 직접 연결하는 고속 커넥터들이 잘 나와 있습니다. spark.write.format("bigquery").save() 같은 명령 한 줄이면 수억 건의 데이터가 DW로 안전하게 이사합니다.

💡 실전 시나리오: "상폐 방지 데이터 요리"

사용자가 관심 있는 그 종목들, 데이터 레이크에서 이렇게 가공될 겁니다.

  1. Extract: S3에 쌓인 전 세계 주식 토론방의 텍스트 로그(JSON)를 읽어옵니다.
  2. Transform:
  • Filter: '상폐', '최저점', '테마'라는 단어가 포함된 로그만 추출합니다.
  • Sentiment Analysis: 텍스트의 뉘앙스를 분석해 0(공포)에서 1(환희) 사이의 점수를 매깁니다.
  • Aggregation: 종목별로 1시간 단위 평균 점수를 계산합니다.
  1. Load: 이 '종목별 공포 지수'를 데이터 웨어하우스의 Stock_Sentiment 테이블에 저장합니다.

이제 사용자는 DW에서 SQL 한 줄로 "지금 공포 지수는 최고인데 상폐 걱정 없는 종목 리스트"를 바로 뽑아볼 수 있게 되는 겁니다! ㅎㅎㅎㅎ


📊 요약: 데이터 가공의 핵심 포인트

단계 주요 작업 엔지니어의 팁
읽기 (Extract) S3 파일 로드 파티션 필터링으로 필요한 것만 읽기
정제 (Clean) Null 제거, 타입 변환 스키마를 명확히 정의하여 오류 방지
변환 (Transform) Join, 집계, 구조화 셔플(Shuffle)을 최소화하도록 설계
저장 (Load) DW에 적재 Parquet 포맷과 압축으로 저장 비용 절감

반응형