[CS] 효율적인 API 성능 개선 전략

Hyunjun Kim·2025년 7월 18일
0

Computer_Science

목록 보기
12/19

효율적인 API 성능 개선 전략

서비스 규모가 작을 때는 서버(Provider)와 클라이언트(Consumer) 간의 API 통신 효율에 대해 큰 고민 없이 개발이 가능하다.
하지만 트래픽이 증가하고 데이터 요청량이 많아지면, 테이블 간 조인과 쿼리 연산이 많아지고 이는 곧 시스템 전반의 성능 저하로 이어진다.
API의 성능은 데이터 흐름 최적화, 리소스 절감, 비용 효율화라는 세 가지 측면에서 모두 중요하다.

API 성능을 향상시킬 수 있는 실용적인 전략 8가지를 알아보자.


1. 압축(Compression)

리스폰스 데이터를 압축하여 네트워크 전송량을 줄이는 방식이다. 분석 시스템에서 JSON 형태의 구조화된 데이터를 대량 전송할 때, GZIP 등의 압축 방식을 적용하면 전송 시간과 비용을 모두 줄일 수 있다.

import gzip
import json

data = {'user_id': 1, 'events': ['click', 'view', 'purchase']}
json_data = json.dumps(data).encode('utf-8')
compressed_data = gzip.compress(json_data)

데이터 전송량이 줄어들면 API Gateway와 Downstream 시스템에서 발생하는 비용도 줄어들게 된다. 특히 데이터 수집 또는 분석 API 호출이 빈번한 환경에서는 필수 전략이다.


2. 상태 유지(Stateful Session)

로그인 이후 일정 시간 동안 사용자의 상태를 서버에서 유지하는 방식이다.

  • 사용자 정보 조회 시 매번 전체 데이터를 조회하지 않고
  • 로그인 후 일정 시간(예: 15분) 동안 캐시된 정보를 사용

이 방식은 RDS 등의 리소스를 과도하게 사용하는 것을 방지하고, 반복적인 쿼리 요청을 줄이므로 성능 최적화에 매우 유효하다.


3. 캐싱(Cache)

데이터 분석 시스템에서 동일한 쿼리 요청이 반복될 경우, 캐싱은 필수 전략이다.
Redis와 같은 인메모리 저장소를 활용하여 결과를 캐시하면 데이터 레이크, 웨어하우스 접근 비용을 줄일 수 있다.

import redis

r = redis.Redis()
cached = r.get('user:123:metrics')

if cached:
    result = json.loads(cached)
else:
    result = compute_heavy_aggregation()
    r.setex('user:123:metrics', 300, json.dumps(result))

캐싱 전략은 대시보드 API, 집계 지표 API 등 비실시간성 API에 특히 효과적이다.


4. HEAD 요청 활용

GET 요청을 보내기 전에 실제 콘텐츠를 내려받지 않고 메타정보만 확인할 수 있다면 API 부하를 상당히 줄일 수 있다.

데이터 분석 플랫폼에서, 테이블 업데이트 여부를 사전 확인할 때 유용하다. ETag, Last-Modified 헤더를 활용하여 데이터가 변경되었는지만 판단하고, 필요할 때만 전체 데이터를 재요청하는 방식이다.


5. 오버패칭(Overfetching) 최소화

컨슈머가 필요하지 않은 데이터까지 받는 것은 API 성능 저하의 주범이다.
SQL로 대용량의 데이터를 조회할 때 SELECT *가 아닌 필요한 컬럼만 선택해 조회하는 것이 당연하듯, API에서도 정밀한 응답 설계가 필수이다.

이 문제를 해결하기 위한 GraphQL 같은 대안도 존재하지만, REST API에서도 엔드포인트를 분리하거나 쿼리 파라미터로 필드를 제한하는 전략을 사용할 수 있다.

GET /api/users/123?fields=name,age,joined_at

오버페칭 vs 언더페칭


6. 필터링 최적화

서버에서 불필요한 전체 데이터를 내려주고 클라이언트에서 필터링하는 방식은 비효율적이다.
데이터 분석에서 SQL에서 WHERE절을 제대로 쓰는 것처럼, API에서도 요청 단에서 필터링 로직을 적용해야 한다.

예를 들어, 특정 기간의 이벤트만 조회하거나, 상태값이 일치하는 경우만 필터링하도록 구현한다.

GET /api/events?start_date=2023-01-01&end_date=2023-01-31&status=success

필터링 로직과 함께 페이징, 정렬, 검색 옵션 등을 API 레벨에서 지원해야 분석 성능도 확보된다.


7. 데이터 집합체 설계

분석 시스템에서는 여러 테이블을 조인한 결과를 다루는 일이 흔하다.
이를 위한 API를 여러 개로 나누기보다는, 뷰(view)나 집계 테이블을 주기적으로 갱신하고, 이를 단일 API로 제공하는 전략이 유효하다.

CREATE MATERIALIZED VIEW user_profile_summary AS
SELECT u.id, u.name, a.balance, COUNT(e.id) as event_count
FROM users u
LEFT JOIN accounts a ON u.id = a.user_id
LEFT JOIN events e ON u.id = e.user_id
GROUP BY u.id, u.name, a.balance;

이렇게 생성된 결과를 /api/users/summary 등의 API에서 제공하면 응답 속도도 빠르고, 불필요한 조인도 줄일 수 있다.


8. API 계층화

사용자와 관리자가 동일한 API를 쓰는 것은 불필요한 리스크다. 관리용 API는 데이터 범위가 넓고, 보안 요구사항도 높다. 따라서 역할 기반으로 API를 계층화하고, URI 구조나 서브도메인으로 명확히 구분하는 것이 좋다.

예시:

  • 일반 사용자: api.myservice.com/v1/users/me
  • 관리자용: admin-api.myservice.com/v1/user-search

또한, v1, v2와 같은 버저닝을 통해 안정성과 호환성을 함께 관리할 수 있다.


참고 자료

profile
Data Analytics Engineer 가 되

0개의 댓글