이 글은 Data Engineering Zoomcamp의 Module 6: Batch Processing를 기반으로,
Apache Spark 의 아키텍처, 실행 구조, 그리고 내부 처리 메커니즘을 정리한 글입니다.
목차
- Apache Spark란 무엇인가
- Spark를 사용하는 이유
- Spark의 기본 구조 (Driver / Master / Executor)
- Spark의 데이터 처리 방식 (Partition 기반 처리)
- Spark에서의 Transformation과 Action
- Spark SQL과 DataFrame
- Spark가 실무에서 중요한 이유
- Spark에서 GroupBy가 동작하는 방식
- Shuffle이 중요한 이유
- Spark에서 Join이 동작하는 방식
- GroupBy와 Join의 공통 구조
- RDD와 DataFrame의 관계
- 참고자료/실습
1. Apache Spark란 무엇인가
Apache Spark는 대규모 데이터를 분산 환경에서 처리하기 위한 오픈소스 분산 처리 엔진입니다.
Spark는 데이터를 저장하는 시스템이 아니라, 데이터를 읽어서 계산하고 결과를 다시 저장하는 실행 엔진입니다.
Data Lake → Spark → 결과 저장
Spark는 하나의 컴퓨터가 아니라 여러 대의 컴퓨터(클러스터)에서 동시에 작업을 수행할 수 있는 구조입니다.
이러한 분산 처리 능력 때문에 대용량 데이터 처리에 적합한 시스템입니다.
2. Spark를 사용하는 이유
2-1. 대규모 데이터 처리
수십 GB에서 수 TB 이상의 데이터를 처리할 때, 단일 머신 기반 스크립트로는 한계가 있습니다.
Spark는 여러 노드가 동시에 데이터를 처리하는 구조이기 때문에 대규모 데이터에 적합한 방식입니다.
2-2. 확장성
데이터가 증가하면 노드를 추가하여 확장할 수 있는 구조입니다.
이를 Scale-Out 구조라고 합니다.
2-3. 다양한 인터페이스 지원
Spark는 다음과 같은 방식으로 사용할 수 있는 구조입니다.
- SQL 기반 처리
- Python (PySpark)
- Scala
- Java
3. Spark의 기본 구조
3-1. Driver
Driver는 Spark 애플리케이션을 시작하는 역할을 수행하는 구성 요소입니다.
코드를 실행하고, 실행 계획(DAG)을 생성하며, 작업을 클러스터에 제출하는 역할을 합니다.
Driver는 개발자의 로컬 머신 Airflow Task, 별도 실행 서버 같은 형태로 존재할 수 있습니다.
3-2. Spark Master
Spark Master는 클러스터를 관리하는 역할을 수행합니다.
- 작업을 Executor에 분배
- Executor의 상태를 관리
- 장애 발생 시 작업을 재할당
3-3. Executor
Executor는 실제 연산을 수행하는 노드입니다.
- Partition 단위로 데이터 처리
- 메모리와 CPU를 사용하여 연산 수행
- 결과를 저장소에 기록

4. Spark의 데이터 처리 방식
Spark는 Partition 기반으로 데이터를 처리하는 구조입니다.
DataFrame
├─ Partition 1
├─ Partition 2
├─ Partition 3
└─ Partition N
Partition 수가 많을수록 병렬 처리 성능이 높아지는 구조입니다.
DataFrame은 내부적으로 여러 개의 Partition으로 구성되어 있습니다.
5. Spark에서의 Transformation과 Action
5-1. Transformation
Transformation은 데이터를 변환하는 연산입니다.
- select
- filter
- withColumn
- groupBy
- join
이 연산들은 즉시 실행되지 않고, 실행 계획만 생성하는 구조입니다.
5-2. Action
Action은 실제 실행을 트리거하는 연산입니다.
- show()
- count()
- write()
- collect()
Action이 호출되는 순간, Spark는 이전까지 정의된 모든 Transformation을 실행합니다.
이 구조를 Lazy Evaluation 기반 실행 방식이라고 합니다.
6. Spark SQL과 DataFrame
Spark는 SQL 기반 처리도 지원하는 구조입니다.
DataFrame을 임시 테이블로 등록하면 SQL로 조회할 수 있습니다.
df.createOrReplaceTempView("table_name")
SELECT *
FROM table_name
WHERE ...
GROUP BY ...
즉, Spark는 Data Lake 위에서 직접 SQL을 실행할 수 있는 구조입니다.
데이터 웨어하우스가 없어도 SQL 기반 분석이 가능한 환경입니다.
7. Spark가 실무에서 중요한 이유
Spark는 단순히 빠른 처리 엔진이 아니라, 다음과 같은 이유로 중요합니다.
- 대규모 데이터 집계가 가능한 구조
- SQL과 코드 기반 처리를 동시에 지원하는 환경
- 머신러닝과의 결합이 용이한 구조
- 클라우드 스토리지(S3, GCS 등)와 자연스럽게 통합되는 구조
특히 Data Lake 기반 아키텍처에서는 Spark가 중심 역할을 수행하는 경우가 많습니다.
8. Spark에서 GroupBy가 동작하는 방식
Spark에서 GroupBy는 단순한 집계 연산이 아니며, 분산 환경에서 데이터를 재배치하고 결합하는 구조를 가지는 연산입니다.
GroupBy는 기본적으로 두 단계로 동작합니다.
8-1. 1단계: Partition 내부 집계
Spark는 먼저 각 Partition 안에서 부분 집계를 수행하는 방식입니다.
예를 들어 Partition 1에 다음과 같은 데이터가 있다면,
(zone=1, amount=100)
(zone=1, amount=200)
해당 Partition 내부에서 먼저 집계가 수행됩니다.
(zone=1, amount=300)
이 단계에서는 네트워크 이동이 발생하지 않는 구조입니다.
각 Executor가 자신이 담당한 Partition에 대해서만 계산을 수행하는 방식입니다.
8-2. 2단계: Shuffle 및 최종 집계
문제는 동일한 key가 다른 Partition에도 존재할 수 있다는 점입니다.
예를 들어 Partition 2에도 zone=1이 있다면, 최종 집계를 위해 동일 key를 하나의 Partition으로 모아야 하는 구조입니다.
이 과정이 Shuffle입니다.
Shuffle 단계
- key 기준으로 데이터가 재분배
- 네트워크를 통해 데이터 이동
- 동일 key가 같은 Partition으로 모임
이후 해당 Partition에서 최종 집계가 수행됩니다.
즉, GroupBy는 Partition 내부 집계, Shuffle, 최종 집계의 구조로 동작하는 방식입니다.
9. Shuffle이 중요한 이유
Shuffle은 Spark에서 가장 비용이 큰 연산입니다.
Shuffle이 발생하는 연산은 다음과 같습니다.
- GroupBy
- Join
- OrderBy
- Distinct
Shuffle 과정
- 네트워크 IO가 발생합니다.
- 디스크 IO가 발생할 수 있습니다.
- Executor 간 데이터 이동이 이루어집니다.

따라서 Spark 성능 튜닝에서 가장 중요한 부분은 Shuffle을 최소화하는 구조를 설계하는 것입니다.
10. Spark에서 Join이 동작하는 방식
Join은 두 테이블을 특정 key 기준으로 결합하는 연산으로, GroupBy와 마찬가지로 key 기반 재배치가 필요한 구조입니다.
SELECT *
FROM revenue r
JOIN zones z
ON r.zone = z.location_id;
해당 연산도 key 기준으로 데이터를 모아야 하는 구조입니다.
10-1. 두 개의 큰 테이블을 Join하는 경우
두 테이블이 모두 큰 경우 Spark는 Sort-Merge Join 방식을 사용하는 구조입니다.
동작 방식
- 각 테이블에서 join key를 생성합니다.
- key 기준으로 Shuffle을 수행합니다.
- 동일 key를 가진 레코드를 같은 Partition으로 모읍니다.
- Partition 내부에서 정렬 후 병합합니다.
이 방식은 GroupBy와 매우 유사하며, Shuffle이 반드시 발생하는 연산으로 실행 단계가 여러 Stage로 분리됩니다.
10-2. 작은 테이블을 Join하는 경우 (Broadcast Join)
한쪽 테이블이 매우 작은 경우 Spark는 다른 전략을 사용하는 구조로, 이를 Broadcast Join이라고 합니다.
동작 방식
- 작은 테이블 전체를 모든 Executor에 복사합니다.
- 각 Executor는 자신이 처리하는 큰 테이블 Partition에 대해 메모리 내 lookup을 수행합니다.
- 네트워크 Shuffle 없이 결합이 이루어집니다.
이 방식은 Shuffle이 발생하지 않으며, 빠른 연산이 가능합니다.
Spark는 작은 테이블일 경우 자동으로 Broadcast Join을 선택하는 구조입니다.
11. GroupBy와 Join의 공통 구조
GroupBy와 Join은 내부적으로 매우 유사한 구조를 가집니다.
공통점
- key 기반 연산입니다.
- 동일 key를 같은 Partition으로 모으는 구조입니다.
- Shuffle이 핵심 단계입니다.
- External Merge Sort 기반으로 동작하는 방식입니다.
Join은 두 데이터셋에 대한 key 기반 결합이며, GroupBy는 단일 데이터셋에 대한 key 기반 집계라는 차이만 존재하는 구조입니다.
12. RDD와 DataFrame의 관계
Spark의 가장 기본 데이터 구조는 RDD(Resilient Distributed Dataset)입니다.
RDD 특징
- 저수준 API입니다.
- map, reduce, flatMap 등 함수형 연산 기반입니다.
- 직접적인 제어가 가능한 구조입니다.
DataFrame 특징
- 스키마 기반 구조입니다.
- Catalyst Optimizer에 의해 최적화됩니다.
- SQL과 자연스럽게 통합됩니다.
13. 참고 자료 / 출처
- Data Engineering Zoomcamp Repo: https://github.com/DataTalksClub/data-engineering-zoomcamp
- Apache Spark Github Repo: https://github.com/apache/spark
- Apache Spark 공식 사이트: https://spark.apache.org/