기술 검토 및 선정 - 100-hours-a-week/2-hertz-wiki GitHub Wiki
항목 | 기술/프레임워크 | 버전 |
---|---|---|
Backend Framework | Spring Boot | 3.4.5 |
Programming Language | Java | 21 (LTS) |
GC (Garbage Collector) | Shenandoah GC | Java 21 내장 |
RDBMS | MySQL | 8.0 |
NoSQL | Redis | 7.4.2 |
Local Cache | Caffeine | 3.1.8 |
Realtime Comm. | Socket.IO | 2.0.5 |
Message Broker | Kafka | 3.6.2 |
Kafka Metadata 관리 | ZooKeeper | 3.8.2 |
Push 알림 방식 | SSE (Server-Sent Events) | - |
- 자동 재연결
- 이벤트 ID로 메시지 중복 방지 | - 양방향 통신 가능
- 효율적인 실시간 인터랙션
- 다양한 데이터 형식 지원 | | ❌ 단점 | - 서버 → 클라이언트만 가능
- 대용량/빈번한 데이터 전송엔 부적합 | - 구현 복잡도 높음
- 커넥션 유지 비용 존재
- 재연결 로직 수동 구현 필요 |
-
서비스 특성
- 서버 → 클라이언트 방향의 일방향 알림 전송만 필요
- 복잡한 양방향 통신(WebSocket 수준)은 요구되지 않음
-
SSE의 장점
- HTTP 기반 프로토콜 → 구현 및 유지보수가 매우 간단
- 브라우저에서 자동 재연결 기본 지원
- 메시지 중복 방지 기능 기본 제공
- WebSocket에 비해 리소스 소비가 적음 → 서버에 부담을 덜 줌
- 수천 명 이상의 클라이언트를 효율적으로 처리 가능
-
WebSocket 대비 비교
- WebSocket은 양방향 통신에 적합하지만, 복잡한 세션 관리와 커넥션 유지 비용 존재
- 우리 서비스 요구사항(알림 푸시)에는 오버스펙
-
최종 선택: SSE (Server-Sent Events)
-
알림 푸시처럼 서버 → 클라이언트 일방향 통신에 최적
-
구현 간편성, 리소스 절감, 대규모 클라이언트 처리 측면 모두 만족
-
참고자료
항목 | 기술/프레임워크 | 버전 |
---|---|---|
Backend Framework | Spring Boot | 3.4.5 |
Programming Language | Java | 21 (LTS) |
GC (Garbage Collector) | Shenandoah GC | Java 21 내장 |
RDBMS | MySQL | 8.0 |
NoSQL | Redis | 7.4.2 |
Local Cache | Caffeine | 3.1.8 |
Realtime Comm. | Socket.IO | 2.0.5 |
Message Broker | Kafka | 3.6.2 |
Kafka Metadata 관리 | ZooKeeper | 3.8.2 |
Push 알림 방식 | SSE (Server-Sent Events) | - |
현재 대한민국에서의 백엔드 개발자 채용 시장은 Java 기반의 Spring Framework를 중심으로 형성되어 있습니다. 하지만 각 프로그래밍 언어가 얼마나 많이 사용되고 있는지를 통계적으로 보여주는 ‘TIOBE Index**'에 따르면,** 2025년 4월 기준 인기도 지표가 다음과 같습니다.

Java는 여전히 상위권 언어이지만 1위 또는 2위는 아닌 것을 확인할 수 있습니다.
우선 Java는 다음과 같은 핵심 강점을 갖고 있습니다.
- 운영체제 독립성: "Write Once, Run Anywhere"라는 슬로건처럼, Java는 JVM을 통해 다양한 운영체제에서 동일한 코드를 실행할 수 있어 플랫폼 호환성이 뛰어납니다.
- 자동 메모리 관리: Java는 가비지 컬렉터를 통해 불필요한 메모리를 자동으로 정리해, 개발자의 메모리 관리 부담을 줄이고 오류를 방지합니다.
- 동적 클래스 로딩: Java는 필요한 클래스만을 실행 시점에 메모리에 로딩하는 동적 로딩을 지원합니다. 이는 애플리케이션의 초기 로딩 속도를 개선하고, 모듈 단위의 유연한 확장이 가능하도록 도와줍니다.
하지만 이러한 기능들은 다른 언어에서도 어느 정도 제공되고 있으며, 기술적으로 Java만의 독점적인 장점은 아닙니다.
-
정부 정책 영향
- 대한민국 정부는 공공 정보시스템 개발 시 전자정부 표준프레임워크 사용을 사실상 권장하고 있음
- 해당 프레임워크는 Java 기반 Spring Framework 위에 구축
- 행정안전부 고시 제2021-3호에도 관련 권고 사항 명시
-
프로젝트 수주와 납품에서 유리
- 적용 여부가 프로젝트 인수 평가 기준에 반영
- Java(Spring) 스택을 사용하면 공공사업 수주에 유리
-
장기 운영 전제
- 공공 시스템은 보통 5~10년 이상 장기 운영을 전제로 함
- 생태계가 협소한 언어보다 국내 인프라와 인력 풀이 풍부한 Java 선호
-
민간 IT 기업으로의 확산
- 카카오, 네이버, 배달의민족 등 주요 민간 기업들도 Spring Framework 채택
- 안정성과 인력 수급의 이점을 고려한 선택
-
결론
- 대한민국에서는 공공기관과 민간기업 모두 Java 기반 Spring을 사실상의 기술 표준처럼 사용 중
-
Spring Boot란?
- Spring Framework의 복잡한 설정을 간소화한 실질적 표준 구현체
- 최근 Spring 개발은 대부분 Spring Boot 기반으로 진행
-
전자정부 표준프레임워크의 변화
- 과거: 순수 Spring MVC 기반
- 현재: Spring Boot를 내부적으로 사용하는 구조로 개선
-
산업 현황 반영
- 공공 프로젝트조차 Spring Boot 기반으로 전환 중
- 복잡한 설정 없이 빠른 개발 가능 → 생산성 향상
-
최종 선택: Java 기반 Spring Boot Framework
-
취업 경쟁력 확보
-
실무 적응력 향상
-
방대한 레퍼런스 및 커뮤니티 존재 → 팀 프로젝트 문제 해결에 유리
-
참고자료
https://yozm.wishket.com/magazine/detail/2910/
https://www.tiobe.com/tiobe-index/
Spring Boot의 1.x, 2.x, 3.x 버전의 핵심 차이점을 간단히 정리한 표는 아래와 같습니다.
구분 | Spring Boot 1.x | Spring Boot 2.x | Spring Boot 3.x |
---|---|---|---|
Java 지원 | Java 7 이상 | Java 8 이상 (Java 11 권장) | Java 17 이상 (최소 요구사항) |
Spring Framework | Spring Framework 4.x | Spring Framework 5.x | Spring Framework 6.x |
Servlet 지원 | Servlet 3.0 이상 | Servlet 3.1 이상 | Servlet 6.0 이상 |
기본 내장 서버 | Tomcat 8 기본 | Tomcat 9 기본 | Tomcat 10.1 (Jakarta EE 10 기반) |
Reactive 지원 | 미지원 | WebFlux 추가 ⭐️ | WebFlux 유지 |
Jakarta EE | javax.* 패키지 사용 | javax.* 유지 | *jakarta.로 전면 전환 ⭐️ |
보안 구성 | Spring Security 초기화 코드 필요 | Spring Security DSL 개선 | Spring Security DSL + 최소 필수 설정 유지 |
종속성 관리 |
spring-boot-starter-* 도입 |
BOM 개선 및 더 많은 Starter 제공 | deprecated 된 starter 정리 및 업데이트 |
마이그레이션 | 1 → 2: 상대적으로 쉬움 | 2 → 3: 패키지명 변경으로 대규모 수정 필요 ⭐️ | 주로 jakarta.* 호환성 이슈 |
-
Spring 지원 체계
- Spring은 VMware Tanzu Open Source Software Support를 따름
- 지원 기간
- Major version: 3년 지원
- Minor version: 최소 24개월 지원
- Spring은 release 주기가 짧고, 현재도 지속적으로 새로운 버전을 출시 중


-
Spring Boot 버전 수명 주기
- SpringBoot 공식 사이트 기준 (2025.04.22)
- OSS Support 지원 기간이 가장 긴 버전: 3.4.x
-
최종 선택: Spring Boot 3.4.5
-
2025년 4월 기준, 공식적으로 가장 최신이며 권장되는 안정 버전
-
장기 지원(3년)을 보장받을 수 있어 안정적인 프로젝트 운영 가능
-
참고자료
GC 종류 | 핵심 기능 | 특징 | 사용 적절 상황 |
---|---|---|---|
G1 GC (Garbage First) | |||
Java 7 | Region 기반 메모리 관리로 병렬 GC 가능 | - 메모리를 동일한 region으로 나누고, 이 영역들을 병렬로 정리하기 떄문에 STW 예측가능해져서 성능 향상 | - 대규모 서비스의 일반적인 실시간 처리 환경에 적합. |
- 안정성과 예측 가능한 GC 원할 때 | | ZGC (Z Garbage Collector) Java 11 | - stop-the-world 최소화
- STW 시간은 대부분 10밀리초 이내로 유지 | - GC 작업을 애플리케이션과 병렬로 수행
- CPU 리소스 많이 사용 | - 금융/게임/실시간 알림 등 지연 시간 최소화가 중요한 시스템 | | Shenandoah GC Java 12 | - stop-the-world 최소화
- 낮은 latency와 낮은 memory fragmentation | - region으로 나누는 것은 G1 GC와 동일하지만 대부분 GC 작업을 애플리케이션과 병렬로 수행
- CPU 리소스 많이 사용 | - 다수 동시 사용자 처리 / 대규모 서버에서의 실시간 반응 필요할 때 | | Parallel GC Java 1.3 | - Throughput 최적화 (CPU 자원을 GC에 집중)
- 멀티 스레드 GC로 빠른 전체 힙 정리 | Serial GC의 멀티스레드 버전 → STW(Stop-the-World) 방식을 사용하므로 일시 중지 시간이 발생 | - 백그라운드 작업 위주 또는 짧은 작업 시간 중요하지 않은 배치 시스템 | | Serial GC Java 1.2 | - 단일 스레드로 동작하는 가장 간단한 GC
- 작은 footprint, 간단한 구조 | 애플리케이션 실행을 일시 중지하고 메모리를 청소 | - 클라이언트 앱, 소형 서버, 임베디드 장치 등 리소스 제한 환경에 적합 |
- 최소 지연 시간이 필요 → ZGC / Shenandoah
- 실시간 + 안정성 → G1 GC (기본 선택으로 무난)
- 처리량 우선, 지연 허용 → Parallel GC
- 소규모 단일 앱 → Serial GC
- 실시간 채팅: latency(지연 시간)에 민감 → ZGC, Shenandoah
- 1:N 다수 사용자 참여: 빠른 메시지 브로드캐스팅 요구 → ZGC, Shenandoah
- 속보 뉴스 반응: 순간적으로 수천~수만 요청이 몰릴 수 있는 burst 트래픽 → ZGC, Shenandoa
항목 | ZGC | Shenandoah |
---|---|---|
설계 철학 ⭐️ | Pause를 수 밀리초 미만으로 줄이는 게 목표 | Pause 시간도 줄이면서 Throughput도 손상 안 되게 |
포인터 방식 | Colored Pointer (load barrier) | Brooks Pointer (write barrier + indirection) |
GC 알고리즘 | Region 기반, fully concurrent→ compact도 concurrent하게 수행 | Region 기반, compact도 concurrent→ write barrier 활용 |
쓰레드 부하 ⭐️ | 낮은 GC pause를 위해 애플리케이션 쓰레드에 더 많은 GC 부하 전가 | 애플리케이션 쓰레드 부하와 GC 쓰레드 부하 균형 |
Throughput 영향 ⭐️ | GC가 너무 적극적으로 pause를 줄이려다보니, CPU 리소스 사용 증가로 Throughput이 손해볼 수 있음 | Pause 줄이면서도 CPU 자원 활용을 효율적으로 설계해서 Throughput 감소폭이 적음 |
-
서비스 특성
- 1:1 및 1:N 실시간 채팅 기능 포함
- GC Stop-The-World(STW) pause 시간 최소화가 핵심 목표
-
ZGC 고려 사항
- Latency(지연 시간) 최소화에 매우 강점
- 단점: 트래픽 폭주 시 Throughput 저하 가능성 존재
-
Shenandoah GC 고려 사항
- Pause 시간을 짧게 유지하는 동시에
- Throughput(처리량) 감소폭이 적어 대규모 이벤트 처리에 안정적
- 메시지 브로커 기반 알림 시스템(튜닝 레포트 등)과 궁합이 좋음
-
최종 선택: Shenandoah GC
-
Latency와 Throughput의 균형을 가장 잘 충족
-
실시간성과 대규모 트래픽 처리를 모두 만족하는 현실적 선택
-
참고자료
https://smileostrich.tistory.com/entry/Inside-Garbage-CollectionShenandoah-ZGC

2025년 3월에 마지막으로 업데이트된 Oracle Java SE의 버전별 지원 로드맵 자료에 따르면, 현재 Java LTS 버전 중 긴 보장기간을 가진 버전은 Java 8, , Java 11, Java 17, Java 21, Java 25(아직 미출시)입니다.
버전 | 주요 기능/변화 |
---|---|
Java 8 (2014) | 1. Lambda |
- Stream API 제공
- Optional
- 새로운 날짜,시간 API 제공 (ex: LocalDateTime)
- 디폴트 메소드 (Default Methods) | | Java 11 (2018) | 1. String 기능 향상 - isBlank(), strip()
- File 기능 향상 - writeString(), readString()
- var 키워드 사용 가능
- 새로운 HTTP 클라이언트 API | | Java 17 (2021, LTS) | 1. Spring Boot 3.x.x 버전은 JDK 17 이상 부터 지원
- Switch에 대한 패턴 매칭 (Preview)
- recode class도입 | | Java 21 (2023, LTS) | 1. Spring Boot 3.2 부터 지원
- Virtual Threads (가상 스레드)
- Record Patterns (레코드 패턴)
- Sequenced Collections
- Improved Garbage Collectors (ZGC 및 Shenandoah 가비지 컬렉터의 성능이 개선 ) |
- 각 버전 별 특징 구체적인 설명
- Java 8
- Lambda(람다 표현식)
- 익명 함수를 간단히 표현하는 문법
- 보통 Functional Interface (추상 메서드가 1개인 인터페이스)와 함께 사용
- 왜 도입됐는가? → 익명 클래스의 불편함 해소, 코드 간결화
- 함수형 프로그래밍과의 관계? → Java에서도 일급 함수를 흉내낼 수 있게 됨
- Stream API
- 컬렉션을 함수형 스타일로 반복, 필터링, 매핑 등을 간단하게 처리할 수 있는 API
- Optional 클래스
- null 참조를 다루기 위한 컨테이너 클래스로, 보다 안전한 코드를 작성할 수 있습니다.
-
NullPointerException
방지에 도움 - vs Null-check :
NullPointerException
방지 못함, 조건문 중첩될 경우 가독성 떨어짐
- 새로운 날짜와 시간 API (java.time 패키지)
- 불변 객체(Immutable) 설계
-
명확한 단위별 클래스 구분:
LocalDate
,LocalTime
,LocalDateTime
,ZonedDateTime
- 가존
Date
와Calendar
단점-
Date
나Calendar
객체는 불변성 부족해서 쓰레드 안전하지 않음 -
Calendar.MONTH == 0
은 1월, 사람 입장에선 직관적이지 않음 -
Date
하나로 날짜 + 시간 + 타임존 포함. 의미 분리가 안 됨
-
- 디폴트 메소드 (Default Methods) : 인터페이스에 기본 메소드를 정의하여 기존 코드를 깨지 않고 기능을 추가할 수 있습니다.
- 인터페이스에 메서드 구현을 허용하여 기존 클래스들의 코드를 깨지 않고 기능을 추가 가능
- Lambda(람다 표현식)
- Java 11
- String 기능 향상 : String 클래스에 몇 가지 유용한 메소드가 추가
- isBlank(): 문자열이 공백인지 확인.
- strip(): 공백을 제거.
-
trim()
vsstrip()
차이? →strip()
은 유니코드 공백까지 제거,trim()
은 ASCII 공백만 제거
-
- repeat(int count): 문자열을 반복.
- File 기능 향상 : Files 클래스에 메소드를 추가하여 파일을 더 쉽게 읽고 쓸 수 있게 했음
- writeString(), readString()
- Java 11 전에는 어떻게 했을까?
→
BufferedReader
,InputStream
,StringBuilder
조합으로 복잡했음
- var 키워드 : 로컬 변수 타입 추론 키워드
- Hash와 같은 복잡한 제네릭 타입을 단순화할 때 사용한다
- 타입이 모호한 경우 사용하지 않는다
- 새로운 HTTP 클라이언트 API:
- 새 HTTP 클라이언트를 도입하여, HTTP/2 및 WebSocket을 지원 가능
- 비동기 요청도 가능
- 기존 HttpURLConnection의 문제점? → 코드가 장황하고, 설정이 복잡하며 유지보수 어려움
- String 기능 향상 : String 클래스에 몇 가지 유용한 메소드가 추가
- Java 17
- Sealed Classes
- 상속 가능한 클래스를 제한할 수 있음
- sealed class 도입 이유는? → 확장 가능한 클래스를 제한함으로써 보안성, 유지보수성, 예측 가능성 증가
- Switch에 대한 패턴 매칭 (Preview)
- 예를 들어:
switch
문에서 instanceof 체크 + 타입 캐스팅을 한 번에 처리
- 예를 들어:
- recode class 도입
-
record
는 불변 데이터 객체(Value Object)를 간편하게 정의 - 생성자, getter,
equals()
,hashCode()
,toString()
자동 생성 - DTO, 조회 결과, 설정 값 등에 자주 사용됨
-
- Strong Encapsulation by Default
- 강력한 캡슐화가 기본값으로 설정되어 모듈 간의 명시적 접근이 필요하게 됨
- Java 9부터 도입된 모듈 시스템(JPMS)의 연장선
- Java 17에서는 JDK 내부 API에 대한 강력한 캡슐화가 기본 적용
- 왜 캡슐화를 강화했나? → 내부 구현에 의존한 코드를 막고, 명확한 인터페이스 기반 설계 유도
- 만약 라이브러리나 프레임워크 사용 시 JDK 내부 API 의존하게 됨 → 오류 발생 가능성↑
- Sealed Classes
- Java 21
- Virtual Threads (가상 스레드)
- 가상 스레드는 경량 스레드로, 기존의 OS 스레드와는 별개로 Java 내부에서 관리
- 기존 Thread API를 그대로 사용하면서도 수천~수만 개의 동시성 처리 가능
- 왜 등장했는가? → 고성능 서버/비동기 환경 (예: 웹 서버, 마이크로서비스)에서 Thread exhaustion 문제 해결
- JVM 내부에서 관리되는 경량 스레드입니다. 운영체제의 리소스를 거의 사용하지 않기 때문에 수천 개의 스레드도 쉽게 생성 가능
- VM이 자체적으로 스케줄링을 수행하기 때문에 컨텍스트 스위칭이 매우 가볍고 효율적
- Record Patterns (레코드 패턴)
- 기존의
record
와switch pattern matching
을 결합한 문법 -
record
는 불변 객체임으로 안정적으로 패턴 매칭에 사용 가능 -
instanceof
에서 변수 추출까지 한 번에 가능 → 가독성, 유지보수성 증가 - 추후
switch
패턴 매칭과 함께 자주 활용됨
- 기존의
- Sequenced Collections
- 기존
List
,Set
,Map
인터페이스에 순서를 보장하는 새로운 API 추가
- 기존
- Improved Garbage Collectors (ZGC 및 Shenandoah 가비지 컬렉터의 성능이 개선 )
- ZGC (JEP 439): Pause time 1ms 이하, 초대용량 힙에서 성능 향상
- Shenandoah GC (JEP 438): Low-pause GC, 하드 리얼타임 요구되는 시스템에서 성능 개선
- Virtual Threads (가상 스레드)
- Java 8
-
Spring Boot 요구사항
- Spring Boot 3.4.4 버전은 Java 17 이상을 요구
-
Java 17 고려 사항
- 2021년 9월 출시, 3년간 검증된 안정적 LTS 버전
- 널리 사용되어 생태계가 매우 풍부하고 안정성 검증 완료
-
Java 21 고려 사항
- 2023년 9월 출시된 최신 LTS 버전
- Java 17의 기능을 모두 포함하면서 추가 기능 제공
- Virtual Threads(가상 스레드) 도입
- Shenandoah GC 성능 개선
- 향후 확장성과 장기 유지보수에 유리
-
서비스 특성과의 적합성
- 신규 프로젝트로서 장기적인 유지보수와 확장성 고려 필요
- 실시간 채팅, 알림 등 고동시성 처리 요구
- 수천 개의 동시 작업을 효율적으로 처리할 수 있는 Virtual Threads가 큰 장점
-
최종 선택: Java 21
-
최신 기능(Virtual Threads) 활용 가능
- 기존 쓰레드 모델보다 가볍고 수천 개의 작업을 효율적으로 처리
- 비동기 복잡성을 줄이며 고성능 서버 구성 가능
-
Shenandoah GC 성능 개선
-
장기적 유지보수와 확장성 모두 충족
-
참고자료
https://www.oracle.com/kr/java/technologies/java-se-support-roadmap.html
https://docs.spring.io/spring-boot/system-requirements.html?utm_source=chatgpt.com
항목 | PostgreSQL | Oracle | MySQL |
---|---|---|---|
라이선스 | 오픈소스 (PostgreSQL License, BSD) | 상용 (Oracle Proprietary) | 오픈소스 (GPL), 일부 상용 에디션 존재 |
플랫폼 지원 | Windows, macOS, Linux 등 | Windows, Linux, Unix 등 | Windows, macOS, Linux 등 |
ACID 준수 | ✅ 완전 지원 | ✅ 완전 지원 | ✅ InnoDB 사용 시 지원 |
확장성 | 사용자 정의 함수/타입/인덱스 등 가능 | 매우 높음 (PL/SQL 등 다양한 기능 포함) | 제한적 (확장은 있지만 제한됨) |
트랜잭션 지원 | ✅ MVCC 기반 | ✅ MVCC 기반 | ✅ (InnoDB 엔진 사용 시) |
스토어드 프로시저 | ✅ PL/pgSQL 등 지원 | ✅ PL/SQL | ✅ 지원 (BEGIN...END 문법 등) |
파티셔닝 기능 | ✅ 기본 제공 (Declarative Partitioning) | ✅ 매우 고급 기능 지원 | ✅ 일부 기능 제공 (버전 의존적) |
레플리케이션 | ✅ 기본 제공 (Streaming Replication) | ✅ 고급 레플리케이션 (Data Guard 등) | ✅ 기본 지원 (Replication, Group Replication) |
커뮤니티/지원 | 활발한 커뮤니티, 문서 풍부 | 기업 고객 중심, 공식 지원 필요 | 활발한 커뮤니티, 다양한 문서 존재 |
성능 | 복잡한 쿼리에서 우수 | 대용량 처리에 최적화 | 단순 쿼리/읽기 성능 우수 (InnoDB 기준) |
NoSQL 기능 | ✅ JSON, HStore 지원 | ✅ JSON 지원, 일부 Key-Value 처리 가능 | ✅ JSON 지원 (5.7 이상) |
대표 사용처 | 데이터 분석, GIS, 복잡한 웹서비스 등 | 엔터프라이즈급 ERP, 금융 시스템 | 중소규모 웹서비스, CMS 등 |
-
팀의 기술 스택 경험
- 팀원 모두 Java + Spring Boot 개발 경험 보유
- 주로 MySQL 데이터베이스를 사용한 경험 축적
-
현재 프로젝트 특성
- CRUD 중심 REST API 웹 서비스
- 빠른 스프린트 주기, 배포 및 운영까지 고려한 실무형 개발 환경
-
기술 선택 기준
- 부하 대응 및 성능 개선이 수시로 필요한 상황
- 학습 리스크를 최소화하고 안정적 백엔드 로직 구현에 집중 필요
-
PostgreSQL / Oracle 검토
- PostgreSQL: 기능은 강력하지만 학습 리스크 증가
- Oracle: 대규모 시스템에 최적이나 복잡도 및 비용 부담 큼
-
MySQL 장점
- 이미 익숙하고 풍부한 레퍼런스 존재
- 빠른 개발, 안정적 운영에 적합
- 실무 적응력 강화 및 서비스 완성도 향상에 유리
-
MySQL 버전 현황
- 현재 8.x 버전이 가장 널리 안정적으로 사용 중
-
버전 선택 고려사항
- Spring Boot + JPA 환경과 호환성 확보 필요
- 최신 버전은 의존성 충돌 가능성 존재
- MySQL 5.7은 2023년 10월부로 공식 지원 종료
-
MySQL 8.0 장점
- 보안 강화, 성능 개선, 커뮤니티 안정성 확보
- 대규모 운영 환경에서도 충분히 검증된 버전
-
최종 선택: MySQL 8.0
-
기존 경험을 살려 빠른 구축 및 안정적 운영 가능
-
Spring Boot + JPA 최적 호환
-
보안, 성능, 커뮤니티 지원 모두 충족
-
참고자료
https://www.integrate.io/ko/blog/postgresql-vs-mysql-which-one-is-better-for-your-use-case-ko/
https://hinweis.tistory.com/127
https://ddaily.co.kr/m/page/view/2024011705473798270
https://dev.mysql.com/doc/relnotes/mysql/8.0/en/?utm_source=chatgpt.com
항목 | Redis | Memcached |
---|---|---|
데이터 구조 | 다양한 구조 지원 (String, List, Set, Hash, ZSet 등) | 단순한 Key-Value (String only) |
정렬 기능 |
ZSet 으로 정렬된 순위 구현 가능 (점수 기반) |
정렬 기능 없음 (애플리케이션에서 수동 처리) |
Replication | Master-Slave 구조 지원 | 기본적으로 복제 미지원 |
클러스터링 | Redis Cluster, Sentinel 지원 | 기본 클러스터링 미지원, 수동 샤딩 필요 |
멀티 스레드 지원 | 단일 스레드 (성능은 충분) | 멀티 스레드 지원 |
메모리 관리 | 세분화된 정책: LRU, LFU, TTL, volatile/random 등 다양한 eviction 정책 제공 | 간단한 LRU 기반 삭제 정책만 지원 |
Pub/Sub | 내장 기능 제공 | 미지원 |
트랜잭션 | MULTI/EXEC 명령어로 지원 | 미지원 |
스크립트 실행 | Lua 스크립트 실행 지원 | 미지원 |
사용 사례 | 세션 저장, 랭킹 시스템, 실시간 알림, 메시지 큐, 캐시 등 | 단순 DB 캐시, 세션 캐시, 페이지 캐시 등 |
- 사용 목적: 빠른 소셜 로그인 후 사용자 정보 임시 저장
-
저장 방식:
-
카카오ID
를 Key로 사용 -
(Refresh Token, 만료 시간)
을 Value로 저장
-
-
특징:
- 이후 API(예: 유저 정보 등록)에서 이 값을 조회해 SQL에 최종 저장
- 로그인 후 정보 미입력 사용자에 대비해 TTL(Time To Live) 설정 필수
- 빠른 로그인 응답을 위해 읽기/쓰기 속도 최우선
- 사용 목적: 이메일 인증 시 발급되는 인증 토큰 임시 저장
-
활용 방식:
- 인증 요청 시 NoSQL에 인증 토큰 저장
- 사용자 클릭 시 해당 토큰 조회 및 검증
-
특징:
- 인증 미완료 사용자를 대비한 TTL 설정 필수
- 메일 전송 및 인증 확인 프로세스 속도를 고려해 고속 처리 적합
- 사용 목적: 사용자 세션이나 RT(Refresh Token) 등 단기 토큰 저장
-
활용 방식:
- 로그인 시 토큰을 저장하고, 요청마다 빠르게 검증
- TTL을 이용해 자동 만료 관리
-
특징:
- 짧은 수명 + 빈번한 접근에 최적화
- 빠른 인증/인가 처리와 높은 동시성 대응 가능
Caffeine (Local) + NoSQL (Global) + MySQL (Persistent)
-
시나리오:
- 최초 조회: MySQL → Caffeine 저장
- 재조회: Caffeine에서 직접 응답 (빠름)
- 좋아요(반응) 발생 시: NoSQL에 저장 (Caffeine은 변경 없음)
- 재조회 시: 목록은 Caffeine, 좋아요 수는 NoSQL에서 조합
- 주기적 동기화: NoSQL → MySQL 반영 (비동기)
-
역할 분리:
계층 역할 Caffeine 수정 없는 정적 목록 캐시 (서버 메모리 내, 초고속 응답) NoSQL 여러개 반응 수와 같은 동적 데이터 캐시 (서버 간 공유) MySQL 최종 데이터 저장소 (주기적 반영) -
장점:
- 실시간성과 속도 확보
- 오토스케일링 시 정적 데이터는 서버별 저장, 동적 데이터는 NoSQL로 통합 관리
-
고려중인 사항
- 반응 수를 서버 간 공유하기 위해 Redis를 쓰는 것은 현재는 적절하지만, 초대규모 트래픽에서는 Pub/Sub 또는 Kafka log 기반 event sourcing으로 전환 필요
Kafka + NoSQL + SQL 조합으로 확장성 + 속도 + 영속성 확보
-
NoSQL 역할:
역할 설명 실시간 브로드캐스트 Kafka로 받은 메시지를 WebSocket 서버에 푸시할 때 중간 캐시 역할 단기 메시지 캐시 최근 메시지, 채팅방 목록, 안읽은 수 등 고속 조회용 임시 저장소 -
기타 특징:
- 서버 간 메시지 브로드캐스트 시 중앙 캐시로 활용
- SQL에는 주기적 배치 저장으로 내구성 확보
- 소셜 로그인 처리
RT, 만료시간을 TTL 기반으로 저장해야 하며, key-value 이상 구조 필요
- ❌ Memcached는 TTL만 가능하고, 복잡한 구조 저장에는 부적합
- 이메일 인증 관리
인증 토큰의 TTL 설정 및 고속 읽기/쓰기가 핵심
- ❌ Memcached는 TTL만 제공하고, 인증 토큰 만료 후 처리 관리가 번거로움 → 만료된 key에 대한 이벤트나 후처리 기능은 제공하지 않습니다.
- 튜닝 레포트 캐싱 (Caffeine + Redis + MySQL 구조)
정적·동적 데이터 분리, 서버 간 공유 가능한 캐시 필요
- ❌ Memcached는 서버 간 데이터 공유 구조에 한계 + 정렬 기능 없음 → Memcached는 각 서버가 가진 자기 메모리 안에서만 데이터를 저장합니다. 따라서 여러 서버가 동시에 접근해야 하는 데이터(예: 좋아요 수 순위)는 공유하기 어렵습니다.
- 1:1 및 N:M 실시간 채팅
Kafka 중계 후 메시지 전달 + 단기 캐싱 + WebSocket 연계
- ❌ Memcached는 Pub/Sub, 스트림 기능이 없어 브로드캐스트/메시지 추적 불가
-
최종 선택: Redis 7.4.2
-
고성능 Key-Value 저장 + TTL 관리 + Pub/Sub 기능 지원
-
다양한 데이터 구조 및 서버 간 데이터 공유 지원
-
실시간 채팅, 인증 관리, 캐시 저장에 모두 최적화
-
참고자료
https://escapefromcoding.tistory.com/704
- 게시글, 튜닝 레포트 같은 변경이 거의 없는 정적 목록을 초고속으로 조회하기 위해 “로컬 캐시” 필요합니다.
- 로컬 캐시로 Redis의 메모리 부담을 덜어주고, Redis보다 더 빠른 속도로 정적 데이터 반환 기능
- 반면, 서버 수는 오토스케일링을 통해 늘어날 수 있으므로 반응 수 같은 빈번하게 변경되는 동적 데이터도 Redis로 관리할 계획입니다.
- 궁극적으로는 데이터 신뢰성을 보장하기 위해 MySQL에 저장해야 합니다.
- 구글의 Guava Cache를 계승해서 만든, 더 빠르고 효율적인 로컬 캐시 라이브러리
- JVM(Java Virtual Machine) 메모리 안에서 동작 (따라서 다른 서버들과 데이터 공유는 못 함)
- 고성능, 저지연, 효율적 메모리 관리를 목표로 설계됨
- Spring Boot에서도
spring-boot-starter-cache
와 같이 쉽게 통합 가능
"Caffeine은 JVM 기반 애플리케이션에서 메모리 안에 데이터를 빠르게 저장하고 조회할 수 있게 도와주는, 매우 빠른 캐시 라이브러리"입니다.
특징 | 설명 |
---|---|
최신 캐시 알고리즘 | W-TinyLFU 기반 → "자주 + 최근 사용된 데이터"를 스마트하게 유지 |
비동기 지원 |
AsyncLoadingCache 로 비동기 캐싱 가능 |
만료 정책 | TTL(지속 시간), TTI(비사용 시간) 기반 자동 만료 지원 |
최대 크기 제어 | 지정한 크기만큼만 캐시를 유지하고 초과 시 자동으로 제거 (Eviction) |
통계 제공 | hit/miss, eviction 같은 캐시 통계 수집 가능 |
기술 | 설명 | 차이점 |
---|---|---|
Guava Cache | 구글이 만든 초기 로컬 캐시 라이브러리 | - 성능이 Caffeine보다 느리고, 알고리즘이 옛날 것(LRU 기반). |
- Caffeine은 Guava를 "대체"하는 목적으로 나왔음. | | Ehcache | 오래된 자바 캐시 솔루션 (Spring에서도 옛날에 많이 씀) | - 디스크 저장, 클러스터링(복잡한 설정 가능) 지원 → 대신 무거움.
- 단순 로컬 캐시만 원하면 Caffeine이 훨씬 가벼움. | | Infinispan | RedHat이 만든 복합 캐시(로컬+분산 둘 다 가능) | - 너무 무거움. 캐시 + 분산 데이터 그리드 용도.
- 그냥 빠른 로컬 캐시만 쓰고 싶으면 부적합. |
항목 | 조회 속도 (QPS 기준) |
---|---|
Caffeine | 100,000 QPS 이상 |
Guava Cache | 30,000 ~ 40,000 QPS |
Ehcache (메모리) | 10,000 ~ 20,000 QPS |
Infinispan (분산) | 1,000 ~ 5,000 QPS |
✅ Caffeine은 특히 다중 코어, 멀티스레드 환경에서 성능 차이가 더 크다.
✅ Guava는 단일 스레드라면 쓸 만하지만 멀티스레드 가면 성능 급감소.
Guava Cache는 성능 한계, Ehcache는 복잡성 과잉, Infinispan은 오버스펙이라는 이유로 제외하고, 최종적으로 빠르고 경량화된 고성능 로컬 캐시를 제공하는 Caffeine을 선택했습니다.
-
최종 선택: Caffeine
-
빠르고 경량화된 고성능 로컬 캐시
-
설정이 간단하면서도 다양한 캐시 만료 정책 지원
-
단일 서버 환경과 멀티 서버 Caffeine-Redis 하이브리드 구조에 적합
-
참고자료
https://erjuer.tistory.com/127
https://github.com/ben-manes/caffeine/wiki/benchmarks?utm_source=chatgpt.com
8️⃣ 양방향 통신 : Socket.IO
실시간 양방향 통신을 구현하기 위한 대표적인 방식으로는 Spring WebSocket(STOMP + SockJS)와 Socket.IO가 있습니다. 두 방식 모두 실시간 메시지 전송, 자동 재연결, 네임스페이스/룸 기반 통신, N:M 브로드캐스트 등의 기능을 제공합니다.
다만 구현 방식에 차이가 있습니다.
Spring WebSocket(STOMP + SockJS)와 **Socket.IO**의 기능적 차이
Spring WebSocket (STOMP + SockJS) | Socket.IO | |
---|---|---|
기본 프로토콜 | WebSocket, STOMP | WebSocket 기반 + 자체 프로토콜 |
Fallback 지원 | ✅ SockJS 사용 시 가능 (Long Polling 등) | ✅ 기본 내장 (자동 Fallback) |
자동 재연결 | ❌ 기본 제공 X (직접 구현 필요) | ✅ 기본 내장 |
메시지 수신 확인 (Acknowledgement) | ❌ 직접 구현 필요 | ✅ 기본 내장 |
Broadcast 기능 | ❌ 직접 구현 필요 (채널 구분, 토픽 구독 필요) | ✅ 기본 내장 (room/namespace 기능 제공) |
Room/Namespace 구조 | ❌ 직접 topic 관리 | ✅ 기본 지원 |
설정 난이도 | 복잡 (STOMP, SockJS 설정 필요) | 단순 (기본 설정만으로도 사용 가능) |
Spring Boot와의 통합 | ✅ Spring 기반 프로젝트에 자연스럽게 통합 | ❌ 별도 서버 또는 라이브러리 사용 필요 |
브라우저 호환성 | ✅ SockJS 통해 다양한 브라우저 호환성 확보 | ✅ 기본 제공 |
기능 커스터마이징 | ✅ 유연한 커스터마이징 가능 (보안, 인증 등) |
-
Spring WebSocket (STOMP + SockJS) 특징
- Spring Boot와 자연스럽게 통합 가능
- 별도 서버 없이 자체 WebSocket 서버 구성 가능 → 인프라 비용 부담 적음
- 단점:
- 브라우저 Fallback, 메시지 수신 확인(Acknowledgement), 브로드캐스트 기능은 직접 구현 필요
- 특히 Acknowledgement는 기본 제공되지 않아 별도 로직 개발 필요
-
Socket.IO 특징
- JavaScript 기반의 실시간 통신 라이브러리
- Java를 포함해 다양한 언어에서 사용 가능
- 메시지 수신 확인(Acknowledgement), 자동 재연결, Fallback, 브로드캐스트 기능 기본 내장
- 빠른 개발 및 유지보수가 용이
- 복잡한 설정 없이 즉시 실시간 기능 구현 가능
-
선택 기준
- 빠른 개발 속도
- 유지보수의 간편함
- 다양한 플랫폼(웹, 앱) 확장성 고려
- 최종 선택: Socket.IO
- 메시지 수신 확인, 자동 재연결, 브라우저 Fallback, 브로드캐스트 기능 모두 기본 지원
- 별도 설정 없이 즉시 실시간 통신 기능 구현 가능
- 빠른 개발 및 다양한 플랫폼 확장에 유리
Socket.IO의 버전으로는 2.0.5를 선택했습니다. 그 이유는 다음과 같습니다.
항목 | 설명 |
---|---|
Java 17, Java 21 호환성 | 2.0.5는 Java 21 환경에서도 문제 없이 작동하도록 업데이트됨 |
Spring Boot 3.x 호환성 | Jakarta EE 전환 (javax → jakarta 네임스페이스 변경) 대응 완료 |
성능 개선 | Netty 4.1.x 기반 최적화 반영 (SocketIO 내부적으로 Netty 기반) |
버그 수정 | WebSocket 핸드셰이크, JSON 변환 에러 등 주요 버그 수정됨 |
액티브 유지보수 | 2024년에도 PR과 이슈 응답이 이루어지는 비교적 살아있는 프로젝트 |
- 참고 자료
Kafka | RabbitMQ | Redis Pub/Sub | |
---|---|---|---|
실시간성 | 중간 (지연 수 ms~수십 ms) | 중간 (ms 단위) | 빠름 (최소 지연) |
메시지 보관 | 디스크 저장 (지속성 매우 강함) | 메모리+디스크 | 저장 X (전송 후 바로 소멸) |
메시지 유실 방지 | 소비자가 죽어도 재전송 가능 | ack/retry 구조로 방지 가능 | 구독자가 없으면 바로 유실 |
재처리/이력 조회 | ✅ 가능 (offset 기반 재처리) | ❌ 불가능 | |
복잡도 | 높음 (Zookeeper 필요하거나 Kafka Streams 등 추가 설정) | 중간 | 낮음 (간단한 설정만으로 가능) |
구조 | 분산 처리, 파티션 기반 확장 | 큐 기반 처리, 다양한 라우팅 | pub/sub 단순 구조 |
사용성 | DevOps + 학습곡선 존재 | 라우팅 설정 이해 필요 | 매우 쉬움 |
스케일링 | 매우 우수 (고성능 스트리밍) | 클러스터 지원 (수평 확장 가능) | Redis Cluster로 수평 확장 가능 |
실시간 채팅 적합도 | ⭐ 중~고 (방대한 사용자 수 + 메시지 저장 필요할 때) | ⭐⭐ 중 (ack/retry 필요한 경우) | ⭐⭐⭐ 최고 (간단하고 빠른 채팅용에 최적) |
-
RabbitMQ 제외 이유
- 다양한 메시징 패턴과 라우팅 기능 제공
- 단점:
- 메시지 소비 후 삭제 → 장애 발생 시 재처리 어려움
- 여러 소비자가 동시에 읽을 경우 메시지 순서 보장 불가
- 실시간 채팅처럼 순서가 중요한 서비스에는 부적합
-
Redis Pub/Sub 제외 이유
- 빠르고 구조가 단순함
- 단점:
- 메시지 저장 기능 없음 → 구독자가 오프라인이면 메시지 유실
- 수신 확인(acknowledgement) 기능 부재 → 신뢰성 낮음
- 안정적인 메시지 전달이 중요한 실시간 알림/채팅 시스템에는 부적합
-
Kafka 고려 사항
- 고속 스트리밍 처리 능력 보유
- 장애 발생 시에도 메시지 재처리 가능 (offset 기반)
- 수평 확장성 뛰어남 → 사용자 증가에도 안정적 대응
- 다양한 알림 이벤트를 비동기 이벤트 스트림으로 처리 가능
- 튜닝 레포트(속보 기사) 발행, 메시지 수신, 매칭 성공/실패, 공지사항, 시그널 수신
- Redis/SSE 기반 사용자 맞춤 알림 시스템과 잘 연동됨
- 최종 선택: Kafka 3.6.2
항목 | ZooKeeper 기반 | KRaft 기반 |
---|---|---|
메타데이터 저장 | 외부 ZooKeeper | Kafka 내부 Raft |
구성 복잡성 | Kafka + ZooKeeper (복잡) | Kafka 단독 (단순) |
컨트롤러 선출 | ZooKeeper에서 단일 컨트롤러 | Raft 기반 다중 컨트롤러 가능 |
운영 경험 | 풍부 (안정적) | 최근 도입 (제한적) |
호환성 | 모든 도구와 호환 | 일부 도구 호환성 미흡 가능 |
적합 대상 | 기존 시스템, 안정성 중시 | 신규 프로젝트, 클라우드 환경 |
우리 서비스는 Kafka를 알림 이벤트 허브로 사용하며, 시스템의 안정성과 기존 도구들과의 호환성을 최우선으로 고려하고 있습니다.
- ✅ 안정성: ZooKeeper 기반 Kafka는 수년간 검증된 방식으로, 대규모 실서비스에서 널리 사용되어 운영 리스크가 낮음
- ✅ 호환성: Kafka와 연동되는 도구(Spring Kafka, Kafka Connect 등)가 ZooKeeper 기반 환경에 최적화되어 있어 기존 기술 스택과의 연동 이슈가 없음
- ✅ 운영 경험: 클라우드 인프라 팀에서 ZooKeeper 기반 운영 방식에 익숙하며, 장애 대응 및 트러블슈팅 경험이 축적되어 있어 내부적으로도 이 방식을 선호
따라서, 현 시점에서는 안정성과 예측 가능한 운영을 위해 ZooKeeper 기반 Kafka 클러스터를 선택했습니다. 다만, 추후 KRaft가 완전히 안정화되면 전환도 고려할 수 있습니다.
-
최종 선택: ZooKeeper 3.8.2
-
3.8.2 버전이 Kafka 3.6.x와 공식적으로 호환, 2025년 4월 기준 최신 안정 릴리스
-
안정적이고 검증된 방식으로 Kafka 메타데이터 관리 수행
-
참고자료
https://f-lab.kr/insight/high-performance-data-processing-with-redis-and-kafka-20240613
https://sjh9708.tistory.com/151
항목 | SSE (Server-Sent Events) | WebSocket |
---|---|---|
✅ 장점 | - 설정 간단 (HTTP 기반) |
- 자동 재연결
- 이벤트 ID로 메시지 중복 방지 | - 양방향 통신 가능
- 효율적인 실시간 인터랙션
- 다양한 데이터 형식 지원 | | ❌ 단점 | - 서버 → 클라이언트만 가능
- 대용량/빈번한 데이터 전송엔 부적합 | - 구현 복잡도 높음
- 커넥션 유지 비용 존재
- 재연결 로직 수동 구현 필요 |
-
서비스 특성
- 서버 → 클라이언트 방향의 일방향 알림 전송만 필요
- 복잡한 양방향 통신(WebSocket 수준)은 요구되지 않음
-
SSE의 장점
- HTTP 기반 프로토콜 → 구현 및 유지보수가 매우 간단
- 브라우저에서 자동 재연결 기본 지원
- 메시지 중복 방지 기능 기본 제공
- WebSocket에 비해 리소스 소비가 적음 → 서버에 부담을 덜 줌
- 수천 명 이상의 클라이언트를 효율적으로 처리 가능
-
WebSocket 대비 비교
- WebSocket은 양방향 통신에 적합하지만, 복잡한 세션 관리와 커넥션 유지 비용 존재
- 우리 서비스 요구사항(알림 푸시)에는 오버스펙
-
최종 선택: SSE (Server-Sent Events)
-
알림 푸시처럼 서버 → 클라이언트 일방향 통신에 최적
-
구현 간편성, 리소스 절감, 대규모 클라이언트 처리 측면 모두 만족
-
참고자료