분산 컴퓨팅, 언제 클러스터로 언제 그리드로 가야 하나
밀접 결합·느슨한 결합의 차이부터 클러스터·그리드·Hadoop 생태계까지, 분산 시스템을 설계할 때 실제로 부딪히는 선택지를 정리한다.
2026-08-12 · 최초 발행 2025-12-28
서버 한 대의 CPU와 메모리를 아무리 늘려도 언젠가 상한선에 부딪힌다. 이 벽을 넘는 방법은 결국 하나다 — 여러 컴퓨터를 네트워크로 묶어 하나의 일을 나눠 하게 만드는 것. 문제는 "여러 대로 나눈다"는 말이 실제로는 완전히 다른 두 세계를 가리킨다는 데 있다.
밀접 결합과 느슨한 결합은 다른 문제다
슈퍼컴퓨터나 SMP 시스템처럼 CPU들이 공유 메모리나 고속 상호연결로 묶여 동기적으로 실행되는 구조를 밀접 결합(Tightly-Coupled)이라 부른다. 반대로 클러스터·그리드·클라우드처럼 독립적인 컴퓨터들이 이더넷이나 InfiniBand 같은 네트워크로 통신하며 비동기로 움직이는 구조가 느슨한 결합(Loosely-Coupled)이다.
일반적으로 "분산 컴퓨팅"이라 부르는 것은 후자다. 이 구조가 가진 네 가지 성질 — 자율성(각 노드가 독립적인 OS를 갖고 개별 장애가 격리된다), 이질성(서로 다른 하드웨어·OS가 프로토콜로만 통신한다), 동시성(비동기 메시지 전달이라 경쟁 조건을 직접 관리해야 한다), 확장성(노드를 추가하면 성능이 늘어나는 scale-out 구조) — 이 네 가지가 분산 시스템 설계 전반을 관통한다.
이 구조를 택하는 이유는 단순하다. 범용 하드웨어(Commodity Hardware)를 슈퍼컴퓨터보다 싸게 쓸 수 있고, 노드 하나가 죽어도 전체가 죽지 않는 내결함성을 얻으며, 자원을 지리적으로 흩어 재난 복구까지 가능해진다. 대신 그 대가로 일관성 관리, 네트워크 지연, 다중 테넌트 보안 같은 새로운 문제가 따라온다 — 이 문제들은 글 뒷부분에서 다시 다룬다.
클러스터: 근접한 자원을 하나처럼 묶는다
클러스터는 물리적으로 가까운 컴퓨터들을 고속 로컬 네트워크로 묶어 단일 시스템처럼 중앙에서 관리하는 구조다. 목적에 따라 세 갈래로 나뉜다.
HPC 클러스터는 연산 성능 자체를 최대화하는 게 목표다. MPI로 노드 간 통신을 하고 InfiniBand나 10GbE 같은 저레이턴시 네트워크를 쓰며, 기상 예측이나 분자 동역학, 유한 요소 해석처럼 계산량이 큰 작업에 쓰인다. HA 클러스터는 반대로 가동 시간을 최대화하는 게 목적이라 Active-Standby 구성에 Heartbeat 모니터링, 자동 Failover, 공유 스토리지를 갖추고 데이터베이스나 파일 서버처럼 멈추면 안 되는 시스템을 지탱한다. Load Balancing 클러스터는 Active-Active로 여러 노드가 동시에 요청을 나눠 받는 구조로, 웹 서버나 애플리케이션 서버의 수평 확장에 쓰인다.
이 세 유형을 실제로 굴리는 소프트웨어도 성격이 다르다. SLURM은 HPC 클러스터의 작업 스케줄링과 리소스 할당을 표준적으로 담당하고, Pacemaker + Corosync는 HA 클러스터에서 멤버십 관리와 Failover를 처리하며, Kubernetes는 컨테이너 오케스트레이션 위에서 자동 스케일링과 자가 치유를 제공한다.
그리드: 조직 경계를 넘는 자원 연합
클러스터가 한 조직이 가까운 자원을 중앙에서 관리하는 구조라면, 그리드 컴퓨팅은 지리적으로 흩어진 여러 조직의 자원을 Globus Toolkit 같은 미들웨어로 묶어 가상의 슈퍼컴퓨터를 구성하는 접근이다.
| 특성 | 클러스터 | 그리드 |
|---|---|---|
| 지리적 위치 | 근접 | 분산 |
| 소유권 | 단일 조직 | 다중 조직 |
| 네트워크 | 고속 LAN | WAN/인터넷 |
| 관리 | 중앙 집중 | 분산 |
| 동질성 | 높음 | 낮음 |
그리드는 계층 구조로 동작한다. Fabric Layer가 CPU·스토리지 같은 물리적 자원을, Connectivity Layer가 네트워크와 보안 프로토콜을, Resource Layer가 개별 자원 관리를, Collective Layer가 자원 발견과 스케줄링을, 최상위 Application Layer가 사용자 응용을 담당한다.
SETI@home, Folding@home, LHC@home 같은 자원봉사 컴퓨팅 프로젝트가 BOINC 플랫폼 위에서 이 모델을 대중적으로 보여준 사례다. 참가자의 개인 컴퓨터가 유휴 시간에 계산을 나눠 맡는 방식은, 그리드가 소유권이 흩어진 자원도 협업 대상으로 삼을 수 있음을 보여준다.
위치 투명성: 자원이 어디 있는지 몰라도 되게 만들기
분산 시스템이 커질수록 자원의 물리적 위치를 사용자나 애플리케이션이 알 필요가 없어야 관리가 가능해진다. DNS는 논리적 이름을 IP 주소로 바꿔줘 서버 위치가 바뀌어도 이름은 그대로 쓸 수 있게 하고, NFS·CIFS 같은 분산 파일 시스템은 네트워크 경로를 로컬 경로처럼 마운트하며 HDFS는 블록 단위로, GFS·Ceph는 객체 단위로 저장 위치를 추상화한다. UDDI나 Consul, etcd 같은 서비스 레지스트리는 서비스 발견과 동적 바인딩으로 같은 역할을 애플리케이션 계층에서 수행한다.
Scale-out이 지켜야 하는 원칙
노드를 늘려 성능을 선형적으로 끌어올리려면 아키텍처가 몇 가지 조건을 만족해야 한다. 서버가 세션 상태를 갖지 않는 무상태(Stateless) 설계여야 요청을 아무 노드로나 자유롭게 분산할 수 있고, 데이터와 서비스를 복제(Replication)해야 가용성과 읽기 성능이 함께 올라간다. 데이터를 여러 노드에 분할(Partitioning/Sharding)해야 병렬 처리가 되고 핫스팟을 피할 수 있으며, 컴포넌트 간에는 메시지 큐를 낀 느슨한 결합이 필요하다. 이 네 가지 중 하나라도 어긋나면 노드를 늘려도 성능이 선형으로 늘지 않는다.
Hadoop이 빅데이터 처리의 표준이 된 이유
2003~2004년 Google이 GFS와 MapReduce 논문을 발표하자, Yahoo의 Doug Cutting이 2006년 이를 오픈소스로 구현한 게 Hadoop이다. 범용 하드웨어로 페타바이트급 데이터를 처리한다는 아이디어가 이후 빅데이터 생태계 전체의 뼈대가 됐다.
HDFS는 메타데이터를 관리하는 NameNode와 실제 블록을 저장하는 DataNode로 나뉜다. NameNode가 파일·디렉토리 네임스페이스와 블록 위치 정보를 쥐고 있다는 것 자체가 단일 장애점이라, Secondary NameNode로 백업하거나 Zookeeper 기반 HA 구성으로 보완한다. DataNode는 Heartbeat로 상태를 보고하며 장애 시 자동으로 복구된다.
HDFS는 128MB 기본 블록 크기로 대용량 파일에 최적화돼 있어 작은 파일에는 비효율적이고, Append 연산도 제한적이라 Write Once, Read Many 패턴을 전제로 설계됐다. 계산을 데이터가 있는 노드로 옮기는 데이터 지역성(Data Locality)으로 네트워크 트래픽을 줄이고, 기본 복제 계수 3으로 서로 다른 랙에 복제본을 두어 노드 장애 시 자동 재복제가 일어난다.
MapReduce는 이 위에서 돌아가는 프로그래밍 모델이다. Map 단계가 입력을 키-값 쌍으로 병렬 변환하고, Shuffle & Sort 단계가 같은 키를 같은 Reducer로 모으며, Reduce 단계가 값을 집계해 HDFS에 저장한다.
단어 빈도를 세는 Word Count는 MapReduce의 구조를 가장 잘 보여주는 예다.
// Mapper
public class WordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(LongWritable key, Text value, Context context) {
String line = value.toString();
for (String w : line.split("\\s+")) {
word.set(w);
context.write(word, one);
}
}
}
// Reducer
public class WordCountReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
public void reduce(Text key, Iterable<IntWritable> values, Context context) {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
context.write(key, new IntWritable(sum));
}
}
Hadoop 2.0부터는 YARN이 리소스 관리를 MapReduce에서 분리해 Spark나 Tez 같은 다른 처리 엔진도 같은 클러스터 자원을 나눠 쓸 수 있게 했다. ResourceManager가 전역 스케줄링을, NodeManager가 노드별 리소스를, ApplicationMaster가 애플리케이션별 조정을, Container가 실제 CPU·메모리 할당 단위를 맡는다.
결국 남는 것은 CAP의 트레이드오프
분산 시스템을 아무리 잘 설계해도 CAP 정리 — Consistency, Availability, Partition Tolerance 세 가지 중 최대 두 가지만 동시에 보장할 수 있다는 원칙 — 는 피해갈 수 없다. 네트워크 분할은 실제로 일어나므로, 결국 선택은 분할이 발생했을 때 일관성을 지킬지 가용성을 지킬지의 문제로 좁혀진다. 이 선택에 따라 강한 일관성을 쓸지 최종 일관성을 쓸지가 갈리고, 분산 트랜잭션이 필요하면 Two-Phase Commit이나 Paxos·Raft 같은 합의 알고리즘이 등장한다. 네트워크 지연은 비동기 처리와 로컬 캐싱, 데이터의 근접 배치로 완화하고, 다중 테넌트 환경에서는 통신 암호화와 인증·권한 관리가 클러스터 하나짜리 시스템보다 훨씬 무거운 과제가 된다.
밀접 결합이냐 느슨한 결합이냐, 클러스터냐 그리드냐, 강한 일관성이냐 최종 일관성이냐 — 분산 컴퓨팅의 설계는 결국 이 세 갈림길 위에서 반복해서 갈라진다.