엘라스틱 서치(Elasticsearch)에서 리뷰 데이터 저장 방식과 동기화 전략

1. 문제 발생

일반적인 정적 데이터는 CRUD와 함께 실시간으로 저장하는 것이 일반적이다. 그러나 프로젝트에서 리뷰 데이터를 Logstash를 통해 저장하는 방식을 선택하면서, MySQL에서 변경되는 데이터를 엘라스틱 서치와 어떻게 동기화할 것인지에 대한 고민이 필요했다.

 

2. 문제 원인

  • 현재 코드에서 리뷰 데이터는 특정 상품의 감성 분석을 위해서만 사용된다.
  • 리뷰 데이터는 실시간 갱신이 필요하지 않다. 주기적으로 감성 분석이 필요한 순간에만 동기화하면 된다.
  • 제품(Product)의 경우 사용자 요청이 자주 발생하므로, 데이터가 변경될 때마다 갱신해야 한다. 그러나 리뷰 데이터는 인기 상품을 나열하는 특정 주기(예: 하루 한 번 갱신)마다 업데이트하면 충분하다.
  • 따라서 MySQL에서 변경될 때마다 엘라스틱 서치에 동기화할 필요 없이, 정해진 주기에 맞춰 동기화하는 방식이 더 적합했다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
CRUD 방식으로 실시간 동기화 MySQL에서 변경될 때마다 Elasticsearch 갱신 데이터 최신성 유지 불필요한 연산 증가, 리소스 낭비
Logstash를 이용한 주기적 동기화 정해진 주기에만 동기화 수행 리소스 절약, 성능 최적화 실시간 반영 불가
Kafka 등 이벤트 기반 처리 변경 이벤트가 발생할 때만 동기화 최신성 유지, 비동기 처리 가능 추가 인프라 필요

 

4. 문제 해결: Logstash 기반 주기적 동기화 적용

(1) 리뷰 데이터는 주기적 갱신이 적합

  • 인기 상품 추천을 위해 리뷰 데이터를 하루 한 번 감성 분석하는 구조이므로, MySQL에서 변경될 때마다 갱신할 필요가 없음.
  • 불필요한 연산을 줄이고, 엘라스틱 서치의 리소스를 절약할 수 있음.
  • 예를 들어, 인기 상품을 하루에 한 번 갱신한다면, 리뷰 데이터도 하루에 한 번 동기화하면 충분하다.

(2) Logstash의 데이터 삭제 처리 문제 해결

  • Logstash는 기본적으로 데이터를 추가하는 방식으로 동작하기 때문에, MySQL에서 삭제된 데이터를 반영할 수 없음.
  • 하지만 현재 프로젝트에서는 소프트 딜리트(Soft Delete) 방식을 사용하여 문제를 해결함.
  • MySQL에서 리뷰 데이터를 삭제할 때, 실제로 데이터를 삭제하는 것이 아니라 is_deleted 플래그를 업데이트하는 방식.
  • Logstash가 MySQL에서 데이터를 불러올 때, is_deleted 값이 반영되므로 정합성이 유지됨.

하드 딜리트 방식이었다면? MySQL에서 데이터가 삭제되면, Logstash는 해당 데이터를 감지하지 못해 엘라스틱 서치에 남아있게 됨. 그러나 소프트 딜리트 방식을 사용하면, MySQL에서 삭제된 데이터도 동기화 가능.

 

5. 결론

  • 리뷰 데이터는 CRUD 기반 실시간 갱신이 필요하지 않으며, 주기적인 감성 분석 시점에만 동기화하는 것이 가장 효율적이다.
  • Logstash 기반으로 리뷰 데이터를 동기화하되, 소프트 딜리트를 활용해 데이터 정합성을 유지한다.
  • 이 방식은 불필요한 연산을 줄이고, 엘라스틱 서치의 리소스 사용을 최적화하는 데 효과적이다.

엘라스틱 서치(Elasticsearch)와 트랜잭션 락 문제 해결

1. 문제 발생

내가 담당한 상품과 주문 데이터는 정합성을 유지하기 위해 락이 필요했다. 기존에는 MySQL만 사용했기 때문에 MySQL의 트랜잭션 락을 활용하면 됐다. 하지만 추가로 엘라스틱 서치를 검색 엔진으로 도입하면서, 엘라스틱 서치의 데이터 동기화 과정에서 락이 필요한 문제가 발생했다.

 

2. 문제 원인

  • MySQL은 트랜잭션을 지원하지만, 엘라스틱 서치는 ACID 트랜잭션을 지원하지 않는다.
  • MySQL에서 데이터를 업데이트한 후, 엘라스틱 서치에도 동일한 데이터를 업데이트해야 하는데, 이 과정에서 동기화 지연이 발생할 수 있다.
  • 만약 MySQL에는 데이터가 업데이트되었지만, 엘라스틱 서치에 즉시 반영되지 않으면 데이터 불일치(Inconsistency) 문제가 발생할 수 있다.
  • 이를 방지하기 위해서는 MySQL의 트랜잭션에 엘라스틱 서치의 CRUD 작업도 포함하는 방식이 필요했다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
MySQL 트랜잭션만 사용 MySQL에서만 락을 걸고 엘라스틱 서치는 비동기 처리 구현이 간단함 데이터 일관성 문제 발생 가능
엘라스틱 서치 락 구현 엘라스틱 서치 내에서 락을 설정하여 트랜잭션처럼 동작 검색 엔진 단에서 동기화 가능 성능 저하 및 트랜잭션 완전 보장이 어려움
MySQL 트랜잭션 내에 엘라스틱 서치 CRUD 포함 MySQL 트랜잭션이 진행될 때 엘라스틱 서치도 동기화 수행 데이터 정합성 유지 가능 일부 요청 속도 저하 가능

 

4. 문제 해결: MySQL 트랜잭션 락에 엘라스틱 서치 CRUD 포함

가장 안정적인 방법은 MySQL 트랜잭션 내에서 엘라스틱 서치의 CRUD(Create, Read, Update, Delete) 작업도 포함시키는 것이었다.

  • MySQL에서 트랜잭션을 시작하고, 해당 데이터에 대한 변경 사항을 반영하는 동안 엘라스틱 서치에도 동시에 업데이트 수행
  • MySQL에서 커밋이 완료되면, 엘라스틱 서치에서도 색인을 갱신하여 데이터 일관성을 유지
  • 트랜잭션이 롤백되면, 엘라스틱 서치 업데이트도 취소하도록 구현
  • 이벤트 기반 동기화를 추가하여, 변경된 데이터를 트리거로 활용해 엘라스틱 서치를 최신 상태로 유지

결론: MySQL과 엘라스틱 서치의 동기화를 위해 MySQL 트랜잭션 내부에서 엘라스틱 서치의 CRUD 작업을 함께 수행하는 방식을 선택했다. 이를 통해 데이터 일관성을 유지하면서도 성능 저하를 최소화할 수 있다.

실상 엘라스틱 서치에 자체적으로 존재하는 보안은 SECURE GURD만 있다고 무방하다.

 

그 외에 존재하는 LDAP, OAuth, SAML과 같이 대부분의 기업이 자체적으로 사용하는 인증 시스템을 도입하는 경우가 많다

[실제로 현재 엘라스틱 서치 최신 버전인 8.x을 보면 이런 점을 의식한 것인지 보안을 강제하는 경우도 생겼다.]

 

실상 보안의 종류가 적은 편이라 이유를 찾기 애매하지만 굳이 이유가 붙을 만한 요소는 SSL 정도가 있을 것이다. SSL/TSL은 흔히 데이터 전송 보호 및 무결성을 보장하기 위해서 존재한다. 엘라스틱 서치는 분산 환경으로 보통 구성되고 노드간의 통신이 많은 편이다. 데이터가 자주 왕래하는 만큼 데이터 네트워크 통신의 보안이 중요해 진 것이다.

 

Q. 하지만 VPN과 방화벽도 네트워크 보안을 수행해 줄 수 있을 텐데 굳이 SSL/TLS를 사용한 이유가 있는가?

A. 있다. VRN의 경우 네트워크 트래픽을 보호하는 것은 맞지만, 엘라스틱 서치 내부 노드간 트래픽 보호가 안된다. 방화벽은 특정 IP만 허용하지만 네트워크 내부 공격(내부 직원, 관리자, 감염된 내부시스템에 의한 공격)에 취약한 점은 마찬가지이다.

 

왜 SSL은 내부 공격에도 강한가?

더보기

🔍 SSL/TLS가 내부 공격을 방어하는 방식

VPN과 방화벽이 네트워크 보안을 강화해도, Elasticsearch 내부 노드 간 통신을 보호하지 못하는 문제가 있습니다.

SSL/TLS는 이러한 내부 공격을 방어하는 핵심 역할을 합니다.


1️⃣ 내부 공격(Insider Attack)이란?

VPN과 방화벽만 사용하면 발생할 수 있는 내부 공격

  • VPN은 외부 트래픽을 암호화하지만, 내부 트래픽은 보호하지 않음
  • 방화벽은 외부 접근을 차단하지만, 내부 공격(관리자, 직원, 내부 감염된 시스템)에는 취약함

🔻 내부 공격의 예시

  1. 내부 관리자가 네트워크에서 Elasticsearch 데이터 패킷을 가로채서 조회
  2. 감염된 내부 시스템(악성코드에 감염된 서버)이 네트워크에서 통신을 가로채고 데이터 유출
  3. 권한이 없는 직원이 Elasticsearch 트래픽을 감청하여 고객 정보를 탈취

VPN과 방화벽만으로는 위 공격을 방어할 수 없음!

Elasticsearch 내부 노드 간 트래픽도 안전하게 암호화해야 함


2️⃣ SSL/TLS가 내부 공격을 방어하는 방법

SSL/TLS는 Elasticsearch 내부 노드 간 통신을 암호화하여 데이터를 보호합니다.

🔹 📌 SSL/TLS의 주요 보안 기능

기능 설명
1. 데이터 암호화 (Encryption) - 노드 간 트래픽을 암호화하여 패킷 감청을 방어- 관리자가 네트워크를 감청하더라도 내용을 볼 수 없음
2. 무결성 보호 (Integrity Protection) - 트래픽이 **중간에서 변조되는 것(Man-in-the-Middle Attack, MITM)**을 방지
3. 인증(Authentication) - 서버와 클라이언트가 신뢰할 수 있는 인증서로만 통신- 공격자가 가짜 Elasticsearch 노드를 만들어도 접근 불가능

3️⃣ 예제: VPN/방화벽과 SSL 적용 차이

🚨 [방화벽 & VPN만 사용한 경우]

✅ 방화벽: 특정 IP만 허용

✅ VPN: 외부에서 내부로 오는 트래픽은 보호

내부 네트워크 공격에 취약

Elasticsearch 노드 간 통신 감청 가능

➡ 내부 직원이 네트워크 스니핑(패킷 감청) 도구(예: Wireshark)로 데이터를 가로챌 수 있음!


🛡️ [SSL/TLS를 적용한 경우]

Elasticsearch 노드 간 트래픽 암호화

내부 감청 및 변조 방지

MITM(중간자 공격) 방어

패킷 감청을 시도해도 암호화되어 해독 불가능

➡ 내부 공격자가 패킷을 가로채더라도 내용을 볼 수 없음!


4️⃣ 결론: SSL/TLS는 내부 네트워크 보안의 마지막 방어선

  • VPN, 방화벽만으로는 내부 네트워크 공격을 완벽히 방어할 수 없음
  • SSL/TLS는 노드 간 트래픽을 암호화하여 내부 패킷 감청 및 변조를 방어
  • Elasticsearch 보안의 필수 요소로 SSL/TLS 적용이 권장됨!

💡 즉, 방화벽과 VPN은 외부 위협을 막지만, SSL/TLS는 내부 공격을 방어하는 역할을 함! 🚀

위의 접은글의 내용 대로 사실 다양한 이유가 있지만, 가장 큰 이유는 SSL/TLS가 보편적인 데이터 전송 보안에 해당하는 것이 큰 이유이다. 많은 공인된 기관이 인증한 보안 표준인 점이 실상 큰 사용에 이유로서 알려져 있다.

실제로 엘라스틱 서치에 적용 가능한 보안은 한정적이기에, 다음의 보안들이 추가되었다.

  1. SSL/TLS 적용 = 데이터 전송 암호화
  2. 사용자 역할별 인증 활성화 RBAC = 역할별 인덱스 접근 제한
  3. Audit Logging(감사 로깅) = 접근자, 데이터등을 감시

사실 4번의 경우 logback을 사용해서 로그 데이터를 이미 저장하고 있는데 왜 굳이 필요하냐라고 할 수 있는데, logback에서 나오는 로그는 스프링 애플리케이션의 로그만 저장된다.

 

엘라스틱 서치의 보안에 해당하는 로그 (인증 실패, 접근 차단, 역할 변경, 수십번 로그인 시도, 계정 마다의 행동 기록)의 경우 logbackd으로는 당연히 저장이 안된다. 이를 위해서 Audit Logging 설정이 필요하다.

 

엘라스틱 서치(Elasticsearch)와 MySQL 데이터 저장 방식 비교

1. 문제 발생

기본적으로 MySQL에 데이터를 저장하는데, 동일한 데이터를 엘라스틱 서치에도 전부 저장해야 하는지에 대한 고민이 발생했다. 데이터가 중복 저장되면 시스템 부하가 증가할 수 있으며, 관리 복잡성이 높아질 수 있다는 판단과 어차피 백업의 기능으로 보면 되는거 아닌가 라는 판단 2개가 상충하는 상황이였다.

 

2. 문제 원인

  • MySQL은 데이터 저장 및 관리가 주된 역할이지만, 엘라스틱 서치는 검색 최적화에 초점이 맞춰진 데이터 저장소다.
  • MySQL에 저장된 데이터를 그대로 엘라스틱 서치에 저장하면 중복 저장 문제가 발생하여 저장 공간 낭비데이터 동기화 비용 증가 등의 문제가 생길 수 있다.
  • 엘라스틱 서치의 강점은 빠른 검색인데, 모든 데이터를 저장하는 것은 불필요한 리소스 낭비가 될 수 있다.

 

3. 문제 해결책 수립

해결 방법 비교

해결 방법 설명 장점 단점
모든 데이터 저장 MySQL과 동일한 데이터를 엘라스틱 서치에도 저장 데이터 일관성 유지 저장 공간 낭비, 동기화 부담 증가
검색에 필요한 데이터만 저장 검색이 필요한 필드만 엘라스틱 서치에 저장 빠른 검색 속도, 효율적인 리소스 활용 일부 데이터는 MySQL에서 조회해야 함
캐싱 레이어 활용 Redis 등의 캐시를 사용하여 MySQL과 엘라스틱 서치 간 부하를 줄임 데이터 접근 속도 향상 추가적인 인프라 운영 필요

 

4. 문제 해결: 검색에 필요한 데이터만 저장

엘라스틱 서치에는 검색에 필요한 정보만 저장하는 것이 가장 효율적인 해결책이다.

  • 불필요한 데이터 저장을 최소화하여 시스템 리소스를 절약할 수 있음
  • 검색 속도를 최적화하고, 필요한 데이터만 색인하여 검색 효율을 높일 수 있음
  • 데이터 동기화 부담을 줄여 유지보수 비용을 절감할 수 있음
  • MySQL과의 역할 분리를 명확하게 하여 검색 및 저장의 목적을 최적화할 수 있음
  • MySQL도 자체적인 스냅샷 혹은 백업이 존재야한다.

결론: MySQL과 엘라스틱 서치는 목적이 다르다. 따라서 모든 데이터를 중복 저장하는 것이 아니라, 검색이 필요한 데이터만 엘라스틱 서치에 저장하는 것이 가장 효율적인 방식이다.

 

아래 정리는 백엔드 면접간단히 기억하고 설명하기 좋은 형태로 작성되었습니다. 각 키워드마다 핵심 요약특징장단점비교(대안/차이점)연계 질문 & 간단 답변 예시 순으로 정리하였고, 실제 현업 경험이 있으면 그 예시를 더해주시면 좋습니다.


1. 데이터베이스 (RDB vs NoSQL)

  • 핵심 요약
    • RDB(Relational Database): 테이블 형태, SQL 사용, 정형화된 스키마, ACID 보장
    • NoSQL: 문서/키-값/컬럼/그래프 등 다양한 모델, 스키마 유연
  • 특징
    • RDB: 정교한 JOIN, 강력한 트랜잭션
    • NoSQL: 수평 확장 쉬움, 높은 성능(특정 케이스), 스키마 유연
  • 장단점
    • RDB 장점: 데이터 무결성·일관성 보장, 복잡한 쿼리 지원
    • RDB 단점: 수직 확장 의존(Scale-up), 유연성 낮음
    • NoSQL 장점: 대규모 트래픽 처리에 유리, 스키마 변경이 자유롭고 빠름
    • NoSQL 단점: JOIN이 어려움(또는 미지원), 트랜잭션 일관성이 약함(Eventual Consistency)
  • 비교 (대안/차이점)
    • RDB vs NoSQL:
      • 정합성/트랜잭션이 중요 → RDB 적합
      • 유연한 스키마 & 대규모 확장 필요 → NoSQL 적합
  • 연계 질문 & 간단 답변 예시
    1. Q: "NoSQL에서 트랜잭션을 보장하려면 어떻게 해야 하나요?"
      A: 몽고DB의 경우 멀티 도큐먼트 트랜잭션 지원(4.0+), 하지만 RDB만큼은 아님. SAGA 패턴 등을 도입하기도 함.
    2. Q: "RDB에서 대규모 트래픽을 처리하려면?"
      A: 샤딩, Replication, Connection Pool 튜닝 등으로 대응. 필요시 NoSQL로 일부 기능 분산.

2. RESTful API

  • 핵심 요약
    • HTTP 메서드(GET, POST, PUT, DELETE)와 리소스 중심의 URI 설계
  • 특징
    • 클라이언트-서버 구조 명확
    • 무상태성(Stateless)으로 확장성 높음
  • 장단점
    • 장점: 사용이 쉽고 범용적, 캐싱 가능, 확장성 우수
    • 단점: Over-fetching / Under-fetching 문제, 실시간 양방향 통신에 비효율적
  • 비교 (대안/차이점)
    • GraphQL: 필요한 데이터만 요청 가능, 단일 엔드포인트
    • gRPC: HTTP/2 기반 바이너리 프로토콜, 낮은 지연시간
  • 연계 질문 & 간단 답변 예시
    1. Q: "RESTful에서 상태를 어떻게 관리하나요?"
      A: 쿠키/세션/토큰(JWT) 기반 인증으로 관리. API 자체는 무상태 유지.
    2. Q: "REST API가 Over-fetching 문제를 일으킨다면 어떻게 해결?"
      A: GraphQL 도입, API 쪼개기, 혹은 필드를 동적으로 선택할 수 있는 기능 제공 등.

3. GraphQL

  • 핵심 요약
    • 클라이언트가 필요한 데이터만 지정해서 요청하는 쿼리 언어
  • 특징
    • 단일 엔드포인트 /graphql
    • 스키마 정의로 정확한 타입 보장
  • 장단점
    • 장점: Over/Under-fetching 해결, 강력한 타입 시스템
    • 단점: 서버 캐싱 복잡, 학습 곡선 존재
  • 비교 (대안/차이점)
    • RESTful API: 여러 엔드포인트, 단순 구조
    • GraphQL: 단일 엔드포인트로 유연한 데이터 요청
  • 연계 질문 & 간단 답변 예시
    1. Q: "GraphQL에서 캐싱은 어떻게 처리하나요?"
      A: 주로 클라이언트 레벨에서 캐싱(Apollo Client 등). 서버 캐싱은 REST보다 복잡.
    2. Q: "GraphQL로 파일 업로드는 어떻게 하나요?"
      A: Mutation을 사용하거나, 별도 REST 엔드포인트로 처리 후 URL만 GraphQL로 전달.

4. Spring Boot

  • 핵심 요약
    • 스프링 프레임워크를 간편하게 시작할 수 있는 자동 설정 + 내장 WAS 제공
  • 특징
    • 스타터(Starter) 의존성, 내장 Tomcat, 설정 최소화
  • 장단점
    • 장점: 빠른 개발 & 배포, 일관된 구조
    • 단점: 의존성 무거움, 커스터마이징 복잡
  • 비교 (대안/차이점)
    • Spring Boot vs Node.js(Express): 자바 생태계 vs 자바스크립트 생태계, 동기 vs 비동기 중심
    • Spring Boot vs Quarkus/Micronaut: 경량화 프레임워크
  • 연계 질문 & 간단 답변 예시
    1. Q: "Spring Boot에서 내장 톰캣 대신 다른 서버를 쓸 수 있나요?"
      A: 예. spring-boot-starter-jetty나 undertow 등 교체 가능.
    2. Q: "스프링 부트에서 설정 오버라이딩은 어떻게?"
      A: application.properties/yaml 혹은 프로파일 별 설정 사용.

5. Spring Security

  • 핵심 요약
    • 스프링 기반의 인증/인가 프레임워크
  • 특징
    • Filter 체인 구조, 다양한 인증 방식(JWT, OAuth2, Basic Auth 등) 지원
  • 장단점
    • 장점: 강력하고 유연한 보안, 스프링과 밀접 통합
    • 단점: 설정 복잡도 높음, 학습 곡선
  • 비교 (대안/차이점)
    • 직접 JWT 필터 구현 vs Spring Security Filter 체인 사용
    • OAuth 라이브러리 (Passport.js 등)와 비교
  • 연계 질문 & 간단 답변 예시
    1. Q: "Spring Security에서 필터 순서를 제어하는 방법은?"
      A: @Order 또는 SecurityFilterChain을 커스텀하여 순서 지정.
    2. Q: "JWT 토큰 만료 시 재발행 로직은 어떻게 구현?"
      A: Refresh Token 사용, 만료 시점에 재발행 엔드포인트 호출.

6. Docker & Kubernetes

  • 핵심 요약
    • Docker: 컨테이너 기술, 애플리케이션을 격리된 환경에서 실행
    • Kubernetes(K8s): 컨테이너 오케스트레이션 툴
  • 특징
    • Docker: 이미지로 환경 통일, CI/CD 연계 용이
    • K8s: Pod, Deployment, Service 등으로 확장성, 자동화
  • 장단점
    • Docker 장점: 경량 가상화, 이식성 높음
    • Docker 단점: 네트워크·스토리지 세팅 복잡
    • K8s 장점: 자동 스케일링, 롤링 업데이트
    • K8s 단점: 초기 설정·운영 난이도 높음
  • 비교 (대안/차이점)
    • Docker Compose vs Kubernetes (Compose는 단일 서버, K8s는 분산 운영)
    • 다른 오케스트레이션 툴: Nomad, Docker Swarm
  • 연계 질문 & 간단 답변 예시
    1. Q: "쿠버네티스에서 무중단 배포(롤링 업데이트)는 어떻게 동작?"
      A: Deployment가 새 버전의 Pod을 단계적으로 띄우고, 오래된 Pod을 점진적으로 종료.
    2. Q: "Dockerfile 최적화 방법?"
      A: Multi-stage build, 이미지 레이어 최소화, 불필요한 파일 제거.

7. Kafka

  • 핵심 요약
    • 분산 메시징 및 스트리밍 플랫폼, 로그 기반 저장
  • 특징
    • 높은 처리량, 다수의 Consumer Group 가능, 파티션 단위 병렬 처리
  • 장단점
    • 장점: 대규모 데이터 처리, 영구 저장(디스크)
    • 단점: 운영 복잡도 높음, 브로커/주키퍼 관리 필요
  • 비교 (대안/차이점)
    • RabbitMQ: 큐 기반, 메시지 지연 적고 라우팅 유연
    • Redis Pub/Sub: 인메모리, 메시지 영구 보관 X
  • 연계 질문 & 간단 답변 예시
    1. Q: "Kafka에서 At Least Once를 보장하려면?"
      A: acks=all, min.insync.replicas 설정, Consumer 수동 Commit.
    2. Q: "Topic 파티션 수 결정 기준?"
      A: 예상 소비량, 병렬 처리 수, 브로커 수 등에 따라 결정.

8. Redis

  • 핵심 요약
    • 인메모리 데이터베이스로 빠른 읽기/쓰기가 특징
  • 특징
    • Key-Value, Pub/Sub, Sorted Set 등 다양한 자료구조 제공
  • 장단점
    • 장점: 캐싱에 매우 유리, 실시간 처리 가능
    • 단점: 메모리 기반이라 데이터 유실 가능성, 영속성(AOF/RDB) 설정 필요
  • 비교 (대안/차이점)
    • Memcached: Key-Value만 지원, 구조 단순
    • Redis: 다양한 자료구조, Lua 스크립팅 등 확장성
  • 연계 질문 & 간단 답변 예시
    1. Q: "Redis에서 데이터 영속화 어떻게 보장?"
      A: RDB 스냅샷, AOF(Append Only File) 설정.
    2. Q: "Redis Cluster에서 샤딩은 어떻게 동작?"
      A: 해시 슬롯(Hash Slot) 기반 분산.

9. JPA & Hibernate

  • 핵심 요약
    • 자바 기반의 ORM(Object-Relational Mapping) 프레임워크
  • 특징
    • SQL 대신 **엔티티(Entity)**를 조작, JPQL 사용
  • 장단점
    • 장점: 생산성 향상, DB 변경 시 코드 수정 최소화
    • 단점: 복잡한 쿼리 최적화 어려움, Lazy 로딩 N+1 문제
  • 비교 (대안/차이점)
    • MyBatis: SQL 매퍼 중심, 쿼리 직접 작성
    • JDBC 직접 사용: 세밀한 제어 가능하지만 보일러플레이트 많음
  • 연계 질문 & 간단 답변 예시
    1. Q: "N+1 문제는 무엇이며 해결 방법은?"
      A: 연관관계 로딩 시 매번 추가 쿼리 발생. fetch join, EntityGraph, Batch Size등으로 최적화.
    2. Q: "Spring Data JPA는 어떻게 Repository를 생성?"
      A: 인터페이스 기반, JpaRepository<T, ID>를 상속하면 기본 CRUD 제공.

10. CI/CD (Jenkins, GitHub Actions)

  • 핵심 요약
    • 지속적 통합(Continuous Integration) & 지속적 배포(Continuous Deployment) 자동화 도구
  • 특징
    • 코드 푸시 → 자동 빌드 → 테스트 → 배포 파이프라인
  • 장단점
    • 장점: 빠른 피드백, 릴리스 주기 단축
    • 단점: 초기 설정 복잡, 환경 설정 관리 필요
  • 비교 (대안/차이점)
    • Jenkins: 자체 호스팅, 플러그인 풍부
    • GitHub Actions: GitHub에 통합, YAML 기반
  • 연계 질문 & 간단 답변 예시
    1. Q: "CI 파이프라인 구성 시 가장 중요한 고려사항?"
      A: 빌드 속도, 테스트 안정성, 환경 일관성.
    2. Q: "CD 시점(Deploy vs Delivery) 차이는?"
      A: Delivery는 준비 상태, Deployment는 실제 프로덕션 반영.

11. 로그 & 모니터링 (ELK Stack, Prometheus)

  • 핵심 요약
    • ELK(Elasticsearch, Logstash, Kibana): 로그 수집·분석·시각화
    • Prometheus: 시계열 모니터링 & 알람 시스템
  • 특징
    • 실시간 로그 분석, 대시보드 구성, 장애 탐지
  • 장단점
    • 장점: 장애 신속 대응, 성능 최적화 데이터 확보
    • 단점: 구성 복잡, 리소스 사용 많음
  • 비교 (대안/차이점)
    • ELK vs Splunk: Splunk는 상용, UI/기능은 강력하지만 비용 큼
    • Prometheus vs Grafana: Grafana는 시각화, Prometheus는 데이터 수집
  • 연계 질문 & 간단 답변 예시
    1. Q: "Elasticsearch 인덱스 설계를 잘못하면 무슨 문제가 생기나요?"
      A: 검색 성능 저하, 스토리지 급증, 클러스터 불안정.
    2. Q: "Prometheus Alertmanager는 무엇을 하나요?"
      A: 임계값 초과 시 Slack, 이메일 등으로 알림을 보냄.

12. HTTP & WebSocket

  • 핵심 요약
    • HTTP: 요청/응답 기반 프로토콜
    • WebSocket: 양방향 실시간 통신 프로토콜
  • 특징
    • HTTP: Stateless, 단방향
    • WebSocket: 서버-클라이언트 간 지속 연결, 실시간 송수신
  • 장단점
    • HTTP 장점: 광범위한 표준, 캐싱 가능
    • HTTP 단점: 풀링/롱 폴링으로 실시간 구현 비효율
    • WebSocket 장점: 실시간 양방향, 이벤트 주도
    • WebSocket 단점: 연결 관리 복잡, 서버 리소스 부담
  • 비교 (대안/차이점)
    • HTTP SSE(Server-Sent Events): 서버→클라이언트 단방향 스트리밍
    • WebSocket: 양방향
  • 연계 질문 & 간단 답변 예시
    1. Q: "WebSocket 연결 수가 많을 때 서버 부하를 줄이는 방법?"
      A: 로드밸런싱, 클러스터링, 메시지 브로커 연계(Stomp 등).
    2. Q: "Stateless한 HTTP를 유지하면서 실시간 알림은 어떻게 구현?"
      A: WebSocket, SSE, 혹은 주기적 폴링 기법.

13. 트랜잭션 관리

  • 핵심 요약
    • DB 작업이 ACID 속성을 지키도록 묶어주는 메커니즘
  • 특징
    • Local Transaction vs Distributed Transaction(2PC, Saga 등)
  • 장단점
    • 장점: 데이터 무결성 보장
    • 단점: 성능 저하(락), 분산 트랜잭션은 복잡도 증가
  • 비교 (대안/차이점)
    • Local Transaction: 단일 DB 내에서 처리
    • Distributed Transaction: 여러 마이크로서비스/DB 연동 (Saga, 2PC)
  • 연계 질문 & 간단 답변 예시
    1. Q: "왜 2PC는 잘 안 쓰이고 Saga를 선호하나요?"
      A: 2PC는 락으로 인한 성능 저하 & 장애 시 복잡함, Saga는 서비스 간 보상 트랜잭션으로 유연.
    2. Q: "스프링에서 @Transactional의 전파(Propagation) 옵션은?"
      A: REQUIRED, REQUIRES_NEW, SUPPORTS 등 7가지. 상황에 맞게 사용.

14. Circuit Breaker (Resilience4j, Hystrix)

  • 핵심 요약
    • 장애가 발생한 서비스를 잠시 회로를 열어 트래픽을 차단하고 전체 장애 전파를 막는 패턴
  • 특징
    • ClosedOpenHalf-Open 상태 전이
    • 장애 지표(에러율 등)에 따라 회로를 열고 닫음
  • 장단점
    • 장점: 장애 확산 방지, 서버 보호
    • 단점: 잘못된 설정 시 정상 요청도 차단될 수 있음
  • 비교 (대안/차이점)
    • Hystrix(Netflix OSS) vs Resilience4j(더 가볍고 최신)
    • Bulkhead(격리), Rate Limiter도 유사한 보호 패턴
  • 연계 질문 & 간단 답변 예시
    1. Q: "Circuit Breaker가 Open 상태가 되었을 때 어떤 로직이 동작?"
      A: 폴백(Fallback) 로직 호출, 혹은 예외 반환. 일정 시간 후 Half-Open으로 전환.
    2. Q: "Circuit Breaker와 Retry는 어떻게 조합?"
      A: 필요 시 재시도( Retry ) + 서킷브레이커로 장애 완화. 설정 주의 필요(과도한 트래픽 발생 방지).

15. MSA (Microservices Architecture)

  • 핵심 요약
    • 기능별로 독립 배포/운영이 가능한 마이크로서비스 형태의 아키텍처
  • 특징
    • 각 서비스가 자체 DB, 독립된 라이프사이클
    • 서비스 간 통신(REST, gRPC, 메시지 브로커 등)
  • 장단점
    • 장점: 확장성, 독립 배포, Fault Isolation
    • 단점: 서비스 간 통합 복잡, 장애 추적 어려움, 운영 비용 증가
  • 비교 (대안/차이점)
    • Monolithic: 하나의 큰 애플리케이션, 배포/확장이 일괄적
    • MSA: 작은 단위로 분리, 각각 독립 운영
  • 연계 질문 & 간단 답변 예시
    1. Q: "MSA에서 데이터 일관성은 어떻게 맞추나요?"
      A: 분산 트랜잭션 대신 이벤트 소싱, Saga 패턴, 최종적 일관성 개념 적용.
    2. Q: "서비스가 너무 많이 쪼개지면 어떤 문제가 생기나요?"
      A: 서비스 간 의존성 복잡, 배포/운영 비용 급증, 개발·운영 인력 부족 현상.

정리 & 활용 팁

  • 면접 대비: 각 키워드를 문장 2~3개로 짧게 말할 수 있도록 암기하고, 필요 시 추가 상세를 붙이는 방식이 좋습니다.
  • 연계 질문: 실제 면접에서는 한 키워드만 물어보지 않고, “그럼 이 경우엔 어떻게 하죠?” 식으로 파생 질문이 많으니 위의 연계 질문들을 연습해 보시면 답변에 큰 도움이 됩니다.
  • 실무 경험 추가: 가능하면 “프로젝트에서 ~~로 구현했는데, ~~ 문제를 이렇게 해결했다”처럼 개인 경험을 연결하면 면접관의 호응을 얻기 좋습니다.

 

1. 문제 발생

Kafka 메시징 시스템을 운영하는 과정에서, 메시지를 딱 한 번만 정확히 전송하는 Exactly-Once 방식에서 최소 한 번 전송하는 At-Least-Once 방식으로 변경할 필요가 발생했다. 이 과정에서 성능과 데이터 정합성 사이의 균형을 맞추는 것이 중요한 과제가 되었다.

2. 원인 분석

2.1 Exactly-Once 방식의 문제점

  1. 성능 저하:
    • Exactly-Once 방식은 트랜잭션을 사용하여 메시지를 철저히 관리하기 때문에 네트워크 및 처리 속도가 느려짐.
    • Kafka의 Exactly-Once Processing은 모든 메시지를 한 번만 처리해야 하므로, 추가적인 오버헤드가 발생.
  2. 운영 복잡성 증가:
    • Exactly-Once 모드를 사용하려면 Kafka, 프로듀서, 컨슈머, 외부 데이터 저장소(RDBMS, NoSQL 등) 간의 정합성을 보장해야 하므로 설정과 유지보수가 복잡해짐.
    • 장애 발생 시 트랜잭션을 롤백해야 하는데, 이 과정에서 데이터 일관성을 유지하기 위한 추가적인 로직이 필요함.
  3. 트랜잭션 비용 증가:
    • Exactly-Once 메시징을 위해서는 Kafka의 트랜잭션 프로토콜을 활용해야 하며, 이는 일반적인 메시징보다 높은 리소스를 요구.
    • 병렬 처리를 제한할 수 있으며, 전체적인 시스템 응답 속도를 저하시킬 가능성이 있음.

2.2 At-Least-Once 방식의 장점

  1. 성능 개선:
    • 메시지를 최소 한 번 이상 보낼 수 있기 때문에 네트워크 및 시스템 부하가 줄어들며, 더 빠른 처리 속도를 보장.
    • 트랜잭션 오버헤드 없이 빠른 처리 가능.
  2. 운영이 단순해짐:
    • Exactly-Once 방식에 비해 설정이 간단하며, 장애 복구 시에도 전체 트랜잭션을 롤백하지 않고 개별 메시지를 기반으로 정합성을 관리 가능.
    • 중복 메시지가 발생할 수 있지만, 서비스 레이어에서 멱등성(idempotency)을 보장하면 문제 해결 가능.
  3. 확장성 증가:
    • At-Least-Once 방식은 다량의 메시지를 빠르게 처리할 수 있어, 높은 트래픽을 감당해야 하는 시스템에서 유리.
    • 클러스터 확장 시에도 성능 저하 없이 안정적인 운영 가능.

3. 해결책 수립

3.1 해결책 비교

해결책 장점 단점
Exactly-Once 메시징 데이터 정합성을 철저히 유지 성능 저하, 운영 복잡성 증가
At-Least-Once 메시징 + 멱등성 처리 성능 유지, 운영 간소화, 확장성 증가 중복 메시지 처리 필요

 

3.2 최적 해결책 선택

At-Least-Once 방식에서 멱등성 처리(idempotency) 를 추가하는 방식이 가장 현실적인 해결책으로 판단됨.

  • 선택 이유:
    • Exactly-Once 방식은 성능 저하 및 운영 복잡성이 크므로, 대량의 트래픽을 처리하는 환경에서는 비효율적.
    • At-Least-Once 방식에서는 메시지가 중복될 가능성이 있지만, 고유 ID(UUID) 기반 중복 방지, Redis 캐싱, 데이터베이스 중복 검사 등의 기법을 적용하면 데이터 정합성을 유지하면서도 성능을 확보할 수 있음.
    • 특히, 고속 처리가 필요한 마이크로서비스 환경에서는 At-Least-Once 방식이 더 유리함.

4. 결론

Kafka 운영 과정에서 Exactly-Once 방식에서 At-Least-Once 방식으로 변경한 이유는 성능 저하와 운영 복잡성을 줄이면서도 확장성을 확보하기 위함이었다. 중복 메시지를 방지하기 위해 멱등성 로직을 적용하여 데이터 정합성을 유지하는 것이 핵심 해결책이었다.

변경 전 방식 변경 후 방식 주요 이유
Exactly-Once At-Least-Once + 멱등성 처리 성능 최적화, 운영 간소화, 확장성 증가

Kafka 운영 시, 설정 최적화 및 모니터링을 병행하여 장애 발생 시 빠르게 대응하는 전략이 필요하다. At-Least-Once 방식은 중복 메시지 처리를 필요로 하지만, 적절한 멱등성 로직을 적용하면 성능과 데이터 정합성을 모두 만족할 수 있는 현실적인 대안이 된다.

1. 메시지 순서 보장 문제

1.1 문제 발생

Kafka는 기본적으로 파티션 단위로 메시지의 순서를 보장하지만, 다중 파티션을 사용할 경우 메시지 순서가 보장되지 않는 문제가 발생했다. 이로 인해 서비스의 일관성이 깨지고, 처리 순서가 중요한 비즈니스 로직에 혼란이 발생했다.

 

1.2 원인

  1. 다중 파티션 사용 시 순서가 보장되지 않음
    • Kafka는 메시지를 여러 개의 파티션에 분산 저장하며, 컨슈머가 다수일 경우 각 컨슈머가 다른 순서로 메시지를 소비할 수 있음
  2. 리밸런싱(Rebalancing) 과정에서 메시지 순서가 깨짐
    • 컨슈머 그룹이 리밸런싱될 경우 특정 컨슈머가 다른 파티션을 처리하게 되어 순서가 깨질 가능성이 존재

1.3 해결책 수립

  1. 단일 파티션 사용 : 순서를 절대적으로 보장하지만 확장성이 떨어짐
  2. Kafka Streams를 활용한 순서 재구성 : 운영 부담이 크고 개발이 복잡함
  3. 메시지 키를 활용하여 동일한 파티션으로 메시지 전송 : 순서를 유지하면서도 확장성이 뛰어남 (최적 해결책)

 

1.4 해결 방법 선택 및 이유

메시지 키를 활용하여 동일한 파티션으로 메시지를 전송

ProducerRecord<String, String> record = new ProducerRecord<>("order-topic", orderId, orderData);
producer.send(record);
  • 선택 이유: 동일한 키(Order ID 등)를 가진 메시지는 같은 파티션에 저장되어 순서가 유지되므로, 다중 파티션을 사용할 경우에도 일관성을 보장할 수 있음. 성능 저하를 최소화하면서도 확장성을 유지할 수 있는 가장 실용적인 방법.
  • 다른 방법과의 비교: 단일 파티션을 사용하는 방법은 절대적인 순서를 보장할 수 있으나, 성능 확장성이 제한되므로 현실적으로 적용이 어렵다. 반면, Kafka Streams를 이용한 순서 재구성 방식은 추가적인 개발 및 설정이 필요해 운영 부담이 크다.

2. 중복 메시지 처리 문제

2.1 문제 발생

Kafka는 기본적으로 At-Least-Once 메시징을 보장하기 때문에 컨슈머가 동일한 메시지를 여러 번 소비할 가능성이 발생했다. 이는 데이터의 중복 삽입, 리소스 낭비 및 트랜잭션 오류로 이어질 수 있다.

 

2.2 원인

  1. 컨슈머 오프셋 커밋 실패
    • 컨슈머가 메시지를 처리한 후 오프셋 커밋 전에 장애가 발생하면 동일한 메시지가 다시 처리될 가능성이 있음
  2. 프로듀서에서 동일한 메시지가 여러 번 전송될 가능성
    • 네트워크 장애 등으로 인해 프로듀서가 동일한 메시지를 여러 번 보낼 수 있음

2.3 해결책 수립

  1. Kafka의 Exactly-Once Processing 활용 : 중복 방지가 가능하지만 성능 부담이 큼
  2. Redis 또는 DB를 활용한 중복 방지 로직 추가 : 외부 스토리지가 필요하여 운영 비용 증가
  3. 멱등한 메시지 처리(Idempotent Consumer) 구현 : 트랜잭션을 단순하게 유지하면서도 중복 처리가 가능 (최적 해결책)

2.4 해결 방법 선택 및 이유

멱등한 메시지 처리(Idempotent Consumer) 구현

  • 선택 이유: 가장 일반적인 해결 방법으로, UUID 등의 고유한 ID를 활용해 중복 메시지를 무시함으로써 트랜잭션을 단순하게 유지할 수 있음. Kafka의 Exactly-Once Processing보다 성능 부담이 적고 설정이 간단하여 운영 비용이 낮아짐.
  • 다른 방법과의 비교: Kafka의 Exactly-Once Processing 모드는 중복 메시지 문제를 원천적으로 해결할 수 있으나, 성능 부담이 크고 설정이 복잡하여 운영에 부담이 된다. Redis 또는 데이터베이스를 활용한 중복 방지 방식은 단순하지만, 외부 스토리지를 필요로 하므로 유지 비용이 발생한다.

3. 결론

Kafka 운영 과정에서 발생한 메시지 순서 보장 및 중복 메시지 처리 문제를 트러블슈팅한 결과, 주요 해결 방법과 그 이유를 정리하면 다음과 같다.

문제점 원인 해결 방법 선택 이유
메시지 순서 보장 문제 다중 파티션 사용, 리밸런싱 발생 메시지 키 지정 확장성과 성능을 고려하여 일관성 유지 가능
중복 메시지 처리 문제 컨슈머 오프셋 커밋 실패, 중복 전송 멱등성 처리 설정이 간단하고 성능 부담이 적음

 

1. 문제 상황

서비스 간 비동기 메시징을 도입하려 할 때, Redis PUB/SUB, RabbitMQ, Kafka 중 어떤 메시지 브로커를 사용할지 고민해야 했다. 각각의 기술은 특정 용도에 강점을 가지고 있지만, 서비스 요구 사항에 따라 적절한 선택이 필요했다.

 

1.1 서비스 요구 사항

  1. At-Least-Once 메시지 보장: 메시지가 손실되지 않아야 함
  2. 구독형 메시징 지원: 하나의 이벤트를 여러 개의 소비자가 구독할 수 있어야 함
  3. 확장성과 내구성: 대량의 메시지를 안정적으로 처리할 수 있어야 함
  4. 클러스터링 및 장애 복구 가능성: 서비스가 확장되더라도 안정적으로 운영 가능해야 함

이를 기반으로 Redis PUB/SUB, RabbitMQ, Kafka를 비교한 결과, Kafka를 선택하게 되었다.


2. Redis PUB/SUB의 한계

Redis는 빠르고 간단한 구독(Publish-Subscribe) 모델을 제공하지만, 특정 요구 사항을 충족하기 어려웠다.

 

2.1 장점

  1. 빠른 메시징 속도: 메모리 기반이므로 지연이 거의 없음
  2. 간단한 구조: 설정이 쉽고 사용하기 간편함
  3. 실시간 처리 가능: 즉각적인 메시지 전송 가능

2.2 한계점

  1. 메시지 저장 기능 부족: 메시지가 소비되면 사라지므로, 메시지를 다시 받아야 할 경우 별도의 저장소가 필요함
  2. 신뢰성 부족: 서버가 재시작되면 메시지 손실 가능성 높음
  3. 확장성 부족: 클러스터링을 통한 메시지 분산이 어렵고, 트래픽이 커질수록 관리 부담 증가

Redis를 사용하면서 At-Least-Once 보장을 하려면 별도의 저장소(RDBMS, 파일 시스템 등)에 데이터를 보관해야 함


3. RabbitMQ의 한계

RabbitMQ는 전통적인 메시지 브로커로서 신뢰성 높은 메시징을 제공하지만, 특정 요구 사항을 만족하기 어려웠다.

 

3.1 장점

  1. 메시지 저장 가능: 디스크 기반으로 메시지를 보관 가능
  2. 복잡한 메시지 라우팅 지원: 여러 개의 Exchange 타입을 제공하여 유연한 메시지 전달 가능
  3. 트랜잭션 지원: 메시지를 처리하는 동안 실패하면 다시 처리 가능

3.2 한계점

  1. 구독형 메시징 부족: 하나의 메시지를 여러 개의 그룹이 구독하는 기능이 없음 (여러 그룹에서 동일한 메시지를 사용하려면 별도의 메시지 복제 필요)
  2. 확장성 문제: 클러스터링을 통해 확장 가능하지만, 대량 트래픽 처리에는 한계
  3. 메시지 처리량이 Kafka보다 낮음: 대량의 데이터 스트리밍에는 적합하지 않음

RabbitMQ는 메시지 저장과 트랜잭션을 보장하지만, 하나의 메시지를 여러 개의 소비자가 구독하는 구조가 필요할 경우 메시지를 여러 번 전송해야 함.


4. Kafka를 선택한 이유

Kafka는 대량의 메시지를 안정적으로 처리할 수 있는 분산형 메시지 브로커로, 높은 내구성과 확장성을 제공한다.

 

4.1 장점

  1. 메시지 저장 가능: 메시지를 로그 형태로 저장하여 재처리 가능
  2. 구독형 메시징 지원: 하나의 메시지를 여러 개의 컨슈머 그룹이 구독 가능
  3. 확장성 우수: 클러스터링을 통해 수평 확장 가능
  4. 대량 데이터 처리 가능: 초당 수백만 개의 메시지를 처리할 수 있음
  5. 장애 복구 가능: 데이터 복제(replication) 기능이 있어 장애 발생 시에도 데이터 유실 없음

4.2 한계점

  1. 구성 및 운영이 복잡: Kafka 클러스터를 관리하려면 추가적인 인프라 설정이 필요함
  2. 레이지 소비(Lazy Consumption) 특성: 실시간 처리보다는 대량의 데이터를 안정적으로 전달하는 데 적합
  3. AWS에서 비용 부담: Kafka를 AWS에서 운영할 경우 클러스터링 비용이 상당히 높음

최종 선택: Kafka는 대량의 메시지를 안정적으로 처리해야 하고, 여러 개의 서비스가 동일한 메시지를 구독해야 하는 경우 최적의 선택이었다. 특히 메시지가 일정 시간 보관된다는 점에서 MSA의 정합성 문제 해결에 큰 장점을 보였다.


5. Kafka 사용 결정 요약

메시지 브로커 구독형 메시징 메시지 저장 확장성 운영 비용
Redis PUB/SUB O X 제한적 낮음
RabbitMQ X O 중간 중간
Kafka O O 높음 높음

 

5.1 Kafka를 선택한 이유

  1. At-Least-Once 메시지 보장이 가능하고, 메시지를 저장할 수 있음
  2. 여러 컨슈머 그룹이 동일한 메시지를 구독할 수 있어 중복 메시지 전송이 필요 없음
  3. 대량 트래픽을 안정적으로 처리할 수 있는 확장성 제공

5.2 추가 고려사항

  1. Kafka를 AWS에서 클러스터링으로 운영할 경우 비용이 높아질 수 있음
  2. 작은 규모의 서비스에서는 Kafka 대신 RabbitMQ나 Redis를 사용하여 운영 부담을 줄일 수도 있음

결과적으로, Kafka는 대규모 분산 시스템에서 높은 확장성과 데이터 보존 기능이 필요한 경우 최적의 선택지였으며, 서비스의 요구 사항에 맞춰 RabbitMQ나 Redis와 병행하여 사용할 수도 있다.

 

더보기

Kafka가 RabbitMQRedis Pub/Sub보다 빠르고 대용량 처리에 적합한 이유는 설계 철학과 내부 아키텍처에서 차이가 납니다.
아래에 핵심 비교와 함께 Kafka가 왜 "빠르고 튼튼한 메시지 처리 시스템"인지 깔끔하게 정리해드릴게요.


🚀 Kafka가 더 빠른 이유 요약

항목 Kafka RabbitMQ Redis Pub/Sub
기반 구조 디스크 기반 로그 (Append-only) 메모리 기반 + 디스크 저장 (옵션) 순수 메모리 기반
처리 방식 Batch 전송, Zero-Copy, 비동기 전송 메시지 큐잉 후 소비자에게 푸시 Pub/Sub으로 단순 브로드캐스트
확장성 파티션 기반 수평 확장 (분산 처리) 큐 기반, 확장은 가능하나 상대적으로 어려움 클러스터링 가능하지만 분산 처리 설계 아님
내구성 디스크에 저장, 메시지 유실 없음 디스크 저장 설정 가능 기본적으로 휘발성, 메시지 유실 가능
처리량 (Throughput) 초당 수십~수백만 메시지 처리 가능 중간 수준 (적절한 구성 필요) 작고 빠르지만 지속성과 확장성 부족
메시지 소비 방식 Pull 기반, 컨슈머가 원하는 속도로 읽음 Push 기반, 소비자가 느리면 큐 적재됨 브로드캐스트 기반, 메시지 저장 안 됨

🔍 주요 기술적 차이 (좀 더 디테일하게)

✅ Kafka: 왜 빠른가?

  1. 디스크 기반 Append-Only 구조
    → 데이터는 순차적으로만 기록되며, 랜덤 I/O보다 훨씬 빠름.
    → 디스크를 효율적으로 사용하므로 수백 GB 이상 데이터도 OK.
  2. Zero-Copy 기술 사용
    → 메시지를 전송할 때, OS 커널 버퍼를 직접 활용해서 CPU 사용 없이 네트워크 전송.
    → Kafka가 초고속인 핵심 기술 중 하나.
  3. 배치 처리 + 압축 전송
    → 여러 메시지를 묶어서 한번에 전송, 압축으로 네트워크 사용 최적화.
  4. 분산 구조 (Partition + Broker)
    → 토픽을 여러 파티션으로 나눠 병렬 처리 → 무한 확장 가능.

❗ RabbitMQ와 Redis는 왜 느릴 수 있을까?

🐰 RabbitMQ

  • AMQP 기반으로 메시징 규약이 더 정교하지만, 무겁고 유연함이 있음.
  • Push 기반이라 소비자가 느리면 큐에 메시지가 쌓이고 병목 발생.
  • 메시지 보존, 라우팅, 보안 설정 등은 다양하지만, 고속 처리보다는 안정적 메시징에 초점.

🧠 Redis Pub/Sub

  • 단순한 메모리 기반 브로드캐스트 방식.
  • 메시지를 publish할 때 구독 중인 클라이언트에게 바로 전달.
  • 저장하지 않기 때문에 유실 위험 높고, 스케일링 어려움.
  • 초고속이긴 하지만 신뢰성과 유연성이 낮음, 실시간 로그나 임시 알림 등에 적합.

🎯 언제 Kafka를 쓰면 좋은가?

  • 수십만 건 이상 데이터를 실시간으로 안정적이고 빠르게 처리하고 싶을 때
  • 로그 수집, 스트리밍, 빅데이터 파이프라인, 이벤트 중심 아키텍처 등
  • 시스템 간 비동기 연동 + 메시지 유실 방지가 중요한 경우

💡 요약 정리 한 줄씩!

  • Kafka: 빅데이터용 초고속 트럭 (순차적, 대용량, 튼튼함)
  • RabbitMQ: 스마트한 우편집중국 (메시지 라우팅, 신중한 전달)
  • Redis Pub/Sub: 무전기 (빠르지만 저장 안 되고, 즉시 전달만)

 

1. 대량 데이터 처리의 중요성

Elasticsearch는 대량의 데이터를 빠르게 검색하고 분석할 수 있는 분산형 검색 엔진이지만, 적절한 데이터 처리 전략이 없으면 성능 저하와 클러스터 불안정이 발생할 수 있다. 특히 데이터 삽입(Bulk Insert), 데이터 파티셔닝, 시간 기반 인덱싱과 같은 전략을 활용하면 효율적인 데이터 처리가 가능하다.


2. 대량 데이터 삽입(Bulk Insert)

Elasticsearch는 개별 문서를 하나씩 삽입하는 방식보다 **벌크 API(Bulk API)**를 활용하여 여러 개의 문서를 한 번에 삽입하는 것이 훨씬 효율적이다.

 

(1) Bulk API 활용

 

Bulk API는 한 번의 요청으로 여러 개의 문서를 삽입할 수 있도록 설계되었다. 이를 활용하면 네트워크 오버헤드를 줄이고, 인덱싱 성능을 극대화할 수 있다.

예제 코드 (Python Elasticsearch 라이브러리 사용)

from elasticsearch import Elasticsearch, helpers

es = Elasticsearch(["http://localhost:9200"])  # Elasticsearch 클러스터 연결

# 샘플 데이터 생성
data = [
    {"_index": "test-index", "_id": i, "_source": {"name": f"User {i}", "age": i % 50}}
    for i in range(100000)
]

# Bulk API를 이용한 데이터 삽입
helpers.bulk(es, data)

 

(2) Bulk Insert 시 고려해야 할 사항

  • 배치 크기 조절: 너무 큰 배치는 클러스터 부하를 초래할 수 있으므로, 적절한 크기(예: 5,000~10,000 문서)를 설정
  • CPU 및 메모리 부하 관리: 백그라운드에서 데이터를 점진적으로 삽입
  • 리프레시 간격 조정: refresh_interval을 조절하여 인덱싱 성능 향상 (refresh_interval=-1 설정 후 일괄 삽입 후 복원)

설정 예제

PUT test-index/_settings
{
  "index": {
    "refresh_interval": "-1"  
  }
}

벌크 삽입 후 복원

PUT test-index/_settings
{
  "index": {
    "refresh_interval": "1s"  
  }
}

3. 데이터 파티셔닝 (Shard & Index Design)

Elasticsearch는 샤딩(Sharding)과 인덱스 설계(Index Design)를 적절히 설정하면 대량 데이터 처리를 더욱 효율적으로 할 수 있다.

 

(1) 샤드 개수 조정

 

샤드는 Elasticsearch에서 데이터를 저장하는 기본 단위이며, 클러스터 성능에 큰 영향을 미친다.

  • 샤드 개수는 데이터 크기와 노드 수를 고려하여 설정
  • 너무 많은 샤드는 관리 오버헤드를 증가시킴
  • 샤드 크기는 10GB~50GB 정도가 적절함

샤드 개수 계산 공식

샤드 개수 = 예상 데이터 크기(GB) / 50GB

예를 들어, 예상 데이터 크기가 500GB이면, 샤드 개수는 500GB / 50GB = 10개

 

(2) 인덱스 설계 전략

  • 수직 파티셔닝: 서로 다른 유형의 데이터를 별도의 인덱스로 나누어 저장 (예: 로그 데이터, 사용자 데이터 분리)
  • 수평 파티셔닝: 동일한 유형의 데이터를 여러 개의 샤드에 분산 저장하여 부하 분산
  • Alias 활용: 여러 개의 인덱스를 가상으로 하나의 인덱스로 취급하여 데이터 검색 시 유연성 증가

Alias 예제

POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "log-2023-*",
        "alias": "logs"
      }
    }
  ]
}

4. 시간 기반 인덱싱(Time-Based Indexing)

대량의 데이터를 처리할 때, 시간 단위로 인덱스를 생성하여 관리하는 방식이 유용하다. 특히 로그 데이터, IoT 데이터, 이벤트 스트리밍 데이터에서 많이 활용된다. 다만 스프링과 같이 사용하는 경우 Alias로 관리할 필요가 있다.

 

(1) 시간 기반 인덱스 설계

  • 일일 인덱스 (daily index): logs-YYYY-MM-DD
  • 주간 인덱스 (weekly index): logs-YYYY-WW
  • 월간 인덱스 (monthly index): logs-YYYY-MM

예제: ELK 스택에서 로그 관리할 경우

PUT logs-2024-03-01
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 1
  }
}

 

(2) ILM (Index Lifecycle Management) 적용

시간이 지나면 데이터를 자동으로 이동시키는 정책을 설정하여 저장 비용을 절감할 수 있다.

ILM 정책 예제

PUT _ilm/policy/logs_policy
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "50GB",
            "max_age": "7d"
          }
        }
      },
      "warm": {
        "actions": {
          "allocate": {
            "include": { "_tier_preference": "warm" }
          }
        }
      },
      "cold": {
        "actions": {
          "allocate": {
            "include": { "_tier_preference": "cold" }
          }
        }
      }
    }
  }
}

5. 결론

  • 대량 데이터 삽입 시 Bulk API를 활용하여 네트워크 부하를 줄이고 성능을 극대화
  • 샤드 개수와 인덱스 설계를 최적화하여 데이터 처리 성능을 개선
  • ILM을 도입하여 오래된 데이터를 자동으로 관리하고 저장 비용 절감

1. 클러스터 구성 개요

Elasticsearch 클러스터는 확장성과 안정성을 고려하여 여러 개의 노드로 구성된다. 처음에는 단순히 노드를 종류별로 나열하는 방식으로 운영을 했지만, 마스터 노드의 경우 1개만 있을 경우 다운될 경우 엘라스틱 서치가 마비될 것을 대비하여 2개를 두었지만, 서로 마스터 노드 투표를 자신에게 해버려서 마스터 노드가 선출이 안되는 오류가 발생했다. 데이터 노드의 경우 대용량 데이터 처리가 되면서 단순히 모든 데이터를 동일한 방식으로 저장하는 것은 효율이 떨어졌고 중요도에 따른 카테고리화를 진행할 필요성이 생기기 시작했다. 데이터 노드 수가 증가됨에 따라 AWS의 ELB와 동일하게 로드벨런싱을 담당하는 요소의 필요성 또한 부각되기 시작하였다.

 

(1) 클러스터 노드 구성 및 이유

노드 유형 개수 역할 선정 이유
마스터 노드 3개 클러스터 상태 관리, 노드 헬스 체크, 샤드 배치 조정 홀수 개(3개)로 유지하여 선출 과정에서 네트워크 분할(Partition) 문제 방지, 고가용성 확보
코디네이터 노드 1개 클라이언트 요청 처리, 검색 및 집계 부하 분산 검색 부하가 높은 환경에서 별도의 코디네이터 노드가 있으면 부하 분산이 용이함
Hot 데이터 노드 3개 최신 데이터 저장, 빠른 검색 처리 최신 데이터를 빠르게 검색할 수 있도록 성능이 높은 노드에서 운영
Warm 데이터 노드 3개 중간 단계 데이터 저장, 검색 성능 중간 장기적으로 검색 빈도가 줄어드는 데이터를 따로 저장하여 리소스를 효율적으로 활용
Cold 데이터 노드 3개 오래된 데이터 저장, 저비용 스토리지 활용 자주 조회되지 않는 데이터를 비용이 낮은 스토리지에 저장하여 클러스터 운영 비용 절감

 

(2) 주요 설계 원칙

  • 마스터 노드는 데이터 노드 역할을 하지 않도록 분리하여 성능 저하 방지
  • 홀수 개(3개, 5개 등)로 운영하여 선출 과정에서 네트워크 분할(Partition) 문제 예방
  • Hot-Warm-Cold 구조를 활용하여 데이터 저장 비용 최적화
  • 코디네이터 노드를 통해 검색 부하를 분산하여 성능을 향상

2. 클러스터 운영 전략

클러스터 운영 시 고려해야 할 주요 요소는 노드 배치, 샤드 할당, 부하 분산이다. 각 요소를 적절히 관리하면 성능 저하와 장애를 방지할 수 있다.

 

(1) 마스터 노드의 역할 및 구성 이유

 

마스터 노드는 클러스터의 전반적인 상태를 관리하며, 노드 간의 통신과 샤드 배치를 조정한다. 3개의 마스터 노드를 운영하면 **선출 과정(Election Process)**에서 안정성을 확보할 수 있다.

  • 마스터 노드를 3개로 설정한 이유
    • Elasticsearch의 Split Brain 문제 방지
    • 홀수 개(3, 5 등)로 유지하면 선출 과정에서 안정성 증가
    • 장애 발생 시 빠른 마스터 선출 가능

 

(2) 데이터 노드(HWC 구조) 운영 및 구성 이유

 

데이터 노드는 Hot-Warm-Cold 구조로 분리하여 관리할 수 있다.

데이터 노드 유형 역할 및 특징 선정 이유
Hot 노드 최신 데이터 저장, 빠른 검색 수행 SSD 사용, 높은 CPU 성능 요구, 빠른 응답 속도 필요
Warm 노드 일정 시간이 지난 데이터 저장, 성능과 비용 균형 유지 검색 빈도가 낮아지므로 비용 절감을 위해 일반 HDD 사용 가능
Cold 노드 오래된 데이터 저장, 저비용 스토리지 활용 거의 조회되지 않는 데이터 보관을 위한 비용 최적화 목적

왜 HWC 구조를 사용했는가?

  • 검색 성능 최적화: 최근 데이터를 Hot 노드에 저장하여 빠르게 검색 가능
  • 비용 절감: 오래된 데이터는 저비용 스토리지로 이동하여 유지 비용 최소화
  • 확장성 확보: 데이터가 증가해도 클러스터가 원활하게 운영될 수 있도록 계층화하여 관리

3. 장애 대응 및 복구 전략

클러스터 장애는 다양한 원인으로 발생할 수 있으며, 미리 대비하는 것이 중요하다.

 

(1) 장애 유형 및 해결책

장애 유형 원인 해결책
마스터 노드 장애 네트워크 단절, 하드웨어 오류 3개 이상의 마스터 노드 유지, 빠른 리더 선출 설정
데이터 노드 과부하 대량의 검색 요청, 샤드 불균형 코디네이터 노드 추가, 샤드 리밸런싱 수행
디스크 공간 부족 과도한 데이터 저장 ILM(인덱스 수명 주기) 적용, 오래된 데이터 Cold 노드로 이동

4. 결론

  • 마스터 노드는 홀수 개(3개)로 설정하여 안정적인 클러스터 운영을 보장
  • Hot-Warm-Cold 구조를 도입하여 검색 성능과 비용을 최적화
  • 코디네이터 노드를 활용하여 검색 부하를 효과적으로 분산
  • 장애 대응 전략을 구축하여 클러스터 운영의 안정성을 유지

 

+ Recent posts