infra
Platform

모듈 맵

[Infra Ops] HTTP 요청이 서버에 도달하기까지의 전체 흐름

0 / 52 완료

펼치기
0 / 52 완료0%

Infra-ops · 11 / 52

[Infra Ops] HTTP 요청이 서버에 도달하기까지의 전체 흐름

Client → DNS → L4/L7 LB → WAF → Nginx → Tomcat → App → DB까지 — 장애 발생 시 어느 구간이 문제인지 정확히 짚어내기 위한 요청 흐름 추적 실무

🚨INCIDENT ALERT
HIGH

새벽 2시 15분. 슬랙 알림이 울립니다. "결제 API 오류 급증 — 고객 민원 다수 접수됨". 모니터링 대시보드를 열어보니 HTTP 5xx 에러율이 갑자기 치솟고 있습니다.

Tomcat은 살아있습니다. DB도 응답합니다. 그런데 왜 502가 쏟아질까요.

이 상황에서 "어느 구간이 문제인가"를 5분 안에 파악하지 못하면 복구는 점점 늦어집니다. HTTP 요청이 클라이언트에서 DB까지 거치는 모든 구간을 알고 있어야 — 장애 위치를 빠르게 좁힐 수 있습니다.

이번 챕터에서 배울 것
  • 1DNS 조회 순서(/etc/hosts → DNS 서버)와 TTL의 의미를 설명할 수 있다
  • 2L4/L7 로드밸런서의 차이와 X-Forwarded-For 헤더의 역할을 설명할 수 있다
  • 3Nginx의 요청 처리 흐름과 access_log에서 upstream 정보를 읽을 수 있다
  • 4curl -v로 HTTP 요청 전체 흐름을 추적하고 각 단계를 해석할 수 있다
  • 5502 에러 발생 시 Nginx-Tomcat 구간의 문제를 진단하는 루틴을 실행할 수 있다

DNS와 도메인 해석 단계

요청의 시작은 도메인 이름을 IP 주소로 바꾸는 것입니다. 이 변환이 실패하거나 잘못된 IP를 반환하면 요청은 아예 시작되지 않습니다.

💡개념

DNS 조회 순서와 /etc/hosts의 역할

브라우저가 https://example.com을 요청하는 순간, OS는 IP 주소를 알아내기 위해 순서대로 다음 위치를 조회합니다.

HTTP 요청 전체 흐름 — DNS에서 DB까지

IP를 변경했는데 일부 사용자만 계속 구 서버로 접속하는 문제가 있었습니다. DNS TTL이 아직 살아있어 캐시된 IP를 사용하고 있었기 때문입니다. 개발팀에서 /etc/hosts에 테스트 서버 IP를 등록해뒀다가 실수로 운영 서버에도 같은 파일을 배포해 트래픽이 엉뚱한 서버로 가기도 합니다. DNS가 어떻게 동작하는지 모르면 이런 상황에서 원인조차 찾을 수 없습니다.

1단계 — /etc/hosts 우선 조회

OS가 가장 먼저 확인하는 곳입니다. 파일에 도메인-IP 매핑이 있으면 DNS 서버로 질의를 보내지 않고 즉시 사용합니다.

로컬 터미널
# /etc/hosts 예시
127.0.0.1   localhost
192.168.1.50  internal-api.company.com

이 특성을 알면 두 가지 실수를 이해할 수 있습니다. 개발계에서 /etc/hosts에 내부 도메인을 추가해뒀다가 운영계에서 그 항목 때문에 잘못된 서버로 요청이 가는 경우, 반대로 장애 대응 중 hosts를 수정했지만 다른 서버에는 반영 안 된 경우가 대표적입니다.

2단계 — /etc/resolv.conf로 DNS 서버 지정

/etc/hosts에 항목이 없으면 /etc/resolv.conf에 기록된 DNS 서버로 질의를 보냅니다.

로컬 터미널
# /etc/resolv.conf 예시
nameserver 8.8.8.8       # 첫 번째로 질의할 DNS 서버
nameserver 8.8.4.4       # 첫 번째 실패 시 대체
search company.com       # 짧은 호스트명에 자동으로 붙이는 도메인

DNS 질의 흐름 — 캐시 → 재귀 질의

DNS 서버가 응답을 갖고 있으면 캐시에서 즉시 반환합니다. 없으면 루트 DNS → TLD DNS → 권한 DNS 순으로 재귀 질의를 수행합니다.

TTL(Time To Live)과 DNS 전파

DNS 레코드에는 TTL이 설정돼 있습니다. TTL이 300이면 5분 동안 캐시가 유지됩니다. IP를 변경해도 기존 TTL이 만료되기 전까지는 옛 IP로 요청이 갈 수 있습니다. "도메인 바꿨는데 일부 사용자만 반영이 안 된다"는 이 TTL 때문입니다.

내부 DNS vs 공인 DNS

사내 서비스는 공인 DNS에 등록하지 않습니다. 내부 DNS 서버를 따로 운영하거나 /etc/hosts를 사용해 내부 도메인을 해석합니다. 인프라 엔지니어는 내부 DNS 레코드 추가 요청을 자주 받습니다.

로드밸런서 통과 단계

DNS가 반환한 IP는 실제 서버의 IP가 아니라 로드밸런서의 VIP(가상 IP)인 경우가 대부분입니다.

💡개념

L4 vs L7 로드밸런서, 그리고 클라이언트 IP 보존

Nginx 접근 로그에서 모든 IP가 같은 주소로 찍히는 현상이 있었습니다. 앞에 L7 로드밸런서가 있는데 X-Forwarded-For 헤더 설정이 없어서 Nginx 입장에서는 모든 요청이 LB에서 오는 것처럼 보였기 때문입니다. 클라이언트 IP를 모르면 특정 사용자 문제 추적도, 보안 차단도 불가능해집니다. L4와 L7의 동작 방식 차이가 IP 보존 방법을 결정합니다.

L4 로드밸런서 — IP:Port 기반 라우팅

L4 LB는 패킷의 IP 주소와 포트만 보고 라우팅합니다. HTTP 헤더를 읽지 않습니다. 처리 속도가 빠르지만 URL 경로나 헤더 기반 라우팅은 불가능합니다.

클라이언트 IP 보존 방법으로 DSR(Direct Server Return)이나 프록시 프로토콜을 사용하지만, 설정이 없으면 서버에서 보이는 $remote_addr은 LB의 IP가 됩니다.

L7 로드밸런서 — HTTP 헤더 기반 라우팅

L7 LB는 HTTP 요청 전체를 읽습니다. URL 경로, 쿠키, 헤더 값에 따라 다른 서버로 보낼 수 있습니다.

L7 LB가 요청을 백엔드로 전달할 때 원래 클라이언트 IP를 헤더에 담아 보냅니다.

헤더내용
X-Forwarded-For클라이언트 실제 IP (프록시 체인 포함 가능)
X-Real-IP최종 클라이언트 IP만 단독으로 기록
X-Forwarded-Proto원래 프로토콜 (http / https)

Nginx의 access_log에서 $remote_addr은 LB의 IP를, $http_x_forwarded_for는 실제 클라이언트 IP를 출력합니다.

WAF(Web Application Firewall)

대부분의 L7 LB 앞단이나 내부에 WAF가 위치합니다. SQL Injection, XSS, 비정상 요청 패턴을 탐지해 차단합니다. WAF가 요청을 차단하면 클라이언트에게 403이 반환되고 Nginx에는 요청이 도달하지 않습니다. "서버는 정상인데 403이 떨어진다"면 WAF 차단 로그를 먼저 확인해야 합니다.

SSL 종료 위치

SSL(TLS)을 어디서 끊느냐는 보안 정책과 운영 편의성의 균형입니다.

종료 위치장점단점
LB에서 종료인증서 한 곳에서 관리, 백엔드 부하 감소LB → Nginx 구간은 평문 HTTP
Nginx에서 종료암호화 구간 연장서버마다 인증서 관리 필요

내부망이 신뢰 가능하면 LB에서 종료하는 것이 일반적입니다.

Nginx 처리 단계

LB를 통과한 요청은 Nginx에 도달합니다. Nginx는 요청을 직접 처리하거나 Tomcat으로 전달합니다.

💡개념

Nginx의 요청 처리 흐름과 로그 읽기

Nginx는 단순한 정적 파일 서버가 아니라 요청을 받아 어디로 보낼지 결정하는 트래픽 제어 지점입니다. location 블록 매칭 규칙을 모르면 특정 경로의 502 원인을 찾는 데 한참이 걸리고, access_log의 upstream 변수를 읽지 못하면 어느 Tomcat 인스턴스에 문제가 생겼는지 파악할 수 없습니다. Nginx 설정과 로그 구조를 이해하는 것이 요청 흐름 추적의 핵심입니다.

요청 수신 → server 블록 → location 블록

특정 API 경로만 502가 났는데 Tomcat은 살아있었습니다. Nginx 설정을 확인하니 해당 경로의 location 블록이 Tomcat이 아닌 다른 upstream을 바라보고 있었습니다. location 블록 매칭 규칙을 몰라서 어떤 요청이 어디로 가는지 파악하지 못했기 때문입니다. access_log의 $upstream_addr을 읽을 수 있으면 요청이 어느 Tomcat으로 갔는지 1분 안에 확인할 수 있습니다.

Nginx는 도착한 요청의 Host 헤더와 URL 경로를 보고 어떻게 처리할지 결정합니다.

Nginx
server {
    listen 80;
    server_name example.com;

    # 정적 파일 직접 서빙
    location /static/ {
        root /var/www/html;
    }

    # 동적 요청은 Tomcat으로 전달
    location /api/ {
        proxy_pass http://tomcat_upstream;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

upstream tomcat_upstream {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    keepalive 32;          # 커넥션 재사용 (매 요청마다 TCP 연결 새로 맺지 않음)
}

정적 파일 vs proxy_pass

  • 정적 파일(.html, .js, .css, 이미지): Nginx가 디스크에서 직접 읽어 응답. Tomcat까지 가지 않습니다.
  • /api/ 경로: proxy_pass로 Tomcat에 전달. Nginx는 중간 전달자 역할.

access_log에서 읽을 수 있는 정보

Nginx
# 기본 log_format에 upstream 정보 추가
log_format main '$remote_addr - $request - $status - $upstream_addr - $upstream_response_time - $http_x_forwarded_for';
변수의미
$remote_addr요청을 보낸 IP (LB IP가 찍힘)
$http_x_forwarded_for실제 클라이언트 IP
$upstream_addr요청을 전달한 Tomcat 서버 IP:Port
$upstream_response_timeTomcat 응답 시간 (초 단위)
$status최종 HTTP 상태 코드

$upstream_response_time이 길어지기 시작하면 Nginx-Tomcat 구간이 아니라 Tomcat 내부(또는 DB)가 느린 것입니다.

HTTP 상태코드 — 운영 중 자주 만나는 오류

Tomcat + App + DB 단계

Nginx로부터 요청을 받은 Tomcat은 Java 애플리케이션을 실행합니다.

💡개념

Tomcat에서 DB까지의 처리 흐름과 로그 위치

Nginx는 빠른데 응답이 느리다는 제보가 왔습니다. Nginx $upstream_response_time을 보니 30초가 찍혀 있었고, Tomcat catalina.out에는 DB 커넥션 타임아웃 오류가 가득했습니다. 문제는 Nginx-Tomcat 구간이 아니라 Tomcat-DB 구간이었습니다. 어느 단계에서 시간이 소비되는지 알아야 정확한 원인을 찾을 수 있습니다.

요청 처리 순서

Tomcat 수신
  → Filter 체인 (인증, 로깅, CORS 등)
    → Dispatcher Servlet
      → Controller (URL 매핑)
        → Service (비즈니스 로직)
          → Repository / DAO
            → DB Connection Pool에서 커넥션 획득
              → SQL 실행 → DB 응답
            → 커넥션 반환 (Pool로 되돌림)
          ← 결과 반환
        ← DTO 조립
      ← JSON 직렬화
    ← HTTP 응답
  ← Nginx로 반환
← 클라이언트에 전달

DB Connection Pool

Tomcat은 매 요청마다 DB에 새로 연결하지 않습니다. 미리 만들어둔 커넥션 Pool에서 빌려 쓰고 반납합니다. Pool의 커넥션이 모두 사용 중이면 요청은 대기 상태가 됩니다. 이 대기가 쌓이면 Tomcat 응답 시간이 길어지고 결국 Nginx에서 타임아웃이 발생해 502가 됩니다.

각 단계별 로그 위치

구성요소로그 위치확인할 내용
Nginx/var/log/nginx/access.log요청 유입, 상태 코드, upstream 응답 시간
Nginx/var/log/nginx/error.logupstream 연결 실패, 타임아웃
Tomcat$CATALINA_HOME/logs/catalina.outJVM 오류, 애플리케이션 예외
애플리케이션/app/logs/application.log (경로 다양)비즈니스 로직 에러
DBMySQL slow query log느린 쿼리 (long_query_time 초과)

응답은 역순으로 반환됩니다. DB → Repository → Service → Controller → Tomcat → Nginx → LB → 클라이언트. 각 구간에서 처리 시간이 누적됩니다.

단계별 요청 추적 실습

DNS 해석 확인
🔍curl -v 출력 해석 방법
  • * Trying IP:PORT... — TCP 연결 시도. 여기서 멈추면 LB/방화벽 문제
  • * Connected to ... — TCP 연결 성공. 이 줄이 나오면 L4 통과
  • * SSL connection using TLS... — SSL 핸드셰이크 진행. 인증서 문제는 여기서 확인
  • > GET /api/health HTTP/1.1 — 요청 전송 (이후는 Nginx가 받음)
  • < HTTP/1.1 200 OK — 응답 상태 코드. 502면 Nginx-Tomcat 구간 문제
  • 연결 자체가 안 되면 (connection refused) Nginx가 응답 안 하는 것
Nginx 로그에서 요청 흐름 추적
🔍Nginx 로그에서 확인할 핵심 패턴
  • 특정 $upstream_addr에만 502가 집중 → 해당 Tomcat 인스턴스 장애
  • 모든 upstream에 502 → Nginx-Tomcat 방화벽 차단이나 네트워크 문제 가능성
  • $upstream_response_time이 30초 근접 → Tomcat keepalive timeout 설정 확인
  • $remote_addr이 전부 같은 IP → LB IP가 찍히는 것 (정상). $http_x_forwarded_for로 실제 클라이언트 파악

장애 시나리오 — 새벽 2시의 502 추적

💼
실무 맥락
현업 패턴

장애 대응 루틴 — 어느 구간인지 5분 안에 좁히는 방법

새벽 2시에 결제 API 오류 알림이 오면 다음 순서로 확인합니다.

1단계 — 구간 범위 파악 (1분)

외부에서 접근이 아예 안 되는지, 내부에서는 되는지 확인합니다. 외부만 안 되면 LB 또는 WAF 구간입니다. 내부에서도 안 되면 Nginx 이하 구간입니다.

2단계 — Nginx 로그 확인 (1분)

로컬 터미널
tail -50 /var/log/nginx/access.log
tail -50 /var/log/nginx/error.log

502 에러가 보이고 upstream이 언급되면 Nginx-Tomcat 구간입니다. 에러가 없으면 Nginx까지는 정상.

3단계 — Tomcat 직접 연결 확인 (1분)

로컬 또는 서버
curl -v http://WAS_IP:8080/health

이 명령이 성공하면 Nginx 설정 문제입니다. 실패하면 Tomcat 자체 또는 그 이하(DB, 커넥션 풀)를 확인합니다.

4단계 — 로그 수집 및 에스컬레이션 (2분)

각 계층 로그를 확인하고 개발팀에 공유합니다.

로컬 터미널
# Tomcat 에러 로그
tail -100 /opt/tomcat/logs/catalina.out | grep -E 'ERROR|Exception'

# DB 연결 상태 (DBA에게 확인 요청)
# slow query log, connection count 등

"어느 구간이 문제인가"를 먼저 좁혀야 복구 방향이 결정됩니다. 로그도 안 보고 Tomcat부터 재시작하는 것은 원인을 모르는 채로 증거를 지우는 행위입니다.

다음 모듈에서는 Nginx 설정의 핵심 — 가상 호스트, 리버스 프록시, SSL 설정을 실습합니다.

지식 확인

퀴즈 — 4문제

Q1

사용자가 브라우저에 도메인을 입력했을 때 DNS 조회가 이루어지는 순서로 올바른 것은?

Q2

L4/L7 로드밸런서를 통과한 요청에서 클라이언트의 실제 IP를 얻으려면 어떤 HTTP 헤더를 참조해야 하는가?

Q3

Nginx에서 502 Bad Gateway 에러가 발생하는 가장 일반적인 원인은?

Q4

curl로 HTTP 요청의 전체 흐름(연결 과정, 요청/응답 헤더, 타이밍 등)을 상세하게 추적할 때 사용하는 옵션은?

0 / 4 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

30📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요

infra-ops중급 · 65
[Infra Ops] Nginx 리버스 프록시와 로드밸런싱 설정
인프라 서비스 운영 트랙 계속
linux입문 · 30
[Linux] 개발자가 왜 리눅스 서버와 커맨드라인을 반드시 배워야 하는가
Linux 트랙 시작점