✅ 문제 배경
회사 내부 시스템이나 개발 환경에서는 종종 Let's Encrypt 같은 인증기관(CA)을 거치지 않고, OpenSSL 등으로 만든 자체 서명된 인증서(Self-signed certificate) 를 사용하는 경우가 많습니다. 예를 들면, 다음과 같은 시스템에 자체 인증서가 사용될 수 있습니다:
- 내부 로그인 서버 (예: Keycloak)
- 내부 파일 저장 서버 (예: MinIO)
- API 서버 (직접 만든 HTTPS 서버)
이때 이들 서버와 Node.js 기반 서버(Next.js, NestJS 등) 가 통신하려고 하면, 아래와 같은 에러가 발생할 수 있습니다:
Error: self signed certificate
UNABLE_TO_VERIFY_LEAF_SIGNATURE
🧨 왜 이런 문제가 생기나요?
📌 1. HTTPS는 신뢰 기반으로 작동합니다
HTTPS는 웹 브라우저나 서버가 "상대방이 진짜인지" 확인하기 위해 공식적으로 인증된 신뢰 기관(CA) 에서 발급한 인증서를 사용합니다.
📌 2. Node.js도 똑같이 검증합니다
Node.js도 기본적으로 운영 체제에 내장된 '공식 인증서 목록(CA 목록)' 만을 신뢰합니다. 이 목록에 등록된 인증서만 믿습니다.
📌 3. 그런데 자체 서명 인증서는?
- 자체 서명된 인증서는 이 공식 목록에 없기 때문에 신뢰하지 않습니다.
- 인증기관이 검증해준 적도 없고, Node.js 입장에서 보면 "이거 누가 만든 건데? 못 믿겠어!" 같은 상태입니다.
✅ 방법 1. NODE_TLS_REJECT_UNAUTHORIZED=0 (모든 검증 무시 – 개발 한정)
services:
node-app:
image: your-node-app
environment:
- NODE_TLS_REJECT_UNAUTHORIZED=0
이 설정은 모든 HTTPS 인증서 검증을 끕니다.
🚨 주의
- 이 방법은 너무 위험해서 운영 환경에서는 절대 사용하면 안 됩니다.
- 공격자가 중간에 끼어들어도 눈치 못 챌 수 있습니다.
- 정말 개발 중 "일단 되게만 하자" 할 때만 임시로 쓰세요.
✅ 방법 2. 신뢰할 인증서를 수동으로 지정 (NODE_EXTRA_CA_CERTS)
이 방법은 안전하고, 운영 환경에서도 사용할 수 있습니다.
📌 과정 요약
- 서버가 사용하는 인증서를 .crt 형식으로 저장
- docker-compose로 해당 인증서를 컨테이너 내부에 복사
- Node.js가 해당 인증서를 추가 신뢰 목록으로 인식하도록 환경 변수 설정
📁 디렉토리 구성 예시
project/
├── docker-compose.yml
└── certs/
└── my-ca.crt ← 자체 서명된 인증서
🛠️ docker-compose.yml 예시
services:
node-app:
image: your-node-app
volumes:
- ./certs/my-ca.crt:/usr/local/share/ca-certificates/my-ca.crt:ro
environment:
- NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/my-ca.crt
이렇게 설정하면, Node.js는 my-ca.crt 인증서를 공식 CA처럼 믿고 통신합니다.
대부분의 fetch, axios, graphql, grpc 요청이 오류 없이 작동하게 됩니다.
✅ 방법 3. 시스템 trust store 전체 교체 (SSL_CERT_FILE)
Linux 시스템에 존재하는 전체 신뢰 CA 목록을 덮어쓰는 방법입니다.
📁 먼저 호스트에서 기존 목록과 합치기
cat /etc/ssl/certs/ca-certificates.crt ./certs/my-ca.crt > combined-ca.crt
🛠️ docker-compose.yml 예시
services:
node-app:
image: your-node-app
volumes:
- ./combined-ca.crt:/etc/ssl/certs/ca-certificates.crt:ro
environment:
- SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
이 방법은 전체 시스템에서 사용하는 인증서 목록을 교체하므로 보다 광범위하게 적용되며, 역시 코드 수정 없이 적용 가능합니다.
✅ 요약
방법 | 설명 | 보안성 | 환경 |
NODE_TLS_REJECT_UNAUTHORIZED=0 | 인증서 검증 무시 | ❌ 매우 낮음 | 개발 전용 |
NODE_EXTRA_CA_CERTS | 특정 인증서만 신뢰 | ✅ 안전 | 운영 가능 |
SSL_CERT_FILE | 전체 신뢰 인증서 목록 교체 | ✅ 보안적 | 운영 가능 |
'Javascript' 카테고리의 다른 글
[JS] 일반 함수, 화살표 함수 (0) | 2025.04.13 |
---|---|
[typescript] 선언 합침, 외부 선언 (0) | 2025.03.15 |
[TS] Omit (0) | 2025.03.08 |
[JS] ESLint와 TypeScript 설정에서 ES 버전 차이 (0) | 2024.09.01 |
[JS] Turborepo를 활용한 공통 라이브러리 관리 (0) | 2024.08.31 |