Google Search Console을 확인하다가 이상한 점을 발견했습니다. http://www.kichang.info/가 404 에러를 반환하고 있었습니다. 분명 DNS에 www A 레코드는 설정해두었는데, 왜 404가 뜨는 걸까요?

DNS 설정을 확인해보니 www A 레코드는 정상적으로 서버 IP를 가리키고 있었습니다. 문제는 DNS가 아니라 서버(Traefik) 레벨에 있었습니다.
Traefik은 리버스 프록시로서, 들어오는 요청의 Host 헤더를 보고 어떤 서비스로 라우팅할지 결정합니다. 제 설정에는 kichang.info만 등록되어 있었고, www.kichang.info로 들어오는 요청은 어떤 서비스와도 매칭되지 않아 404를 반환하고 있었던 것입니다.
# 기존 상태
kichang.info → 웹 서비스로 라우팅 ✅
www.kichang.info → 매칭되는 라우터 없음 → 404 ❌www 요청을 non-www로 리디렉션하는 Traefik 설정을 추가했습니다. 각 구성 요소가 어떤 역할을 하는지 하나씩 살펴보겠습니다.
# /data/coolify/proxy/dynamic/www-redirect.yaml
http:
routers:
www-redirect-https:
entryPoints:
- https
rule: Host(`www.kichang.info`)
service: noop@internal
middlewares:
- www-to-non-www
tls:
certResolver: letsencrypt
priority: 1000
www-redirect-http:
entryPoints:
- http
rule: Host(`www.kichang.info`)
service: noop@internal
middlewares:
- www-to-non-www-https
priority: 1000
middlewares:
www-to-non-www:
redirectRegex:
regex: "^https://www\\.kichang\\.info(.*)"
replacement: "https://kichang.info${1}"
permanent: true
www-to-non-www-https:
redirectRegex:
regex: "^http://www\\.kichang\\.info(.*)"
replacement: "https://kichang.info${1}"
permanent: trueRouter는 "어떤 요청을 받아들일 것인가"를 정의합니다. www 404 문제의 핵심 원인이 바로 www 요청을 받아들이는 라우터가 없었다는 것입니다.
www-redirect-https 라우터
www-redirect-https:
entryPoints:
- https
rule: Host(`www.kichang.info`)
service: noop@internal
middlewares:
- www-to-non-www
tls:
certResolver: letsencrypt
priority: 1000속성 | 값 | 역할 |
|---|---|---|
| https | 443 포트(HTTPS)로 들어오는 요청만 이 라우터가 처리 |
| Host(`www.kichang.info`) | Host 헤더가 www.kichang.info인 요청만 매칭 |
| noop@internal | 실제 백엔드 서비스 없음. 리디렉션만 수행하므로 Traefik 내장 noop 서비스 사용 |
| www-to-non-www | 이 라우터를 통과하는 요청에 적용할 미들웨어 지정 |
| letsencrypt | www 서브도메인용 SSL 인증서 자동 발급. 이 설정이 없으면 https://www.kichang.info 접속 시 SSL 에러 발생 |
| 1000 | 다른 라우터보다 먼저 매칭되도록 높은 우선순위 부여. 와일드카드 라우터에 먼저 잡히는 것을 방지 |
www-redirect-http 라우터
www-redirect-http:
entryPoints:
- http
rule: Host(`www.kichang.info`)
service: noop@internal
middlewares:
- www-to-non-www-https
priority: 1000HTTP(80 포트) 요청을 처리하는 라우터입니다. HTTPS 라우터와 거의 동일하지만 두 가지 차이점이 있습니다:
entryPoints: http - 80 포트 요청 처리
tls 설정 없음 - HTTP는 암호화되지 않으므로 TLS 설정 불필요
다른 미들웨어 사용 - HTTP → HTTPS 업그레이드도 함께 수행
Middleware는 "요청을 어떻게 처리할 것인가"를 정의합니다. 여기서는 정규식 기반 리디렉션을 수행합니다.
www-to-non-www 미들웨어
www-to-non-www:
redirectRegex:
regex: "^https://www\\.kichang\\.info(.*)"
replacement: "https://kichang.info${1}"
permanent: true속성 | 값 | 역할 |
|---|---|---|
| ^https://www\\.kichang\\.info(.*) | 매칭할 URL 패턴. |
| https://kichang.info${1} | 리디렉션 대상 URL. |
| true | 301 영구 리디렉션 사용. SEO 관점에서 중요 - 검색 엔진에게 "이건 영구적인 이동"임을 알림 |
경로 보존이 중요한 이유:
# 경로 보존 O (올바른 동작)
https://www.kichang.info/blog/my-post → https://kichang.info/blog/my-post
# 경로 보존 X (잘못된 동작)
https://www.kichang.info/blog/my-post → https://kichang.info/ ← 사용자가 원한 페이지로 못 감www-to-non-www-https 미들웨어
www-to-non-www-https:
redirectRegex:
regex: "^http://www\\.kichang\\.info(.*)"
replacement: "https://kichang.info${1}"
permanent: trueHTTP www 요청을 처리하는 미들웨어입니다. 두 가지 작업을 한 번에 수행합니다:
www 제거: www.kichang.info → kichang.info
HTTPS 업그레이드: http:// → https://
이렇게 하면 리디렉션 횟수를 줄일 수 있습니다:
# 미들웨어 하나로 처리 (효율적)
http://www.kichang.info → https://kichang.info (1회 리디렉션)
# 별도 처리 시 (비효율적)
http://www.kichang.info → https://www.kichang.info → https://kichang.info (2회 리디렉션)HTTP와 HTTPS 요청을 모두 처리하기 위해서입니다.
# 사용자가 접근할 수 있는 4가지 경로
http://kichang.info → (기존 설정) → https://kichang.info ✅
https://kichang.info → (목적지) ✅
http://www.kichang.info → www-redirect-http → https://kichang.info ✅
https://www.kichang.info → www-redirect-https → https://kichang.info ✅이제 www를 붙이든 안 붙이든, HTTP든 HTTPS든 모든 경로가 최종적으로 https://kichang.info로 수렴합니다.
# 1. Traefik dynamic config 디렉토리로 이동
cd /data/coolify/proxy/dynamic
# 2. 설정 파일 생성
sudo nano www-redirect.yaml
# 3. 위의 전체 설정 내용 붙여넣기 후 저장
# 4. Traefik이 자동으로 설정을 감지하여 적용 (재시작 불필요)Traefik은 dynamic configuration 디렉토리를 watch하고 있어서, 파일이 추가되거나 수정되면 자동으로 반영됩니다.
# curl로 리디렉션 확인
curl -I http://www.kichang.info
# 예상 출력
HTTP/1.1 301 Moved Permanently
Location: https://kichang.info/
# HTTPS도 확인
curl -I https://www.kichang.info
# 예상 출력
HTTP/2 301
location: https://kichang.info/www와 non-www가 모두 같은 콘텐츠를 보여주면, 검색 엔진은 이를 중복 콘텐츠로 인식할 수 있습니다. 301 리디렉션으로 정규(canonical) URL을 명확히 지정합니다.
외부 사이트에서 www.kichang.info로 링크를 걸어도, 301 리디렉션을 통해 링크의 SEO 가치(link equity)가 kichang.info로 전달됩니다.
301 (permanent: true) - "영구 이동" - 검색 엔진이 새 URL로 인덱싱
302 (permanent: false) - "임시 이동" - 검색 엔진이 원래 URL 유지www 리디렉션은 영구적인 설정이므로 반드시 301을 사용해야 합니다.
# DNS 설정 (필요하지만 충분하지 않음)
www A 123.456.789.0
# 서버(Traefik) 설정도 필수!
→ www 요청을 받아들이는 라우터 추가 필요# tls.certResolver 없으면
https://www.kichang.info → SSL 인증서 에러 (NET::ERR_CERT_COMMON_NAME_INVALID)
# 해결: certResolver 추가
tls:
certResolver: letsencrypt# 잘못된 regex (경로 캡처 안 함)
regex: "^https://www\\.kichang\\.info"
replacement: "https://kichang.info"
# 올바른 regex (경로 캡처 및 보존)
regex: "^https://www\\.kichang\\.info(.*)"
replacement: "https://kichang.info${1}"www 리디렉션은 "설정하면 특별히 득이 없지만, 안 하면 분명히 손해"인 작업입니다. 제대로 설정되어 있지 않으면:
일부 사용자가 404 에러를 경험
검색 엔진이 중복 콘텐츠로 인식
외부 링크의 SEO 가치 분산
Traefik의 dynamic configuration을 활용하면 서비스 재시작 없이 www 리디렉션을 적용할 수 있습니다. 한 번 설정해두면 신경 쓸 일이 없으니, 아직 설정하지 않았다면 지금 바로 적용해보세요.