SRV 레코드가 실제로 하는 일

대부분의 DNS 레코드는 “이 이름이 어디 있나?”에 답합니다. A 레코드는 IPv4 주소를, MX 레코드는 메일 호스트를 돌려주죠. SRV 레코드는 더 날카로운 질문에 답합니다. “이 도메인에서 이 특정 서비스가 — 어떤 포트로, 어떤 우선순위로, 부하를 얼마씩 나눠서 — 어디 사는가?” 그 추가 정보가 핵심입니다. A 레코드는 클라이언트에게 example.com의 주소는 알려줄 수 있어도, XMPP 클라이언트에게 채팅이 호스트 xmpp1.example.com의 포트 5222에서 돌고, 첫 번째가 죽었을 때만 써야 할 백업이 xmpp2에 있다고는 못 알려줍니다. SRV는 할 수 있습니다.

RFC 2782(2000년 2월, 실험적이던 RFC 2052를 대체)에 정의된 이 레코드는 네 개의 값을 한 답에 담습니다. 넷을 다 맞추면 프로토콜을 아는 클라이언트 — 메일 Autodiscover, SIP, XMPP, 액티브 디렉터리, 마인크래프트 등 — 가 호스트명과 포트를 하드코딩하지 않고도 서비스를 찾아냅니다. 하나라도 틀리면 실패가 대개 조용합니다. 그래서 처음에 신중하게 설정할 값어치가 있습니다.

이름이 레코드의 절반이다

네 값에 앞서 소유자 이름이 있고, 형태가 엄격합니다.

_service._proto.name.

_service와 _proto는 둘 다 밑줄로 시작합니다 — 의도적으로요. 이 레이블이 실제 호스트명과 절대 충돌하지 않게 하려는 겁니다(_sip이라는 이름의 일반 호스트는 없으니까요). _proto는 거의 항상 _tcp 아니면 _udp입니다. 그래서 example.com의 SIP-over-TLS 레코드는 _sip._tls.example.com이 소유하고, XMPP 클라이언트 접속 레코드는 _xmpp-client._tcp.example.com이 소유합니다.

밑줄을 빠뜨리거나, 프로토콜 레이블을 잘못 쓰거나, _service._proto 접두사가 아니라 맨 도메인에 레코드를 붙이면, 올바른 이름으로 조회한 클라이언트는 NXDOMAIN을 받습니다. 레코드가 완벽하게 만들어졌어도 엉뚱한 이름에 앉아 있어 보이지 않는 겁니다.

네 개의 필드

IN SRV 뒤에, 순서대로:

_sip._tls.example.com. 3600 IN SRV 10 60 443 sipdir.example.com.
                                    │  │   │   └─ Target
                                    │  │   └───── Port
                                    │  └───────── Weight
                                    └──────────── Priority
  • Priority는 MX preference와 똑같이 작동합니다. 숫자가 낮을수록 먼저 시도됩니다. 클라이언트는 더 높은 걸 건드리기 전에, 닿을 수 있는 target 중 priority 숫자가 가장 낮은 것에 접속해야 합니다. 이게 주/백업 제어예요. 메인 호스트를 10, 페일오버를 20에 두면, 10에 있는 게 전부 안 닿을 때만 클라이언트가 20으로 내려갑니다.
  • Weight는 같은 priority를 공유하는 target들 사이에서 부하를 나눕니다. 둘 다 priority 10인데 weight가 60과 40이면 대략 60% / 40%로 클라이언트를 나눠 받습니다. Weight는 서로 다른 priority 사이에서는 무의미합니다 — 동점을 가를 뿐이에요. (RFC 2782상 weight 0인 레코드도 선택될 작지만 정의된 확률을 가집니다. 꺼지는 게 아닙니다.)
  • Port는 서비스가 실제로 듣는 TCP/UDP 포트입니다. 이게 SRV의 강점이에요 — 프로토콜 기본 포트에 묶이지 않습니다. 단, 별도 필드입니다. 포트를 Target에 host:443처럼 붙이면 안 됩니다. 흔한 잘못된 레코드 실수예요.
  • Target은 서비스를 돌리는 호스트명이고, A/AAAA로 해석돼야 하며 CNAME이면 안 됩니다(FAQ 참고). 여기 점(.) 하나만 있으면 “여기서 서비스 제공 안 함”이라는 특수 신호입니다.

SRV 설정이 어긋나는 흔한 방식

  • CNAME target. 가장 잦은 실수. 클라이언트에 따라 반쯤 되기도 하고 완전히 실패하기도 해서 디버깅이 미칠 노릇입니다. Target은 A/AAAA 이름이어야 합니다.
  • Target에 포트를 붙임. Target 필드의 sipdir.example.com:443은 무효입니다. 포트는 자기 필드가 따로 있어요.
  • 밑줄 누락 또는 프로토콜 오기. _sip._tcp 대신 sip._tcp, 또는 실제로는 _tls/_udp가 필요한데 _tcp. 클라이언트는 정확한 이름을 묻습니다 — 아슬아슬한 오타도 완전한 실패입니다.
  • 웹사이트에 효과를 기대함. 브라우저는 HTTP에 SRV를 조회하지 않습니다. 웹 트래픽이 목적이면 SRV는 그 장치가 아닙니다.
  • Target의 trailing dot 혼동. 존 파일에서 정규화 안 된 Target에는 존 origin이 덧붙습니다. 완전정규화된 Target을 trailing dot과 함께 쓰지 않으면 sipdir.example.com.example.com을 가리키게 됩니다.

DechoNet으로 진단

  • DNS 조회는 정확히 _service._proto.name을 질의해, 레코드가 실제로 돌려주는 priority·weight·port·target을 보여줍니다 — 레코드가 올바른 이름에 존재하는지, 네 필드가 당신이 설정했다고 믿는 값을 담고 있는지 확인할 수 있어요. Target이 주소로 해석되는지도 보여주니, 클라이언트가 걸리기 전에 CNAME target을 잡아낼 수 있습니다.

확인 체크리스트

  • 레코드 소유자 이름이 _service._proto.도메인이고, 밑줄 두 개와 올바른 프로토콜 레이블(_tcp·_udp·_tls)을 갖췄는지 확인.
  • Target이 CNAME이 아니라 A/AAAA 레코드로 해석되는지 확인.
  • Port 필드가 실제 서비스 포트를 담고, Target에 중복으로 붙어 있지 않은지 확인.
  • Priority가 의도한 주/백업 순서를 반영하는지 확인(낮을수록 먼저 시도).
  • 부하 분산 중이라면, 분산 대상 target들이 같은 Priority를 공유하고 Weight 합이 기대대로인지 확인.
  • 변경 후에는 옛 레코드의 TTL을 기억하세요 — 만료 전까지 클라이언트가 이전 답을 계속 쓸 수 있습니다.

SRV가 문제가 아닐 때

레코드는 멀쩡한데 서비스에 여전히 닿지 못한다면, SRV 레코드는 제 할 일을 다 한 것이고 결함은 그 하류에 있습니다. Target 호스트가 죽었거나, Port가 닫혔거나 방화벽에 막혔거나, 서비스가 레코드가 말하는 자리에서 실제로 듣고 있지 않은 거죠. 그 지점에서는 DNS 편집을 멈추고, target 호스트가 그 포트에서 직접 응답하는지 확인하세요 — 레코드는 애초에 서비스가 아니라 이정표였을 뿐입니다.

내 도메인에서 바로 확인

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