DNS, 메일 서버

DNS에 대해 공부하고, 도메인에 IP를 연결하는 방법을 알아봅니다. 또한 메일 서버와 SMTP, POP3, IMAP에 대해 알아봅니다.
DNS, 도메인, 메일 서버, IMAP, SMTP, POP3


DNS

DNSDNS

웹 뿐만아니라 TCP/IP를 기반으로 하는 통신은 모두 IP 주소를 기반으로 하고 있습니다.

  • kim@52.79.229.209
  • http://52.79.229.209
  • http://[2001:db8:a0b:12f0::1]

하지만 위처럼 복잡한 IP 주소를 공개적으로 사용하기는 쉽지 않겠습니다. 이 문제를 해결하기 위해서 DNS(Domain Name System)라는 데이터베이스 시스템이 구성되었습니다. DNS는 www.google.com과 같은 도메인(Domain)과 아이피에 대한 정보를 매칭해둔 전세계에 공개된 DB입니다.

여기서 DB라는 말은 DBMS같은 구체적인 구현체가 아니라 단순히 데이터의 집합을 의미하고 있습니다.

누가 DB를 관리하는지?

네트워크 파트에서 언급했던 IP 주소를 관리하는 국제기관인 ICANN에서 DNS를 관리하고 있습니다. 하지만 전세계의 수 많은 요청을 단일 서버에서 처리한다는 것은 불가능하기에, DNS는 분산 데이터베이스로 구성되어 있습니다.

DNS TreeDNS Tree

위처럼 ICANN에서는 국가 및 기업에 .kr, .jp, .com, .net, .org 같은 최상위도메인(TLD; Top-Level Domain)의 관리를 위임하고, 다시 그 밑으로 DB가 거미줄처럼 분산되어 있습니다. 한국에 할당된 .kr 도메인과 IP는 KISA(한국인터넷진흥원)에서 관리하고 있습니다.

DB에 도메인을 추가하려면?

추가하고자 하는 도메인-IP의 상위 DB에, 즉 benzen.io에 대한 정보를 추가하려면 .io의 DB에 데이터를 추가하면 됩니다. 여러 도메인 등록 대행 업체(Domain Registrar)를 통해 인터넷으로 도메인을 구입 할 수 있습니다.

GodaddyGodaddy

이후 등록 대행 업체에서 운영하는 DB에 도메인에 대한 정보를 추가하거나, 혹은 본인이나 다른 업체에서 운영하는 DB에 도메인 정보에 대한 관리를 위임하도록 설정 할 수 있습니다.

DB를 어떻게 조회하는지?

53번 포트를 사용하는 TCP, UDP 기반의 DNS 프로토콜을 이용해 전세계에 공개된 DB 서버와 서버-클라이언트 통신으로 조회합니다.

DNS ResolvingDNS Resolving

위처럼 DNS 조회는 트리 구조의 분산 DB를 헤멜 필요가 있기 때문에 많은 비용이 소모됩니다. 이 때문에 정보 관리를 위한 Authoritative DNS 서버 외에, 캐싱을 통해 질의 응답의 비용을 줄이기 위한 Recursive DNS 서버들이 존재합니다. (위 그림에서 Local DNS)

Set DNS Server By DHCPSet DNS Server By DHCP

머신이 LAN에(KT, LT 데이콤 등의 ISP 또는 그 서브넷) 연결되면서 IP를 할당 받을 때, 자신의 IP와 함께 ISP에서 운영하는 Recursive DNS 서버의 주소를 같이 전달 받습니다. 이후 머신에서 DNS를 조회 할 때는 OS에 설정된 Local DNS 서버로 질의를 보내게 됩니다.

고수준에서 웹 브라우저 같은 프로그램을 작성 할 때 도메인에 해당하는 IP를 조회하려면, OS API를 이용해서 DNS를 조회 할 수 있습니다.

Node.js에서 DNS 조회

const dns = require('dns');
dns.lookup('benzen.io', (err, address, family) => {
  console.log(address, family); // family는 IPv4인지 IPv6인지를 의미합니다.
});
// Output: 52.79.229.209 4

DNS 레코드

도메인을 구입한 후에 그 정보를 등록하는 대목을 구체적으로 살펴보겠습니다.

네임 서버 설정

Godday의 네임서버 그대로 사용Godday의 네임서버 그대로 사용

DNS 서버(네임 서버라고도 함)들은 DNS 프로토콜에 응대하는 서버 프로그램을 운영하고 있습니다. 도메인을 구입한 후, 도메인 구매 대행 업체의 네임 서버에 도메인 정보를 등록 할 수 있습니다.

Godday 말고 다른 네임서버를 사용Godday 말고 다른 네임서버를 사용

혹은 다른 DNS 서버로 그 정보 관리를 위임하도록 설정 할 수 있습니다. 이때 다른 업체의 네임 서버로, 혹은 직접 구축하여 운영하는 DNS로 그 관리를 위임하게 됩니다.

네임 서버 구축에 대한 구체적인 내용은 다루지 않고, 네임 서버에 등록하여 인터넷에 제공 할 수 있는 정보의 포맷에 대해서 알아보겠습니다.

레코드 관리

DNS 레코드 (AWS)DNS 레코드 (AWS)

도메인에 대한 정보는 레코드라는 단위로 원하는 대로 등록 할 수 있습니다. 레코드는 A, CNAME, MX, NS, SOA, TXT 등의 타입을 가집니다.

A (Address)

도메인과 연결될 실제 IP 주소를 제공

benzen.io.        A  52.79.229.209
xyz.benzen.io.    A  52.79.229.211
google.benzen.io. A  216.58.220.238

CNAME (Canonical Name)

도메인과 연결될 다른 도메인을 제공

*.benzen.io.              CNAME  benzen.io.
google.google.benzen.io.  CNAME  google.com.

MX (Mail Exchanger)

메일주소에 쓰인 도메인이 연결될 다른 도메인들을 제공

benzen.io.         MX    10 mail-1.benzen.io.
                         20 mail-2.benzen.io.
mail-1.benzen.io.  A     52.79.229.209
mail-2.benzen.io.  A     52.79.229.210

TXT

다양한 목적으로 사용될 수 있는 텍스트 정보를 제공

benzen.io.  TXT   "google-site-verification=l6t1DZxxKxxPNAZcdc9zXQ" // 도메인 소유권을 인증하는 용도
benzen.io.  TXT   "v=spf1 ip4:52.79.229.209 -all" // 메일 발송 서버의 IP 주소를 알리는 용도 (스팸 정책 관련)

SOA (Start of Authority)

네임 서버에 대한 정보(영역 표시) 및 등록된 레코드들에 대한 동기화 정책을 제공

NS (Name Server)

하위 도메인의 관리를 다른 네임 서버로 위임하는 등, 참조하는 네임 서버에 대한 정보를 제공

DNS Propagation

DNS PropagationDNS Propagation

이렇게 구성된 레코드들이 실제로 전세계의 인터넷에 반영되기까지 짧게는 몇 분에서 몇 시간까지의 시간이 소요됩니다. 그 이유는 Local DNS 서버들이 캐시를 갱신하는데 시간 간격을 두기 때문입니다.

이메일

Mail ExchangeMail Exchange

인터넷에서 메일이 어떻게 송수신되는지 이해해보도록 하겠습니다.

SMTP

Telnet으로 이메일 보내기Telnet으로 이메일 보내기

송신자는 SMTP(Simple Mail Transfer Protocol)라는 프로토콜을 통해 메일 서버에 메일의 발신을 요청합니다. 이때 터미널에서 직접 SMTP 프로토콜로 서버에 접속해서 이메일을 작성 할 수 있습니다.

하지만 대부분의 이메일 서비스 제공자(구글, 네이버 등)들은 웹이나 다른 GUI 프로그램을 통해 메일을 보낼 수 있도록, SMTP에 쓰이는 포트(TCP 25번 등)를 외부에 공개합니다. 따라서 사용자들은 다양한 클라이언트 프로그램에서 이메일을 발송 할 수 있습니다.

MS OutlookMS Outlook

메일 발신 요청을 받은 발신 메일 서버의 프로세스는 DNS 조회를 통해 수신 메일 서버를 파악하고, 작성된 이메일을 전송합니다. 수신 메일 서버에서는 스팸 여부를 다양한 기준으로 판단하여 메일을 필터링해 서버에 보관하게 됩니다.

이때 메일 서버간의 이메일 전달(SMTP Relay)에도 SMTP 프로토콜이 쓰입니다.

POP3, IMAP

POP3, IMAPPOP3, IMAP

이후 수신자는 이메일 서비스 제공자가 제공하는 POP3(Post Office Protocol) 또는 IMAP(Internet Message Access Protocol) 프로토콜을 통해서, 웹, GUI 프로그램 등 여러 클라이언트에서 이메일을 읽을 수 있습니다.

POP3 vs IMAPPOP3 vs IMAP

POP3와 IMAP의 차이는 POP3는 수신자가 클라이언트에서 이메일을 다운로드하면 서버에서 이메일을 바로 삭제한다는 점입니다. 반면 IMAP은 사용자가 삭제하기 전까지 이메일을 서버에 보관하기 때문에, 여러 클라이언트에서 이메일을 수신 할 수 있으며, 동기화 등의 기능을 제공합니다.

메일 서버를 구축하여 운영하는 경우에는 서버 자원의 여유에 따라 POP3, IMAP의 도입을 선택 할 수 있겠습니다.

이메일 송수신 위임하기

메일 서버 구축에 대한 내용은 다루지 않고, 소유하고 있는 도메인으로 이메일을 대리 발신, 수신하는 시나리오에 대해 알아보겠습니다. 본인의 도메인에 연결될 메일 서버를 직접 구축하고 운영 할수도 있지만, 이메일 서비스 제공자들에 이메일 송수신을 위임하는 경우가 많습니다. 이때는 단순히 이메일 송수신 서비스를 구매하고, 본인이 소유한 도메인 정보를 갱신하면 됩니다.

mailmail.com의 서비스를 이용한다면

benzen.io.   MX   mx.mailmail.com. 10
benzen.io.   TXT  "v=spf1 include:mailmail.com -all"

TXT의 SPF(Sender Policy Framework) 정보를 통해서 benzen.io 도메인으로 발송되는이메일이 mailmail.com을 경유할 수 있다는 정보를 DNS에 제공하면 스팸 메일로 필터링되는 경우를 줄일 수 있습니다.

웹 메일 클라이언트웹 메일 클라이언트

이후 메일 서비스 제공자가 웹 메일 등의 클라이언트 인터페이스를 제공한다면, 이를 이용해서 메일을 송수신 수 있습니다.

Mail App (macOS)Mail App (macOS)

또는== SMTP, POP3 또는 IMAP등의 프로토콜 정보가 제공된다면 Outlook, Gmail 등의 이메일 클라이언트 프로그램에 연동해서 이메일을 송수신== 할 수 있습니다.

프로그램에서 이메일 발신

직접 작성한 프로그램에서 이메일을 보낼 때도 이메일 서비스 제공자 서버의(혹은 자체 구축한 메일서버의) SMTP 프로토콜을 이용 할 수 있습니다. 물론 어느 플랫폼에나 고수준으로 추상화된 라이브러리가 있습니다.

Node.js에서 이메일 발신

const nodemailer = require('nodemailer');

const transporter = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: 'youremail@gmail.com',
    pass: 'yourpassword'
  }
});

const mailOptions = {
  from: 'youremail@gmail.com',
  to: 'myfriend@yahoo.com',
  subject: 'Sending Email using Node.js',
  text: 'That was easy!'
};

transporter.sendMail(mailOptions, function(error, info){
  if (error) {
    console.log(error);
  } else {
    console.log('Email sent: ' + info.response);
  }
});

*[TLD] : Top-Level Domain, Top-Level Domain
*[SMTP]: Simple Mail Transfer Protocol
*[POP3]: Post Office Protocol
*[IMAP]: Internet Message Access Protocol

목차
6. 개발과 배포
7. 다른 플랫폼으로
저자

김동욱

개발 경력 약 10년, 전문 분야는 웹 및 각종 응용 소프트웨어 플랫폼입니다. Codeflow를 운영하고 있습니다.

2018년 04월 09일 업데이트

지원되지 않는 웹 브라우저거나 예기치 않은 오류가 발생했습니다.