뮤랑이는 웹캠을 사용하기 때문에 HTTP가 아닌 HTTPS로 배포해주어야 했다. 자세한 내용은 이 글 ISSUE : Camera API HTTP 작동 불가에 써놓았다.
이번 기회에 네트워크 공부도 좀 하고, 삽질(..)도 좀 할 겸해서 https 등록하면서 네트워크 공부도 해보았다. https 등록 과정을 그냥 따라하는 데에 그치지 않고 궁금한 것들마다 파보니까, CS 개념과 연관된 부분이 많아서 재밌었다.
SSL 등록하기 - CA에 직접? ACM?
우선 스프링 서버에 HTTPS를 적용하려면 SSL 인증서를 발급받아야 한다. CA(Certificate Authority), 즉 공식 발급 기관에 인증서 발급 요청을 해야 한다. 하지만 CA를 통해 인증서를 발급받으면 유료이고, 3개월마다 갱신해주어야 한다. 또한 만약 서버를 Scale-out(다중 인스턴스)할 경우, 각 인스턴스마다 인증서를 등록해주어야하는 번거로움이 있다.
다행히 AWS의 AWS Certificate Manager(ACM)를 사용하면, 무료이고, SSL을 자동 갱신해주고, 로드밸런서를 통해 다중 인스턴스에 한번에 적용할 수 있다. 그래서 이번 프로젝트에서는 AWS를 통해 인증서를 발급받고, 로드밸런서에 해당 인증서를 등록해주기로 했다.
우선 EC2로 http://www.murange.site 를 배포한 상태였고, 이를 HTTPS로 등록하려면 다음의 과정을 거쳐야 한다. 이 글에서는 따라하기 위한 방법 설명이라기보단 각 단계에서 배울 수 있는 개념들 위주로 정리해보았다.
HTTPS 배포 과정
- AWS Certificate Manager(ACM)에서 SSL 인증서 발급받기
- Route 53(DNS 서버)에 도메인 등록하기
- 로드밸런서 생성하고 DNS와 연결, HTTP 요청을 HTTPS로 리다이렉트하도록 설정해주기
1. SSL 인증서 발급받기
위에서 언급했듯이 AWS Certificate Manager를 통해 SSL 인증서를 발급받을 수 있다.
이 인증서 발급 후, 인증서 관리 페이지에서 Route 53(DNS)의 Route 53에 레코드 생성 버튼을 통해 DNS에 등록해주어야 한다.
2. Route 53(DNS 서버)에 도메인 등록하기
AWS의 Route 53은 도메인 서버이다. 도메인 서버는 IP와 도메인을 매칭시켜주는 역할을 한다. 참고로 도메인 서버는 네임서버와 같은 의미이다. (DNS = NS) 브라우저에 도메인을 입력하면, DNS에서 매칭되는 IP 주소를 전달받아 해당 IP로 클라이언트와 서버가 통신하게 된다.
사용자가 도메인을 입력하면, Route 53(DNS)에서 매칭되는 IP 주소를 알려주는 역할을 한다. Route 53에 도메인을 등록하면, 기본적으로 NS와 SOA타입이 자동 생성된다. 이 NS 타입은 네임서버로, 사용자가 도메인 입력 시 IP 주소를 알려주는 서버들이다. 만약 한 서버가 다운되었을 때 다른 서버에 질의할 수 있도록 4개의 서버를 AWS가 자동 지정해준다.
만약 가비아에서 도메인을 구매하고 IP를 연결하면 자동으로 가비아의 네임서버들(NS 타입)이 할당된다. 이 네임서버를 AWS Route 53에서 할당받은 네임서버로 변경해주어야 한다.
각 레코드(해당 DNS에 들어온 요청을 어떻게 처리할 것인지에 대한 정보)에 대한 설명은 다음과 같다.
- NS 타입은 사용자가 도메인을 입력 시 IP주소를 반환해주는 NS 서버가 있는 레코드이다. (자동 생성) ⇒ 가비아의 기본 NS를 이 레코드의 주소로 바꿔주어야 한다.
- SOA 타입은 이 DNS 서버의 설정에 대한 레코드이다. (자동 생성)
- A 타입은 Address로, 연결될 주소를 입력하는 레코드이다.
- CNAME 타입은 도메인주소를 다른 도메인 주소로 매핑시키는 레코드 (별칭으로 사용할 도메인을 입력하는 레코드이다. 혹은 SSL 관련 레코드이다.)
A 타입의 경우, 여기서는 DNS를 사용하므로 도메인명에 하나의 IP가 아닌 로드밸런서 주소를 입력해주어야 한다.
A 타입이랑 CNAME 타입(별칭 용도)의 차이는, 예시로 구분하면 쉽다. 만약 murange.site에 할당된 ip가 43.207.67.173이고, www.murange.site로도 해당 사이트에 접속하게 하고 싶다고 가정해보았다. 이때 ip 주소가 A타입이고 www.murange.site가 CNAME 타입이다. 여러 별칭이 있을 때, 별칭들은 모두 CNAME에 등록해주면 ip주소가 변경되었을 때 A타입의 ip 한번만 변경해주면 되어 편리하다. (각각의 도메인명 마다 ip 주소를 바꾸지 않고 정식(?) 도메인에 할당된 ip 한번만 바꾸면 된다)
혹은 CNAME 타입은 SSL 인증서 발급 후 등록 시 생성되는 레코드이다. 가장 첫번째 과정에서 언급했듯이 SSL 인증서 발급 후, Route 53에 레코드 생성
버튼을 통해 원하는 도메인에 등록해주어야 한다. 그러면 자동으로 CNAME이 등록된다. 그러면 Route 53(DNS)에 SSL이 등록된다!
3. 로드밸런서에 HTTP 요청을 HTTPS로 리다이렉트하도록 설정해주기
로드밸런서는 다중 서버를 모니터링하며 부하, 정상 상태 등을 고려하여 현재 적절한 서버에 분산시켜주는 역할을 한다. 로드밸런서를 사용하면 다중 인스턴스를 사용하더라도, 한번에 SSL을 적용할 수 있다. 또한 로드밸런서에 HTTP로 접속하더라도 HTTPS로 리다이렉트되도록 설정해준다.
우선 AWS에는 다음과 같은 로드밸런서 종류가 있다.
- Application Load Balancer : L7 계층 (http/https) 프로토콜
- Network Load Balancer : L4 계층 (TCP/UDP) 프로토콜
Application Load Balancer은 어플리케이션 계층에서 로드밸런싱해준다. HTTP/HTTPS 프로토콜의 헤더를 보고 라우팅한다. 즉, 어플리케이션 계층까지의 모든 헤더 정보를 보고 라우팅해준다. 이 로드밸런서는 L7계층의 프로토콜인 SSL을 적용해줄 수 있다. 그리고 Network Load Balancer은 전송 계층에서 로드밸런싱해주는 로드밸런서로, 어플리케이션 계층까지 가지 않고 TCP/IP 프로토콜의 헤더를 보고 라우팅을 한다.
- Application Load Balancer : L7 계층 (http/https) 프로토콜
- Network Load Balancer : L4 계층 (TCP/UDP) 프로토콜
지금은 로드밸런서를 통해 HTTP 요청을 HTTPS 프로토콜로 리다이렉트시켜주기 때문에, L7 어플리케이션 계층의 로드밸런서(ALB)를 사용해주어야 한다.
리스너는 해당 프로토콜 + 포트가 지정하는 서버(타겟 그룹)로 라우팅하는 역할을 한다. 즉, 리스너에 따라 지정한 타겟 그룹으로 요청이 전달된다.
타겟 그룹은 EC2 인스턴스들의 그룹이다. 다중 인스턴스를 사용할 경우 해당 타겟 그룹에 여러 인스턴스들을 선택해주면 된다. (이 프로젝트에서는 SSL을 위해 로드밸런서를 사용하므로 타겟 그룹안에 한 개의 EC2 인스턴스만 있다. 그림은 일반적으로 로드밸런서를 사용할때처럼 다중 인스턴스이다. 또한 프로젝트에서는 https로 리다이렉트되지만 그림은 일반적인 로드밸런서를 표현하고자 다르게 나타냈다.) 현재 프로젝트에서는 http 요청을 https로 리다이렉트해주는 데, 이 설정도 로드밸런서에서 해준다.
각 리스너와 타겟 그룹을 설정해주고, http → https로 리다이렉트 설정해주면 위와 같다.
그리고 로드밸런서는 타겟 그룹 단위로 헬스 체크를 해서 정상 상태인 타겟 그룹으로만 요청을 라우팅한다. 이때 타겟 그룹은 기본적으로 여러 인스턴스 중 라운드 로빈 알고리즘(순차적으로 배정)을 통해 분산 처리한다. 하지만 이는 요청 처리 시간이 달라 비효율적일 수 있기에 대신 LOR 알고리즘을 선택해 분산 처리할 수 있다.
전체 과정을 정리해보면,
- 사용자가 도메인명 www.murange.site 입력
- DNS에서 해당 도메인의 연결된 주소 반환 (여기서는 로드밸런서 주소를 반환)
- 만약 http일 경우, 로드밸런서에서 https로 리다이렉트
- {https, 443} 리스너의 타겟그룹이 정상일 경우 해당 타겟 그룹의 EC2로 요청 접수!
현재 프로젝트에서 EC2를 하나만 사용하므로 그대로 그림에 나타내었다.
AWS에 이러한 등록과정들을 마냥 따라하니까 실수가 많이 생겼어서 알아야 하는 개념들 위주로 정리해보았다. 확실히 아니까 보이는 것들이 많고 어디서 실수가 생겼는지도 알고.. 무엇보다 AWS, 네트워크 과정에 친해진 것 같다.