1. AWS EC2에 React 웹 배포하기 (feat. Nginx)
드디어 써보는 클라우드 기반 웹 배포
이전에 제작했던 과제 채점 웹서비스는 연구실 서버를 이용하는 온프레미스 방식이었는데,
드디어 AWS EC2를 사용해서, 클라우드 방식으로 웹을 배포했다.
구글링하면서 이 블로그와 이 블로그를 많이 참고했는데, 도전하면서 한 삽질을 정리하려고 한다👏
🤔 들어가기 전, 어떤 웹 서비스인가요?
룸메이트가 교내 데이터 시각화 경진대회에 참여했는데, 그 결과물을 보여주기 위한 매개체를 찾고 있었다. PPT로 만들기엔 아깝다고
그 즈음 나는 취업 준비 명목으로 2개 과목만 듣고 있었는데, 웹으로 구현하면 나를 써달라고 했고,
그 결과 내 고객님이 되었다.ㅋㅋ
사실 백엔드가 필요없을 정도로 규모가 크지 않아서 프론트엔드쪽 욕심을 크게 낼 수 있는 프로젝트가 될 것 같다.
아직 레이아웃과 자잘한 기능만 추가해 놓은 상태라, AWS를 사용해서 배포하는 것부터 삽질록을 작성한다.
⚙️ AWS EC2 Instance 생성하기
AWS EC2에서 인스턴스 생성 -> AMI 중 Amazon Linux 2 AMI 선택 -> t2.micro (Free Tier 사용 가능) 선택
인스턴스 상세 설정 (Configure Instance Details)은 그대로 두고, 스토리지 추가 (Add Storage)에서 Free Tier의 최대 SSD 용량인 30GB로 수정
태그 추가 (Add Tags)는 인스턴스의 정보를 관리하기 편하게 설정할 수 있지만, 나는 그대로 넘어갔다.
보안 그룹 설정 (Configure Security Group)에서 SSH는 내 아이피(My IP)로 설정하고,
HTTP와 HTTPS를 추가한 뒤 모든 곳(Anywhere)으로 설정하여 배포하는 웹에 어디서든 접근할 수 있도록 한다.
이후 인스턴스를 생성하고, SSH Key pair를 설정한다.
키 이름을 적으면 private key (.pem
파일)를 다운로드 받을 수 있다.
적절한 곳에 다운로드한 후 인스턴스 생성을 마친다.
🔥 SSH로 인스턴스에 접근하기
위 이미지처럼 인스턴스가 실행 중(running)이 되면 로컬에서 EC2 인스턴스에 접속할 수 있으며,
아까 다운로드 받은 private key 파일을 사용할 때가 왔다.
Windows 10, 11 기준으로 파일을 다음으로 옮긴다.
C:\Users\{사용 중인 로컬 계정명}\.ssh
처음 위 경로로 들어가면 known_hosts
, config
파일만 있을 수 있다.
aws_web_newkey.pem
파일이 옮긴 다운로드 받은 private key.
메모장을 켠 후, config
파일을 메모장으로 드래그 & 드롭하면 수정할 수 있다.
다음 내용을 추가한다.
Host {사용하려는 이름. 마음대로 적는다}
HostName {호스트 네임}
User ec2-user
IdentityFile ~/.ssh/{private key 파일명}.pem
호스트 네임은 아래 이미지에서 찾을 수 있다.
여기서 빨간 네모 안의 내용을 복사하여 위 {호스트 네임} 에 붙여넣고 저장한다.
⛏️ 키 파일 권한 조정 및 접속
다운로드 받은 private key인 .pem
파일의 권한을 수정해야 한다.
.pem
파일 우클릭 -> 속성 -> 보안 탭 클릭 -> 고급 버튼 클릭 -> 상속 해제 (상속 제거를 누르면 전체 제거 가능) -> 창 닫기
이후, 보안 탭에서 편집 버튼 클릭 -> 추가 버튼 클릭 -> 개체 이름 텍스트 창에 자신의 계정명 추가 -> 이름 확인 후 확인
이후, 읽기 및 실행, 읽기는 허용으로, 쓰기는 거부로 설정한다.
이곳을 참조하면 친절히 스크린샷까지 있다.
그 다음, cmd에서 다음 명령어를 입력한다.
C:\Users\{로컬 계정명} > ssh {위의 Host에 적은 이름}
윈도우 cmd에서 SSH 명령어를 사용할 수 없다면, OpenSSH 서비스를 설치해야 한다. 여기 참고
C:\Users\{내 계정}>ssh aws_webs_ec2
The authenticity of host 'XXXXXXXXXXXXXXXXXXXXXXXXXXX' can't be established.
ECDSA key fingerprint is SHA256:/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' (ECDSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
처음 접속 시 다음과 같은 질문이 나오는데, yes
를 입력해 주면 된다.
📑 Github 원격 저장소에서 클론 받아오기
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for '#########################'
요즘은 HTTPS 기반으로 Github 계정 및 패스워드를 입력해 클론 받는 것이 막혔나 보다.
따라서 SSH 기반으로 인증한 후에야 클론을 받을 수 있다.
다음 명령어를 입력한다.
// EC2 인스턴스에서 진행하고 있는 중
$ cd ~/.ssh
$ ssh-keygen -t ed25519 -C "{당신의 이메일}@example.com"
// ed25519 방식으로 생성되지 않는다면, RSA 방식으로 진행한다
$ ssh-keygen -t rsa -b 4096 -C "{당신의 이메일}@example.com"
위 명령어를 입력하면,
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/XXXXXXXX/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
저장하려는 위치와, SSH 키에 대한 비밀번호를 물어본다.
위치는 그대로 놔둬도 괜찮고, 비밀번호는 Github에서 설정하기를 권장하고 있다. 나는 안했지만
모든 설정을 마치면, 두 개의 파일(id_ed25519
, id_ed25519.pub
)이 생성된다.
Your identification has been saved in /home/ec2-user/.ssh/id_ed25519.
Your public key has been saved in /home/ec2-user/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXX my-mail@example.com
The key's randomart image is:
+--[ED25519 256]--+
| o.=.. |
| E = |
| * O . |
|. = o . |
| o * = .S |
| B @.o+ |
| . |
| .=.. .* |
| o=*o.o. |
+----[SHA256]-----+
이제 이 키를 Gihtub SSH Key에 등록해야 한다.
다음 명령어를 입력해서 복사하도록 하자.
$ cat id_ed25519.pub
.pub
은 public key, .pub
이 없는 파일은 private key이며 절대 공개하면 안 되므로 유의하도록 하자.
Github에 로그인하여 Settings -> SSH and GPG Keys에 들어간다.
여기서 New SSH Key 버튼을 누르고,
적절한 이름과 함께 방금 전 복사했던 내용을 넣고 저장하면, SSH 기반으로 git clone
이 가능해진다.
git clone git@github.com:newForinux/XXXXXXXXXXXXXXXXX
Cloning into 'XXXXXXXXXXXXXXXXXXXXXX'...
Warning: Permanently added the RSA host key for IP address 'XXX.XXX.XXX.XXX' to the list of known hosts.
remote: Enumerating objects: 100, done.
remote: Counting objects: 100% (100/100), done.
remote: Compressing objects: 100% (61/61), done.
remote: Total 100 (delta 42), reused 90 (delta 35), pack-reused 0
Receiving objects: 100% (100/100), 333.99 KiB | 7.26 MiB/s, done.
Resolving deltas: 100% (42/42), done.
💎 필요한 패키지 설치
패키지를 업데이트하고, Nginx 웹 서버와 git을 설치해 주자.
// Amazon Linux 2 AMI는 CentOS 기반이다
$ sudo yum update
$ sudo yum install git
$ sudo yum install nginx
Nginx를 설치하려고 하면
$ sudo yum install nginx
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
No package nginx available.
Error: Nothing to do
nginx is available in Amazon Linux Extra topic "nginx1"
To use, run
# sudo amazon-linux-extras install nginx1
Learn more at
https://aws.amazon.com/amazon-linux-2/faqs/#Amazon_Linux_Extras
위와 같은 알림이 뜰 수 있는데,
# sudo amazon-linux-extras install nginx1
이 부분을 그대로 작성해서 Nginx를 설치할 수 있다
React 앱을 빌드 / 배포하기 위해서 yarn과 NodeJS 또한 설치하도록 하자.
$ curl -o- -L https://yarnpkg.com/install.sh | bash
$ source ~/.bashrc
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
$ . ~/.nvm/nvm.sh
$ nvm install node
📢 나와 같이 저 버전이 신경쓰이는 사람을 위해 이 곳을 참조하면 현 버전에 맞는 커맨드를 확인할 수 있다.
이후 yarn
을 사용해서 의존성 파일을 설치하고, 빌드한다.
$ yarn install
$ yarn run build --prod
🚨 여기서 잠깐!
... 무수한 에러 내용 ...
make: *** [Release/obj.target/libsass/src/libsass/src/ast.o] Error 127
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/home/ec2-user/.ssh/XXXXXXXXXXXXXXXXXXXXXXX/node_modules/node-gyp/lib/build.js:194:23)
gyp ERR! stack at ChildProcess.emit (node:events:390:28)
gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12)
gyp ERR! System Linux 4.14.252-195.483.amzn2.x86_64
gyp ERR! command "/home/ec2-user/.nvm/versions/node/v17.1.0/bin/node" "/home/ec2-user/.ssh/XXXXXXXXXXXXXXXXXXXXXXX/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /home/ec2-user/.ssh/XXXXXXXXXXXXXXXXXXXXXXX/node_modules/node-sass
gyp ERR! node -v v17.1.0
gyp ERR! node-gyp -v v7.1.2
😳??
의존성 설치부터 힘겨운 싸움이었으나…
개발 환경의 node 버전과 EC2 인스턴스에서 설치한 node의 버전이 안맞을 때 발생하는 에러였다.
현재 node 버전은 17.1.0
버전이고,
혹시 몰라서 확인해 본 로컬 node 버전은 15.4.0
이었다.
후…🙄
다음 명령어를 통해 현재 설치된 node 버전을 변경했다.
$ nvm deactivate
$ nvm uninstall v17.1.0
$ nvm install v15.4.0
이후 다시 의존성 설치 / 빌드를 시도했더니 문제가 없었다!
🧶 Nginx 웹 서버 설정하기
nginx.conf
가 서비스의 설정을 확인할 수 있도록 만들어 주자.
$ sudo vi /etc/nginx/nginx.conf
명령어를 입력하여, http
블록 안의 server
블록을 주석 처리(#) 하고,
include /etc/nginx/sites-enabled/*.conf;
를 추가하여 sites-enabled
설정 파일을 포함시킨다.
...
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*.conf; <-- 추가!!
# server {
# listen 80;
# listen [::]:80;
# server_name _;
# root /usr/share/nginx/html;
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
# location / {
# }
# error_page 404 /404.html;
# location = /40x.html {
# }
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
#}
...
Nginx를 처음 설치하면 sites-available
, sites-enabled
디렉토리가 없다. 만들어 주자.
$ sudo mkdir /etc/nginx/sites-available
$ sudo mkdir /etc/nginx/sites-enabled
$ sudo vi /etc/nginx/sites-available/{만들 설정 파일명}.conf
파일 내용은 다음과 같이 작성한다.
server {
listen 80;
location / {
root /home/ec2-user/{클론 받은 React 앱 루트 경로}/build;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
이후, 심볼릭 링크 파일을 만들고 테스트한다.
$ sudo ln -s /etc/nginx/sites-available/#######.conf /etc/nginx/sites-enabled/{만든 설정 파일명}.conf
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
이렇게 나오면 테스트가 성공한 것이며,
nginx: [emerg] unexpected "}" in /etc/nginx/nginx.conf:84
nginx: configuration file /etc/nginx/nginx.conf test failed
위와 같이 뜨면 테스트가 실패한 것이다. Nginx.conf
또는 sites-available
에다가 만든 설정 파일을 점검하자. (;
하나 빼먹어서 오류가 났당ㅎㅎ)
이제 다 왔다👏
$ sudo systemctl start nginx
명령어를 입력해서 웹 서버를 구동하고, 로컬에서 EC2 인스턴스의 IP 주소를 입력하면
빌드한 React 웹 서비스가 연결된다.
✨ 결과
다음 포스팅은 무료 도메인 + AWS ROUTE 53을 사용해서 도메인으로 웹 서비스를 연결하는 것에 다루도록 하겠다😊