Spark 클러스터 아키텍처와 언어 API
Spark: The Definitive Guide (Excerpts, Databricks Preview, 2017) — Chapters 2-6 — Bill Chambers & Matei Zaharia Chapter 2: A Gentle Introduction to Spark — Spark's Basic Architecture, Spark Applications, Spark's Language APIs (pp.3-7)
이 모듈을 다 읽으면
- 단일 머신이 아닌 클러스터가 필요한 이유와 클러스터 매니저의 역할을 설명할 수 있다
- 드라이버 프로세스와 익스큐터 프로세스의 역할 분담을 구분해 설명할 수 있다
- Spark의 로컬 모드와 클러스터 모드의 차이를 설명할 수 있다
- Scala/Python/SQL/Java/R 각 언어 API가 Spark 코드로 변환되는 방식을 설명할 수 있다
단일 머신은 대용량 데이터 처리에 필요한 자원과 시간을 감당하지 못하기 때문에, 여러 머신의 자원을 하나처럼 묶은 클러스터와 이를 조율하는 프레임워크가 필요하다. Spark는 클러스터 매니저(Standalone, YARN, Mesos) 위에서 드라이버 프로세스와 다수의 익스큐터 프로세스로 구성된 Spark 애플리케이션을 실행하며, 드라이버가 애플리케이션 상태 유지·작업 분석·스케줄링을 전담하고 익스큐터는 할당받은 코드 실행과 상태 보고만 담당한다. 사용자는 Scala, Python, SQL, Java, R 등 다양한 언어 API로 드라이버를 조작할 수 있으며, Structured API를 쓰는 한 언어에 관계없이 동일한 핵심 개념이 동일한 성능 특성으로 클러스터에서 실행된다.
왜 클러스터가 필요한가
가정이나 회사에서 쓰는 한 대의 컴퓨터는 영상 감상이나 스프레드시트 작업에는 충분하지만, 대용량 데이터를 처리하기에는 연산 자원이 부족하거나 처리 시간이 지나치게 길어질 수 있다. 클러스터는 여러 머신의 자원을 모아 마치 하나의 큰 컴퓨터처럼 사용할 수 있게 해주는 머신 그룹이다. 다만 머신을 여러 대 모아두는 것만으로는 부족하고, 그 머신들에 걸쳐 작업을 분배하고 조율할 프레임워크가 필요하다. Spark가 바로 클러스터 전체에 걸친 데이터 처리 태스크의 관리·조율을 담당하는 도구다.
Spark가 실제로 태스크를 실행할 머신 클러스터는 Spark의 Standalone 클러스터 매니저, YARN, Mesos 같은 클러스터 매니저가 관리한다. 사용자는 Spark 애플리케이션을 이 클러스터 매니저에 제출(submit)하고, 클러스터 매니저는 애플리케이션이 작업을 완료할 수 있도록 자원을 배정해준다.
핵심 포인트
- 단일 머신은 자원 부족(또는 처리 시간 문제)으로 대용량 데이터 처리에 한계가 있다
- 클러스터는 여러 머신의 자원을 하나처럼 묶은 것이고, Spark는 그 클러스터 위에서 작업 실행을 관리·조율하는 프레임워크다
- 클러스터의 물리적 자원 배정은 Standalone, YARN, Mesos 같은 클러스터 매니저가 담당하며, Spark 애플리케이션은 이 클러스터 매니저에 제출된다
Spark 애플리케이션: 드라이버와 익스큐터
Spark 애플리케이션은 드라이버 프로세스 하나와 다수의 익스큐터 프로세스로 구성된다. 드라이버 프로세스는 클러스터의 한 노드에 위치하며 세 가지 역할을 수행한다 — 애플리케이션에 대한 정보 유지, 사용자 프로그램에 대한 응답, 그리고 익스큐터 전반에 걸친 작업의 분석·분배·스케줄링이다. 드라이버는 Spark 애플리케이션의 심장과 같은 존재로, 애플리케이션이 살아있는 동안 모든 관련 정보를 유지한다.
반면 익스큐터는 두 가지 일만 한다 — 드라이버가 할당한 코드를 실행하는 것, 그리고 그 실행 상태를 드라이버 노드에 보고하는 것이다. 즉 작업을 어떻게 나눌지 결정하는 두뇌 역할은 전적으로 드라이버가 맡고, 익스큐터는 지시받은 연산만 수행하는 실행 단위다.
마지막 구성 요소인 클러스터 매니저는 물리적 머신들을 통제하고 Spark 애플리케이션에 자원을 배정한다. 하나의 클러스터 위에서 여러 Spark 애플리케이션이 동시에 실행될 수 있다. 사용자는 노드마다 몇 개의 익스큐터를 둘지 설정으로 지정할 수 있다.
핵심 포인트
- 드라이버 프로세스: 애플리케이션 정보 유지, 사용자 프로그램 응답, 익스큐터 전반의 작업 분석·분배·스케줄링을 전담한다
- 익스큐터 프로세스: 드라이버가 할당한 코드 실행과 그 상태를 드라이버에 보고하는 역할만 한다
- 클러스터 매니저는 물리 머신을 통제하고 Spark 애플리케이션에 자원을 배정하며, 하나의 클러스터에서 여러 Spark 애플리케이션이 동시에 돌 수 있다
로컬 모드
Spark는 클러스터 모드 외에 로컬 모드도 지원한다. 드라이버와 익스큐터는 결국 프로세스일 뿐이므로, 여러 머신에 걸쳐 존재할 수도 있고 한 머신 위에만 존재할 수도 있다. 로컬 모드에서는 이 프로세스들이 클러스터 대신 사용자의 개별 컴퓨터에서 스레드로 실행된다. 원서는 로컬 모드를 염두에 두고 쓰여서, 예제 대부분은 한 대의 머신에서도 그대로 실행 가능하다.
핵심 포인트
- 로컬 모드에서는 드라이버·익스큐터가 클러스터가 아닌 한 대의 머신에서 스레드로 동작한다
- 로컬 모드와 클러스터 모드의 핵심 개념(드라이버/익스큐터 역할 분담)은 동일하다
Spark의 언어 API
Spark의 언어 API는 다른 언어에서도 Spark 코드를 실행할 수 있게 해준다. Spark는 각 언어에서 동일한 핵심 개념을 제공하고, 이 개념들은 클러스터에서 실행되는 Spark 코드로 번역된다. DataFrame·SQL 같은 Structured API를 사용하는 한, 어떤 언어를 쓰든 동일한 성능 특성을 기대할 수 있다(다만 이 부분은 다소 미묘한 지점이 있어 뒤에서 더 자세히 다룬다).
- Scala: Spark는 주로 Scala로 작성되어 있어 Scala가 Spark의 '기본' 언어다. - Python: Scala가 지원하는 구성 요소 대부분을 Python도 지원한다. - SQL: Spark는 ANSI SQL 2003 표준을 지원하여, 분석가나 비프로그래머도 Spark의 빅데이터 처리 능력을 쉽게 활용할 수 있다. - Java: Spark는 Scala로 작성되었지만 Java로도 Spark 코드를 작성할 수 있도록 신경 써서 설계되었다. - R: Spark core에 포함된 SparkR과, R 커뮤니티가 만든 별도 패키지 sparklyr 두 가지 통합 방법이 있다.
각 언어 API는 동일한 핵심 개념을 유지한다. 사용자에게는 SparkSession이라는 진입점이 제공되며, Python이나 R에서 Spark를 쓸 때 사용자는 JVM 명령을 직접 작성하지 않는다 — 대신 Python/R 코드를 작성하면 Spark가 이를 익스큐터 JVM에서 실행 가능한 코드로 번역한다.
핵심 포인트
- Scala가 Spark의 기본 언어이며, Python은 Scala가 지원하는 구성 요소 대부분을 지원한다
- Spark는 ANSI SQL 2003 표준을 지원해 SQL만으로도 Spark의 처리 능력을 활용할 수 있다
- R은 Spark core에 포함된 SparkR과 커뮤니티 패키지 sparklyr 두 가지 방식으로 통합된다
- Python/R 코드는 사용자가 직접 JVM 명령을 작성하지 않아도 Spark가 익스큐터 JVM에서 실행 가능한 코드로 번역해준다