1. 개요
Node.js에서 HTTPS 요청을 보내다 보면
인증서 관련 오류를 만나는 경우가 있다.
대표적으로 다음과 같은 메시지다.
UNABLE_TO_VERIFY_LEAF_SIGNATURESELF_SIGNED_CERT_IN_CHAINDEPTH_ZERO_SELF_SIGNED_CERTCERT_HAS_EXPIREDERR_TLS_CERT_ALTNAME_INVALID
이런 오류를 처음 보면
"서버가 이상한가?" 정도로 생각하기 쉽다.
하지만 실제로는
인증서 체인, 만료, 호스트명, CA 신뢰 목록 등
여러 원인으로 발생할 수 있다.
이 글에서는 Node.js에서 인증서 오류가 나는 이유와
어떻게 확인해야 하는지 정리한다.
2. 왜 인증서 오류가 발생하는가
HTTPS 연결에서는
단순히 암호화만 하는 것이 아니다.
Node.js는 서버가 보낸 인증서를 보고
다음 항목을 검증한다.
- 신뢰할 수 있는 CA가 발급했는가
- 인증서 체인이 올바른가
- 인증서가 만료되지 않았는가
- 접속한 도메인과 인증서의 호스트명이 일치하는가
즉, 인증서 오류는
대부분 이 검증 과정 중 하나가 실패했다는 의미다.
3. 가장 자주 보는 오류 1: UNABLE_TO_VERIFY_LEAF_SIGNATURE
이 오류는 보통
서버 인증서를 신뢰 체인 끝까지 검증하지 못할 때 발생한다.
대표적인 원인은 다음과 같다.
- Intermediate 인증서 누락
- 신뢰하지 않는 CA 사용
- 사설 인증서 체인 문제
즉, 서버 인증서 자체는 있어도
그 인증서를 "누가 보증하는지"를 끝까지 따라가지 못하는 상황이다.
확인할 것
- 서버가 Intermediate 인증서를 함께 보내는가
- 사용하는 CA가
Node.js에서 신뢰되는가 - 사내 프록시나 보안 장비가 인증서를 바꾸고 있지는 않은가
4. 가장 자주 보는 오류 2: SELF_SIGNED_CERT_IN_CHAIN
이 오류는 인증서 체인 안에
신뢰되지 않는 self-signed 인증서가 포함되어 있을 때 발생한다.
주로 다음과 같은 상황에서 나타난다.
- 사내망 프록시가 자체 인증서를 끼워 넣는 경우
- 개발 환경에서 self-signed 인증서를 사용하는 경우
- 내부 서비스가 사설 CA를 사용하는 경우
즉, 인증서가 형식상 잘못된 것이 아니라Node.js가 기본적으로 신뢰하지 않는 인증서라는 의미다.
확인할 것
- 사내 프록시 인증서를 사용 중인가
- 로컬/개발 서버에서 self-signed 인증서를 쓰고 있는가
- 별도 CA 등록이 필요한 환경인가
5. 가장 자주 보는 오류 3: DEPTH_ZERO_SELF_SIGNED_CERT
이 오류는 서버가 self-signed 인증서를 직접 사용하고 있을 때 자주 발생한다.
즉, 인증서 체인을 따라 올라갈 CA가 없고,
서버 인증서 자신이 곧 서명자 역할까지 하고 있는 경우다.
이 상황은 로컬 개발에서는 흔하지만,
기본 설정의 Node.js에서는 신뢰되지 않는다.
확인할 것
- 개발용 인증서인가
- 운영 환경에서도 self-signed 인증서를 쓰고 있지는 않은가
- 테스트 환경에서만 예외 처리가 필요한가
6. 가장 자주 보는 오류 4: CERT_HAS_EXPIRED
이 오류는 비교적 단순하다.
인증서의 유효 기간이 끝났다는 뜻이다.
대표적인 원인은 다음과 같다.
- 서버 인증서 만료
- Intermediate 인증서 만료
- 시스템 시간 문제
겉으로는 "서버는 잘 열리는데 Node.js만 실패한다"처럼 보일 수 있지만,
실제로는 인증서 만료가 원인인 경우가 많다.
확인할 것
- 서버 인증서 만료일
- Intermediate 인증서 만료일
- 서버와 클라이언트 시스템 시간이 정확한가
7. 가장 자주 보는 오류 5: ERR_TLS_CERT_ALTNAME_INVALID
이 오류는 도메인과 인증서 대상이 맞지 않을 때 발생한다.
예를 들어:
api.example.com에 접속했는데- 인증서에는
www.example.com만 포함된 경우
이 경우 인증서는 유효할 수 있어도
현재 접속 대상과 일치하지 않기 때문에 실패한다.
요즘은 보통 인증서의 SAN(Subject Alternative Name)을 기준으로 검증한다.
확인할 것
- 접속 중인 도메인이 무엇인가
- 인증서 SAN에 해당 도메인이 포함되어 있는가
- 와일드카드 인증서 범위가 맞는가
8. 로컬에서는 되는데 서버에서만 실패하는 이유
실무에서 가장 헷갈리는 상황 중 하나다.
로컬에서는 정상인데
배포 서버에서만 인증서 오류가 나는 경우가 있다.
대표적인 이유는 다음과 같다.
- 운영 서버의 CA 신뢰 목록 차이
- 사내 네트워크 프록시 영향
- 컨테이너 이미지에 루트 인증서가 부족한 경우
- Node.js 버전 또는 OpenSSL 환경 차이
즉, 같은 코드여도
실행 환경이 다르면 인증서 검증 결과가 달라질 수 있다.
9. 인증서 오류를 확인할 때 가장 먼저 볼 것
인증서 오류를 만나면
다음 순서로 확인하는 것이 좋다.
- 인증서가 만료되었는가
- 접속 도메인과 SAN이 일치하는가
- Intermediate 인증서가 누락되지 않았는가
- 신뢰하지 않는 CA 또는 self-signed 인증서인가
- 실행 환경의 CA 저장소가 충분한가
즉, 오류 메시지만 보지 말고
검증 단계별로 확인해야 한다.
10. Node.js에서 기본 HTTPS 요청 예시
const https = require("https");
https.get("https://example.com", (res) => {
console.log(res.statusCode);
}).on("error", (err) => {
console.error(err);
});
이 코드는 단순하지만,
연결 과정에서 TLS 핸드셰이크와 인증서 검증이 함께 수행된다.
즉, 요청이 실패했다면
단순한 네트워크 오류가 아니라
인증서 검증 실패일 수도 있다.
11. 무엇을 확인하면 좋을까
실제 확인 포인트는 크게 네 가지다.
1. 인증서 만료일
- 서버 인증서가 만료되지 않았는가
- 중간 인증서도 만료되지 않았는가
2. 도메인 일치 여부
- 현재 접속 URL과 SAN이 일치하는가
3. 인증서 체인
- Intermediate 인증서가 빠져 있지 않은가
- 서버가 체인을 올바르게 전달하는가
4. 신뢰할 수 있는 CA인가
- 사설 CA 또는 self-signed 인증서인가
- 실행 환경이 그 CA를 신뢰하는가
12. rejectUnauthorized: false로 넘기면 안 되는 이유
개발 중에는 아래처럼 우회하는 경우가 있다.
const agent = new https.Agent({
rejectUnauthorized: false,
});
이렇게 하면 연결은 될 수 있다.
하지만 이는 문제 해결이 아니라
인증서 검증 자체를 끄는 것이다.
즉, 상대 서버가 진짜인지 확인하지 않고 통신하게 된다.
운영 환경에서는 매우 위험하다.
👉 인증서 오류의 핵심은
"어떻게 우회할까"가 아니라
"왜 검증이 실패했는가"를 찾는 것이다.
13. 실무에서 자주 하는 실수
인증서 오류를 다룰 때 자주 하는 실수는 다음과 같다.
- 서버 인증서만 보고 Intermediate 인증서를 확인하지 않음
- 도메인 불일치를 놓침
- 로컬 환경에서만 테스트하고 배포 서버 차이를 보지 않음
- 사내 프록시가 인증서를 바꾸는 상황을 놓침
rejectUnauthorized: false로 임시 처리한 뒤 그대로 배포함
즉, 인증서 오류는
단순한 코드 문제가 아니라
런타임 환경과 신뢰 체인 전체를 함께 봐야 하는 문제다.
14. 정리
Node.js인증서 오류는 대부분 TLS 검증 실패에서 발생한다- 대표 원인은 체인 문제, 만료, 도메인 불일치, self-signed 인증서다
- 로컬과 운영 환경의 CA 신뢰 목록 차이도 중요한 원인이다
- 오류 메시지에 따라 확인 포인트가 조금씩 다르다
- 우회보다 원인 파악이 먼저다
결국 핵심은
"서버 인증서가 있는가"가 아니라
"그 인증서를 지금 환경에서 신뢰할 수 있는가"다.
15. 결론
Node.js에서 인증서 오류가 나는 이유는
생각보다 다양하다.
하지만 대부분은 몇 가지 범주로 정리할 수 있다.
- 신뢰 체인 문제
- 만료 문제
- 도메인 불일치
- self-signed 또는 사설 CA 문제
이 흐름을 이해하고 나면
에러 메시지를 봤을 때도
어디부터 확인해야 할지 훨씬 명확해진다.
특히 실무에서는
우회 설정을 넣기보다
인증서 검증이 어떤 단계에서 실패했는지 파악하는 것이 더 중요하다.
'Develope > Node.js' 카테고리의 다른 글
| Node.js Event Loop란 무엇인가? 동작 원리와 setTimeout, setImmediate 차이 (1) | 2026.04.15 |
|---|---|
| Node.js에서 TLS 인증서 검증은 어떻게 동작하는가 (0) | 2026.04.14 |
| Node.js에서 신뢰하는 CA 인증서 목록 확인 방법 (0) | 2026.04.08 |
| Express IP 주소 가져오기 (0) | 2022.09.14 |
| NVM을 이용하여 Node.js 버전 변경 또는 관리하기 (0) | 2021.01.27 |