TTL이 실제로 정하는 것

DNS 레코드의 TTL은 리졸버가 응답을 캐시에 들고 있다가 네임서버에 다시 물어보기까지 허용되는 시간(초)입니다. 그게 전부입니다.

DNS에는 ‘밀어 넣기’가 없습니다. 레코드를 바꾸면 권한 네임서버는 그 즉시 새 응답을 내주지만, 이미 예전 응답을 캐시한 리졸버는 자기 사본이 만료될 때까지 예전 응답을 계속 내줍니다. 흔히 말하는 ‘DNS 전파’는 전 세계의 캐시가 제각각 만료되는 과정일 뿐입니다. 변경 후 최악의 지연은 지금 설정한 TTL이 아니라 각 리졸버가 레코드를 캐시할 당시의 TTL입니다.

TTL 때문에 겪는 놀라운 일 대부분이 이 한 문장으로 설명됩니다.

  • TTL이 86400인 레코드의 IP를 바꾸면 일부 사용자는 최대 하루 동안 예전 IP로 갑니다.
  • TTL을 300으로 낮추고 5분 뒤에 IP를 바꾸면 달라지는 것이 없습니다. 낮추기 전에 캐시한 리졸버는 여전히 “86400초 동안 유효”라고 적힌 사본을 들고 있습니다.
  • TTL을 낮춘 효과는 예전 TTL이 완전히 끝난 뒤에야 나타납니다.

캐시는 리졸버에만 있지 않습니다. 운영체제, 브라우저, 애플리케이션도 캐시하고, 모두가 TTL을 지키지는 않습니다. 예를 들어 JVM은 레코드의 TTL이 아니라 자기 설정 networkaddress.cache.ttl을 따릅니다. OpenJDK 기본값은 30초이고, security manager가 설치돼 있으면 영원히 캐시합니다. 시작할 때 한 번 이름을 풀고 연결을 계속 재사용하는 프로세스는 재시작하기 전까지 변경을 아예 보지 못합니다.

TTL 읽기: 캐시된 값과 권한 서버의 값

공용 리졸버에 물으면 캐시에 남은 시간이 줄어드는 숫자로 나옵니다.

dig +noall +answer www.example.com A @8.8.8.8
www.example.com.	2793	IN	A	192.0.2.10

1분 뒤에 다시 돌리면 숫자가 줄어 있습니다. 대형 공용 리졸버는 서로 독립된 캐시를 여러 개 운영하므로 연달아 물어도 숫자가 들쭉날쭉할 수 있습니다. 정상입니다.

실제로 설정한 TTL을 보려면 내 네임서버에 직접 물어야 합니다.

dig +short NS example.com
dig +noall +answer www.example.com A @ns1.example-dns.net
www.example.com.	3600	IN	A	192.0.2.10

권한 서버는 항상 설정한 값을 그대로 돌려줍니다. 공용 리졸버의 남은 TTL이 권한 서버 값보다 크다면, 그 리졸버는 TTL을 낮추기 전에 레코드를 캐시한 것이고 기다리는 수밖에 없습니다.

DNS 조회는 공용 리졸버가 지금 알려 주는 TTL을 보여 줍니다. 내 설정값이 아니라 ‘캐시에 남은 시간’으로 읽으세요. 전파 확인은 여러 공용 리졸버에 한꺼번에 물어보므로, 아직 예전 응답을 들고 있는 곳이 있는지 가장 빨리 확인할 수 있습니다.

상황별 권장값

TTL초어울리는 경우
1분60헬스 체크 기반 장애 전환처럼 빨리 바꾸는 것 자체가 목적일 때
5분300급하게 바꿀 수도 있는 레코드, 이전 작업 전후 기간
10분600로드밸런서나 CDN 대상에 무난한 중간값
1시간3600손댈 일 없는 A, AAAA, CNAME, TXT의 기본값
4시간14400안정된 레코드. cPanel 기반 호스팅의 존 기본값으로 흔함
1일86400NS 레코드처럼 1년에 한 번 바뀔까 말까 한 것

제 기본값은 이렇습니다. 일반 웹 레코드는 3600, 장애 때 다른 곳으로 돌려야 할 수 있는 레코드는 300, NS는 86400. MX도 길게 둬도 됩니다. 보내는 쪽 메일 서버가 상대 서버에 닿지 않으면 큐에 넣고 재시도하기 때문입니다. 다만 메일 서비스를 옮기기 전에는 다른 레코드처럼 낮춰야 합니다.

600이라는 값에 특별한 의미는 없습니다. 10분이고, 쿼리를 많이 늘리지 않으면서 커피 한 잔 마시는 동안 변경이 반영되길 원할 때 적당합니다. 14400은 4시간입니다. 움직일 일 없는 레코드에는 괜찮지만, 옮겨야 하는 날 그 값을 발견하면 괴롭습니다.

TTL을 낮게 두는 비용

낮은 TTL은 공짜가 아니고, “전부 60으로 두면 된다”는 나쁜 조언입니다.

  • 쿼리가 늘어납니다. 만료될 때마다 네임서버까지 한 번씩 더 왕복합니다. Route 53처럼 쿼리 수로 과금하는 곳에서는 규모가 커지면 실제 비용이 됩니다.
  • 캐시 미스가 느립니다. 리졸버가 내 네임서버까지 가야 하는 방문자는 그 왕복만큼 기다립니다. TTL이 길면 대부분의 방문자가 데워진 캐시를 씁니다.
  • 장애 때 버티는 힘이 줄어듭니다. DNS 제공사가 다운되면 TTL이 하루인 레코드는 캐시 덕분에 몇 시간 동안 계속 동작합니다. TTL 60초짜리는 1분 안에 캐시에서 사라집니다. 네임서버에 닿지 않을 때 만료된 데이터로 계속 응답하는 serve-stale(RFC 8767)을 구현한 리졸버도 있지만, 모든 리졸버가 그렇다고 기대할 수는 없습니다.

낮은 TTL은 변경이 예상될 때 꺼내 쓰는 도구입니다. 그 기간이 아니면 긴 쪽이 모두에게 낫습니다.

이전 전에: 낮추고, 기다리고, 바꾸고, 다시 올리기

TTL 계획이 곧바로 효과를 내는 유일한 상황입니다.

  1. 권한 서버에서 현재 TTL을 확인합니다. 86400이라고 해 봅시다.
  2. 변경보다 최소한 예전 TTL 한 바퀴 이상 앞서 300으로 낮춥니다. 86400이면 24시간보다 일찍입니다. 여유를 더 두세요.
  3. 리졸버들이 낮아진 값을 들고 있는지 확인합니다. 공용 리졸버 몇 곳에 물어서, 줄어드는 TTL이 어디서나 300 이하인지 봅니다.
  4. 변경합니다. TTL을 지키는 리졸버라면 대략 5분 안에 새 응답을 가져갑니다.
  5. 예전 서버를 한동안 살려 둡니다. 앞서 말했듯 TTL을 무시하는 클라이언트가 있습니다. 예전 호스트는 최소 하루, 가능하면 더 오래 응답하거나 리다이렉트하게 두세요.
  6. 되돌릴 일이 없다고 확신하면 TTL을 다시 올립니다. 이 단계를 잊어서 존 전체가 영원히 300으로 남는 경우가 많습니다.

실제로 바뀌는 레코드의 TTL을 낮추고 있는지 확인하세요. www가 lb.example.net의 CNAME이고 옮기는 것이 로드밸런서라면, 중요한 것은 CNAME의 TTL이 아니라 lb.example.net 주소 레코드의 TTL입니다.

TTL 최댓값

TTL 필드는 32비트지만 RFC 2181은 이를 2147483647초(2^31 − 1, 약 68년)로 제한하고, 최상위 비트가 켜진 값은 0으로 취급하라고 정합니다.

그 근처에 갈 일은 없습니다. 리졸버는 자기 설정으로 TTL을 자릅니다. BIND의 max-cache-ttl 기본값은 1주, Unbound의 cache-max-ttl은 1일입니다. DNS 제공사 관리 화면도 하루에서 멈추는 경우가 많습니다. 실제로 86400을 넘는 TTL은 거의 차이를 만들지 못하고, 급하게 레코드를 바꿔야 하는 날에는 발목을 잡습니다.

TTL 최솟값과 제공사의 하한

규격상 최솟값은 0이고, “이 조회에만 쓰고 캐시하지 말라”는 뜻입니다. 설정할 수 있는지는 DNS 호스팅에 달려 있습니다.

  • Cloudflare는 대부분의 요금제에서 60초 미만을 받지 않습니다(Enterprise는 30초).
  • 등록기관의 DNS 관리 화면 중에는 정해진 값 몇 개만 고를 수 있고 그중 최솟값이 300초 이상인 곳도 있습니다.
  • Route 53의 alias 레코드는 TTL을 아예 입력받지 않습니다.

리졸버 운영자도 최소 캐시 시간을 설정할 수 있습니다(예: Unbound의 cache-min-ttl). 기본값은 꺼져 있지만 남의 리졸버를 내가 통제할 수는 없습니다. 60초 미만은 지켜진다는 보장이 없다고 보고 계획하세요.

부정 캐시: 없는 레코드의 TTL

리졸버는 “이 이름은 없다”는 응답도 캐시합니다. 그 시간은 존의 SOA 레코드에서 나옵니다. RFC 2308에 따라 부정 응답의 TTL은 SOA 레코드 자체의 TTL과 SOA의 마지막 필드(MINIMUM) 중 작은 값입니다.

dig +noall +answer SOA example.com
example.com.	3600	IN	SOA	ns1.example-dns.net. hostmaster.example.com. 2026100701 7200 3600 1209600 300

이 경우 부정 응답은 300초 동안 캐시됩니다. 없는 이름을 조회하면 authority 섹션에서 실제로 적용되는 값을 볼 수 있습니다.

dig +noall +authority nosuch.example.com

레코드를 만들기 전에 그 이름을 먼저 조회했을 때 문제가 됩니다. new.example.com을 시험 삼아 조회해 NXDOMAIN을 받은 뒤 레코드를 추가하면, 리졸버는 부정 TTL이 끝날 때까지 계속 “없다”고 답합니다. CA가 인증서 검증 레코드를 너무 일찍 조회했을 때도 같은 일이 생깁니다. 리졸버는 부정 캐시도 따로 상한을 두지만(BIND max-ncache-ttl 기본값 3시간), SOA MINIMUM이 크면 여전히 몇 시간을 잃을 수 있습니다.

내가 통제하지 못하는 레코드: 상위 존의 NS

네임서버 위임 정보는 두 곳에 있습니다. 내 존 안의 NS 레코드는 내가 정한 TTL을 갖습니다. 상위 존, 즉 .com 서버들이 내주는 사본은 상위 존의 TTL을 따릅니다. .com은 이틀입니다.

dig +norecurse +noall +authority example.com NS @a.gtld-servers.net
example.com.	172800	IN	NS	ns1.example-dns.net.
example.com.	172800	IN	NS	ns2.example-dns.net.

글루 레코드(내 도메인 안에 있는 네임서버의 IP)도 같은 위임 응답에 같은 방식의 TTL로 실려 옵니다. 리졸버마다 상위 존의 위임 정보를 계속 쓰는지, 내 존의 NS 레코드로 갈아타는지가 다르므로 DNS 제공사를 바꿀 때는 둘 중 긴 쪽을 기준으로 계획하세요. 전환 뒤 며칠은 예전 제공사도 올바른 존 사본을 내주게 두는 것이 안전합니다. 존에 DNSSEC 서명을 쓰고 있다면 DS 레코드도 상위 존에 상위 존의 TTL로 있으므로, 제공사를 바꿀 때 더욱 신경 써야 합니다.

Cloudflare 프록시 레코드의 “Auto”

레코드를 프록시(주황색 구름)로 켜면 Cloudflare가 자기 애니캐스트 주소로 응답하고, TTL은 “Auto”로 표시됩니다. 300초이고 바꿀 수 없습니다.

장점도 있습니다. 공개 응답이 Cloudflare의 IP라서, 레코드가 가리키는 원 서버를 바꿔도 공개 응답은 그대로입니다. 원 서버 변경은 리졸버 캐시와 상관없이 Cloudflare 엣지가 반영하는 대로 적용됩니다. 반면 레코드를 프록시와 DNS 전용 사이에서 전환하면 공개 응답이 바뀌므로 이 5분 TTL의 영향을 받습니다. DNS 전용(회색 구름) 레코드는 내가 설정한 TTL이 그대로 리졸버에 전달됩니다.

함께 보면 좋은 글

내 도메인에서 바로 확인

무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.