본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 4. · 15 Views
대규모 알고리즘 완벽 가이드
빅데이터 시대에 필수적인 대규모 알고리즘의 핵심 개념을 초급 개발자도 쉽게 이해할 수 있도록 설명합니다. 병렬 컴퓨팅부터 클라우드 활용까지, 실무에서 바로 적용할 수 있는 지식을 담았습니다.
목차
1. 대규모 알고리즘 개론
어느 날 김개발 씨는 회사에서 새로운 프로젝트를 맡게 되었습니다. 하루에 수억 건의 로그 데이터를 분석해야 하는 일이었습니다.
평소처럼 for 루프를 돌리니 컴퓨터가 멈춘 것처럼 꼼짝도 하지 않았습니다.
대규모 알고리즘은 한마디로 방대한 양의 데이터를 효율적으로 처리하기 위한 특별한 접근 방식입니다. 마치 거대한 창고에서 물건을 찾을 때 혼자 뒤지는 것과 수십 명이 나눠서 찾는 것의 차이와 같습니다.
이것을 제대로 이해하면 테라바이트 규모의 데이터도 합리적인 시간 안에 처리할 수 있게 됩니다.
다음 코드를 살펴봅시다.
# 단일 처리 vs 대규모 처리 비교
def single_process(data):
# 한 번에 하나씩 순차 처리
results = []
for item in data:
results.append(process(item))
return results
def parallel_process(data, num_workers=4):
# 여러 워커가 동시에 처리
from multiprocessing import Pool
with Pool(num_workers) as pool:
results = pool.map(process, data)
return results
김개발 씨는 입사 2년 차 백엔드 개발자입니다. 지금까지 다뤄본 데이터는 기껏해야 수만 건 정도였습니다.
그런데 이번에 맡은 프로젝트는 차원이 달랐습니다. 매일 쏟아지는 사용자 로그가 수억 건에 달했습니다.
처음에 김개발 씨는 평소 하던 대로 코드를 작성했습니다. 데이터베이스에서 전체 데이터를 가져와서 Python으로 한 줄씩 처리하는 방식이었습니다.
실행 버튼을 누르고 커피를 마시러 갔다 왔는데, 진행률이 0.1%도 안 되어 있었습니다. 선배 개발자 박시니어 씨가 지나가다 김개발 씨의 모니터를 보고 멈췄습니다.
"혹시 전체 데이터를 메모리에 올리고 순차 처리하고 있어요?" 김개발 씨가 고개를 끄덕이자 박시니어 씨가 의자를 끌어다 앉았습니다. 그렇다면 대규모 알고리즘이란 정확히 무엇일까요?
쉽게 비유하자면, 대규모 알고리즘은 마치 대형 물류창고의 운영 방식과 같습니다. 작은 편의점은 점원 한 명이 모든 물건을 관리할 수 있습니다.
하지만 쿠팡 물류센터 같은 곳에서 한 사람이 모든 물건을 관리한다면 어떨까요? 말도 안 되는 일입니다.
그래서 구역을 나누고, 각 구역마다 담당자를 배치하고, 컨베이어 벨트로 물건을 이동시킵니다. 대규모 알고리즘이 없던 시절에는 어땠을까요?
개발자들은 단순히 더 좋은 컴퓨터를 사는 것으로 문제를 해결하려 했습니다. CPU 클럭 속도가 올라갈수록 프로그램도 빨라졌기 때문입니다.
하지만 물리적 한계에 부딪혔습니다. 발열 문제로 인해 단일 코어의 속도를 무한정 높일 수 없게 된 것입니다.
더 큰 문제는 데이터의 증가 속도가 하드웨어 발전 속도를 앞질렀다는 점입니다. 바로 이런 문제를 해결하기 위해 대규모 알고리즘이라는 분야가 발전하게 되었습니다.
대규모 알고리즘의 핵심은 분할 정복입니다. 거대한 문제를 작은 조각으로 나누고, 각 조각을 동시에 처리한 뒤, 결과를 합치는 방식입니다.
이를 위해서는 알고리즘 자체를 병렬화할 수 있도록 설계해야 합니다. 위의 코드를 살펴보겠습니다.
첫 번째 함수 single_process는 전통적인 방식입니다. 데이터를 하나씩 순서대로 처리합니다.
두 번째 함수 parallel_process는 Pool을 사용해 여러 워커 프로세스가 동시에 작업합니다. 같은 일을 하지만 후자가 훨씬 빠릅니다.
실제 현업에서는 이보다 훨씬 복잡한 시스템을 사용합니다. 수백 대의 서버가 클러스터를 이루고, 데이터는 분산 파일 시스템에 저장됩니다.
Hadoop, Spark 같은 프레임워크가 이런 복잡한 작업을 추상화해줍니다. 하지만 주의할 점도 있습니다.
모든 문제가 병렬화에 적합한 것은 아닙니다. 이전 계산 결과에 의존하는 순차적 알고리즘은 아무리 서버를 늘려도 빨라지지 않습니다.
이것이 바로 나중에 배울 암달의 법칙과 관련됩니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.
박시니어 씨의 설명을 들은 김개발 씨는 새로운 세계가 열린 느낌이었습니다. 데이터가 커지면 하드웨어만 업그레이드하면 된다고 생각했는데, 근본적으로 접근 방식 자체가 달라야 한다는 것을 깨달은 것입니다.
실전 팁
💡 - 데이터 크기가 기가바이트를 넘어가면 대규모 처리 방식을 고려해야 합니다
- 알고리즘을 설계할 때부터 병렬화 가능 여부를 염두에 두세요
2. 고성능 인프라 특징
김개발 씨가 대규모 알고리즘 공부를 시작하자 회사에서 새로운 기회가 찾아왔습니다. 바로 신규 데이터 분석 시스템의 인프라 구축에 참여하게 된 것입니다.
그런데 회의실에서 나온 용어들이 너무 생소했습니다. 스케일 업?
스케일 아웃? 분산 시스템?
고성능 인프라는 대규모 데이터 처리를 가능하게 하는 물리적, 논리적 기반 시설입니다. 마치 고속도로 시스템과 같습니다.
아무리 좋은 차가 있어도 비포장 도로에서는 제 속도를 낼 수 없듯이, 아무리 좋은 알고리즘도 인프라가 받쳐주지 않으면 무용지물입니다.
다음 코드를 살펴봅시다.
# 분산 시스템의 기본 구조 예시
class DistributedSystem:
def __init__(self, nodes):
self.nodes = nodes # 여러 서버 노드
self.coordinator = nodes[0] # 조정자 노드
def distribute_data(self, data):
# 데이터를 노드들에게 분배
chunk_size = len(data) // len(self.nodes)
for i, node in enumerate(self.nodes):
start = i * chunk_size
node.receive(data[start:start+chunk_size])
def collect_results(self):
# 각 노드의 결과를 수집
return [node.get_result() for node in self.nodes]
김개발 씨가 참석한 인프라 회의는 두 시간 넘게 이어졌습니다. 처음에는 멍하니 듣고만 있었지만, 점점 패턴이 보이기 시작했습니다.
선배들이 계속 반복하는 키워드가 있었습니다. 바로 확장성이었습니다.
회의가 끝난 후 김개발 씨는 박시니어 씨에게 물었습니다. "선배, 스케일 업이랑 스케일 아웃이 뭐예요?" 박시니어 씨가 화이트보드 앞으로 걸어갔습니다.
고성능 인프라의 확장 방식은 크게 두 가지입니다. 첫 번째는 스케일 업(Scale-Up), 수직 확장입니다.
기존 서버의 성능을 높이는 방식입니다. CPU를 더 좋은 것으로 바꾸고, 메모리를 늘리고, SSD를 더 빠른 것으로 교체합니다.
마치 자동차 엔진을 더 강력한 것으로 튜닝하는 것과 같습니다. 두 번째는 스케일 아웃(Scale-Out), 수평 확장입니다.
서버의 수를 늘리는 방식입니다. 성능이 보통인 서버 열 대가 슈퍼컴퓨터 한 대보다 저렴하면서도 더 큰 처리량을 낼 수 있습니다.
마치 택배 차량을 한 대에서 열 대로 늘리는 것과 같습니다. 대규모 시스템에서는 주로 스케일 아웃 방식을 선호합니다.
이유가 있습니다. 스케일 업은 물리적 한계가 있습니다.
아무리 좋은 CPU도 성능에 상한선이 있습니다. 반면 스케일 아웃은 이론적으로 무한히 확장 가능합니다.
구글, 아마존 같은 거대 기업들이 수십만 대의 서버를 운영하는 이유입니다. 하지만 스케일 아웃에는 새로운 문제가 따라옵니다.
바로 분산 시스템의 복잡성입니다. 여러 대의 서버가 협력하려면 서로 통신해야 합니다.
네트워크 지연이 발생하고, 일부 서버가 고장 날 수도 있습니다. 위의 코드는 분산 시스템의 기본 구조를 보여줍니다.
여러 노드가 있고, 조정자가 데이터를 분배하고, 결과를 수집합니다. 실제 시스템은 이보다 훨씬 복잡하지만 핵심 개념은 동일합니다.
고성능 인프라의 또 다른 특징은 장애 허용성입니다. 서버 한 대가 고장 나도 전체 시스템은 계속 동작해야 합니다.
이를 위해 데이터를 여러 곳에 복제하고, 고장 난 서버의 작업을 다른 서버가 대신 처리하는 메커니즘이 필요합니다. 실제 현업에서 고성능 인프라를 구축하려면 네트워크 토폴로지, 스토리지 시스템, 로드 밸런싱 등 고려할 요소가 매우 많습니다.
클라우드 서비스의 등장으로 이런 복잡한 인프라를 직접 구축하지 않고도 필요한 만큼 빌려 쓸 수 있게 되었습니다. 회의 내용을 복습하던 김개발 씨는 고개를 끄덕였습니다.
알고리즘만 잘 짜면 되는 줄 알았는데, 그 알고리즘이 돌아갈 무대를 이해하는 것도 중요하다는 것을 깨달은 것입니다.
실전 팁
💡 - 초기에는 스케일 업으로 시작하되, 성장에 따른 스케일 아웃 계획을 세워두세요
- 클라우드 서비스를 활용하면 인프라 관리 부담을 크게 줄일 수 있습니다
3. 병렬 컴퓨팅 이론적 한계
김개발 씨는 병렬 처리의 매력에 푹 빠졌습니다. 서버를 늘리면 늘릴수록 처리 속도가 빨라지니까요.
그래서 팀장님에게 제안했습니다. "서버를 열 배로 늘리면 속도도 열 배 빨라지지 않을까요?" 팀장님의 대답은 의외였습니다.
병렬 컴퓨팅의 이론적 한계는 아무리 많은 프로세서를 투입해도 성능 향상에 상한선이 존재한다는 것입니다. 마치 요리사를 아무리 많이 고용해도 한 냄비의 수프가 끓는 시간은 줄지 않는 것과 같습니다.
이 한계를 이해하면 현실적인 시스템 설계가 가능해집니다.
다음 코드를 살펴봅시다.
# 병렬화 가능 부분과 불가능 부분
import time
def sequential_part():
# 순차적으로만 실행 가능한 부분
time.sleep(2) # 초기화, 최종 집계 등
def parallel_part(workers):
# 병렬로 나눌 수 있는 부분
time.sleep(8 / workers) # 워커 수만큼 분할
def total_execution(workers):
# 전체 실행 시간 = 순차 + 병렬
seq_time = 2 # 순차 부분은 고정
par_time = 8 / workers # 병렬 부분만 분할
return seq_time + par_time
# 무한대 워커로도 2초 이하로 내려갈 수 없음
팀장님은 김개발 씨의 질문에 미소를 지었습니다. 그리고 화이트보드에 간단한 그래프를 그리기 시작했습니다.
"개발 씨, 만약 서버 열 배가 속도 열 배를 보장한다면 모든 회사가 서버를 무한정 늘리고 있겠죠?" 김개발 씨는 그제야 자신의 질문이 순진했다는 것을 깨달았습니다. 병렬 컴퓨팅에는 본질적인 한계가 있습니다.
그리고 이 한계는 수학적으로 증명되어 있습니다. 가장 핵심적인 문제는 순차적 실행이 반드시 필요한 부분이 존재한다는 것입니다.
프로그램의 모든 부분이 동시에 실행될 수 있는 것은 아닙니다. 어떤 작업은 이전 작업의 결과가 있어야만 시작할 수 있습니다.
쉽게 비유하자면, 책을 읽는 것을 생각해봅시다. 10명이 책 한 권을 나눠 읽으면 10배 빨리 끝날까요?
그렇지 않습니다. 1장을 읽지 않으면 2장의 내용이 이해가 안 됩니다.
소설은 순차적으로 읽어야 하는 특성이 있습니다. 반면, 도서관의 모든 책에서 특정 단어를 찾는 작업은 어떨까요?
10명이 책을 나눠 맡으면 거의 10배 빨라집니다. 각 책은 독립적이기 때문입니다.
위의 코드를 보겠습니다. 전체 작업 시간이 10초라고 가정합니다.
그중 2초는 초기화나 최종 결과 집계처럼 순차적으로만 실행 가능한 부분입니다. 나머지 8초만 병렬화할 수 있습니다.
워커가 1명이면 총 10초가 걸립니다. 워커가 8명이면 순차 2초와 병렬 1초로 총 3초가 됩니다.
하지만 워커를 아무리 늘려도 2초 밑으로는 내려갈 수 없습니다. 순차 부분은 분할이 불가능하기 때문입니다.
이것이 바로 병렬 컴퓨팅의 수확 체감 법칙입니다. 초반에는 프로세서를 늘릴수록 극적으로 빨라지지만, 어느 시점이 지나면 효과가 미미해집니다.
그리고 결국 한계점에 도달합니다. 실무에서 이 한계를 인식하는 것은 매우 중요합니다.
무작정 서버를 늘리는 것은 비용 낭비일 수 있습니다. 대신 순차적 부분을 줄이거나, 알고리즘 자체를 더 병렬화하기 쉬운 구조로 재설계하는 것이 효과적입니다.
팀장님의 설명을 들은 김개발 씨는 새로운 질문이 생겼습니다. "그럼 정확히 얼마나 빨라질 수 있는지 계산할 수 있나요?" 팀장님이 고개를 끄덕였습니다.
"물론이지. 그게 바로 암달의 법칙이야."
실전 팁
💡 - 성능 최적화 전에 병렬화 가능한 부분과 불가능한 부분을 먼저 파악하세요
- 순차적 부분을 줄이는 알고리즘 개선이 서버 증설보다 효과적일 수 있습니다
4. 암달의 법칙
김개발 씨는 다음 날 출근하자마자 암달의 법칙을 검색했습니다. 컴퓨터 과학자 진 암달이 1967년에 발표한 이 법칙은 50년이 지난 지금도 여전히 유효했습니다.
공식을 보는 순간 김개발 씨는 왜 그동안 이걸 몰랐는지 아쉬워졌습니다.
암달의 법칙은 프로그램의 병렬화 비율에 따른 최대 성능 향상을 계산하는 공식입니다. 마치 병목 구간이 있는 고속도로에서 다른 구간을 아무리 넓혀도 전체 통행량에 한계가 있는 것과 같습니다.
이 법칙을 알면 투자 대비 효과를 정확히 예측할 수 있습니다.
다음 코드를 살펴봅시다.
def amdahl_speedup(parallel_fraction, num_processors):
"""
암달의 법칙에 따른 속도 향상 계산
parallel_fraction: 병렬화 가능한 비율 (0~1)
num_processors: 프로세서 개수
"""
sequential_fraction = 1 - parallel_fraction
# 속도 향상 = 1 / (순차비율 + 병렬비율/프로세서수)
speedup = 1 / (sequential_fraction + parallel_fraction / num_processors)
return speedup
# 90% 병렬화 가능할 때
print(amdahl_speedup(0.9, 10)) # 5.26배
print(amdahl_speedup(0.9, 100)) # 9.17배
print(amdahl_speedup(0.9, 1000)) # 9.91배 (10배가 한계)
김개발 씨는 암달의 법칙 공식을 노트에 적었습니다. 의외로 간단했습니다.
속도 향상은 1을 순차 비율과 병렬 비율을 프로세서 수로 나눈 값의 합으로 나눈 것입니다. 처음에는 공식이 와닿지 않았습니다.
그래서 실제 숫자를 대입해보기로 했습니다. 프로그램의 90%가 병렬화 가능하다고 가정합니다.
꽤 높은 비율입니다. 프로세서가 10개면 속도가 얼마나 빨라질까요?
공식에 대입하면 약 5.26배입니다. 10개 프로세서로 5배 정도밖에 안 빨라지는 것입니다.
프로세서를 100개로 늘리면 어떨까요? 9.17배입니다.
1000개로 늘리면? 9.91배입니다.
아무리 프로세서를 늘려도 10배를 넘지 못합니다. 10%의 순차 실행 부분이 발목을 잡기 때문입니다.
이것이 암달의 법칙이 주는 냉정한 현실입니다. 마치 고속도로의 병목 구간을 생각해보세요.
서울에서 부산까지 가는 길에 대부분은 8차선 고속도로입니다. 하지만 중간에 2차선으로 좁아지는 구간이 10km 있습니다.
다른 구간을 16차선으로 확장해봤자 그 병목 구간 때문에 전체 통행 시간은 크게 줄지 않습니다. 위의 코드를 실행해보면 이 한계가 명확히 드러납니다.
amdahl_speedup 함수는 병렬화 비율과 프로세서 수를 입력받아 예상 속도 향상을 계산합니다. 90% 병렬화에서 프로세서를 10배, 100배, 1000배 늘려도 속도 향상은 10배에 수렴합니다.
그렇다면 암달의 법칙을 어떻게 활용해야 할까요? 첫째, 현실적인 기대치를 설정하는 데 사용합니다.
서버 10대 추가 구매를 검토할 때, 실제로 얼마나 빨라질지 미리 계산할 수 있습니다. 둘째, 병목 지점 파악의 중요성을 깨닫게 합니다.
병렬화 비율을 90%에서 99%로 올리면 최대 성능이 10배에서 100배로 늘어납니다. 1%의 순차 코드를 제거하는 것이 서버 100대를 추가하는 것보다 효과적일 수 있습니다.
실무에서 김개발 씨가 해야 할 일은 명확해졌습니다. 먼저 프로파일링을 통해 순차 실행 부분을 정확히 파악하고, 그 부분을 병렬화할 수 있는지 검토하고, 암달의 법칙으로 기대 성능을 계산한 뒤에 서버 증설을 결정하는 것입니다.
김개발 씨는 노트를 덮으며 생각했습니다. 수학 공식 하나가 이렇게 실용적일 줄이야.
이제 팀장님에게 서버 증설을 제안할 때 정확한 근거를 제시할 수 있게 되었습니다.
실전 팁
💡 - 서버 증설 전에 암달의 법칙으로 예상 효과를 계산해보세요
- 병렬화 비율을 높이는 알고리즘 개선이 종종 더 효과적입니다
5. CUDA와 GPU 컴퓨팅
김개발 씨의 회사에서 새로운 프로젝트가 시작되었습니다. 머신러닝 모델을 학습시켜야 하는데, CPU로는 한 달이 걸린다는 계산이 나왔습니다.
그때 데이터 사이언스 팀의 최ML 씨가 한마디 했습니다. "GPU 써보셨어요?
하루면 끝날 텐데요."
CUDA는 NVIDIA에서 개발한 GPU 프로그래밍 플랫폼입니다. GPU는 수천 개의 작은 코어를 가지고 있어 동시에 수천 개의 연산을 처리할 수 있습니다.
마치 한 명의 천재 수학자보다 천 명의 초등학생이 단순 덧셈을 더 빨리 끝내는 것과 같습니다. 특히 행렬 연산이 많은 딥러닝에서 혁신적인 성능을 보여줍니다.
다음 코드를 살펴봅시다.
# GPU 컴퓨팅 with CuPy (NumPy의 GPU 버전)
import cupy as cp
import numpy as np
# CPU에서 행렬 연산
def cpu_matrix_multiply(size=10000):
a = np.random.rand(size, size)
b = np.random.rand(size, size)
result = np.dot(a, b) # CPU 사용
return result
# GPU에서 행렬 연산
def gpu_matrix_multiply(size=10000):
a = cp.random.rand(size, size) # GPU 메모리에 생성
b = cp.random.rand(size, size)
result = cp.dot(a, b) # GPU의 수천 코어가 동시 처리
return result
김개발 씨는 최ML 씨의 말에 귀가 솔깃했습니다. 한 달이 하루로 줄어든다고요?
그게 가능한 일인가요? 최ML 씨가 설명을 시작했습니다.
"CPU와 GPU의 차이를 아세요?" CPU는 Central Processing Unit, 중앙처리장치입니다. 복잡한 계산을 아주 빠르게 처리할 수 있는 강력한 코어를 몇 개 가지고 있습니다.
보통 4개에서 16개 정도입니다. 마치 박사급 전문가 몇 명이 어려운 문제를 푸는 것과 같습니다.
GPU는 Graphics Processing Unit, 그래픽처리장치입니다. 원래 게임 화면을 렌더링하기 위해 만들어졌습니다.
화면의 수백만 픽셀을 동시에 계산해야 하기 때문에 수천 개의 작은 코어를 가지고 있습니다. 각 코어는 CPU 코어보다 단순하지만, 수가 압도적입니다.
쉽게 비유하자면, 복잡한 방정식 하나를 푸는 것은 CPU가 빠릅니다. 하지만 단순한 덧셈 백만 개를 동시에 해야 한다면?
GPU의 수천 코어가 나눠서 처리하면 순식간입니다. CUDA는 이 GPU의 계산 능력을 일반 프로그래밍에 활용할 수 있게 해주는 플랫폼입니다.
NVIDIA가 개발했고, GPU 컴퓨팅의 사실상 표준이 되었습니다. 위의 코드를 보겠습니다.
CuPy는 NumPy와 거의 동일한 문법을 제공하지만, 연산이 GPU에서 수행됩니다. np.dot은 CPU에서, cp.dot은 GPU에서 행렬 곱셈을 합니다.
10000x10000 행렬 곱셈에서 GPU가 CPU보다 수십 배 빠를 수 있습니다. 딥러닝이 폭발적으로 성장한 배경에는 GPU 컴퓨팅이 있습니다.
신경망 학습은 본질적으로 거대한 행렬 연산의 반복입니다. GPU에 완벽히 맞는 작업입니다.
TensorFlow, PyTorch 같은 딥러닝 프레임워크들이 내부적으로 CUDA를 사용하는 이유입니다. 하지만 주의할 점도 있습니다.
모든 작업이 GPU에 적합한 것은 아닙니다. GPU는 동일한 연산을 대량으로 수행할 때 효과적입니다.
조건 분기가 많거나 순차적 의존성이 있는 작업에서는 CPU가 더 나을 수 있습니다. 또한 GPU 메모리 제한도 고려해야 합니다.
GPU 메모리는 보통 8GB에서 24GB 정도입니다. 데이터가 이보다 크면 배치로 나눠 처리하거나 여러 GPU를 사용해야 합니다.
최ML 씨의 설명을 들은 김개발 씨는 딥러닝 팀이 왜 고가의 GPU 서버를 사용하는지 이해가 되었습니다. 적절한 도구를 사용하면 불가능해 보이는 일도 가능해지는 것입니다.
실전 팁
💡 - GPU 컴퓨팅이 필요하다면 CuPy, PyTorch, TensorFlow 같은 프레임워크를 활용하세요
- 데이터 전송 오버헤드를 줄이기 위해 가능한 많은 연산을 GPU에서 연속 처리하세요
6. 아파치 스파크 활용
김개발 씨의 회사에서 데이터 파이프라인을 전면 개편하기로 했습니다. 기존 시스템은 매일 밤 배치 작업으로 전날 데이터를 처리했는데, 이제는 실시간에 가깝게 처리해야 했습니다.
그때 데이터 엔지니어 이데이터 씨가 제안했습니다. "스파크로 가죠."
아파치 스파크는 대규모 데이터 처리를 위한 오픈소스 분산 컴퓨팅 프레임워크입니다. 마치 수십 대의 트럭이 하나의 물류 시스템으로 움직이는 것처럼, 수백 대의 서버가 하나의 논리적 시스템으로 동작합니다.
Hadoop MapReduce의 후속으로, 메모리 기반 처리로 훨씬 빠른 속도를 제공합니다.
다음 코드를 살펴봅시다.
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, count, avg
# 스파크 세션 생성
spark = SparkSession.builder \
.appName("LogAnalysis") \
.getOrCreate()
# 대용량 로그 파일 읽기 (수십 GB도 처리 가능)
logs = spark.read.json("hdfs://cluster/logs/2024/")
# 분산 처리로 집계
result = logs \
.filter(col("status") >= 400) \
.groupBy("endpoint") \
.agg(count("*").alias("error_count"),
avg("response_time").alias("avg_time")) \
.orderBy(col("error_count").desc())
result.show()
이데이터 씨가 회의실 스크린에 스파크 아키텍처를 띄웠습니다. 김개발 씨를 포함한 팀원들이 집중하기 시작했습니다.
"스파크가 뭐길래 다들 스파크, 스파크 하는 걸까요?" 아파치 스파크는 버클리 대학교에서 시작된 프로젝트입니다. Hadoop의 MapReduce가 너무 느리다는 문제를 해결하기 위해 탄생했습니다.
가장 큰 차이점은 메모리 기반 처리입니다. MapReduce는 각 단계마다 결과를 디스크에 저장했습니다.
디스크 입출력은 메모리보다 수백 배 느립니다. 스파크는 가능한 모든 데이터를 메모리에 유지합니다.
그래서 반복적인 연산에서 10배에서 100배까지 빠릅니다. 쉽게 비유하자면, 요리를 할 때 재료를 매번 냉장고에 넣었다 뺐다 하는 것과 조리대 위에 펼쳐놓고 쓰는 것의 차이입니다.
위의 코드를 살펴보겠습니다. SparkSession은 스파크 애플리케이션의 진입점입니다.
spark.read.json으로 HDFS에 있는 대용량 로그 파일을 읽습니다. 수십 기가바이트 파일도 문제없습니다.
핵심은 그다음입니다. filter, groupBy, agg 같은 연산들이 체이닝되어 있습니다.
이 코드가 실행되면 스파크는 자동으로 작업을 여러 서버에 분산합니다. 각 서버가 자신에게 할당된 데이터를 처리하고, 결과를 합칩니다.
개발자는 분산 처리 로직을 직접 작성할 필요가 없습니다. 스파크의 또 다른 장점은 통합된 플랫폼이라는 점입니다.
배치 처리, 스트리밍 처리, 머신러닝, 그래프 처리를 모두 같은 API로 할 수 있습니다. 예전에는 각각 다른 시스템을 배워야 했습니다.
실제 현업에서 스파크는 어떻게 사용될까요? 이커머스 회사에서는 사용자 행동 로그를 스파크로 분석합니다.
수억 건의 클릭 로그에서 어떤 상품이 인기 있는지, 어떤 경로로 구매가 이루어지는지 파악합니다. 금융 회사에서는 사기 탐지에 활용합니다.
실시간으로 들어오는 거래 데이터를 분석해 이상 패턴을 감지합니다. 하지만 스파크가 만능은 아닙니다.
데이터가 기가바이트 수준이라면 굳이 스파크를 쓸 필요가 없습니다. pandas로 충분합니다.
스파크 클러스터를 운영하는 데도 비용과 노력이 필요합니다. 적재적소에 사용하는 것이 중요합니다.
이데이터 씨의 발표가 끝나고 김개발 씨는 손을 들었습니다. "저희 서비스 로그도 스파크로 분석할 수 있을까요?" 이데이터 씨가 웃으며 대답했습니다.
"물론이죠. 다음 스프린트에서 같이 해봐요."
실전 팁
💡 - 테라바이트급 데이터를 다룬다면 스파크 도입을 검토하세요
- 로컬에서 작은 데이터로 먼저 테스트하고 클러스터에 배포하는 방식을 추천합니다
7. 클라우드 컴퓨팅 사례
김개발 씨 회사의 서비스가 갑자기 대박을 쳤습니다. 하루 접속자가 열 배로 늘었습니다.
기존 서버로는 감당이 안 됐습니다. 서버를 사려고 하니 배송에 2주가 걸린다고 합니다.
그때 CTO가 말했습니다. "AWS에서 서버 더 띄워."
클라우드 컴퓨팅은 인터넷을 통해 컴퓨팅 자원을 필요한 만큼 빌려 쓰는 서비스입니다. 마치 전기를 발전소 없이 콘센트에서 쓰는 것처럼, 서버를 직접 사지 않고 클릭 몇 번으로 사용할 수 있습니다.
AWS, Azure, GCP가 대표적이며, 대규모 알고리즘을 실행하기 위한 인프라를 즉시 확보할 수 있습니다.
다음 코드를 살펴봅시다.
# AWS boto3를 사용한 EMR 클러스터 생성 (스파크 실행 환경)
import boto3
emr = boto3.client('emr', region_name='ap-northeast-2')
response = emr.run_job_flow(
Name='DataProcessingCluster',
ReleaseLabel='emr-6.10.0',
Instances={
'MasterInstanceType': 'm5.xlarge',
'SlaveInstanceType': 'm5.xlarge',
'InstanceCount': 10, # 필요한 만큼 조절
'KeepJobFlowAliveWhenNoSteps': False,
},
Applications=[
{'Name': 'Spark'},
{'Name': 'Hadoop'},
],
# 작업 완료 후 자동 종료 = 비용 절감
AutoTerminationPolicy={'IdleTimeout': 3600},
)
CTO의 한마디에 인프라 팀이 움직이기 시작했습니다. 30분 후, 서버 20대가 추가로 가동되고 있었습니다.
김개발 씨는 놀라지 않을 수 없었습니다. 서버를 사려면 몇 주가 걸리는데, 어떻게 이렇게 빨리 가능한 걸까요?
이것이 바로 클라우드 컴퓨팅의 힘입니다. 클라우드 이전 시대에는 어땠을까요?
서비스를 시작하려면 먼저 서버를 구매해야 했습니다. 서버실을 마련하고, 네트워크를 구축하고, 냉방 시설을 갖춰야 했습니다.
초기 투자비용만 수억 원이 들었습니다. 그리고 트래픽이 얼마나 늘어날지 예측해서 미리 용량을 준비해야 했습니다.
예측이 틀리면 서버가 남거나 모자랐습니다. 클라우드는 이 모든 것을 바꿔놓았습니다.
아마존 웹 서비스, 마이크로소프트 애저, 구글 클라우드 플랫폼. 이들은 전 세계에 거대한 데이터센터를 운영합니다.
개발자는 이 자원을 인터넷으로 빌려 씁니다. 서버가 10대 필요하면 10대를 띄우고, 100대가 필요하면 100대를 띄웁니다.
사용한 시간만큼만 비용을 냅니다. 마치 자가용 대신 택시를 타는 것과 비슷합니다.
차를 사면 주차비, 보험료, 정비비가 계속 나갑니다. 택시는 탈 때만 요금을 냅니다.
위의 코드를 보겠습니다. AWS EMR은 관리형 Hadoop과 Spark 서비스입니다.
boto3는 Python에서 AWS 서비스를 제어하는 라이브러리입니다. 이 코드를 실행하면 m5.xlarge 인스턴스 10대로 구성된 스파크 클러스터가 생성됩니다.
몇 분이면 됩니다. 핵심은 탄력성입니다.
블랙프라이데이 같은 이벤트 기간에는 서버를 대폭 늘립니다. 이벤트가 끝나면 줄입니다.
새벽에 트래픽이 적을 때는 최소 서버만 유지합니다. 이런 유연한 스케일링이 클라우드에서는 자동으로 가능합니다.
대규모 알고리즘과 클라우드의 조합은 강력합니다. 예를 들어, 연간 데이터를 한 번에 분석하는 작업이 있다고 합시다.
로컬 서버로는 일주일이 걸립니다. 클라우드에서 서버 100대를 띄우면 2시간 만에 끝납니다.
사용한 200시간 서버 타임만 비용으로 냅니다. 일주일 내내 서버를 유지하는 것보다 저렴합니다.
하지만 클라우드에도 주의할 점이 있습니다. 비용 관리입니다.
서버를 켜놓고 깜빡 잊으면 요금 폭탄을 맞을 수 있습니다. 따라서 AutoTerminationPolicy 같은 설정으로 작업 후 자동 종료를 걸어두는 것이 중요합니다.
김개발 씨는 이번 경험을 통해 현대 개발의 핵심을 깨달았습니다. 인프라는 더 이상 제약 조건이 아닙니다.
필요하면 언제든 확보할 수 있습니다. 중요한 것은 그 인프라를 효율적으로 활용하는 알고리즘과 아키텍처입니다.
실전 팁
💡 - 클라우드 비용 알람을 설정해두면 예상치 못한 과금을 방지할 수 있습니다
- 개발 환경은 로컬이나 소규모 클라우드로, 프로덕션만 대규모로 운영하는 것이 경제적입니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.