금요일

Nginx 502 Bad Gateway 해결 — upstream 에러 원인별 완전 정리

🔍 검색 키워드: nginx 502 bad gateway 해결, nginx upstream 에러, nginx 리버스 프록시 502, nginx proxy_read_timeout, upstream sent too big header

Nginx62�는 리버스 프록시로 쓰다 보면 피할 수 없는 에러가 502다.

502 Bad Gateway
nginx/1.x.x

사용자한테 이게 보이는 순간 장애다. 빠르게 원인 찾고 고쳐야 하는데, 502는 원인이 한두 가지가 아니다. 이 글에서 발생 빈도 높은 원인과 해결책을 순서대로 정리한다.


1. 502 Bad Gateway는 뭔가

Nginx가 업스트림 서버(백엔드 앱, WAS, API 서버)에 요청을 넘겼는데 제대로 된 응답을 못 받았을 때 클라이언트에게 돌려주는 응답이다.

즉, Nginx 자체의 문제가 아니라 Nginx 뒤에 있는 서버의 문제다.


2. 원인별 분류 및 해결

원인 1: 업스트림 서버가 꺼져 있다 (가장 흔함)

에러 로그:

2026/06/26 10:00:00 [error] 12345#0: *1 connect() failed (111: Connection refused)
while connecting to upstream, upstream: "http://127.0.0.1:8080/api/health"

Connection refused가 보이면 백엔드 앱이 죽은 거다.

# 프로세스 확인
ps aux | grep java
ps aux | grep node
ps aux | grep gunicorn

# 포트 리스닝 확인
ss -tlnp | grep 8080

프로세스가 없으면 앱을 재시작한다. 재시작 후에도 바로 죽는다면 앱 자체의 에러 로그를 봐야 한다.

원인 2: 타임아웃

에러 로그:

upstream timed out (110: Operation timed out) while reading response header from upstream

백엔드가 살아있긴 한데 응답이 너무 느린 경우다. Nginx의 기본 타임아웃값(60초)을 넘기면 이 에러가 발생한다.

# nginx.conf 또는 서버 블록
location / {
    proxy_pass http://localhost:8080;

    proxy_connect_timeout 60s;   # 연결 타임아웃
    proxy_send_timeout    60s;   # 요청 전송 타임아웃
    proxy_read_timeout    120s;  # 응답 수신 타임아웃 (이걸 늘리면 됨)
}

배치 작업이나 파일 업로드처럼 처리 시간이 긴 요청은 proxy_read_timeout을 요청 성격에 맞게 올린다. 무작정 크게 올리는 건 좋지 않고, 실제 처리 시간 + 여유분 정도로 설정한다.

원인 3: 업스트림 헤더가 너무 크다

에러 로그:

upstream sent too big header while reading response header from upstream

백엔드 응답의 HTTP 헤더가 Nginx 버퍼 크기를 초과한 경우다. 쿠키가 많거나 커스텀 헤더를 대량으로 쓰는 앱에서 발생한다.

location / {
    proxy_pass http://localhost:8080;

    proxy_buffer_size          128k;
    proxy_buffers              4 256k;
    proxy_busy_buffers_size    256k;
}

헤더 크기를 줄이는 게 근본 해결이지만, 당장 급하면 버퍼를 올린다.

원인 4: Unix 소켓 권한 문제

PHP-FPM이나 Gunicorn을 소켓으로 연결할 때 발생한다.

connect() to unix:/var/run/php-fpm.sock failed (13: Permission denied)
# 소켓 파일 권한 확인
ls -la /var/run/php-fpm.sock

# 소켓 파일 소유권 변경
chown www-data:www-data /var/run/php-fpm.sock
chmod 660 /var/run/php-fpm.sock
; /etc/php-fpm.d/www.conf
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

3. 빠른 진단 순서

# 1. Nginx 에러 로그 확인 (제일 먼저)
tail -f /var/log/nginx/error.log

# 2. 업스트림 서버 상태 확인
curl -I http://127.0.0.1:8080/

# 3. 포트 리스닝 확인
ss -tlnp | grep 8080

# 4. Nginx 설정 문법 검사
nginx -t

# 5. Nginx 재시작 (설정 변경 후)
systemctl reload nginx

에러 로그에 Connection refused, timed out, Permission denied, too big header 중 뭐가 찍혀 있는지 먼저 보는 게 핵심이다.


4. 원인별 체크리스트

에러 로그 키워드 원인 해결 방법
Connection refused 업스트림 프로세스 다운 앱 재시작
timed out 응답 지연 proxy_read_timeout 증가
too big header 헤더 버퍼 부족 proxy_buffer_size 증가
Permission denied 소켓 권한 문제 소켓 파일 권한 수정
no live upstreams 업스트림 그룹 전체 다운 업스트림 서버 상태 확인

5. 실무 팁 — health check 설정

업스트림이 다운됐을 때 Nginx가 알아서 fallback하도록 설정할 수 있다.

upstream backend {
    server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 backup;  # 메인이 죽으면 이걸로
}

max_fails는 해당 서버를 비활성화하기 전 실패 허용 횟수, fail_timeout은 비활성화 유지 시간이다.


정리

Nginx 502는 반드시 /var/log/nginx/error.log를 먼저 봐야 한다. 에러 메시지가 원인을 정확히 알려준다. Connection refused면 앱 프로세스 확인, timed out이면 타임아웃 설정, too big header면 버퍼 설정 — 이 세 가지가 전체 502의 대부분을 차지한다.

작성일: 2026-06-26

Redis WRONGTYPE Operation 해결 — 키 타입 충돌 완벽 정리

TypeScript cannot find module 해결 — ts(2307) 에러 완벽 정리

🔍 검색 키워드: typescript cannot find module, ts2307 에러 해결, tsconfig paths 설정, typescript module not found, cannot find module or its corresponding type declarations

TypeScript 프로젝트 하다 보면 한 번쯤은 꼭 만나는 에러다.

Cannot find module 'X' or its corresponding type declarations. ts(2307)

빌드도 안 되고, IDE에서도 빨간 줄 잔뜩 그어지면서 당황하게 된다. 이 에러는 발생 원인이 여러 가지라 원인을 제대로 모르면 해결책을 찾아 헤매다 시간만 버린다.


1. 증상

error TS2307: Cannot find module '../utils/logger' or its corresponding type declarations.
error TS2307: Cannot find module '@/components/Button' or its corresponding type declarations.
error TS2307: Cannot find module 'lodash' or its corresponding type declarations.

import 구문에서 빨간 줄이 생기고, tsc 실행 시 컴파일이 실패한다. VSCode 같은 IDE에서도 동일하게 에러가 표시된다.


2. 원인별 분류

크게 4가지 패턴으로 나뉜다.

패턴 1: @types 패키지 누락

서드파티 라이브러리를 설치했지만 TypeScript 타입 정의 패키지를 설치하지 않은 경우다. lodash, express, node 같은 라이브러리는 별도의 @types/xxx 패키지가 필요하다.

# 확인 방법
ls node_modules/@types/

# 해결
npm install --save-dev @types/lodash
npm install --save-dev @types/node
npm install --save-dev @types/express

패턴 2: tsconfig.json 경로 별칭(Path Alias) 미설정

@/, ~/ 같은 경로 별칭을 사용하는데 tsconfig에 paths 설정이 없는 경우다. Vite, Next.js, CRA 등에서 흔하게 발생한다.

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "~/*": ["src/*"]
    }
  }
}
주의: Next.js는 tsconfig.json의 paths를 자동으로 인식하지만, Node.js 환경에서 직접 실행할 때는 tsconfig-paths 패키지가 추가로 필요하다.
npm install --save-dev tsconfig-paths

# 실행 시
ts-node -r tsconfig-paths/register src/index.ts

패턴 3: moduleResolution 설정 불일치

Node.js 16+ 혹은 ES Modules를 사용할 때 moduleResolution 설정이 맞지 않는 경우다.

// tsconfig.json
{
  "compilerOptions": {
    "module": "NodeNext",
    "moduleResolution": "NodeNext"
  }
}

NodeNext 설정에서는 import 시 파일 확장자를 명시해야 한다.

// ❌ 에러
import { logger } from './utils/logger';

// ✅ 정상
import { logger } from './utils/logger.js';

컴파일된 결과가 .js이기 때문에 소스에서도 .js 확장자를 써야 한다. 처음엔 이상하게 느껴지지만 ESM 스펙이 이렇다.

패턴 4: node_modules 손상 또는 누락

패키지가 설치되어 있는데도 에러가 난다면 node_modules 자체가 손상됐을 가능성이 있다.

# 클린 재설치
rm -rf node_modules package-lock.json
npm install

3. 원인 진단 체크리스트

점검 항목 확인 방법 해결 방법
@types 패키지 설치 여부 ls node_modules/@types/ npm i -D @types/xxx
tsconfig paths 설정 tsconfig.json 확인 baseUrl + paths 추가
moduleResolution 설정 tsconfig.json 확인 NodeNext 또는 bundler
node_modules 상태 ls node_modules/[패키지명] 클린 재설치
상대 경로 확장자 import 구문 확인 .js 확장자 명시

4. --traceResolution 으로 정확히 추적하기

어디서 모듈을 찾는지 추적하고 싶다면 이 플래그를 쓴다.

tsc --traceResolution 2>&1 | grep -A 5 "Cannot find module"

TypeScript가 어떤 경로를 탐색했는지 전부 출력해준다. 설정 문제인지, 패키지 문제인지 바로 보인다.


5. 실제 사례 — Next.js에서 @/components 경로 에러

Cannot find module '@/components/Button' or its corresponding type declarations.

Next.js 프로젝트에서 흔히 겪는 케이스다.

// tsconfig.json — 이 설정이 없으면 에러 발생
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"]
    }
  }
}

Next.js 13+는 프로젝트 생성 시 자동으로 이 설정을 넣어주지만, 수동으로 구성한 프로젝트나 마이그레이션한 경우 누락되기 쉽다.


6. Jest + TypeScript 환경

Jestl��서도 같은 에러가 발생할 수 있다. Jest는 tsconfig의 paths를 직접 읽지 않기 때문에 별도 설정이 필요하다.

npm install --save-dev babel-jest @babel/preset-typescript ts-jest
// jest.config.js
module.exports = {
  preset: 'ts-jest',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

moduleNameMapper로 tsconfig의 paths와 동일하게 맞춰줘야 한다.


정리

TypeScript cannot find module 에러는 딱 떨어지는 단일 원인이 아니다. 발생 맥락을 보고 위 패턴 중 어디에 해당하는지 진단하는 게 먼저다. --traceResolution으로 탐색 경로를 직접 확인하면 대부분 30분 안에 해결된다.

작성일: 2026-06-26