펀치블로그를 처음 연결할 때 AWS Lightsail 화면에는 등록된 도메인과 같은 이름의 DNS 영역이 함께 보였다. 정적 페이지도 서버에 준비돼 있었다. 그런데 punchblog.com으로 방문했을 때 준비한 페이지가 열리지는 않았다. 도메인 등록, DNS 지정, 웹 서버 연결이 각각 어느 단계까지 끝났는지를 따로 확인해야 했다.
이 글은 2026년 9월 12일 실제 연결 작업 기록과, 작업 후 별도로 저장한 DNS·HTTP 검사 결과를 구분해 정리한 것이다. 처음 실패한 모든 요청의 패킷이나 상세 오류를 보관한 것은 아니므로, 특정 타임아웃의 원인을 하나로 단정하지 않는다.
- AAAA 주소에서 숫자 하나가 빠졌다: 펀치블로그의 IPv6 수정 기록
후속 기록: 10월에는 AWS DNS에서 AAAA 오타를 수정했다. 현재 구성과 IPv4·IPv6 재검사 결과는 이 글에서 확인한다.
- DNS 담당 확인
등록 업체와 NS 위임을 구분하고 실제 담당 DNS의 레코드를 본다.
- Nginx 사이트 선택
같은 서버에서도 도메인에 맞는 server_name과 웹 루트가 필요하다.
- TLS 구간 검사
공개 HTTPS와 원본 HTTPS를 검사 위치에 맞춰 따로 확인한다.
아래 NS 이름·응답 상태·설정 조각은 2026년 9월 12일 연결 작업과 후속 확인 기록이다. 현재 설정을 조회한 값으로 갱신한 것이 아니다. 같은 절차로 다시 확인하면 관찰 시각과 결과를 새 기록으로 남긴다.
첫 확인: 지금 DNS에 답하는 곳은 어디인가

Lightsail에 DNS 영역이 있다는 사실만으로 그 영역의 레코드가 실제 접속에 사용되는 것은 아니었다. 도메인의 NS 레코드를 조회했더니 alec.ns.cloudflare.com과 anita.ns.cloudflare.com이 나왔다. 이번 도메인은 Cloudflare에 위임돼 있었으므로 레코드를 확인할 곳도 Cloudflare였다. 이 두 이름은 펀치블로그에 지정된 값이며 다른 도메인에 그대로 복사할 설정이 아니다.
dig +short punchblog.com NS
dig +short punchblog.com A연결 과정에서 Cloudflare의 루트 A 레코드는 이 사이트를 서비스할 서버 주소로, www의 CNAME은 punchblog.com으로 지정했다. 레코드는 프록시가 켜진 상태였다. 여기서 A 조회 결과가 서버 주소와 다르게 보이는 점을 연결 실패로 오해하지 않도록 주의했다. Cloudflare 공식 문서에 따르면 프록시된 레코드는 공개 DNS 조회에 원본 서버 대신 Cloudflare 주소를 반환한다.
| 관리 화면에서 확인한 값 | 공개 조회로 확인한 것 | 판단 |
|---|---|---|
| 루트 A → 원본 서버 주소 | Cloudflare IP 주소 두 개 | 프록시가 켜져 있으면 서로 다를 수 있음 |
| www CNAME → punchblog.com | 최종 HTTPS 이동 결과 | 이름 해석과 주소 이동은 별도 확인 |
| Lightsail의 DNS 영역 존재 | NS는 Cloudflare | 실제로 위임된 서비스에서 레코드 확인 |
두 번째 확인: 같은 서버에서 어떤 페이지를 열 것인가
DNS가 서버를 가리켜도 Nginx가 새 도메인을 처리할 설정은 따로 필요했다. 작업 당시에는 펀치블로그 전용 가상 호스트가 아직 설치되지 않은 상태였다. 기존 웹 서버에 punchblog.com과 www.punchblog.com을 처리할 별도 설정을 추가하고, 펀치블로그의 정적 출력만 읽는 웹 루트를 지정했다.
Nginx 공식 요청 처리 문서는 수신 주소·포트와 요청의 호스트 이름을 기준으로 서버 설정을 선택한다고 설명한다. 이번에도 같은 서버를 사용하되 도메인에 따라 다른 웹 루트를 선택하도록 구성했다. 도메인이 하나 늘었다고 별도 서버를 먼저 만드는 대신, 이미 준비한 정적 파일을 올바른 도메인에 연결하는 데 집중했다.
# HTTPS server 블록 안의 핵심 부분만 발췌
# 인증서와 HTTP 전환 등 나머지 설정은 이 조각에 포함하지 않음
server_name punchblog.com;
root /var/www/punchblog/current;
index index.html;
location / {
try_files $uri $uri/ =404;
}웹 루트는 원고와 운영 문서가 있는 프로젝트 전체가 아니라 빌드 결과의 복사본으로 정했다. 독자가 받는 HTML·CSS·공개 근거 파일과, 서버 작업용 파일을 한 경로에 섞지 않기 위해서다. 주소를 잘못 입력하면 홈을 200으로 내보내지 않고 404로 끝내도록 했다.
세 번째 확인: 브라우저 앞단과 원본 서버의 HTTPS

punchblog.com과 www.punchblog.com을 모두 포함하는 별도 Let’s Encrypt 인증서를 발급했다. 인증용 HTTP 경로를 먼저 제공하고 webroot 방식으로 발급한 뒤 HTTPS 설정을 적용했다. 인증서가 존재하기 전에 해당 파일을 참조하는 완성 설정부터 적용하지 않도록 순서를 나눴다.
Cloudflare를 거친 HTTPS 요청이 성공하는 것만으로 원본 서버 인증서까지 직접 검사했다고 볼 수는 없다. 그래서 공개 주소의 응답과 함께, 서버 내부에서 Cloudflare를 거치지 않는 요청도 확인했다. 아래 명령의 --resolve는 접속 목적지를 루프백으로 바꾸면서 URL의 호스트 이름과 TLS 검증은 유지한다. 인증서 검사를 생략하는 -k 옵션은 쓰지 않았다.
# 이 사이트를 서비스하는 서버 내부에서만 실행
curl -I --resolve punchblog.com:443:127.0.0.1 \
https://punchblog.com/
curl -I --resolve www.punchblog.com:443:127.0.0.1 \
https://www.punchblog.com/두 원본 요청은 인증서 오류 없이 끝났으며 대표 주소는 200, www는 대표 주소로 향하는 301을 반환했다. 이것은 검사한 시점의 원본 인증서와 응답 확인이다. Cloudflare 계정의 SSL 모드를 API로 조회한 결과나 미래의 자동 갱신 성공 기록은 아니다.
연결 후 실제로 확인한 여섯 가지 응답
아래 표는 도메인 연결을 마친 뒤 2026년 9월 12일 23시 38분 KST에 한 서버에서 순서대로 보낸 HEAD 요청 결과다. 자동으로 리디렉션을 따라가지 않아, 이동 전의 301과 도착지의 200을 별도로 남길 수 있었다. 이 검사는 응답 헤더를 확인하며 브라우저 화면이나 페이지 전체 본문을 판정하지 않는다.
| 확인한 경로 | HTTP 상태 | 이동 목적지 |
|---|---|---|
| 대표 HTTPS 주소 | 200 | — |
| HTTP 주소 | 301 | https://punchblog.com/ |
| www HTTPS 주소 | 301 | https://punchblog.com/ |
| 존재하지 않는 주소 | 404 | — |
| 서버 내부에서 원본 HTTPS | 200 | — |
| 서버 내부에서 원본 www HTTPS | 301 | https://punchblog.com/ |
curl -I https://punchblog.com/
curl -I http://punchblog.com/
curl -I https://www.punchblog.com/
curl -I https://punchblog.com/domain-check-missing-20260912/독자용 확인 절차: 실패한 단계와 최종 본문을 따로 남기기
여기부터는 9월 당시의 측정값이 아니라 같은 문제를 확인할 때 쓸 절차다. 본인이 관리하는 도메인과 기대하는 대표 URL을 먼저 적는다. 아래 example.com은 반드시 자신의 도메인으로 바꾼다. www를 사용한다면 www의 이름 해석도 별도로 확인한다. DNS 응답이 있다는 사실만으로 TLS나 HTML까지 통과한 것은 아니다.
dig +time=3 +tries=1 +short example.com NS
dig +time=3 +tries=1 +short example.com A
dig +time=3 +tries=1 +short example.com AAAA
# 쓰기 가능한 별도 작업 폴더에서 실행: 응답 파일 이름을 구분한다.
curl -sS --connect-timeout 5 --max-time 15 \
-L --max-redirs 5 \
-D response.headers -o response.html \
-w 'http=%{http_code} final=%{url_effective}\n' \
https://example.com/
printf 'curl_exit=%s\n' "$?"첫 네트워크 오류와 HTTP 상태 코드는 다르다. 이 curl 명령은 -f를 사용하지 않아 404·500을 받아도 전송 자체가 완료되면 종료 코드 0일 수 있다. 종료 코드, 최종 http 값, final 주소를 함께 읽는다. response.headers에는 이동 단계의 헤더도 남고 response.html에는 최종 응답 본문이 저장된다. 실패했을 때 남은 파일은 완전한 응답으로 취급하지 않는다.
| 관찰한 값 | 좁혀진 구간 | 다음 확인 |
|---|---|---|
| curl 종료 6 | 호스트 이름 해석 실패 | 도메인 오타·사용 중인 DNS·NS와 레코드 확인 |
| curl 종료 7 | 해석한 목적지로 연결 실패 | 할당 IP·포트·서버 수신·방화벽 확인 |
| curl 종료 28 | 제한 시간 초과 | 오류 메시지로 연결 전·후 구분; 시간 초과만으로 DNS 원인 단정하지 않음 |
| curl 종료 60 | 인증서 신뢰 검증 실패 | 호스트 이름·유효기간·인증서 체인·검사 장치의 시간과 신뢰 저장소 확인 |
| HTTP 301·302가 반복됨 | 리디렉션 경로 | Location과 대표 주소 규칙 확인; 제한 횟수를 늘려 숨기지 않음 |
| 최종 200인데 다른 페이지 | 사이트 선택 또는 내용 문제 | server_name·웹 루트·캐시와 기대 본문 대조 |
완료 조건은 기대하는 대표 URL에서 원하는 글의 고유한 문장이 보이는 것이다. 최종 200만 기록하지 않고 저장한 HTML에서 그 문장을 확인한 다음 브라우저로 CSS·링크도 연다. HEAD는 GET 본문을 확인하지 않으므로 당시의 여섯 HEAD 결과를 이 단계까지 검증한 자료로 읽으면 안 된다.
IPv4는 되지만 일부 환경에서 실패한다면 같은 주소에 curl -4와 curl -6를 각각 적용해 종료 코드·상태·본문을 비교한다. 현재 펀치블로그의 DNS 구성과 양쪽 GET 관찰값은 앞에서 연결한 10월 IPv6 수정 사례에 있다. 이 글의 Cloudflare NS와 프록시 설명은 9월 당시 구성에 대한 기록으로 남긴다.
같은 증상을 만나면 어디부터 볼 것인가
| 증상 | 먼저 확인할 항목 | 그 확인만으로 알 수 없는 것 |
|---|---|---|
| DNS 영역은 있는데 접속이 안 됨 | NS 위임과 실제 담당 서비스의 레코드 | 웹 서버의 도메인 설정·인증서 상태 |
| 도메인에서 다른 사이트가 열림 | 해당 포트의 server_name과 웹 루트 | 본문과 링크가 모두 올바른지 |
| 공개 HTTPS는 되는데 원본이 의심됨 | 원본에 호스트 이름을 유지한 TLS 요청 | Cloudflare 계정의 실제 SSL 모드 |
| 대표 주소는 열리지만 www는 실패 | www DNS와 www 인증서·이동 설정 | 다른 지역의 DNS 반영 여부 |
| 존재하지 않는 글도 200 | 없는 경로의 상태 코드와 본문 | 검색엔진의 최종 색인 판단 |
이번 작업의 결론은 DNS 값을 무작정 다시 입력하거나 기다리는 대신, 이름을 어느 서버가 해석하는지, 웹 서버가 어떤 사이트를 선택하는지, 각 HTTPS 구간이 정상인지 나누어 확인하자는 것이다. 세 단계가 맞아도 내용이나 링크까지 자동으로 완성되지는 않으므로 공개 페이지 검사는 별도로 남긴다.
편집자 의견
9월 연결 사례에서 먼저 고칠 대상은 Lightsail에 보이는 DNS 영역이 아니라 실제 NS가 가리키는 Cloudflare의 레코드라고 판단합니다. 위임받지 않은 영역에서 값을 반복해서 바꿔도 사용자의 이름 조회가 그 값을 읽지 않기 때문입니다. 등록 업체 변경을 먼저 검토하기보다 NS 조회 한 번으로 수정할 위치부터 좁히는 편을 권합니다.
Cloudflare 프록시를 쓰는 당시 조건에서는 공개 A 응답과 원본 서버 IP가 다를 수 있으므로, 그 차이만으로 레코드를 다시 고치지 않겠습니다. 현재의 위임·프록시 상태가 달라졌다면 9월의 NS 이름을 복사하지 않고 지금의 NS와 연결 경로를 새로 확인해야 합니다.
판단 근거: 첫 확인: 지금 DNS에 답하는 곳은 어디인가
의견 추가 2026-10-23 · 본문 자료를 바탕으로 한 편집 판단
운영 기록과 후속 확인 자료
연결 과정은 당시 작업 기록을 바탕으로 정리했습니다. 아래 JSON은 연결이 끝난 뒤 별도로 수행한 DNS 조회와 HTTP HEAD 요청 결과입니다. 초기 실패 요청을 재현한 자료는 아닙니다.
후속 확인 시각: 2026-09-12T14:38:23.385660+00:00
Linux · Python 3.10.12 · curl · dig
Python 3, curl, dig가 있는 환경에서 실행합니다. 기본 실행은 공개 주소만 조회하며 서버 설정을 변경하지 않습니다. 결과 파일이 이미 있으면 덮어쓰지 않습니다.
python3 check-domain.py --output new-observations.json원본 루프백 검사는 펀치블로그를 서비스하는 서버 내부에서만 --origin-loopback 옵션으로 실행합니다. 다른 컴퓨터에서 실행하면 그 컴퓨터의 로컬 주소를 검사하게 됩니다.
참고한 공식 문서
- Cloudflare: authoritative nameservers
- Cloudflare: proxied DNS records
- Nginx: 요청에 사용할 서버 선택
- Nginx: HTTPS 서버와 SNI
- Certbot: webroot 인증 방식
- curl: 요청 옵션·write-out·종료 코드
기존 자료 확인: 2026-10-17 · 원고 수정: 2026-10-24. 잘못된 내용은 정정 요청으로 알려주세요.
이 글의 보완 기록
- · DNS·Nginx·TLS 연결 흐름을 추가하고 당시 기록과 현재 상태의 구분을 명시했다.
- · 9월 당시 관찰값을 보존하고 10월의 실제 DNS 수정·재검사 기록을 연결했다.
- · 역사적 HEAD 기록을 보존하고 독자용 제한 시간·최종 GET 본문 검사와 curl 오류별 다음 행동을 추가했다. 현재 DNS와 과거 구성을 다시 구분했다.
- · 본문 근거에 대한 편집자의 판단과 결론이 달라지는 조건을 추가했습니다. 기존 관찰일·공식 자료 확인일은 유지했습니다.
- · 글별 적용 사례와 반례를 보강했습니다. 기존 관찰일과 원자료 확인일은 유지했습니다.