1. 오버헤드란 ?
계속해서 강의를 듣고, 문제를 해결해나가는 과정에서 자주 들리는 말이 있다.
바로 " 오버헤드 Overhead " 이다.
간단하게 설명하자면, 기본 기능을 수행하는 데 필요한 부가적인 자원 소모를 뜻한다.
우리가 직접적인 일하는 것 외에 추가로 드는 시간, 메모리, 네트워크, 연상 등의 비용을 의미한다고 한다.
오버헤드는 시스템 성능, 확장성, 응답 속도 등에 직접적인 영향을 미치기 때문에 개발자에게 매우 중요한 개념이라고 할 수 있다.
2. 오버헤드 종류
백엔드에서 발생할 수 있는 주요 오버헤드는 아래와 같다.
1. 네트워크 오버헤드 | API 요청/응답, REST 통신 |
---|---|
2. 데이터베이스 오버헤드 | 쿼리 비효율, 인덱스 미사용 |
3. 서버 처리 오버헤드 | 비동기 처리 실패, 과도한 로직 |
4. 스레드/동시성 오버헤드 | 컨텍스트 스위칭, 락 |
5. 메모리 오버헤드 | 캐시 낭비, 메모리 누수 |
6. I/O 오버헤드 | 파일 읽기, 외부 API 호출 |
7. 프레임워크/라이브러리 오버헤드 | DI 컨테이너, ORM |
한번 하나씩 살펴보겠다.
3. 네트워크 오버헤드
1) 생기는 원인
- HTTP는 텍스트 기반 프로토콜이다. 요청을 보낼 때 URL, 헤더, 쿠키, 인증 토큰 등 부가 데이터가 따라붙게 된다.
- 게다가 JSON 같은 데이터 포맷도 사람이 읽기 좋도록 설계된 텍스트라서 실제로는 데이터 크기가 크다.
- 요청을 보내기 위한 TCP 연결 과정(3-way handshake), SSL 암호화까지 포함되면 더 많은 리소스가 쓰이게 된다.
2) 문제
- 모바일 환경이나 해외 사용자에겐 요청 지연이 더 크며, 트래픽이 많아지면 네트워크 비용 증가 및 서버 부하가 증가된다.
- 반복적으로 데이터 요청할 때, 매번 전체 JSON을 보내면 속도 느려진다.
3) 해결 방법
- gRPC, WebSocket 등 경량 프로토콜 사용한다.
- JSON 대신 Binary 형식(예: Protobuf) 사용한다.
- 필요한 필드만 보내도록 DTO 슬림화를 한다. (현재 배우고 있는 부분)
4. 데이터베이스 오버헤드
1) 생기는 원인
- RDBMS(관계형데이터베이스관리시스템) 는 데이터 일관성 보장을 위해 내부적으로 트랜잭션, 락, 버퍼링, 인덱스 등을 동원한다.
- 쿼리가 복잡하거나, 인덱스가 없으면 풀 테이블 스캔이 일어나고 CPU, I/O 사용량이 급증하게 된다.
- ORM 사용 시 내부적으로 자동 쿼리를 날리는데, Lazy Loading을 잘못 쓰면 N+1 문제가 터진다.
2) 문제
- 쿼리 응답이 느려진다.
- 커넥션 풀에 연결이 모자라져서 다른 요청이 대기하게 된다.
- 트랜잭션 길어지면 DB 락이 발생하고 데드락 가능성도 있다.
3) 해결 방법
- 인덱스 튜닝: WHERE, ORDER BY 절에 사용하는 컬럼에 인덱스 추가해준다.
- N+1 문제 해결: join fetch, @EntityGraph 사용한다.
- 쿼리 분석: EXPLAIN, 실행 계획 보기 도구 활용한다.
5. 서버 처리 오버헤드
1) 생기는 원인
- 하나의 요청 처리 과정에서 비즈니스 로직이 복잡해지면, CPU 사용량과 메모리 소비가 증가하게 된다.
- 예: 조건문 + 반복문 + 예외처리 + 외부 호출이 섞이면 계산 비용이 기하급수적으로 증가하게 된다.
- 모든 요청을 동기 방식으로 처리하면, 대기 시간이 누적된다.
2) 문제
- 요청 처리 시간이 길어져 서버가 다른 요청을 못 받게 된다.
- 사용자에게 응답 지연이 생기고, 서버는 과열된다.
3) 해결 방법
- 비즈니스 로직 분리 & 단순화 (서비스 계층 구조화) / 반복되는 로직 캐싱 만들기
- 비동기 처리로 블로킹 줄이기 (@Async, Kafka 등)
6. 스레드/동시성 오버헤드
1) 생기는 원인
- 스레드는 생성할 때마다 메모리와 CPU 컨텍스트를 추가로 필요로 하다.
- 동시에 많은 요청이 들어오면 OS는 스레드를 번갈아 실행 (Context Switching) 하면서 자원이 낭비된다.
- 여러 스레드가 공유 데이터에 접근할 땐 락을 걸어야 하는데, 이 락 대기가 병목을 만든다.
2) 문제
- 컨텍스트 스위칭 비용 증가 → 처리 속도 저하된다.
- 잘못된 락 처리 → 데드락, 레이스 컨디션이 생긴다.
- CPU가 락 대기만 하다가 낭비된다.
3) 해결 방법
- ThreadPoolExecutor 등으로 스레드 수를 통제한다.
- 비공유 상태 기반 설계: 불변 객체, 함수형 프로그래밍 활용한다.
- 락 대신 Atomic 변수, concurrent 패키지 활용한다.
7. 메모리 오버헤드
1) 생기는 원인
- 자주 생성되는 객체(예: DTO, Entity 등)를 계속 새로 만들면 GC 부하가 늘어난다.
- 캐시를 과도하게 사용하면 메모리 점유율이 커진다.
- 잘못된 코드로 메모리 누수 (Memory Leak) 발생 → GC가 해제하지 못한다.
2) 문제
- OutOfMemoryError 발생 가능성이 있다.
- GC가 자주 일어나면 애플리케이션이 멈칫멈칫한다. (Stop the World)
- 전체 서버 성능 저하된다.
3) 해결 방법
- 반복 생성 객체는 싱글턴화 또는 풀링을 해준다.
- 캐시 TTL, LRU 정책 적용 한다.
- GC 튜닝: JVM 옵션 조절 (-Xms, -Xmx, G1GC 등)
8. I/O 오버헤드
1) 생기는 원인
- 파일 입출력, 외부 API 호출, DB 접근은 모두 I/O 블로킹이 발생한다.
?? I/O 블로킹이란? “입출력 작업(예: 파일 읽기, DB 쿼리, 외부 API 호출 등)을 하는 동안, 해당 작업이 끝날 때까지 프로그램 실행이 멈추는 현상” 기다려야만 다음 작업을 할 수 있는 상황임.
- 한 번에 큰 데이터를 읽거나, 외부 응답이 느릴 때 스레드가 대기해야 한다.
2) 문제
- I/O 작업이 길어질수록 서버가 다른 요청을 못 받는다.
- 서버는 스레드를 기다리는 데만 사용 → 자원 낭비하게 된다.
3) 해결 방법
- 비동기/Non-Blocking I/O 사용 (Spring WebFlux, Netty)
- 외부 API는 타임아웃 설정이 필수이다.
- 대용량 데이터는 스트리밍 처리로 해야한다.
9. 프레임워크/라이브러리 오버헤드
1) 생기는 원인
- 프레임워크는 많은 기능을 기본 탑재한다.
예: 스프링은 DI, AOP, 인터셉터, 필터 등 초기 실행 시 많은 컴포넌트를 생성하게 된다.
- ORM (Hibernate 등)은 엔티티 관리, 캐시, SQL 변환 등으로 내부에서 추가 작업을 많이 한다.
2) 문제
- 앱 기동 속도가 느려진다.
- 디버깅이 어렵다. (문제 발생 시 어디서 느려졌는지 알기 어려움)
- 실시간 성능이 저하된다.
3) 해결 방법
- 불필요한 빈 등록 제거한다.
- ORM 설정: fetch type, batch size 최적화해준다.
- 애플리케이션 슬라이싱: 필요한 기능만 사용하는 경량 아키텍처 구성한다.
✅ 오늘의 회고
중간 중간 오버헤드 오버헤드 라고 하는데, 말만 그렇게 들으니 와 닿지 않아서.. 한번 정리해보았다.
강의에 들었던 내용이 중간 중간 나오니? 조금은 와 닿는다.
오늘은 강의를 조금 대충.. 들었는데 내일은 집중해서 팍 듣고 과제 접근해봐야겠다.
'백엔드 부트캠프 > TIL' 카테고리의 다른 글
[내일배움캠프Spring-43일차] N+1 문제 (1) | 2025.04.17 |
---|---|
[내일배움캠프Spring-42일차] Persistence Context 이해하기 (2) | 2025.04.16 |
[내일배움캠프Spring-40일차] 객체지향 (0) | 2025.04.14 |
[내일배움캠프Spring-39일차] @Builder 어노테이션 (0) | 2025.04.11 |
[내일배움캠프Spring-38일차] JWT (0) | 2025.04.10 |