본문 바로가기

프로젝트/디베이트 타이머

[디베이트 타이머 - 3차 스프린트] Backend 기초 인프라 세팅하기

디베이트 타이머 3차 스프린트의 막바지에는 인프라 세팅 과정이 필요했습니다. 기존에 습득했던 인프라 관련 지식들을 복습할 겸, VPC를 세팅하는 처음부터 EC2 + RDS + https 세팅까지 작업해주었는데요. 오늘은 그 세팅과정에 대해 차근차근 소개해보고자 합니다.

 

목표 인프라

세팅하고자 하는 인프라 환경은 다음과 같습니다. 가장 간소화한 인프라 환경 입니다. 그럼 디베이트 타이머 인프라 세팅의  A-Z까지의 과정을 소개해보겠습니다.

 


목차

1. VPC - Subnet 설정하기

    1-1) VPC 생성하기

    1-2) Subnet 생성하기

    1-3) 인터넷 게이트웨이 생성하기

    1-4) 라우팅 테이블 연결하기

 

2. EC2 생성 및 EIP 설정

    2-1) EC2 생성하기

    2-2) EIP 설정하기

 

3. EC2 환경 세팅

    3-1) Swap Memory 세팅

    3-2) JDK17 설치

    3-3) MySql 설치

 

4. RDS 설정하기

 

5. 서브 도메인 세팅

 

6. Nginx를 활용한 Https 설정하기

    6-1) Nginx 설치하기

    6-2) Https 설정하기

    6-3) SSL 인증서 발급받기

    6-4) Listen 규칙 설정하기

    6-5) 인증서 자동갱신 설정하기


1. VPC - Subnet 설정하기

 

1-1) VPC 생성하기

VPC란?

클라우드 환경에서 가상으로 생성된 네트워크를 의미합니다.

 

먼저 AWS 홈페이지에 접속해 로그인 후 VPC를 검색해 줍니다.

 

다음으로 VPC 생성 버튼을 클릭합니다.

 

vpc의 이름과 CIDR 정보를 입력합니다. CIDR란 라우팅 효율성을 향상시키는 IP 할당 방법으로 자세한 설명은 AWS 페이지 설명을 첨부하겠습니다.

 

저는 debate-timer-vpc와 10.0.0.0/24를 CIDR로 설정하였습니다.

 

1-2) Subnet 생성하기

서브넷이란 VPC의 하위 네트워크 집단을 의미합니다. 인터넷과 소통이 가능한 인터넷 게이트웨이와 연결된 서브넷은 public 서브넷, 그렇지 않은 서브넷은 private subnet으로 분류됩니다.

 

이번에는 vpc 목록에 있는 서브넷에 접속해 서브넷 생성을 눌러줍니다.

 

VPC는 앞서 생성한 debate-timer-vpc로 설정합니다.

 

또한 서브넷 같은 경우 CIDR를 10.0.0.0/20으로 설정해 해당 서브넷의 ip 범위를 설정해주었습니다.

 

 

1-3) 인터넷 게이트웨이 생성하기

VPC가 인터넷과 소통하기 위해서는 인터넷 게이트웨이가 필요합니다.

인터넷 게이트웨이 목록을 클릭하고 인터넷 게이트웨이를 생성합니다.

 

 

이후 인터넷 게이트웨이의 이름을 입력하고 게이트웨이를 생성합니다.

 

다시 인터넷 게이트웨이 대시보드로 돌아오면 인터넷 게이트웨이가 생성된 것을 볼 수 있습니다.

이제 인터넷 게이트웨이를 클릭하고 작업 > VPC에 연결을 클릭합니다.

 

이후, 사용가능한 VPC에서 생성했던 VPC를 연결해주면 됩니다.

1-4) 라우팅 테이블 연결하기

 

라우팅 테이블이란 라우터의 설정 정보를 규정하는 테이블을 의미합니다. 즉 어떤 ip로부터의 요청을 다시 특정 ip로 라우팅 해줘~ 라는 설정정보를 담고 있습니다. 우리는 subnet을 public하기 위해 명시적 서브넷 연결을 해주어야 합니다.

 

라우팅 테이블 > 라우팅 테이블 생성 > 서브넷 연결 > 서브넷 연결 편집을 클릭합니다.

 

 

이후 public 서브넷화를 원하는 서브넷을 설정해주면 됩니다.

 

 

이렇게 해서 VPC와 Subnet 설정은 다음과 같은 모습을 띄게 되었습니다.


2. EC2 생성 및 EIP 설정

2-1) EC2 생성하기

AWS 홈페이지에서 EC2를 검색해 들어가줍니다.

 

리전(빌리는 컴퓨터가 있는 지역)이 서울로 설정되어있는지 확인합니다.

 

EC2 콘솔 페이지에서 '인스턴스 시작' 버튼을 누릅니다.

 

이제 원하는 EC2 인스턴스를 커스터마이즈하여 생성할 수 있게 됩니다. 저희는 프리티어(일정 범위 내에서 AWS가 요금 청구를 하지 않는 무료 혜택 제도)를 최대한 활용하고자 다음과 같은 아키텍처를 선택하였습니다.

 

OS : ubuntu
아키텍처 : 64비트(x86)
인스턴스 유형 : t2.micro(프리티어)

 

다음으로 키 페어를 설정해줍니다. 해당 키는 EC2 인스턴스의 접근권한을 확인하는데 사용됩니다. 그러니, 누구에게도 노출되면 안됩니다. 

본 글은 인프라 구축 과정의 전반적인 과정을 다루므로 pem key를 활용해 ssh로 인스턴스에 접근하는 구체적인 활용방안은 다른 레퍼런스를 첨부하는 것으로 대체하도록 하겠습니다.

ref ) EC2 인스턴스에 ssh 접속하기

 

보안그룹 설정에는 ssh, http, https 를 위치무관하게 허용해줍니다.

 

스토리지는 인스턴스의 디스크 공간을 의미합니다. 프리티어에서는 30GB까지 무료로 제공되나 저는 프로젝트 규모를 고려하여 16GB로 설정하였습니다.

 

모두 완료가 되었다면  인스턴스 시작 버튼을 눌러 인스턴스를 생성해주면 됩니다.

 

다시 EC2 대시보드 화면으로 돌아와보면 EC2가 생성된 것을 볼 수 있습니다.

인스턴스 상태가 실행 중(Running)이 아닌 경우는 인스턴스를 띄우고 있는 경우니 조금 기다려주시면 됩니다.

2-2) EIP 설정하기

EIP란?

고정된 IP 주소를 의미합니다.

EC2 인스턴스의 경우 중지 후 다시 부팅을 하게되면 ip 주소를 새로 발급받습니다.

따라서 특정 ip 주소로 고정하는 과정이 필요하며 이를 위해 고정 ip 주소를 발급받아 EC2에 연결해주는 작업이 필요합니다.

 

먼저 EC2 콘솔에서 탄력적 IP 메뉴로 들어갑니다.

 

탄력적 IP 를 발급받습니다.

다시 콘솔로 돌아와서 액션 > 탄력적 IP 할당을 클릭합니다.

 

이제 탄력적 IP를 할당하는 창에서 연결하고자 하는 인스턴스를 클릭해주면 됩니다.

다시 콘솔로 돌아와 확인해보면 EIP주소의 연결된 인스턴스에 할당한 인스턴스가 연결된 모습을 볼 수 있습니다.

 

이제 EC2 설정이 모두 완료되었습니다. 현재까지 완료된 인프라 구조를 보면 다음과 같습니다.

 


3. EC2 환경 세팅

이제 EC2 내에서 스프링 부트 프로젝트를 띄우기 위한 환경을 세팅해보겠습니다. 순차는 다음과 같습니다.

3-1) Swap Memory 세팅
3-2) JDK 설치
3-3) MySQL 설치

 

3-1) Swap Memory 세팅

스왑 메모리(Swap Memory)란?

스왑 메모리란쉽게 말해 메모리 대신 사용가능한 디스크 공간입니다. 다만 디스크를 메모리처럼 로딩해 사용하므로 속도는 느려집니다. 그러나 프리티어인 t2g.micro는 RAM이 1GiB 밖에 되지 않아 프로젝트가 실행 중 죽어버리는 경우가 빈번합니다. 따라서 디스크 공간을 메모리처럼 확보하고자 스왑 메모리를 설정해야 합니다.

 

디베이트 타이머 팀은 4GB의 스왑메모리라면 적당하다고 생각했습니다.

 

1-1. 4GB의 파일 공간 할당

/swapfile 로 4GB의 Swap 공간을 할당합니다.

sudo fallocate -l 4G /swapfile

 

1-2. 파일 권한 설정

root만 읽고 쓸 수 있도록 파일 권한을 설정합니다.

sudo chmod 600 /swapfile

 

1-3. Swap 파일(swapfile)을 스왑 공간으로 활성화

앞서 만든 4GB의 파일을 스왑 공간으로 활성화합니다.

sudo mkswap /swapfile

 

1-4. Swap 활성화

sudo swapon /swapfile

 

1-5. 잘 활성화되었는지 확인

swapon --show

다음처럼 4GB의  /swapfile이 스왑 메모리 list에 등록이 된것을 알 수 있습니다.

 

1-6(선택)) 재부팅 시에도 Swap 파일 자동 활성화 설정하기

재부팅을 하게 되면 스왑파일 설정이 날아갑니다. 이를 방지하기 위해 재부팅 시마다 swapfile을 스왑파일로 자동 활성화하기 위한 설정이 필요합니다. 이를 위해 etc/fstab 파일에 부팅 시 swap 파일을 자동으로 마운트하도록 설정해주는 명령어가 필요합니다.

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

3-2) JDK 17 설치

2-1. 스프링 부트 프로젝트 실행을 위한 JDK 17버전을 설치합니다.

sudo apt update
sudo apt install openjdk-17-jdk

 

2-2. 잘 설치되었는지 확인

java -version

다음처럼 openjdk 의 버전이 표시되었다면 정상적으로 설치된 것입니다.


3-3) mysql 설치

RDS 연결을 위해 mysql을 설치합니다.

 

3-1. myql-client 설치

sudo apt update
sudo apt install mysql-client -y

 

3-2. 잘 설치되었는지 확인

mysql --version

 


4. RDS 설정하기

 

4-1) RDS 생성하기

MySQL용 RDS를 생성합니다.

 

프리티어 템플릿을 클릭해줍니다.

 

username과 password를 지정해줍니다. 저는 username을 admin으로 지정해주었습니다.

 

인스턴스는 db.t4g.micro로 세팅해주었습니다.

 

나머지 설정은 유지한 상태로 연결 란에 있어서 "EC2 컴퓨팅 리소스에 연결"을 클릭합니다. 그리고 인스턴스에는 생성해주었던 EC2 인스턴스를 연결합니다.

 

이렇게 생성하게 되면 자동으로 RDS 인바운드 규칙에는 EC2로부터만 트래픽을 받도록 설정됩니다.

반대로 EC2 3306 아웃바운드 규칙에는 RDS로 부터만 트래픽을 보내도록 설정이 됩니다.

 

 추가구성에서 디폴트 데이터 베이스 이름을 설정해줍니다. 해당 이름을 가진 데이터베이스가 RDS 내에 자동으로 생성됩니다. 저는 debate_timer 라는 디폴트 데이터베이스를 설정해주었습니다.

 

잘 연결되었는지 확인하기

이제 RDS 가 잘 연결되었는지 확인해보겠습니다.

 

EC2 인스턴스에 접근하여 RDS 엔드포인트로 접속을 시도해봅니다.

mysql -h <RDS 엔드포인트> -P 3306 -u <사용자 이름> -p

 

비밀번호를 입력하면 성공적으로 접속된 응답을 받을 수 있습니다.

 

현재까지 세팅된 인프라 환경은 다음과 같습니다.

 


5. 서브 도메인 세팅

가비아에 접속해 디베이트 타이머에서 사용할 도메인을 구입하고자 했습니다. 회의 결과 www.debate-timer.com 으로 선정되었습니다.

 

이제 도메인과 연결할 ip 주소들을 설정해주어야 합니다. 먼저 MyGabia 페이지에 접속합니다.

그럼 구매한 도메인인 debate-timer.com이 있습니다.

'관리' 버튼을 눌러 접속한 이후 DNS 정보 > 도메인 연결 페이지로 들어갑니다.

My DNS 관리 페이지에서 설정 버튼을 클릭합니다.

 

이제 A레코드를 설정하고 하위 도메인을 설정한 후, 인스턴스의 public ipv4주소를 기입해주면 됩니다. 

EC2 인스턴스의 public ipv4 주소는 EC2 콘솔 내에서 확인할 수 있습니다.

 

저는 dev 서버를 띄우는 중이므로 api.dev를 서브 도메인으로 두고 해당 도메인으로 접속 시 dev 인스턴스 ipv4로 접속되도록 ip주소를 매핑하였습니다. 이는 곧 https://api.dev.debate-timer.com 으로 접속 시 dev 서버의 인스턴스 ip 주소로 매핑된다는 것을 의미합니다.

 

*A레코드란? : 해당 DNS를 ip 주소로 매핑합니다 

*CNAMe이란? : 해당 DNS를 또다른 DNS 주소로 매핑합니다.

 

이제 도메인 이름을 가지고 접속을 할 수 있게 되었습니다. 전반적인 인프라 구성은 여기서 목표한 바를 만족하게 됩니다.


6. Nginx를 활용한 Https 설정하기

보안을 위해 Https를 설정해보겠습니다. Https가 왜 보안에 도움이 되는지 모르겠다면 다음 링크를 참조하셔도 좋습니다.


6-1) Nginx 설치하기

저희 팀은 Nginx라는 웹 서버를 활용해 https 설정을 하고자 하였습니다.

 

먼저 EC2 서버에 접속합니다.

 

1.1 nginx 설치하기

sudo apt update
sudo apt install nginx

 

 

1.2 잘 설치되었는지 확인

cd etc
cd ls

 

파일들 사이에 nginx라는 폴더가 생성되었다면 잘 설치된 것입니다.

 

1.3. nginx 실행해보기

sudo service nginx start

 

1.4 실행 상태 확인하기

sudo service nginx status

-> 실행상태가 active 상태이면 실행에 성공한 것입니다.

 

1.5 잘 떴는지 확인해보기

EC2 퍼블릭 ipv4로 접속하면 다음과 같은 nginx 화면이 보이면 실행에 성공한 것입니다.


6-2) Https 설정하기

이제 Let's Encrpt 에서 인증서를 발급받아 Https 설정을 해보겠습니다.

 

2.1 /sites-available에 파일 만들기

cd /etc/nginx/sites-available
sudo vi {설정할 도메인 이름}

sites-available 폴더에 들어가 설정할 도메인 이름을 가진 폴더를 만들어줍니다. 저의 경우는 api.dev.debate-timer.com을 입력해주었습니다.

 

 

2.2 listen 설정하기

server {
    listen 80;
    listen [::]:80;
    server_name api.dev.debate-timer.com; #허용할 서버 도메인


    location / {
        return 308 https://$host$request_uri; #301로 리다이렉트하면 POST도 GET으로 전달됨.
    }
}

 

이제 허용할 서버 도메인을 대상으로 리다이렉트를 설정합니다. 해당 listen 규칙의 경우 http 80포트로 오는 규칙을 https로 http method를 유지한 채 리다이렉션 하는 것을 의미합니다.

 

 

2.3 sites-enabled에도 같은 파일 작성

sudo ln -s /etc/nginx/sites-available/{설정할 도메인 이름} /etc/nginx/sites-enabled/

이제 소프트 링크를 통해 해당 도메인 파일과 같은 파일을 sites-enabled 하위에도 만들어줍니다.

소프트 링크란 바로가기처럼 다른 파일이나 디렉터리에 참조를 생성하는 것을 의미합니다.

 

다시 sites-enabled를 접속하면 링크가 걸린 바로가기 파일(api.dev.debate-timer.com)이 하나 생성된 것을 볼 수 있습니다.

 

 

2.4 서버 이름 버킷 사이즈 증량

버킷 사이즈 에러를 방지하기 위해 서버 이름 버킷 사이즈를 조정해야 합니다. 만약 서버 이름이 길거나 복잡할 때 발생가능한 해쉬 충돌 문제를 해결하기 위해 해당 설정이 필요합니다.nginx.conf 파일로 접속합니다.

cd ~/nginx
sudo vim nginx.conf

 

server_names_hash_bucket_size 64; 라고 적혀져 있는 주석을 주석해제 해줍니다.

server_names_hash_bucket_size 64;  # 주석해제

 

*만약 설정을 하지 않는다면?

더보기

다음과 같은 해쉬 사이즈가 작다는 에러가 발생가능합니다.

nginx: [emerg] server_names_hash_bucket_size: too small

 

 

2.5 nginx 재시작

이제 설정 파일이 제대로 되었는지 확인해봅시다. nginx 구동 테스트를 해봅니다.

sudo nginx -t #구동 테스트

 

문법 오류 없이 잘 작성되었다면 다음과 같은 성공 문구가 뜹니다.

 

nginx를 재시작합니다.

sudo service nginx restart #다시 시작

 


6-3) SSL 발급받기

 

본격적으로 인증서 발급을 위해 certbot을 설치하고 nginx 자동편집 구성을 통해 https를 적용해보겠습니다.

 

3-1. certbot 설치

먼저 certbot을 설치합니다. certbot이란 무료 SSL 인증서 제공 서비스인 Let's Encrpt 에서 인증서를 발급받고 관리하는 도구입니다.

sudo snap install certbot --classic #cerbot 설치

 

3-2. Nginx SSL 인증서 발급

다음으로 Nginx 웹 서버에서 SSL인증서를 설치하고 자동으로 Https를 설정하도록 명령합니다.

sudo certbot --nginx #자동 편집

그럼 어떤 도메인에 Https를 적용할 것인지 묻는데요. 여기서 해당 도메인 번호를 입력합니다. 저의 경우는 1번 도메인인 dev.debate-timer.com을 대상으로 Https를 적용할 것이었기에 1을 입력했습니다.

 

추후 Successfully received certificate 라는 문구가 뜨면 인증서가 발급되었다는 것을 알 수 있습니다.


6-4) Listen 규칙 편집하기

 

다시 sites-available 파일로 접근합니다.

sudo cd /etc/nginx/sites-available/
sudo cat dev.debate-timer.com

 

그럼 Certbot이 발급된 인증서를 제공하도록 Nginx 구성을 자동으로 편집해놓은 모습을 볼 수 있습니다.

 

해당 파일을 해석해보자면 다음과 같습니다.

  • 443 요청 → 308요청으로 리다이렉트
  • 80 요청 → 301 요청으로 리다이렉트

그러나 301요청의 경우 POST요청의 경우도 GET으로 리다이렉트 되는 문제가 있었다. 따라서 308요청으로 리다이렉트하도록 파일을 수정해주어야 한다.또한 443 요청의 경우 308이 아닌 localhost(EC2 서버)의 8080포트로 프록피 패스를 통해 리다이렉션해주어야 한다.

 

해당 수정을 한 이후의 dev.debate-timer.com 파일을 다시 한번 보겠습니다.

 

다시 파일을 해석하면 다음과 같습니다.

  • https 443 요청 → localhost 8080(스프링 부트 서비스)으로 포트포워딩
  • http 80 요청 → https요청으로 리다이렉션

이제 Listen 규칙 편집이 완료되었습니다.


6-5) 인증서 자동 갱신 설정하기

 

Let's Encrypt에서 발급한 인증서의 경우 90일동안만 유효하기에 자동갱신을 설정해주어야 합니다.

sudo certbot renew --dry-run


이제 Https 설정까지 모두 완료가 되었습니다. https://{설정된 DNS 주소}를 입력해보면 다음과 같은 502 에러가 납니다. 아직 80포트에서 서버가 돌고 있지 않기 때문에 발생하는 에러이며 https 설정이 정상적으로 된 것을 의미합니다.