# Chapter6. AWS 서버 환경을 만들어보자 - AWS EC2

AWS(Amazon Web Service)라는 클라우드 서비스를 이용해 본격적으로 서버 배포를 진행해 보겠습니다. 외부에서 본인이 만든 서비스에 접근하려면 **24시간 작동하는 서버**가 필수입니다. 24시간 작동하는 서버에는 3가지 선택지가 있습니다.

- 집에 PC를 24시간 구동시킨다.
- 호스팅 서비스(`Cafe 24`, `코리아 호스팅` 등)를 이용한다.
- 클라우드 서비스(`AWS`, `AZURE`, `GCP` 등)를 이용한다.

일반적으로 비용은 호스팅 서비스나 집 PC를 이용하는 것이 저렴합니다. 만약 특정 시간에만 트래픽이 몰린다면 **유동적으로 사양을 늘릴 수 있는 클라우드가 유리합니다.**

##### 클라우드
클라우드 서비스는 인터넷(클라우드)을 통해 서버, 스토리지(파일 저장소), 데이터베이스, 네트워크, 소프트웨어, 모니터링 등의 컴퓨팅 서비스를 제공하는 것입니다. 단순히 물리 장비를 대여하는 것으로 생각하지만, 그렇지는 않습니다.

예를 들어 `AWS`의 `EC2`는 서버 장비를 대여하는 것이지만, 실제로는 그 안의 로그 관리, 모니터링, 하드웨어 교체, 네트워크 관리 등을 기본적으로 지원하고 있습니다. 개발자가 직접 해야 할 일을 `AWS`가 전부 지원을 하는 것입니다.

이런 클라우드에는 몇 가지 형태가 있습니다.

(1) `Infrastructure as a Service` (IaaS, 아이아스, 이에스)
  - 기존 물리 장비를 미들웨어와 함께 묶어둔 추상화 서비스입니다.
  - 가상머신, 스토리지, 네트워크, 운영체제 등의 IT 인프라를 대여해 주는 서비스라고 보면 됩니다.
  - `AWS`의 `EC2`, `S3` 등

(2) `Platform as a Service` (SaaS, 사스)
  - 소프트웨어 서비스를 이야기합니다.
  - 구글 드라이브, 드랍박스, 와탭 등

여기서는 여러 클라우드 서비스(`AWS`, `Azure`, `GCP` 등) 중 `AWS`를 선택합니다. 이유는 다음과 같습니다.

- 첫 가입 시 1년간 대부분 서비스가 무료입니다. 단, 서비스마다 제한이 있습니다.
- 클라우드에서는 기본적으로 지원하는 기능(모니터링, 로그관리, 백업, 복구, 클러스터링 등등)이 많아 개인이나 소규모일 때 개발에 좀 더 집중할 수 있습니다.
- 많은 기업이 `AWS`로 이전 중이기 때문에 이직할 때 `AWS` 사용 경험은 도움이 됩니다. 국내에서는 `AWS` 점유율이 압도적입니다. 쿠팡, 우아한형제들, 리멤버 등 클라우드를 사용할 수 있는 회사에서는 대부분 `AWS`를 사용합니다.
- 사용자가 많아 국내 자료와 커뮤니티가 활성화되어 있습니다.

이 책에서 진행하는 모든 `AWS` 서비스는 `IaaS`를 사용합니다. `AWS`의 `PaaS` 서비스인 빈스톡을 사용하면 대부분 작업이 간소화되지만, **프리티어로 무중단 배포가 불가능**합니다(~~돈을 내고 2대 사용하면 가능합니다~~).

--- 

## 6.1 AWS 회원 가입
**Master 혹은 Visa 카드가 필요합니다.** 본인의 카드 중 `Master` 혹은 `Visa` 카드를 준비한 뒤 진행합니다.

`AWS` 공식 사이트(https://aws.amazon.com/ko/)로 이동한 뒤 **무료 계정 만들기**를 선택합니다.

참고링크 : [AWS 회원가입 따라하기](https://goddaehee.tistory.com/175)

차례대로 진행한 뒤 콘솔 로그인 버튼을 클릭해서 로그인을 진행합니다.

---

## 6.2 EC2 인스턴스 생성하기
`EC2`는 `AWS`에서 제공하는 성능, 용량 등을 유동적으로 사용할 수 있는 서버입니다. 보통 `AWS`에서 리눅스 서버 혹은 윈도우 서버를 사용합니다. 라고 하면 이 `EC2`를 이야기하는 것입니다.

>`EC2`의 이름은 `Elastic Compute Cloud`에서 `C`가 2개가 있어 `C2`라는 이름이 붙었습니다. `AWS`에서는 대부분 첫 글자가 중복되면 숫자로 표기합니다. 비슷한 예로 `AWS`의 `S3`는 `Simple Storage Service`를 줄여가 `S`가 3개라고 하여 `S3`입니다.

`AWS`에서 무료로 제공하는 프리티어 플랜에서는 `EC2` 사용에 다음과 같은 제한이 있습니다.

- 사양이 `t2.micro`만 가능합니다.
  - `vCPU(가상 CPU) 1 Core`, 메모리 `1GB` 사양입니다.
  - 보통 `vCPU` 는 물리 CPU 사양의 절반 정도의 성능을 가집니다.
- 월 750시간의 제한이 있습니다. 초과하면 비용이 부과됩니다.
  - 24시간 * 31일 = 744시간입니다.
  - 즉, **1대의 t2.micro만 사용한다면 24시간** 사용할 수 있습니다.

자 그럼 `EC2`를 만들기 전에, 본인의 리전을 확인해 봅니다.

>리전이란 `AWS`의 서비스가 구동될 지역을 이야기합니다. `AWS`는 도시별로 클라우드 센터를 지어 해당 센터에서 구축된 가상머신들을 사용할 수 있습니다. 이걸 리전이라고 합니다.

>서울 리전이 생기기 전까지는 국내 서비스들은 도쿄 리전을 사용했습니다. 한국과 가장 가까운 지역이라 가장 네트워크가 빠르기 때문입니다. 현재는 서울 리전이 있어 국내에서 서비스한다면 무조건 서울 리전을 선택하면 됩니다.

보통은 처음 리전(웹에서 오른쪽 위의 메뉴에서 확인 가능)이 오아이주로 선택되어 있습니다. 이를 **서울로 변경**합니다.

서울로 리전을 변경했다면 화면 중앙에 있는 검색창에서 `ec2` 를 입력하여 `EC2` 서비스를 클릭합니다.

`EC2` 대시보드가 나오는데, 여기서 중앙에 있는 `[인스턴스 시작]` 버튼을 클릭합니다. 인스턴스란 `EC2` 서비스에 생성된 가상머신을 이야기합니다.

인스턴스를 생성하는 첫 단계는 `AMI(Amazon Machine Image, 아마존 머신 이미지)`를 선택하는 것입니다. 먼저 `AMI`에 대해 설명하면, `AMI`는 `EC2` 인스턴스를 시작하는 데 필요한 정보를 **이미지로 만들어 둔 것**을 이야기합니다. 인스턴스라는 가상 머신에 운영체제 등을 설치할 수 있게 구워 넣은 이미지로 생각하면 됩니다.

여기서는 `Amazon Linux AMI`를 선택합니다. 아마존 리눅스 2 대신에 아마존 리눅스 1을 선택한 이유는 **아직 국내 자료가 리눅스 1이 더 많기 때문**입니다. 보통 센토스 6 버전으로 진행되는 자료들은 아마존 리눅스 1에서 모두 사용할 수 있습니다. 아마존 리눅스 2는 센토스 7 버전 자료들을 그대로 사용할 수 있습니다. 하지만 굳이 센토스 AMI를 사용하지 않고 아마존 리눅스 AMI를 사용하는 이유는 다음과 같습니다.

- 아마존이 개발하고 있기 때문에 지원받기가 쉽다.
- 레드햇 베이스이므로 레드햇 계열의 배포판을 많이 다뤄본 사람일수록 문제없이 사용할 수 있다.
- `AWS`의 각종 서비스와의 상성이 좋다.
- `Amazon` 독자적인 개발 리포지터리를 사용하고 있어 `yum`이 매우 빠르다.

다음은 인스턴스 유형을 선택하는 단계입니다. 인스턴스 유형에서는 프리티어로 표기된 `t2.micro`를 선택합니다.

다음 단계는 세부정보 구성입니다. 기업에서 사용할 경우 화면상에 표기된 VPC, 서브넷 등을 세세하게 다루지만, 여기서는 혼자서 1대의 서버만 사용하니 별다른 설정을 하지 않고 넘어갑니다.

>VPC와 서브넷 등은 AWS 서비스들의 네트워크 환경을 구성하는 정도로만 이해하면 됩니다. 1인 개발 시 혹은 대량의 서버를 사용하지 않는다면 굳이 별도로 구성할 필요가 없으므로 여기서는 기본 생성되는 값을 사용합니다.

다음 단계는 스토리지 선택입니다. 스토리지는 흔히 **하드디스크**라고 부르는 서버의 디스크(SSD도 포함)를 이야기하며 **서버의 용량**을 얼마나 정할지 선택하는 단계입니다. 여기서 설정의 기본값은 8GB입니다. **30GB까지 프리티어로 가능**하므로 최대치인 30GB로 변경합니다.

태그에는 웹 콘솔에서 표기될 태그인 `Name` 태그를 등록합니다. 태그는 해당 인스턴스를 표현하는 여러 이름으로 사용될 수 있습니다. `EC2`의 이름을 붙인다고 생각하고 넣으면 됩니다. 여러 인스턴스가 있을 경우 이를 태그별로 구분하면 검색이나 그룹 짓기 편하므로 여기서 본인 서비스의 인스턴스를 나타낼 수 있는 값으로 등록합니다.

다음으로 보안 그룹입니다. 보안 그룹은 **방화벽**을 이야기합니다. **서버로 80 포트 외에는 허용하지 않는다**는 역할을 하는 방화벽이 `AWS`에서는 보안 그룹으로 사용됩니다.

이 보안그룹 부분이 굉장히 중요한 부분입니다. 유형 항목에서 `SSH`이면서 포트 항목에서 22인 경우는 **AWS EC2에 터미널로 접속**할 때를 이야기합니다. `pem` 키가 없으면 접속이 안 되니 전체 오픈(0.0.0.0/0, ::/0)하는 경우를 종종 발견합니다. 이렇게 되면 이후 파일 공유 디렉토리나 깃허브등에 실수로 `pem` 키가 노출되는 순간 서버에서 가상화폐가 채굴되는 것을 볼 수 있습니다.

보안은 언제나 높을수록 좋으니 `pem` 키 관리와 **지정된 IP에서만 SSH 접속이 가능**하도록 구성하는 것이 안전합니다. 그래서 본인 집의 IP를 기본적으로 추가하고(**내 IP를 선택하면 현재 접속한 장소의 IP**가 자동 지정됩니다) 카페와 같이 집 외에 다른 장소에서 접속할 때는 **해당 장소의 IP를 다시 SSH 규칙에 추가**하는 것이 안전합니다.

현재 프로젝트의 기본 포트인 8080을 추가하고 `[검토 및 시작]` 버튼을 클릭합니다. 검토 화면에서 보안 그룹 경고를 하는데, 이는 8080이 전체 오픈이 되어서 발생합니다. 8080을 열어 놓는 것은 위험한 일이 아니니 바로 `[시작하기]` 버튼을 클릭합니다.

인스턴스로 접근하기 위해서는 `pem` 키(비밀키)가 필요합니다. 그래서 인스턴스 마지막 단계는 할당할 `pem` 키를 선택하는 것입니다. 인스턴스는 지정된 `pem` 키(비밀키)와 매칭되는 공개키를 가지고 있어 해당 `pem` 키 외에는 접근을 허용하지 않습니다. 일종의 **마스터키**이기 때문에 절대 유출되면 안 됩니다. `pem` 키는 이후 `EC2` 서버로 접속할 때 필수 파일이니 **잘 관리할 수 있는 디렉토리로 저장**합니다. 기존에 생성된 `pem` 키가 있다면 선택하고 없다면 신규로 생성합니다.

`pem` 키까지 내려받았다면 인스턴스 생성 시작 페이지로 이동한 뒤 인스턴스 `id`를 클릭하여 `EC2` 목록으로 이동합니다. 생성이 다 되었다면 IP와 도메인이 할당된 것을 확인할 수 있습니다.

인스턴스도 결국 하나의 서버이기 때문에 IP가 존재합니다. 인스턴스 생성 시에 항상 새 IP를 할당하는데, 한 가지 조건이 더 있습니다. 같은 인스턴스를 중지하고 **다시 시작할 때도 새 IP가 할당**됩니다. 즉, 잠깐 인스턴스를 중지하고 다시 시작하면 IP가 변경되는 것입니다. 이렇게 되면 매번 접속해야 하는 IP가 변경돼서 PC에서 접근할 때마다 IP 주소를 확인해야 합니다. 굉장히 번거로우므로 인스턴스의 IP가 **매번 변경되지 않고 고정 IP를 가지게** 해야 합니다. 그래서 **고정 IP**를 할당합니다.

#### EIP 할당
`AWS`의 고정 IP를 `Elastic IP(EIP, 탄력적 IP)`라고 합니다. `EC2` 인스턴스 페이지의 왼쪽 카테고리에서 **탄력적 IP를 눌러 선택**하고 주소가 없으므로 `[내 주소 할당]` 버튼을 클릭해서 바로 `[할당]` 버튼을 클릭합니다.

새 주소 할당이 완료되면 **탄력적 IP가 발급**됩니다.

방금 생성한 탄력적 IP와 방금 생성한 `EC2` 주소를 연결합니다. **방금 생성한 탄력적 IP를 확인**하고, 페이지 위에 있는 `[작업]` 버튼 -> `[주소 연결]` 메뉴를 선택합니다. 주소 연결을 위해 생성한 `EC2` 이름과 IP를 선택하고 `[연결]` 버튼을 클릭합니다. 연결이 완료되면 왼쪽 카테고리에 있는 `[인스턴스]` 탭을 클릭해서 다시 **인스턴스 목록** 페이지로 이동한 뒤 해당 인스턴스의 **퍼블릭, 탄력적 IP**가 모두 잘 연결되었는지 확인합니다.

여기까지 진행했으면 `EC2` 인스턴스 생성 과정은 끝났습니다. 하지만, 주의할 점이 있습니다. 방금 생성한 탄력적 IP는 **생성하고 EC2 서버에 연결하지 않으면** 비용이 발생합니다. 즉, **생성한 탄력적 IP는 무조건 EC2에 바로 연결해야 하며** 만약 더는 사용할 인스턴스가 없을 때도 탄력적 IP를 삭제해야 합니다. 마찬가지로 비용 청구가 되므로 꼭 잊지 않고 삭제해야 합니다.

---

## 6.3 EC2 서버에 접속하기
방금 생성한 `EC2`로 접속을 해보겠습니다.

### Mac & Linux
자세한 내용은 책을 참조할 것

### Windows
윈도우에서는 `Mac`과 같이 `SSH` 접속하기엔 불편한 점이 많아 별도의 클라이언트(`putty`)를 설치합니다. putty 사이트(`https://www.putty.org/`)에 접속하여 실행 파일을 내려받습니다.

실행 파일은 2가지입니다.

- putty.exe
- puttygen.exe

두 파일을 모두 내려받은 뒤, `puttygen.exe` 파일을 실행합니다.

`putty`는 `pem` 키로 실행이 안 되며 `pem` 키를 `ppk` 파일로 변환을 해야만 합니다. `puttygen`은 이 과정을 진행해 주는 클라이언트입니다. `puttygen` 화면에서 상단 `[Conversions -> Import Key]`를 선택해서 내려받은 `pem` 키를 선택합니다.

그럼 자동으로 변환이 진행됩니다. `[save private key]` 버튼을 클릭하여 `ppk` 파일을 생성합니다. 경고 메시지가 뜨면 `[예]`를 클릭하고 넘어갑니다.

`ppk` 파일이 잘 생성되었으면 `putty.exe` 파일을 실행하여 다음과 같이 각 항목을 등록합니다.

- HostName : `username@public_ip` 를 등록합니다. 우리가 생성한 `Amazon Linux`는 `ec2-user`가 `username`이라서 `ec2-user`@탄력적 IP 주소를 등록하면 됩니다.
- Port : `ssh` 접속 포트인 22를 등록합니다.
- Connection type : `SSH`를 선택합니다.

항목들을 모두 채웠다면 왼쪽 사이드바에 있는 `[Connection -> SSH -> Auth]`를 차례대로 클릭해서 `ppk` 파일을 로드할 수 있는 화면으로 이동합니다. `[Browse...]` 버튼을 클릭해서 조금 전에 생성한 `ppk` 파일을 불러옵니다. 정상적으로 불러왔다면 다시 `[Session]` 탭으로 이동하여 `[Saved Sessions]`에 **현재 설정들을 저장할 이름을 등록**하고 `[save]` 버튼을 클릭합니다.

저장한 뒤 `[open]` 버튼을 클릭하면 다음과 같이 `SSH` 접속 알림이 등장합니다. `[예]`를 클릭합니다. 그럼 `SSH` 접속이 성공한 것을 확인할 수 있습니다.

---

## 6.4 아마존 리눅스 1 서버 생성 시 꼭 해야 할 설정들
아마존 리눅스 1 서버를 처음 받았다면 몇 가지 설정들이 필요합니다. 이 설정들은 모두 자바 기반의 웹 애플리케이션(톰캣과 스플링부트)이 작동해야 하는 서버들에선 필수로 해야 하는 설정들입니다.
- **Java 8 설치** : 현재 이 프로젝트의 버전은 `Java 8`입니다.
- **타임존 변경** : 기본 서버의 시간은 미국 시간대입니다. 한국 시간대가 되어야만 우리가 사용하는 시간이 모두 한국 시간으로 등록되고 사용됩니다.
- **호스트네임 변경** : 현재 접속한 서버의 별명을 등록합니다. 실무에서는 한 대의 서버가 아닌 수십 대의 서버가 작동되는데, IP만으로 어떤 서버가 어떤 역할을 하는지 알 수 없습니다. 이를 구분하기 위해 보통 호스트 테임을 필수로 등록합니다.

방금 진행한 `EC2` 접속 과정을 통해서 `EC2`에 접속한 뒤에 다음 과정을 진행하면 됩니다.

#### Java 8 설치
아마존 리눅스 1의 경우 기본 자바 버전이 7입니다. 이 책에서는 자바 8을 기본으로 사용하므로 자바 8을 `EC2`에 설치합니다. `EC2`에서 다음의 명령어를 실행합니다.

```java
sudo yum install -y java-1.8.0-openjdk-devel.x86_64
```
설치가 완료되었다면 인스턴스의 `Java` 버전을 8로 변경합니다.

```java
sudo /usr/sbin/alternatives --config java
```
그리고 선택 화면에서는 `Java8`을 선택합니다(2 입력).

버전이 변경되었으면 사용하지 않는 `Java7`을 삭제합니다.
```java
sudo yum remove java-1.7.0-openjdk
```
현재 버전이 `Java8`이 되었는지 확인합니다.
```java
java -version
```

#### 타임존 변경
`EC2` 서버의 기본 타임존은 `UTC`입니다. 이는 세계 표준 시간으로 한국의 시간대가 아닙니다. 즉, **한국의 시간과는 9시간 차이**가 발생합니다. 이렇게 되면 서버에서 수행되는 `Java` 애플리케이션에서 생성되는 시간도 모두 9시간씩 차이가 나기 때문에 꼭 수정해야 할 설정입니다. 서버의 타임존을 **한국 시간(KST)**으로 변경합니다.

다음 명령어를 차례로 수행합니다.
```java
sudo rm /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime
```
정상적으로 수행되었다면 `date` 명령어로 타임존이 `KST`로 변경된 것을 확인할 수 있습니다.

#### Hostname 변경
여러 서버를 관리 중일 경우 **IP만으로 어떤 서비스의 서버인지** 확인이 어렵습니다. 그래서 각 서버가 **어느 서비스인지 표현**하기 위해 HOSTNAME을 변경합니다. 다음 명령어로 편집 파일을 열어봅니다.

```java
sudo vim /etc/sysconfig/network
```
참고 링크 : [Linux 기반의 vi(vim) 에디터 사용법](https://jhnyang.tistory.com/54)

참고 링크 : [Amazon Linux 인스턴스의 호스트 이름 변경](https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/set-hostname.html)

변경한 후 다음 명령어로 서버를 재부팅 합니다.
```java
sudo reboot
```
재부팅이 끝나고 나서 다시 접속해 보면 HOSTNAME이 잘 변경된 것을 확인할 수 있습니다.

`Hostname`이 등록되었다면 한 가지 작업을 더 해야 합니다.
호스트 주소를 찾을 때 가장 먼저 검색해 보는 `/etc/hosts`에 변경한 `hostname`을 등록합니다.

다음 명령어로 `/etc/hosts` 파일을 열어 봅니다.
```java
sudo vim /etc/hosts
```
방금 등록한 HOSTNAME을 등록합니다.
```java
127.0.0.1 등록한 HOSTNAME
```
`:wq` 명령어로 저장하고 종료한 뒤 정상적으로 등록되었는지 확인해 봅니다. 확인 방법은 다음 명령어로 합니다.
```java
curl 등록한 호스트 이름
```
만약 잘못 등록되었다면 찾을 수 없는 주소라는 에러가 발생합니다.

`curl: (6) Could not resolve host: .....`

잘 등록하였다면 80 포트로 접근이 안된다는 에러가 발생합니다.

`curl: (7) Failed to connect to .....`

이는 아직 80포트로 실행된 서비스가 없음을 의미합니다. 즉, curl 호스트 이름으로 실행은 잘 되었음을 의미합니다.

`EC2` 설정이 완료되었으니 이제 `AWS`의 데이터베이스 서비스인 `RDS`를 생성하고 설정해 보겠습니다.

---