콘텐츠로 이동

Spark RDD와 데이터셋

개요

여러 노드로 데이터를 나눠 계산하려면, "나눠진 데이터"를 다루는 추상화가 있어야 해요. Spark의 핵심 추상화가 RDD(Resilient Distributed Dataset) 이에요. 공식 문서는 RDD를 "클러스터의 여러 노드에 분할되어 병렬로 연산될 수 있는 요소들의 모음"이라고 정의해요. Resilience(탄력성)이라는 말이 붙은 이유는 노드가 죽어도 자동으로 복구되기 때문이에요. RDD는 파일(HDFS 등)이나 기존 컬렉션에서 만들어 변환하며 쓰고, 메모리에 보관(persist)해서 재사용할 수 있으며, 노드 실패로부터 스스로 복구돼요.

핵심 개념

RDD 만들기

RDD를 만드는 두 가지 길이 있어요.

  • 병렬화된 컬렉션(Parallelized Collections) — 드라이버의 기존 컬렉션(Scala·Python 리스트 등)을 RDD로 바꿔 여러 노드에 분산해요.
  • 외부 데이터셋(External Datasets) — HDFS 같은 Hadoop 지원 파일 시스템의 파일에서 만들거나 변환해요.

Transformation과 Action

RDD 연산은 크게 두 종류로 나뉘어요.

  • Transformation(변환)map, filter처럼 기존 RDD에서 새 RDD를 만들어요. 중요한 건 지연(lazy) 실행이에요. 변환만으로는 실제 계산이 일어나지 않고, 실행 계획만 쌓여요.
  • Action(액션)collect, count처럼 결과를 드라이버로 돌려주거나 저장해서 실제 계산을 트리거해요.

이 지연 실행 덕에 "필요한 만큼만 계산한다"는 최적화가 가능해요. 하지만 주의할 점도 있어요. 예를 들어 액션이 불리기 전엔 변환 안의 코드가 실행되지 않으므로, 누적 변수(accumulator)를 변환 안에서 갱신해도 액션 전엔 값이 안 바뀐다는 걸 기억해야 해요.

클로저(Closures) 이해하기

Spark는 함수를 각 Task가 도는 노드로 복사해서 보내요. 그래서 드라이버의 변수에 접근하는 코드는 각 노드에 복사된 사본에서 동작해요. 이것 때문에 "모든 요소를 세는" 코드를 드라이버 변수로 구현하면 제대로 세지지 않는 문제가 생겨요. 어떤 변수를 모든 노드가 공유해야 하는지에 따라 broadcast variable(모든 노드에 캐시)과 accumulator(합·개수처럼 더해지는 변수)를 써요.

RDD 연산 예시

# 예: 요소 각각을 제곱하는 변환 (지연), 그 다음 셈 (액션)
rdd = sc.parallelize([1, 2, 3, 4])
squares = rdd.map(lambda x: x * x)
print(squares.collect())   # 액션: [1, 4, 9, 16]

지속(Persistence)과 저장 레벨

같은 RDD를 여러 번 재사용한다면 매번 다시 계산하지 않도록 persist() 로 메모리에 보관할 수 있어요. 저장 레벨(메모리만, 메모리+디스크, 직렬화 등)을 골라, 속도와 공간의 균형을 맞춰요. 반복 연산이 많은 알고리즘일수록 캐싱 효과가 커요.

셔플(Shuffle)의 비용

groupByKey, join 같은 연산은 데이터를 노드 간에 재배치하는 셔플을 일으켜요. 셔플은 네트워크·디스크 I/O가 많아서 성능에 큰 영향을 줘요. 셔플이 많을수록 느려지므로, 조인·집계를 설계할 때 셔플을 줄이는 방향이 중요해요.

실제 적용 (데이터스케쳐스)

Events 3계층에서 Spark는 대용량 변환 층을 맡는 걸로 시나리오를 잡아요. 이벤트 데이터를 표준 스키마로 정제하는 무거운 변환을 클러스터에 분산하고, 결과를 창고에 적재하죠. RDD로 직접 다루는 경우는 드물고, 보통 구조화된 DataFrame을 쓰게 되지만, RDD 개념은 분산 처리의 근본이라 이해해 두면 좋아요.

현재는 역량 단계예요. 팀이 다룰 줄 알되 전면 도입 전이죠. RDD를 다룰 때 기억할 점은 transform은 지연되고 action이 실제 계산을 일으킨다는 것과, 셔플을 줄이고 재사용 RDD를 캐시하는 습관이에요. 구조화된 데이터를 다루는 더 현대적인 방식은 Spark SQL과 데이터프레임에서 이어져요.

더 알아보기