Skip to content
Published on

[운영체제] 19. 네트워크와 분산 시스템

Authors

네트워크와 분산 시스템

현대 컴퓨팅 환경은 네트워크로 연결된 여러 컴퓨터가 협력하여 동작합니다. 이 글에서는 네트워크 기초, 분산 시스템의 개념과 과제, 분산 파일 시스템, MapReduce, 그리고 분산 조정 메커니즘을 살펴봅니다.


1. 네트워크 유형

┌───────────────────────────────────────────────┐
│            네트워크 규모별 분류                 │
│                                               │
PAN (Personal Area Network):│  ┌───────────────────┐                        │
│  │ 블루투스, NFC~ 수 미터            │
│  └───────────────────┘                        │
│                                               │
LAN (Local Area Network):│  ┌───────────────────┐                        │
│  │ 이더넷, Wi-Fi     │  건물/캠퍼스 내        │
│  │ 1~10 Gbps        │                        │
│  └───────────────────┘                        │
│                                               │
MAN (Metropolitan Area Network):│  ┌───────────────────┐                        │
│  │ 도시 규모 네트워크 │                        │
│  └───────────────────┘                        │
│                                               │
WAN (Wide Area Network):│  ┌───────────────────┐                        │
│  │ 국가/대륙 간 연결  │  인터넷               │
│  └───────────────────┘                        │
└───────────────────────────────────────────────┘

2. TCP/IP 모델

┌─────────────────────────────────────────────┐
TCP/IP 4계층 모델                  │
│                                             │
│  ┌─────────────────┐                        │
│  │ 응용 계층       │  HTTP, FTP, DNS, SSH (Application)   │  소켓 API│  ├─────────────────┤                        │
│  │ 전송 계층       │  TCP (신뢰성, 순서) (Transport)UDP (빠름, 비연결)│  ├─────────────────┤                        │
│  │ 인터넷 계층     │  IP (주소 지정, 라우팅) (Internet)ICMP, ARP│  ├─────────────────┤                        │
│  │ 네트워크 접근   │  이더넷, Wi-Fi (Link)MAC 주소              │
│  └─────────────────┘                        │
└─────────────────────────────────────────────┘

TCP vs UDP

특성TCPUDP
연결연결 지향 (3-way handshake)비연결
신뢰성보장 (재전송, 순서 보장)미보장
속도상대적으로 느림빠름
용도웹, 이메일, 파일 전송스트리밍, DNS, 게임

소켓 프로그래밍 예시

// TCP 서버 예시 (C)
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int server_fd, client_fd;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);
    char buffer[1024];

    // 1. 소켓 생성
    server_fd = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 주소 바인딩
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(8080);
    bind(server_fd, (struct sockaddr *)&server_addr,
         sizeof(server_addr));

    // 3. 수신 대기
    listen(server_fd, 5);
    printf("서버 대기 중 (포트 8080)...\n");

    // 4. 연결 수락
    client_fd = accept(server_fd,
                       (struct sockaddr *)&client_addr,
                       &client_len);

    // 5. 데이터 수신
    int bytes = recv(client_fd, buffer, sizeof(buffer) - 1, 0);
    buffer[bytes] = '\0';
    printf("수신: %s\n", buffer);

    // 6. 응답 전송
    const char *response = "Hello from server!";
    send(client_fd, response, strlen(response), 0);

    // 7. 연결 종료
    close(client_fd);
    close(server_fd);
    return 0;
}
// TCP 클라이언트 예시 (C)
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

int main() {
    int sock;
    struct sockaddr_in server_addr;
    char buffer[1024];

    // 1. 소켓 생성
    sock = socket(AF_INET, SOCK_STREAM, 0);

    // 2. 서버에 연결
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8080);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
    connect(sock, (struct sockaddr *)&server_addr,
            sizeof(server_addr));

    // 3. 데이터 전송
    const char *message = "Hello from client!";
    send(sock, message, strlen(message), 0);

    // 4. 응답 수신
    int bytes = recv(sock, buffer, sizeof(buffer) - 1, 0);
    buffer[bytes] = '\0';
    printf("서버 응답: %s\n", buffer);

    // 5. 연결 종료
    close(sock);
    return 0;
}

3. 분산 시스템

여러 독립적인 컴퓨터가 네트워크를 통해 협력하여 하나의 시스템처럼 동작합니다.

장점과 과제

장점:                              과제:
┌──────────────────────────┐      ┌──────────────────────────┐
│ 자원 공유                │      │ 네트워크 장애            │
- 저장소, 연산 자원 공유 │      │ - 부분 장애 처리         │
│                          │      │                          │
│ 확장성                   │      │ 일관성 유지              │
- 수평 확장 (노드 추가)  │      │ - 데이터 복제 시 일관성  │
│                          │      │                          │
│ 가용성                   │      │ 보안                     │
- 노드 장애 시 자동 복구 │      │ - 네트워크 통신 보안     │
│                          │      │                          │
│ 성능                     │      │ 시계 동기화              │
- 병렬 처리로 처리량 향상│      │ - 분산 환경 이벤트 순서  │
└──────────────────────────┘      └──────────────────────────┘

CAP 정리

분산 시스템은 일관성(Consistency), 가용성(Availability), 분단 허용성(Partition Tolerance) 세 가지를 동시에 만족할 수 없습니다.

        일관성 (C)
        ╱       ╲
CA        (단일서버)     ╱               ╲
    ╱                  ╲
가용성 (A) ──── 분단 허용성 (P)
         AP / CP

네트워크 분단은 불가피하므로:
- CP 시스템: 일관성 우선 (: ZooKeeper, HBase)
  → 분단 시 일부 요청 거부
- AP 시스템: 가용성 우선 (: Cassandra, DynamoDB)
  → 분단 시 불일치 허용, 나중에 수렴

4. 분산 파일 시스템

NFS (Network File System)

클라이언트 A ──→ ┐
클라이언트 B ──→ ├→ NFS 서버 ──→ 로컬 디스크
클라이언트 C ──→ ┘      │
                        └→ /exports/shared/
                            ├── project/
                            ├── data/
                            └── config/

특징:
- 원격 파일을 로컬처럼 접근 (투명성)
- POSIX 호환 인터페이스
- 클라이언트측 캐싱으로 성능 향상

GFS (Google File System)

대용량 파일을 위한 분산 파일 시스템입니다.

┌──────────────────────────────────────────┐
GFS 아키텍처                   │
│                                          │
│  ┌───────────────┐                       │
│  │  GFS Master   │  ← 메타데이터 관리    │
  (Name Node)    (파일 → 청크 매핑)│  └───────┬───────┘                       │
│          │                               │
│  ┌───────┼───────┬───────┐               │
│  │       │       │       │               │
│  ▼       ▼       ▼       ▼               │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐             │
│ │Chunk│ │Chunk│ │Chunk│ │Chunk│           │
│ │Srv 1│ │Srv 2│ │Srv 3│ │Srv 4│           │
│ └────┘ └────┘ └────┘ └────┘             │
│                                          │
│ 파일 → 64MB 청크로 분할                  │
│ 각 청크는 3개 서버에 복제 (내결함성)└──────────────────────────────────────────┘

HDFS (Hadoop Distributed File System)

GFS의 오픈소스 구현으로, 대규모 데이터 처리에 최적화되어 있습니다.

┌─────────────────────────────────────────┐
HDFS 아키텍처                 │
│                                         │
│  ┌────────────┐                         │
│  │ NameNode   │ ← 메타데이터 (메모리)│  │            │   파일명→블록 매핑       │
│  │            │   블록→DataNode 매핑     │
│  └─────┬──────┘                         │
│        │ Heartbeat + Block Report│  ┌─────┼──────┬──────────┐              │
│  ▼     ▼      ▼          ▼              │
│ ┌────┐┌────┐┌────┐    ┌────┐            │
│ │DN 1││DN 2││DN 3│    │DN 4│            │
│ │    ││    ││    │    │    │            │
│ │Blk1││Blk1││Blk2│    │Blk2│            │
│ │Blk3││Blk2││Blk3│    │Blk1│            │
│ └────┘└────┘└────┘    └────┘            │
│                                         │
│ 기본 블록 크기: 128MB                    │
│ 복제 계수: 3 (기본)└─────────────────────────────────────────┘
// HDFS Java API 예시
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FSDataInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class HdfsExample {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);

        // 파일 쓰기
        Path writePath = new Path("/user/data/output.txt");
        FSDataOutputStream out = fs.create(writePath);
        out.writeUTF("Hello, HDFS!");
        out.close();

        // 파일 읽기
        Path readPath = new Path("/user/data/output.txt");
        FSDataInputStream in = fs.open(readPath);
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(in)
        );
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        reader.close();

        // 파일 삭제
        fs.delete(new Path("/user/data/output.txt"), false);
        fs.close();
    }
}

5. MapReduce

대규모 데이터를 병렬로 처리하는 프로그래밍 모델입니다.

입력 데이터 (3개 분할):

Split 1: "hello world hello"
Split 2: "world foo hello"
Split 3: "bar foo hello"

     │           │           │
     ▼           ▼           ▼
  ┌──────┐   ┌──────┐   ┌──────┐
Map 1 │   │Map 2 │   │Map 3 │   ← Map 단계
  └──┬───┘   └──┬───┘   └──┬───┘
     │           │           
  (hello,1)   (world,1)   (bar,1)
  (world,1)   (foo,1)     (foo,1)
  (hello,1)   (hello,1)   (hello,1)
     │           │           │
     └─────┬─────┘───────────┘
     Shuffle & Sort (키별 그룹화)
  ┌────────┴────────────────────────┐
  │ bar:    [1]  │ foo:    [1, 1]  │ hello:  [1, 1, 1, 1]  │ world:  [1, 1]  └────────┬────────────────────────┘
     ┌─────┴──────┐
     ▼            ▼
  ┌──────┐   ┌──────┐
  │Red. 1│   │Red. 2│   ← Reduce 단계
  └──┬───┘   └──┬───┘
     │           │
  bar:1       hello:4
  foo:2       world:2
// WordCount MapReduce 예시 (Java)
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import java.io.IOException;

// Mapper: 각 단어를 (단어, 1) 쌍으로 출력
public class WordCountMapper
    extends Mapper<Object, Text, Text, IntWritable> {

    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();

    public void map(Object key, Text value, Context context)
        throws IOException, InterruptedException {
        String[] words = value.toString().split("\\s+");
        for (String w : words) {
            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)
        throws IOException, InterruptedException {
        int sum = 0;
        for (IntWritable val : values) {
            sum += val.get();
        }
        context.write(key, new IntWritable(sum));
    }
}

6. 클라우드 스토리지

클라우드 환경에서 대규모 데이터를 저장하고 관리하는 서비스입니다.

┌────────────────────────────────────────────────┐
│          클라우드 스토리지 서비스 비교           │
│                                                │
AWS:│  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐          │
│  │ S3   │ │ EBS  │ │ EFS  │ │Glacier│         │
│  │객체  │ │블록  │ │파일  │ │아카이브│         │
│  └──────┘ └──────┘ └──────┘ └──────┘          │
│                                                │
GCP:│  ┌──────────┐ ┌──────────┐ ┌──────────┐       │
│  │ Cloud    │ │Persistent│ │ Filestore││  │ Storage  │ │ Disk     │ │          │       │
│  └──────────┘ └──────────┘ └──────────┘       │
│                                                │
│  스토리지 클래스 (S3 기준):StandardIAGlacierDeep Archive  ()      ()  (콜드)    (아카이브)│  접근 빈도 높음 ─────────→ 접근 빈도 낮음      │
│  비용 높음 ──────────────→ 비용 낮음           │
└────────────────────────────────────────────────┘

7. 분산 조정 (Distributed Coordination)

합의 알고리즘 - Raft

분산 시스템에서 노드들이 동일한 상태에 합의하는 알고리즘입니다.

Raft 리더 선출:

Node A (Follower)  Node B (Leader)  Node C (Follower)
    │                   │                │
    │  ←── Heartbeat ── │ ── Heartbeat → │
    │                   │                │
X (장애 발생)    │                   │                │
      (타임아웃)       │                │
    │  → Candidate!     │                │
    │                   │                │
    │ ── RequestVote ────────────────→   │
    │ ←──────────────── Vote ────────   │
    │                                    │
    │  → 새로운 Leader!    │                                    │
    │ ── AppendEntries (Heartbeat) ──→   │

ZooKeeper

분산 애플리케이션을 위한 조정 서비스입니다.

┌──────────────────────────────────────┐
ZooKeeper 앙상블              │
│                                      │
│  ┌────────┐ ┌────────┐ ┌────────┐   │
│  │Server 1│ │Server 2│ │Server 3│   │
(Leader)(Follow.)(Follow.)│  │
│  └────────┘ └────────┘ └────────┘   │
│                                      │
ZNode 트리 구조:/│  ├── /config                         │
│  │   ├── /config/database            │
│  │   └── /config/cache               │
│  ├── /locks                          │
│  │   └── /locks/resource1            │
│  └── /members                        │
│      ├── /members/node1              │
│      └── /members/node2              │
└──────────────────────────────────────┘
// ZooKeeper 분산 잠금 예시 (Java, 의사 코드)
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;

public class DistributedLock {
    private ZooKeeper zk;
    private String lockPath;

    public DistributedLock(ZooKeeper zk, String resource) {
        this.zk = zk;
        this.lockPath = "/locks/" + resource;
    }

    public void lock() throws Exception {
        // 임시 순차 노드 생성
        String myNode = zk.create(
            lockPath + "/lock-",
            new byte[0],
            ZooDefs.Ids.OPEN_ACL_UNSAFE,
            CreateMode.EPHEMERAL_SEQUENTIAL
        );

        while (true) {
            // 가장 작은 번호의 노드가 잠금 소유자
            var children = zk.getChildren(lockPath, false);
            String smallest = children.stream()
                .sorted()
                .findFirst()
                .orElse(null);

            if (myNode.endsWith(smallest)) {
                return; // 잠금 획득
            }
            // 그렇지 않으면 이전 노드 감시하며 대기
            Thread.sleep(100);
        }
    }

    public void unlock() throws Exception {
        zk.delete(lockPath, -1);
    }
}

8. 정리

  • 네트워크: TCP/IP 4계층 모델, TCP(신뢰성) vs UDP(빠름)
  • 분산 시스템: 자원 공유와 확장성의 이점, CAP 정리의 트레이드오프
  • 분산 파일 시스템: NFS(전통), GFS/HDFS(대규모 데이터)
  • MapReduce: Map(분산 처리) + Reduce(집계)로 병렬 데이터 처리
  • 클라우드 스토리지: 객체/블록/파일 스토리지, 티어링으로 비용 최적화
  • 분산 조정: Raft 합의 알고리즘, ZooKeeper 조정 서비스
퀴즈: 네트워크와 분산 시스템

Q1. CAP 정리에서 CP 시스템과 AP 시스템의 차이점은?

A1. CP 시스템(예: ZooKeeper)은 네트워크 분단 시 일관성을 유지하기 위해 일부 요청을 거부하여 가용성을 포기합니다. AP 시스템(예: Cassandra)은 네트워크 분단 시에도 모든 요청에 응답하지만, 노드 간 데이터가 일시적으로 불일치할 수 있으며, 나중에 수렴(eventual consistency)합니다.

Q2. HDFS에서 데이터 블록을 3개 복제하는 이유는?

A2. 3개 복제는 내결함성과 성능의 균형을 제공합니다. 1개의 DataNode가 장애를 일으켜도 나머지 2개의 복제본에서 데이터를 읽을 수 있으며, 읽기 요청을 여러 복제본에 분산하여 처리량을 높일 수 있습니다. HDFS는 복제본을 서로 다른 랙에 배치하여 랙 수준의 장애에도 대비합니다.

Q3. MapReduce에서 Shuffle 단계의 역할은?

A3. Shuffle 단계는 Map 출력을 키(key)별로 정렬하고 그룹화하여 같은 키를 가진 모든 값을 하나의 Reducer에 전달합니다. 이 과정에서 네트워크를 통한 데이터 전송이 발생하므로 MapReduce에서 가장 비용이 큰 단계이며, 성능 최적화의 핵심 대상입니다.