Engineering Note
웹 애플리케이션은 어디서 느려지는가: 문제 구간을 좁히는 조사 순서
브라우저부터 네트워크·애플리케이션·DB까지 전체 경로를 나누고, 같은 사용자 동작의 측정값을 비교해 성능 문제의 범위를 좁히는 방법을 정리합니다.
사용자는 화면이 느리다고 합니다. 브라우저가 요청을 늦게 시작하는지, 네트워크에서 기다리는지, 애플리케이션이나 DB가 느린지 아직 모릅니다. 각 시스템의 대시보드가 정상이어도 사용자가 기다린 시간은 설명되지 않을 수 있습니다.
조사의 출발점은 전체 경로를 나누고, 같은 사용자 동작의 측정 근거로 범위를 좁히는 것입니다. 느린 구간이 확인되면 그 안을 더 작게 나누고, 정상으로 확인된 구간은 조사 우선순위에서 뒤로 보냅니다.
서비스망의 네트워크 게이트웨이부터 애플리케이션·DB까지 정상일 수도 있습니다. 그때는 서버 내부를 반복해서 조사하기보다 사용자 단말, 접근 네트워크, 요청 사이의 대기와 화면 표시로 조사를 옮겨야 합니다. 다만 그 판단도 문제가 발생한 요청과 시점의 근거가 있어야 합니다.
1. 느린 동작과 비교 조건을 고정한다
“화면이 느리다”를 “모바일에서 주문 목록을 누른 뒤 첫 목록이 표시될 때까지 느리다”로 바꿉니다. 발생 시각, 화면 경로, 배포 버전, 기기·브라우저, 네트워크 조건, 첫 방문인지 재방문인지 함께 기록합니다. 완료 기준과 재현 조건을 정해야 서로 다른 경험을 같은 문제로 묶지 않을 수 있습니다.
정상일 때 같은 동작을 수행한 기록도 확보합니다. 특정 사용자만 느린지, 특정 화면이나 시간대에 집중되는지부터 나눕니다. 비교할 때는 한 번에 조건 하나를 바꿉니다. 같은 단말에서 회선만 바꾸거나, 같은 회선에서 단말만 바꾸는 식입니다. 이때 DNS 결과, 접속 서버, 인증 상태와 캐시까지 달라졌다면 결과를 특정 원인 하나의 증거로 단정하지 않습니다.
정상 기준도 정합니다. 이전 버전보다 느려졌는지와 사용자가 받아들일 목표를 넘었는지는 별개입니다. 서비스 수준 목표(Service Level Objective, SLO)가 있다면 대상 동작·사용자 집단·평가 기간·성공 기준을 맞춰 비교합니다. 없다면 우선 같은 조건의 정상 기준선을 잡습니다. 문제가 시작된 시각에 배포·설정·데이터 크기·트래픽 구성이 바뀌었는지도 확인하되, 시점이 겹친다는 이유만으로 원인으로 확정하지 않습니다. 서비스 수준 목표의 정의
2. 전체 경로를 나누고 큰 구간부터 비교한다
배포 구조에 맞춰 실제 경로를 적습니다. 다음은 가능한 구성 요소를 나열한 예시이며, 콘텐츠 전송 네트워크(CDN), 웹 애플리케이션 방화벽(WAF), 로드밸런서(LB)의 위치와 순서는 서비스마다 다릅니다.
사용자 동작 → 브라우저의 요청 준비
→ 사용자 단말·접근망·인터넷 또는 사설망
→ 서비스망 진입부와 중간 장비 → 애플리케이션 → DB·캐시·외부 API
→ 응답 전송 → 브라우저의 데이터 처리와 화면 표시
여기서 네트워크 게이트웨이는 서비스망과 다른 네트워크를 연결하는 장비나 기능을 뜻합니다. HTTP 요청을 처리하는 API 게이트웨이와 구분해야 합니다. API 게이트웨이가 있다면 별도 구성 요소로 표시합니다. 응답 경로도 포함하고, 캐시나 Service Worker에서 끝나는 요청은 실제로 거친 경로를 따로 봅니다.
처음부터 모든 장비를 세밀하게 계측할 필요는 없습니다. 먼저 사용자 동작 전체 시간, 브라우저에서 본 요청 시간, 서버 측 처리 시간을 비교합니다. 이 셋의 범위 차이가 다음에 볼 구간을 결정합니다.
다음은 측정 경계를 설명하기 위한 가상의 순차 실행 예시입니다.
| 사용자 동작의 구간 | 걸린 시간 |
|---|---|
| 클릭 후 첫 API 요청을 시작하기 전의 처리와 대기 | 400ms |
| API 세 개를 순서대로 호출하고 응답 본문을 받는 시간 | 900ms |
| 데이터 변환, 화면 갱신, 결과가 그려지기까지 | 1,900ms |
| 사용자가 기다린 전체 시간 | 3,200ms |
각 API의 애플리케이션 처리 시간이 180ms여도 이 화면은 3.2초가 걸릴 수 있습니다. 180ms는 900ms 구간 안에 포함된 일부 시간이며, 전체에 다시 더하는 값이 아닙니다. 실제로 병렬 실행이 있다면 개별 시간의 합보다 결과 표시를 늦추는 의존 경로를 찾아야 합니다. 서로 다른 요청 집단의 p95끼리 더하거나 빼서 이 타임라인을 만들 수는 없습니다.
Chrome DevTools에서 Network와 Performance를 같은 재현 동작에 대해 기록합니다. Network의 요청 시간표(Waterfall)와 요청을 시작한 원인(Initiator)으로 호출 순서와 의존성을 보고, Performance에서는 응답 이후 JavaScript 실행, 스타일 계산, 레이아웃과 페인트가 얼마나 이어지는지 확인합니다. 개발자 PC 한 대의 결과에만 의존하지 말고, 실제 문제가 발생한 기기와 회선 조건으로 비교합니다. Network 도구 · Performance 도구
3. 경계 양쪽의 근거로 의심 구간을 줄인다
브라우저 요청과 서버 기록을 같은 요청 식별자(request ID)나 분산 추적 정보(trace context)로 연결합니다. 분산 추적(trace)은 요청이 여러 서비스를 거치는 경로를 기록하고, span은 그 안의 개별 작업 구간을 나타냅니다. 애플리케이션부터 DB까지 부모·자식 span을 따라가며, 계측되지 않은 구간은 미확인 상태로 남깁니다. 네트워크 장비까지 HTTP request ID가 전파되는 것은 아니므로, 필요한 경우 연결 정보와 해당 시점의 장비·흐름 기록으로 연결해야 합니다. 분산 trace와 span
| 같은 동작에서 확인한 근거 | 다음에 좁혀 볼 구간 |
|---|---|
| 업무 완료는 늦지만 개별 요청의 시작부터 본문 수신까지는 짧음 | 요청 전 처리, 요청 사이의 의존성, 수신 후 렌더링 |
| 브라우저 요청과 서버 측 처리 시간이 모두 김 | 서버 측 구간을 진입부, 애플리케이션, 의존 서비스로 분해 |
| 서비스 진입부의 요청 처리는 긴데 애플리케이션 처리는 짧음 | 진입부의 대기·라우팅·재시도·버퍼링과 앱까지의 연결 |
| 애플리케이션 처리 중 DB 관련 구간이 김 | 연결 풀 대기, DB 왕복, 쿼리 실행과 잠금 대기를 구분 |
| 서버 측 경로는 빠른데 브라우저의 요청 완료는 늦음 | 아직 측정하지 않은 중간 경로, 응답 전송, 사용자망·단말 |
이 비교는 다음 조사 위치를 고르는 근거입니다. 브라우저의 시간에서 서버 시간을 뺀 나머지를 곧바로 “네트워크 시간”이라고 이름 붙이면 안 됩니다. 측정 시작·종료 지점, 본문 전송 포함 여부, 재시도와 버퍼링이 서로 다를 수 있습니다. 서로 다른 호스트의 시각을 비교할 때는 시계 오차도 확인합니다.
“서버가 정상”이라는 판단에는 최소한 다음 조건이 필요합니다.
- 문제가 발생한 요청·시간대·버전이 관측에 포함되어 있다.
- 측정이 어디서 시작하고 끝나는지, 어떤 대기가 포함되는지 안다.
- 성공 요청뿐 아니라 실패·타임아웃·취소와 수집 누락도 확인했다.
- 평균뿐 아니라 분포와 해당 사용자 집단을 확인했다.
p95와 p99는 각각 관측값의 95%, 99%가 그 값 이하인 지점을 뜻합니다. 전체 평균·p95·p99가 정상이어도 특정 경로나 작은 사용자 집단의 지연은 숨을 수 있습니다. 인스턴스별 p99를 평균 내거나, 오류를 우선 보존한 trace의 분포를 전체 요청 분포로 사용하지 않습니다. 여러 인스턴스를 합쳐 볼 때는 같은 관측 기간의 히스토그램 분포를 합친 뒤 백분위수를 추정합니다. 고정 구간을 쓰는 classic histogram은 구간(bucket) 경계가 일치해야 합니다. 표준 지수 구간을 쓰는 native histogram은 해상도가 달라도 호환되는 형태로 합칠 수 있습니다. 어느 방식이든 관심 있는 지연 범위를 구분할 해상도가 충분한지 확인합니다. Prometheus의 histogram 설명
4. 확인된 구간 안에서 다음 증거를 찾는다
서비스망의 네트워크 게이트웨이부터 애플리케이션·DB까지, 해당 요청의 처리와 응답 전송에 문제가 없다고 확인했다면 조사 우선순위를 그 바깥으로 옮깁니다. 브라우저의 요청 시작 전과 수신 후, 사용자 측 네트워크와 아직 관측하지 않은 중간 경로를 확인합니다. 서버가 응답을 내보냈다는 사실과 브라우저가 본문을 모두 받아 사용했다는 사실은 다릅니다.
반대로 서버 내부에서 시간이 늘었다면 해당 구간을 더 나눕니다. CPU가 낮아도 큐나 연결 풀의 대기는 길 수 있습니다. “DB 호출이 느리다”도 풀 획득이 늦은지, DB와의 왕복이 늦은지, 쿼리 실행이 늦은지로 분해해야 해결 방향이 생깁니다.
지연은 요청량·오류·포화와 함께 봅니다. 같은 시간축에서 초당 유입·완료 요청 수, 동시에 처리 중인 요청 수, 큐 길이·대기 시간, 자원 한도를 비교합니다. 완료 처리량은 더 늘지 않는데 대기 요청이 쌓이면 처리 용량이나 병목을 의심할 근거가 됩니다. 전체 CPU 평균이 낮아도 특정 인스턴스나 연결 풀만 포화됐을 수 있습니다. Google SRE의 주요 모니터링 신호
재시도도 사용자 동작과 분리해 셉니다. 한 동작이 여러 시도를 만들면 개별 시도는 빨라도 재시도 사이의 대기 때문에 완료가 늦고, 늘어난 요청이 다시 부하를 키울 수 있습니다. 원래 요청과 재시도 횟수·대기 시간을 연결합니다. 재시도와 부하의 관계
| 관찰한 현상 | 다음에 확인할 근거 | 근거가 맞을 때 검토할 변경 |
|---|---|---|
| 클릭했는데 요청이 늦게 시작됨 | 메인 스레드의 긴 작업, 입력 후 대기(debounce), 토큰 갱신, 선행 요청 의존성 | 긴 작업 분할, 불필요한 대기 제거, 독립 요청 병렬화 |
| Queueing·Stalled·연결 구간이 김 | 요청 우선순위, 연결 재사용, DNS·TLS, 프록시·VPN | 불필요한 요청 축소, 연결·DNS·프록시 경로 점검 |
| 브라우저의 첫 바이트 대기는 긴데 같은 요청의 서버 구간은 짧음 | CDN·WAF·LB의 처리·대기, 네트워크 왕복, 재시도 | 문제가 확인된 중간 경로·정책·연결 수정 |
| 응답 헤더는 빨리 오지만 본문 수신이 김 | 전송 크기, 압축, 회선, 스트리밍·버퍼링, 브라우저 부하 | 응답 데이터 축소, 페이지네이션, 압축·전송 방식 조정 |
| 개별 API는 빠르지만 여러 요청을 기다림 | Waterfall의 직렬 호출, 중복 호출, 폴링 간격 | 의존성 제거, 필요한 데이터 묶기, 중복·폴링 조정 |
| 서버 처리 중 특정 대기가 김 | 큐·연결 풀 대기, DB 잠금·쿼리, 외부 호출·재시도 | 점유 시간·쿼리·호출 패턴 개선, 확인된 자원 제약 해소 |
| 응답은 끝났는데 화면이 늦게 바뀜 | 데이터 파싱·변환, 큰 DOM, 반복 렌더링, 레이아웃·화면 그리기 | 데이터·DOM 축소, 목록 가상화, 작업 분할, 적합한 계산을 Web Worker로 분리 |
브라우저에서 첫 바이트를 기다리는 시간(Time to First Byte, TTFB)을 나타내는 Waiting (TTFB)에는 네트워크 왕복과 서버 응답 준비가 함께 들어갑니다. Content Download가 길어도 회선만 탓할 수는 없습니다. 브라우저가 다른 작업 때문에 본문을 읽는 데 지연이 생길 수도 있습니다. 또한 HTTP/1.1의 연결 제한을 HTTP/2·3에 그대로 적용해서는 안 됩니다. DevTools의 Timing 정의
서버의 HTTP 요청 기록에 요청이 보이지 않는 경우도 구분해야 합니다. 브라우저 캐시나 Service Worker가 처리했을 수 있고, CDN에서 응답했거나 요청이 WAF 등 앞단에서 실패했을 수도 있습니다. CORS preflight, 인증 리다이렉트, 외부 스크립트·폰트처럼 대시보드의 API 집계에 없는 요청도 Waterfall에서 확인합니다.
5. 좁혀진 범위에 맞춰 지표와 도구를 고른다
다음 표에서 의심 구간에 해당하는 신호를 골라 봅니다. 모든 지표를 한꺼번에 추가하기보다, 다음 판단에 필요한 근거를 확보하는 데 집중합니다.
| 계층 | 우선 수집할 신호 | 답하려는 질문 |
|---|---|---|
| 실제 사용자 브라우저 | 로딩 성능·반응성·화면 배치 안정성, 업무 동작 완료 시간, JS 오류·요청 실패 | 어느 화면·기기·지역에서 불편한가 |
| 네트워크 게이트웨이·방화벽 | 연결 상태, 인터페이스 오류·패킷 폐기, 처리량·포화 | 서비스망 경계에서 연결·전송 문제가 있는가 |
| CDN·WAF·LB·API 게이트웨이 | 요청 수, 오류·타임아웃·취소, 지연 분포, 캐시 적중률, 응답 크기 | 요청이 어디까지 도달했고 어느 경계에서 느려졌나 |
| 애플리케이션 | 처리 시간, 큐·이벤트 루프 지연, 스레드·연결 풀 대기, 가비지 컬렉션(GC) 정지 시간 | 실행이 느린가, 실행 기회를 기다리는가 |
| DB·캐시·외부 API | 연결 풀 획득 대기, 쿼리 시간·잠금 대기, 캐시 적중률, 재시도 | 어떤 의존성이 완료를 늦추는가 |
| 실행 환경 | CPU 사용·실행 제한(throttling), 메모리 압력, 디스크 I/O 지연, 네트워크 손실·재전송 | 애플리케이션 바깥의 자원 제약이 있는가 |
| 관측 파이프라인 | 수집 성공률, 데이터 지연·누락, 수집기(Collector) 큐·메모리, 전송 실패 | 정상인가, 아니면 측정 데이터가 빠졌는가 |
서버 내부는 프로파일링으로 더 좁힌다
트레이스로 특정 함수나 서비스 안까지 좁혔는데 내부 시간이 설명되지 않으면 프로파일링(profiling)을 사용합니다. 실행 중인 호출 스택 등을 표본으로 수집해 CPU를 쓰는 코드, 메모리 할당, 잠금 대기를 살펴보는 방법입니다. 예를 들어 JVM에서는 async-profiler를 사용할 수 있습니다. CPU 실행과 대기를 포함한 경과 시간은 다르므로, CPU 프로파일만으로 모든 지연을 설명하려 하지는 않습니다.
대상 프로세스·수집 시간·빈도를 제한하고 계측 자체의 부하도 확인합니다. DB 쿼리 실행이 문제로 좁혀졌다면 쿼리별 실행 계획과 대기 기록을 확인하는 식으로 해당 계층의 도구로 이어갑니다.
실제 사용자 환경을 자동으로 측정한다
실제 사용자 모니터링(Real User Monitoring, RUM)은 웹페이지의 JavaScript가 사용자 브라우저에서 성능을 측정해 서버로 전송하는 방식입니다. 개발팀이 측정 코드나 SDK를 배포하면 운영자는 결과를 원격에서 확인할 수 있습니다. 사용자는 평소처럼 서비스를 이용하면 되며, 별도의 측정 작업은 필요하지 않습니다. web-vitals의 측정·전송 예시
화면 로딩·반응성·리소스 요청 시간은 지원 범위에서 자동 수집하고, “검색 시작 → 결과 표시” 같은 업무 시간은 개발자가 시작·종료 지점을 정의해 계측합니다. User Timing API
RUM으로 문제가 집중되는 화면·기기·버전을 찾고, DevTools로 재현해 원인을 조사합니다. 자동 브라우저가 정해진 동작을 반복하는 합성 테스트는 동일 조건의 비교와 접근 가능 여부 확인을 보완합니다. 페이지나 측정 코드가 실행되기 전에 실패하면 RUM 기록도 없을 수 있으므로, 데이터가 없다는 사실을 정상으로 해석하지 않습니다. 브라우저 지원·샘플링·전송 실패에 따른 누락도 확인합니다.
로딩 속도, 조작 반응, 화면의 안정성을 구분한다
다음 세 가지는 RUM으로 수집할 수 있는 Core Web Vitals입니다. 각 지표가 어떤 질문에 답하는지 보면 의미를 구분하기 쉽습니다.
| 지표 | 무엇을 측정하는가 | 좋은 경험 기준 |
|---|---|---|
| Largest Contentful Paint (LCP) | 주요 내용이 얼마나 빨리 보이는가? 페이지 로딩 시작부터 화면에 보이는 가장 큰 이미지나 텍스트 블록이 표시되기까지의 시간 | 2.5초 이하 |
| Interaction to Next Paint (INP) | 조작에 화면이 얼마나 빨리 반응하는가? 클릭·탭·키 입력 후 다음 화면 갱신까지의 지연으로 평가하는 반응성 | 200ms 이하 |
| Cumulative Layout Shift (CLS) | 화면 배치가 예상치 못하게 얼마나 움직이는가? 읽던 글이나 누르려던 버튼이 갑자기 밀리는 현상을 나타내는 점수. 시간 단위가 아님 | 0.1 이하 |
INP는 개별 클릭의 지연을 그대로 나열한 값이 아니라, 한 페이지 방문 중 관측한 상호작용의 지연을 대표하는 값입니다. 대체로 가장 느린 상호작용을 사용하되, 상호작용이 많으면 일부 극단값을 제외합니다.
이 기준은 페이지 방문별 지표를 모아 모바일과 데스크톱을 나눠 p75, 즉 관측값의 75%가 그 값 이하인 지점에서 평가합니다. 서버 API의 p99 목표나 업무 완료 시간과는 다른 기준입니다. Core Web Vitals 공식 설명
INP가 좋아도 업무 완료는 늦을 수 있습니다. 클릭 직후 로딩 표시는 빠르게 나타나지만 검색 결과는 한참 뒤에 올 수 있기 때문입니다. 업무 완료 시간과 단일 페이지 애플리케이션(SPA)의 내부 화면 전환은 별도로 계측합니다. INP가 측정하는 범위
LCP·INP·CLS는 API 응답 완료 시점에 일괄 확정하지 않습니다. INP·CLS는 페이지 이용 중 갱신될 수 있으므로 web-vitals 같은 라이브러리의 보고 시점에 맞춰 수집합니다. 지표 보고 동작
일부 세션을 측정하고 문제 동작의 상세 정보를 남긴다
다음은 세션의 5%를 무작위로 선택하는 설명용 설계입니다. SDK의 지원 범위를 확인하고 비율과 임계치를 서비스에 맞춰 정합니다.
- 선택한 세션의 동작을 끝까지 추적합니다. 요청마다 다시 추첨하지 않고, 해당 업무에 필요한 응답 본문 수신과 결과 표시를 구분해 기록합니다. 폴링 등 페이지 전체 요청의 종료를 기다리지는 않습니다.
- 기본 통계는 정상 사례도 포함합니다. 선택된 표본의 결과별 건수와 완료 시간 분포, 표본 비율·정책 버전을 남깁니다.
- 느리거나 실패한 동작은 상세 정보도 보냅니다. 임계치 초과·오류·타임아웃·취소에는 요청별 타이밍, 화면·배포 버전, 브라우저 정보와 연결 가능한 trace ID를 덧붙입니다. 수집 범위는 선택된 표본입니다.
- 끝나지 않는 동작은 ‘미완료’로 기록합니다. 임계치와 별도로 관측 기한을 정하고, 기한까지 끝나지 않으면 경과 시간을 보고합니다. 이후 완료 보고는 같은 동작 ID로 연결해 중복 집계를 막습니다. 페이지 종료·통신 단절로 보고가 누락될 수도 있습니다.
예를 들어 임계치가 1초라면 400ms에 끝난 검색은 기본 통계에, 1.8초가 걸린 검색은 상세 정보에도 남깁니다. 관측 기한에 도달한 미완료 동작을 정상 완료 시간 분포에 넣지는 않습니다.
느린 사례만으로 전체 평균·p95·p99나 발생 비율을 계산하지 않습니다. 기본 통계는 표본의 경험을, 상세 정보는 원인을 조사하는 데 씁니다. 비용 설계는 관측 데이터는 얼마나 모아야 할까에서 다룹니다.
DevTools로 재현한 동작을 상세 조사한다
다음 코드는 개발자가 재현 후 DevTools Console에서 현재 버퍼에 남은 fetch·XHR 요청을 확인하는 예시입니다. 앞에서 설명한 자동 RUM 수집과 달리 수동 진단용 코드입니다.
const requests = performance.getEntriesByType('resource')
.filter((entry) => ['fetch', 'xmlhttprequest'].includes(entry.initiatorType));
console.table(requests.map((entry) => ({
path: new URL(entry.name).pathname,
totalMs: Math.round(entry.duration),
requestToFirstByteMs: entry.requestStart > 0 && entry.responseStart > 0
? Math.round(entry.responseStart - entry.requestStart) : null,
bodyMs: entry.responseStart > 0
? Math.round(entry.responseEnd - entry.responseStart) : null,
transferBytes: entry.transferSize,
})));
totalMs는 리소스 요청 시작부터 응답 완료까지이며, 클릭부터 화면 표시까지의 시간은 아닙니다. 첫 바이트 대기도 서버 실행 시간만을 뜻하지 않습니다. 다른 출처의 상세 타이밍에는 Timing-Allow-Origin이 필요하고, 0의 의미는 캐시·노출 제한 등 항목별 조건에 따라 다릅니다. 지속 수집에는 PerformanceObserver와 유한한 버퍼의 관리가 필요합니다. Resource Timing API
브라우저 기록과 서버 계측을 함께 보려면 필요한 서버 구간의 시간을 Server-Timing으로 브라우저에 전달할 수도 있습니다. 이 정보는 분산 추적을 보완합니다.
의심 구간에만 상세 계측을 늘리고, 조사가 끝나면 원래 수집 범위로 되돌립니다.
6. 수정은 같은 사용자 동작으로 검증한다
앞의 가상 예시에서 주문 목록 표시까지 걸린 3.2초를 조사한다면 다음처럼 진행합니다. 실제 장애의 측정 결과가 아니라 조사 순서를 설명하는 예시입니다.
- 같은 요청의 서버 처리를 확인합니다. 브라우저의 API 세 개를 서버 기록과 연결합니다. 각 애플리케이션 처리 시간이 180ms이고 해당 요청의 서버 측 대기에도 이상이 없다면, 우선 브라우저에서 나머지 시간을 찾습니다. 애플리케이션 시간만으로 네트워크 전체가 정상이라고 판단하지는 않습니다.
- 응답 수신과 화면 표시 사이를 좁힙니다. 클릭 후 400ms에 첫 요청이 시작되고, 순차 호출에 900ms가 걸리므로 마지막 본문 수신은 클릭 후 1.3초입니다. 결과 표시는 3.2초이므로 수신 이후 1.9초가 다음 조사 대상입니다.
- Performance 기록에서 그 1.9초를 펼쳐 봅니다. JavaScript 실행, 데이터 변환, 레이아웃과 화면 그리기 중 무엇이 시간을 차지하는지 확인합니다. 예를 들어 큰 목록의 반복 렌더링이 확인됐다면 표시 항목을 줄이거나 목록 가상화를 검토합니다. 기록을 보기 전에 원인을 확정하지 않습니다.
- 변경 후 같은 구간과 전체 시간을 다시 잽니다. 수신 이후 1.9초가 줄었는지, 클릭부터 결과 표시까지의 시간도 함께 줄었는지 확인합니다. 첫 요청 전 400ms와 순차 호출 900ms는 남은 개선 후보로 둡니다.
변경 전후는 같은 화면·기기·네트워크·캐시와 비슷한 요청량·동시 처리 조건에서 반복 비교하고, 실제 사용자 집단의 분포로 다시 확인합니다. 부하가 높을 때만 나타나는 문제는 해당 부하에서도 개선됐는지 검증합니다. 요청 수, 오류율과 자원 사용량도 함께 봅니다. 병렬화가 DB 부하를 늘리거나 캐시가 오래된 결과를 보여주는 식으로 문제가 옮겨가지 않았는지 확인합니다.
조사를 마칠 때는 다음 다섯 가지가 남아 있어야 합니다.
- 느렸던 사용자 동작, 완료의 정의와 비교 기준
- 전체 경로의 측정 경계와 아직 관측하지 못한 범위
- 문제 구간을 좁힌 근거와 정상으로 확인한 구간
- 변경 전후의 사용자 시간, 오류율과 자원 영향
- 평소 수집 정책과 한시적으로 늘린 계측의 종료 조건
웹 성능 조사는 사용자가 기다린 시간 중 아직 설명되지 않은 구간을 찾는 과정입니다. 경계 양쪽의 근거로 범위를 좁히고, 같은 동작이 실제로 빨라졌는지 확인하는 데까지 이어져야 합니다.
함께 읽기 좋은 글
- JVM 메트릭만으로는 컨테이너를 설명할 수 없다 — 애플리케이션 내부 지표 바깥의 자원 제약을 조사할 때 함께 볼 수 있습니다.
- 메트릭은 당겨야 할까, 밀어야 할까: Pull과 Push 수집 방식 비교 — 수집 경로의 실패, 버퍼링과 운영 책임을 다룹니다.