Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Archives
Today
Total
관리 메뉴

밤빵's 개발일지

[TIL]20241214 내 시각에서 이해한 클러스터링 개념 본문

개발Article

[TIL]20241214 내 시각에서 이해한 클러스터링 개념

최밤빵 2024. 12. 14. 09:37

개발을 시작하고 "클러스터링"이라는걸  종종 듣긴 했지만, 어떤 개념인지 정확히 이해하지 못한 채 지나쳐왔다. 지금 진행중인 프로젝트에서도 헬스체크가 구현되면서 서버 상태를 확인하는 기능을 보게됐고, 클러스터링이 어떻게 연결되는지 궁금했다. 그래서 이번에 클러스터링을 학습하면서 내가 이해한 내용을 정리해봤다.


클러스터링

클러스터링은 여러 대의 서버나 시스템을 하나의 그룹으로 묶어 함께 동작하도록 만드는 기술이다. 이렇게 묶인 서버들의 그룹을 클러스터라고 부른다.

 

클러스터링은 크게 두 가지 목표를 가지고 있다.

고가용성(High Availability, HA)

서버 중 하나가 다운되더라도 나머지 서버가 대신 역할을 수행해서 시스템이 멈추지 않도록 한다.

부하 분산(Load Balancing)

하나의 서버에 모든 요청이 집중되지 않도록 여러 서버에 요청을 나누어 처리한다.

 

클러스터링을 적용하면 시스템의 안정성과 성능을 모두 향상시킬 수 있다.


클러스터링이 왜 필요할까?

하나의 서버만 사용해서 서비스를 제공한다고 가정했을 때,

문제 1: 서버가 고장 나면 서비스 전체가 중단된다.
문제 2: 사용자가 급격히 늘어나면, 하나의 서버가 감당할 수 없는 부하가 발생한다.

이 문제를 해결하기 위해 클러스터링이 필요하다. 여러 대의 서버를 묶어두면 하나의 서버가 고장 나더라도 나머지 서버가 서비스 요청을 처리할 수 있고, 부하가 분산되어 시스템이 안정적으로 운영된다.


현재 프로젝트의 헬스체크와 클러스터링

헬스체크는 시스템이 정상적으로 동작하는지 주기적으로 확인하는 기능이다.

package com.sample.pugbrecords.healthCheck;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import java.util.TreeMap;

@RestController
public class HealthCheckController {
    @Value(value="${server.env}")
    private String env;
    @Value(value="${server.port}")
    private String serverPort;
    @Value(value="${server.serveraddress}")
    private String serverAddress;
    @Value(value="${servername}")
    private String serverName;

    // 현재 동작중인 서버 확인 (blue, green)
    // http://"serverIP"/hc
    @GetMapping("/hc")
    public ResponseEntity<?> healthCheck() {
        Map<String, String> responeseData = new TreeMap<>();
        responeseData.put("serverName", serverName);
        responeseData.put("serverAddress", serverAddress);
        responeseData.put("serverPort", serverPort);
        responeseData.put("env", env);
        return ResponseEntity.ok(responeseData);
    }

    @GetMapping("/env")
    public ResponseEntity<?> getEnv() {
        return ResponseEntity.ok(env);
    }
}

→ 이 헬스체크 API를 호출하면 서버가 정상적으로 동작 중인지 확인할 수 있다.

 

이 기능을 클러스터링 환경에서 확장하면 다음과 같이 활용할 수 있다.

헬스체크로 서버 상태 모니터링
여러 서버(노드) 중 하나라도 문제가 생기면 해당 노드를 제외하고 다른 노드가 요청을 처리하도록 할 수 있다.
부하 분산과 연결
클러스터링 환경에서는 로드 밸런서가 여러 서버에 요청을 나눠준다. 이때 헬스체크를 통해 문제가 있는 서버는 로드 밸런서가 요청을 전달하지 않도록 설정할 수 있다.

클러스터링의 동작 

2개의 서버에서 동작한다(현재 프로젝트)

  1. 헬스체크 요청: 각 서버에 /hc API를 호출해 상태를 확인한다.
    • 서버 A: 정상 응답 → {serverName: "server-A", serverAddress: "10.0.0.1", serverPort: "8080", env: "blue"}
    • 서버 B: 정상 응답 → {serverName: "server-B", serverAddress: "10.0.0.2", serverPort: "8081", env: "green"}
  2. 로드 밸런서의 역할: 두 서버 모두 정상 상태이기때문에, 로드 밸런서는 서버 A와 B에 요청을 분산한다.

이런 방식으로 헬스체크와 클러스터링이 함께 동작하면 서버 장애를 감지하고 시스템의 안정성을 보장할 수 있다.


클러스터링 구성 방식

클러스터링에는 크게 두 가지를 많이 사용한다.

Active-Active 방식
  • 모든 서버가 동시에 요청을 처리한다.
  • 장점: 모든 서버를 최대한 활용할 수 있어서 성능이 좋다.
  • 단점: 서버 간 데이터 일관성을 유지하기 어렵다.
Active-Passive 방식
  • 한 서버가 요청을 처리하고, 나머지 서버는 대기 상태로 있다.
  • 장점: 데이터 일관성을 유지하기 쉽다.
  • 단점: 대기 중인 서버의 리소스가 낭비될 수 있다.

클러스터링 적용 시 고려할 점

데이터 일관성

여러 서버에서 데이터를 처리할 때, 데이터가 서로 다르면 문제가 발생할 수 있다.

로드 밸런싱 

부하를 어떻게 나눌지에 대한 정책이 필요하다. 

헬스체크

서버 상태를 주기적으로 확인하고 문제가 생긴 서버를 제외하는 로직이 필요하다.


배운 점과 고민

이번에 클러스터링을 학습하면서 헬스체크와의 연결고리를 발견했다. 클러스터링은 여러 서버를 묶어서 시스템의 안정성과 성능을 보장하는 기술이고, 헬스체크는 그 서버들이 정상적으로 동작하는지 확인하는 중요한 역할을 한다.

현재 프로젝트에서도 클러스터링과 헬스체크를 결합해 더 안정적인 시스템을 설계하고 싶다. 

  • Redis 캐시를 추가해 데이터 일관성을 높이고,
  • 서버 상태 모니터링 로직을 개선해 클러스터링의 초기 단계를 경험해 볼 계획이다.

이번 학습을 통해 이론뿐만 아니라 프로젝트에 실질적으로 적용할 아이디어도 얻을 수 있어 유익했다. 특히 헬스체크 코드가 클러스터링에 어떻게 활용될 수 있을지 고민한 점이 가장 큰 배움이었다.