로드 시간을 60% 줄인 방법
Source: Dev.to
초기 문제: 느린 대시보드
대시보드는 분석, 사용자 활동 로그 및 요약 메트릭을 표시했습니다. 데이터베이스가 커짐에 따라 페이지 로드에 몇 초가 걸리기 시작했습니다. 내부 사용자는 특히 사용량이 많은 시간대에 반응이 느리다고 불평했습니다.
관찰된 증상
- 초기 페이지 로드 시간이 약 5 seconds 정도 걸렸습니다
- API 응답 시간이 일관되지 않았습니다
- 트래픽이 많을 때 데이터베이스 CPU 사용량이 급증했습니다
- 여러 API 호출이 동시에 트리거되었습니다
겉보기에 시스템은 “작동”했습니다. 그러나 데이터가 확장됨에 따라 성능이 저하되었습니다. 이는 실제 소프트웨어 개발에서 흔히 발생하는 문제입니다.
단계 1: 변경하기 전에 측정하기
데이터 없는 성능 최적화는 추측에 불과합니다.
사용한 도구
- 브라우저 개발자 도구 – 네트워크 요청을 분석하기 위해
- 백엔드 로그 – API 응답 시간을 측정하기 위해
- 데이터베이스 쿼리 타이밍 도구 – 느린 쿼리를 식별하기 위해
발견한 내용
- 백엔드가 루프 안에서 여러 데이터베이스 쿼리를 수행하고 있었습니다.
- 일부 쿼리는 인덱스가 없었습니다.
- 프론트엔드가 중복된 API 호출을 하고 있었습니다.
- 큰 페이로드 크기로 인해 전송 시간이 증가했습니다.
문제는 단일 이슈가 아니라 비효율적인 데이터베이스 쿼리, 불필요한 API 호출, 과도한 데이터 전송이 결합된 것이었습니다.
단계 2: 데이터베이스 쿼리 최적화
문제 – N+1 쿼리 문제
백엔드 로직이 사용자 목록을 가져온 뒤, 루프 안에서 관련 활동 데이터를 별도로 조회했습니다.
1 query to fetch users
N additional queries to fetch related data
사용자가 200명이라면 시스템은 201개의 쿼리를 실행했습니다.
해결 방법
- 적절한 조인과 **즉시 로딩(eager loading)**을 사용해 관련 데이터를 하나의 최적화된 쿼리로 가져오도록 쿼리를 다시 작성했습니다.
- 필터링 및 정렬에 자주 사용되는 컬럼에 인덱스를 추가했습니다.
결과
- 데이터베이스 쿼리 수가 크게 감소했습니다.
- 쿼리 실행 시간이 크게 단축되었습니다.
- 서버 CPU 사용량이 안정화되었습니다.
이 변경만으로도 API 응답 시간이 거의 35 % 향상되었습니다.
3단계: 페이로드 크기 축소
문제점
API가 프론트엔드에서 사용하지 않는 필드가 포함된 전체 객체를 반환하고 있었습니다. 일부 응답에는 대시보드에 표시되지 않는 중첩 데이터도 포함되었습니다.
해결 방법
- 필요한 필드만 반환하도록 직렬화 로직을 수정했습니다.
- 활동 로그에 페이지네이션을 구현하여 프론트엔드가 한 번에 수천 개의 레코드를 로드하지 않도록 했습니다.
결과
- 응답 페이로드 크기가 ≈ 50 % 감소했습니다.
- 네트워크 전송 시간이 빨라졌습니다.
- 인지된 성능이 향상되었습니다.
이로 인해 추가로 10–15 % 정도의 성능 향상이 이루어졌습니다.
Step 4: 중복 API 호출 제거
문제
특정 상태 업데이트로 인해 대시보드가 동일한 데이터를 여러 번 가져와 서버 부하가 증가하고 UI가 느려졌습니다.
해결 방법
데이터‑fetching 로직을 리팩터링하여:
- 가능한 경우 Cache 응답을 저장합니다.
- API 호출이 필요할 때만 실행되도록 합니다.
- 불필요한 재‑렌더링으로 인한 반복 호출을 방지합니다.
결과
- 서버 부하 감소.
- UI 상호작용이 원활해짐.
- 초기 렌더링 속도 향상.
Step 5: 캐싱 구현
접근 방식
요약 통계는 매초 변하지 않으므로, 백엔드 수준에서 단기 캐싱을 도입했습니다. 데이터는 모든 요청마다 다시 계산되는 대신, 제어된 간격으로 새로 고쳐집니다.
결과
- 반복적인 데이터베이스 계산 감소.
- 트래픽 피크 시 서버 부하 감소.
- 응답 시간의 일관성 향상.
캐싱은 로드 시간 감소에 또 다른 측정 가능한 효과를 제공했습니다.
Step 6: 프론트엔드 렌더링 성능 개선
The Problem
대시보드가 로드 직후 대용량 리스트와 무거운 차트 컴포넌트를 즉시 렌더링하려고 시도했습니다.
The Fix
구현 내용:
- Lazy loading 비핵심 컴포넌트에 적용.
- Conditional rendering 무거운 요소에 대해 조건부 렌더링 적용.
- Loading placeholders 로딩 자리표시자를 사용해 인지된 성능 향상.
이는 백엔드 속도를 변경하지는 않았지만, 사용자에게 페이지가 더 빠르게 느껴지도록 만들었습니다.
최종 결과
| 지표 | 전 | 후 |
|---|---|---|
| 페이지 로드 시간 | ~5 초 | ~2 초 |
| API 응답 시간 | – | +60 % 더 빠름 |
| 데이터베이스 쿼리 수 | – | 크게 감소 |
| 서버 성능 | – | 트래픽 하에서 더 안정적 |
개선은 점진적이었지만, 함께하면 큰 영향을 만들었습니다.
로드 시간 60 % 단축에서 얻은 주요 교훈
- 먼저 측정 – 무작정 최적화하지 말고, 도구를 사용해 실제 병목을 식별하세요.
- 데이터베이스가 중요 – 효율적인 쿼리와 적절한 인덱싱은 확장 가능한 애플리케이션에 필수적입니다.
- 불필요한 데이터 감소 – 데이터를 적게 전송하면 백엔드와 프론트엔드 성능이 모두 향상됩니다.
- 중복 작업 방지 – 중복 API 호출과 반복 계산은 자원을 낭비합니다.
- 캐싱은 강력 – 짧은 기간이라도 캐싱을 하면 로드를 크게 줄일 수 있습니다.
- 성능은 풀스택 – 최적화는 백엔드 로직, 데이터베이스 설계, 네트워크 전송, 프론트엔드 렌더링을 모두 함께 살펴야 합니다.
Durin (내용이 여기서 끊겼지만, 주요 포인트는 위에 모두 포함되었습니다.)
성능 최적화: 인턴십에서 얻은 교훈
인턴십을 하는 동안, 이 경험은 내가 개발에 접근하는 방식을 바꾸어 놓았습니다. “작동하나요?” 라고만 묻던 것을 “확장성이 있나요?” 와 “효율적인가요?” 라고 묻는 방향으로 바뀌었습니다.
최적화가 중요한 이유
성능 최적화는 영리한 코드를 작성하는 것이 아니라 시스템을 전체적으로 이해하는 것입니다:
- 데이터 흐름
- 데이터베이스가 쿼리를 실행하는 방식
- API가 응답하는 방식
- 브라우저가 콘텐츠를 렌더링하는 방식
로드 시간을 60 % 줄인 것은 한 번의 극적인 변화 때문이 아니라, 신중한 분석, 구조화된 문제 해결, 그리고 점진적인 개선의 결과였습니다.
결론
현실 세계의 소프트웨어 엔지니어링은 영향에 관한 것입니다. 성능을 개선하면 사용자 만족도와 시스템 신뢰성이 직접 향상됩니다. 인턴십 동안 느린 대시보드를 최적화하면서 다음을 배웠습니다:
- 프로덕션 시스템 분석
- 병목 현상 식별
- 실용적인 솔루션 구현
느린 애플리케이션을 다루고 있다면, 다음 간단한 워크플로를 따라 보세요:
- 측정부터 시작합니다.
- 가장 큰 병목 현상을 식별합니다.
- 한 번에 하나씩 문제를 해결합니다.
성능은 사후 고려 사항이 아닙니다.
이는 전문적이고 확장 가능한 소프트웨어 시스템을 구축하는 핵심 부분입니다.