[Photorage] 3. React + Spring 을 AWS EC2 Nginx로 배포하기

최정우·2022년 5월 30일
2

Photorage

목록 보기
6/7

지난 포스팅에서 프로젝트를 Vite로 만들고 스토리북까지 추가해봤다. 이번에는 리액트로 만들 웹을 AWS의 EC2 제품을 이용하여 배포하는 인프라를 구축 해보겠다.

글 제목이 React + Spring이라 헷갈릴 수도 있을 것 같다. 정확히 우리 프로젝트는 MSA로 설계를 진행하고 있고, 나는 Photorage-web이라는 이름으로 프론트 서버를 현재 띄울 것이다. 그럼 굳이 제목에 Spring을 왜 붙여놨냐하면, 내가 AWS에 배포해보기 위해 관련 글을 찾아볼 때 프론트와 백을 분리한 프로젝트인지 아닌지 알기 어려웠던 기억이 있어서 우리 프로젝트는 프론트와 백이 분리가 되어 있다는 것을 명확히 하기 위해 이렇게 글 제목을 정했다.

그 전에 AWS가 뭔지, EC2가 뭔지 전혀 모르겠다면 [AWS 간단 정리]를 보고와도 좋을 것 같다.


해당 글은 이 글 을 보고 진행한 EC2 생성 과정에서 내가 느꼈던 점에 대해 기록한 글이다.

1. 왜 EC2를 쓰나?

사실 구글에 React AWS 배포 라고 검색을 해보면, EC2를 사용하는 예제보다는 S3 혹은 Amplify를 이용한 서버리스 프로젝트에 소개가 대다수이다. 하지만 나는 현재 이 프로젝트에 백엔드 개발 팀이 분명하게 있고, 또 주제가 사진을 다루는 만큼 단순히 S3를 이용한 웹서버를 띄우는 것에는 무리가 있다고 판단했다. 또 추후 기회가 된다면 SSR로 바꾸는 것도 고려하고 있기 때문에 직접 EC2에 Nginx를 설치하여 웹 서버를 띄워보려고 한다.

2. EC2 인스턴스 생성

1) AWS EC2 서비스 페이지 접속


AWS에 가입을 하고 루트 사용자로 로그인을 하게 되면 다음과 같은 페이지가 보일텐데, AWS 서비스에서 EC2가 보인다면 선택을 하고, 안보인다면 모든 서비스를 펼쳐서 EC2에 접속을 하자.

2) 인스턴스 생성


1. 왼쪽 메뉴의 인스턴스를 누른다(현재 위에 사진은 인스턴스를 눌렀을 때 화면이다.)
2. 우측 상단에 인스턴스 시작 버튼을 누른다.

3) AMI 선택(1단계)

해당 사진 우측 빨간 네모안에 보면 총 7단계에 거쳐서 인스턴스를 생성할 수 있게 되어있다. 아마 똑같이 인스턴스 생성을 통해 들어갔는데 위에 사진처럼 뷰가 안보이는 분들도 있을 것이다. 현재 AWS가 웹페이지의 뷰를 새로 만들고 있는 것 같더라. 그럴때는 우측 상단에 기존 탭으로 보기 등의 버튼이 뜰텐데 그것을 누르면 현재와 같은 페이지를 볼 수 있다.

나는 AWS의 체험판 느낌인 프리티어로 생성할 것이기에 왼쪽에 프리티어만을 체크해서 고를 수 있는 운영체제를 살펴보았고, Amazon Linux 2 AMI 64비트를 선택하게 되었다(사실 이쪽 분야는 아는게 너무 없어서 AWS에서 제공하는 설명 보고 최적화 되어있다길래 선택했다).

4) 인스턴스 유형 선택(2단계)

2단계 인스턴스 선택에서 역시 기본으로 선택되어 있는 t2.micro(프리티어)로 선택하였다.
이후 3~5단계에서 세부 설정을 할 수 있지만 참고한 포스팅 글들에서 대부분 넘어가도 괜찮다고 해서 추후 사용하다 뭔가 설정을 추가로 하는일이 있으면 그때 수정하든 새로운 포스팅을 하든 하겠다.

5) 보안 그룹 구성(6단계)

좌측 하단의 규칙 추가 버튼을 위해 http와 사용자 지정 TCP를 추가해주었다.
http는 Nginx로 React를 배포할 것이기에 추가하였고, 사용자 지정 TCP는 추후 node.js 등으로 SSR을 할 것을 대비하여 8000포트를 이용해 추가해주었다.
소스 항목을 통해 내 instance(EC2 서버)에 접근할 수 있는 방법을 제한 할 수 있다. 그런데 아직 이런것을 제한했다 어떤 불상사가 생길지 몰라서 나는 Anywhere 에서 접근할 수 있다는 의미인 0.0.0.0/0 으로 두었다(사실 그냥 추가하고 안만지면 저런 상태로 있다)

6) 새로운 키 페어 생성

7단계 검토에서 지정해준 것들을 확인하고 나면 키페어를 생성하는 창이 나온다.
현재 내 사진에는 생성시에 만들어둔 키페어가 있어서 저렇게 나오는데 새 키페어를 생성해서 이름을 작성하고 다운로드 받아둔 뒤 인스턴스를 시작하자.

  • 이후 다운받은 프리이빗 키(.pem)을 보안된 위치인 .ssh 하위로 이동 + 프라이빗 키 권한을 설정해주자
    $ mv ~/Downloads/[키페어 이름].pem ~/.ssh/[키페어 이름].pem
    $ chmod 400 ~/.ssh/[키페어 이름].pem
    본 프로젝트는 Mac으로 진행했다. 혹시 윈도우에서 하시는분들은 다른 포스팅을 이 부분 이 조금 다를 것 같은데 ec2 window 프라이빗 키 권한설정 등으로 검색해서 진행하자.

3. 인스턴스 연결

위 사진의 숫자 순서대로 클릭하여 연결 페이지로 들어간다.
그런 다음 설치 되어 있는 내장 터미널이든 따로 사용하는 터미널이 있다면 터미널을 켜주자.

그리고 터미널에 '이 부분 복사' 라고 되어있는 곳을 참고하여 입력하면 되는데, 아마 그대로 입력하면 안되고 IP라던가 현재 인스턴스 이름 등은 자기가 세팅한대로 값을 넣어줘야 한다. 그대로 붙여넣기 하고 왜 안되냐고 투덜거리지 말자(나처럼).
형식은 아래와 같다.

$ ssh -i [프라이빗 키(.pem) 경로] [AMI의 사용자 이름]@[인스턴스의 퍼블릭 DNS]


이런 화면이 자신의 터미널에 떴다면 연결에 성공한 것이다.

4. 사용할 패키지 설치

AWS 공식문서를 참고하여 설치를 진행했다.

1) nvm 설치 후 node 설치

다음과 같은 코드 흐름으로 진행했는데 nvm으로 분명 노드를 설치를 했음에도 마지막 5단계에 현재 노드 버전을 콘솔로 찍어보려고 하니 command node not found 뭐 이런 느낌의 에러로 노드가 없다고 나왔다. 그래서 nvm --list 명령어를 통해 노드 버전을 확인해보니 분명 있었는데 안되더라.

이런 문제가 발생하신 분은 아래처럼 해보길 바란다
(참고 링크 - https://tttap.tistory.com/120)

1) nvm install node 대신 nvm install [버전 명(숫자) or lts/이름]으로 설치

  • 프로젝트 생성을 할 때, 별 생각없이 Vite로 생성을 하고 나서 생각하니까 인턴 하고 있는 회사에서 사용중인 node 14.17.5 버전으로 생성했다. 그래서 EC2 인스턴스의 노드도 메이저 버전 14를 맞추기로 했고, 그 중 LTS를 설치했다.
    ex) $ nvm install lts/fermium
  • lts 이름이 확인하고 싶다면 nvm list 명령어를 통해 확인하자.

2) 1번을 하면 노드가 설치 되었을 것이다. 그러먼 nvm use v14(버전명) 또는 nvm use lts/fermium 등과 같은 명령어를 사용하면 nvm이 현재 사용할 노드 버전을 해당 버전으로 바꾼다.

3) 디폴트 노드 버전을 설정한다.

  • nvm alias default 버전명 을 실행하면 된다
    ex) $ nvm alias default lts/fermium

2) git 설치 및 프로젝트 클론

$ sudo yum update // 초기에 package 들을 update 해준다.
$ sudo yum install git // 깃 설치
$ git clone [url] // 프로젝트 코드 클론 ex) git clone https://github.com/[닉네임]/[레포지토리네임]

5. Nginx 설치 및 설정

사실 여기까지도 상당히 낯설고 어려웠다. 조금 만 더 힘내서 해보자.

1) Nginx 설치

$ sudo yum install nginx //Amazon Linux 1 환경
$ sudo amazon-linux-extras install nginx1.12 //Amazon Linux 2 환경(내 경우)

나는 Linux2 환경을 선택해서 아래 코드를 이용하여 설치하였다.

2) React 앱 빌드

지난번에 git clone을 이용하여 프로젝트를 가져왔었다. 해당 프로젝트의 루트 디렉토리로 이동한 후 build를 해주자. 내 글을 그대로 따라 왔다면 해당 프로젝트의 루트 디렉토리는 아래와 같을 것이다.
$ home/ec2-user/[프로젝트 명] 해당 파일로 이동하는 명령어는 cd 이다
ex) $ cd home/ec2-user/photorage-web

이동을 완료했다면,

$ yarn install //필요한 package 설치(미설치 된게 있다면)
$ yarn build //프로젝트 사전 build 명령어

명령어를 통해 build를 하면 되는데, 나는 React를 Vite라는 툴체인으로 프로젝트를 생성하여서 미리 설정되어있는 yarn build 라는 명령어를 통해 손쉽게 빌드 파일을 만들 수 있다(주의할 점, CRA는 빌드된 결과물이 build 라는 이름의 디렉토리에 담기는데, Vite는 dist라는 이름의 디렉토리에 담긴다.)

3) Nginx 설정

여기서부터는 거의 모르는 내용이라 거의 따라했어서 원문의 내용을 그대로 가져오고 내가 겪었던? 첨언할 부분을 추가하겠다.

3-1. nginx.conf 열기
우선 아래 명령어를 통해 해당 파일을 열면 기본적으로 여러 내용이 이미 설정되어 있는 것을 확인할 수 있다.
$ sudo vi /etc/nginx/nginx.conf

nginx.conf 내에서 React 프로젝트의 build로 바로 이어지게 설정할 수도 있지만, 설정들을 깔끔하게 관리하기 위해서 일반적으로 선호되는 방식은 /etc/nginx 내에 sites-enabled 디렉토리를 생성하여 여기에 각 서비스의 설정을 넣고 nginx.conf가 이들을 확인하도록 하는 것이다.

하나의 인스턴스 내부인데도 ‘각 서비스’라고 표현한 것은, 가상 호스트(서버) 개념을 사용할 수 있기 때문이다. 이를 통해 하나의 컴퓨터, 즉 하나의 IP 내에서 여러 웹을 배포할 수 있다.(Nginx의 장점이라 할 수 있겠다. 🤗)

그대로 따라하면 /etc/nginx/ 디렉토리의 nginx.conf 라는 파일이 vi 라는 편집 툴을 이용하여 열리게 될 것이다. vi 사용이 익숙치 않아서 당황할 수 있으나 일단 따라하자.


3-2. nginx.conf 수정
지금은 앞서 말한 대로 sites-enabled 디렉토리에 따로 설정을 만들어줄 것이므로, server 블럭 행들은 모두 주석 처리(행 앞에 #) 하도록 한다. 그리고 server 블럭 바로 위에 아래와 같이 include /etc/nginx/sites-enabled/*.conf;를 추가함으로써 sites-enabled 하위의 설정 파일들을 포함하도록 한다.

... 
include /etc/nginx/conf.d/*.conf;
(✨ 코드 추가) include /etc/nginx/sites-enabled/*.conf;
# server {
#    listen       80 default_server;
#    listen       [::]:80 default_server;
#    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 {
#    }
# }
...

위에서도 말했듯 vi를 이용하는게 익숙치 않을 수 있다(나도 그랬다). 저 부분을 못찾을 수도 있는데 우선 처음 터미널에 바로 수정이 되지않을 것이다. 그럴 때 키보드 i를 누르면 해당 파일을 수정하겠다 라는 뜻이 된다. 그 이후 키보드 방향키를 이용하여 아래로 내리다 보면 위에 나오는 설명이 나오는데 차분히 include 구문을 추가해주고 주석처리 진행해주자.
여기까지 했다면 키보드 esc 누르기 > :wq 입력을 해주자. :wq(저장하고 나가기) 라는 뜻이다.


3-3. sites-available, sites-enabled 설정
일반적인 방식은 sites-available 디렉토리에 필요한 파일들을 작성한 후 이들과 연결되는 symbolic link(symlink)를 sites-enabled에 추가하는 것이다. 때문에 /etc/nginx 내부에 두 디렉토리를 모두 생성해 준다. 그리고 sites-available 내에 원하는 이름으로 설정 파일을 생성해 열도록 한다.

$ sudo mkdir /etc/nginx/sites-enabled
$ sudo vi /etc/nginx/sites-available/#######.conf

지금은 도메인 등록도 되어있지 않고, HTTPS를 위한 준비도 되어있지 않으므로, HTTP에 해당하는 port 80에 대해서 아주 기본 설정만 포함한다.

server {
  listen 80;
  location / {
    root /home/ec2-user/#######/#######/build;(본문 내용 -> 삭제)
  	root /home/ec2-user/#######/dist;(필자 코드 -> 적용) 
    index index.html index.htm(본문 내용인데 필요 없어 보여서 삭제함);
    try_files $uri $uri/ /index.html;
  }
}

location 뒤의 /는 directive라고 하는 부분인데, IP 주소나 도메인의 뒷부분인 URI에 대응된다. /만 쓰면 ‘/’로 시작하는 모든 URI에 해당한다는 것으로 현재 설정은 이 인스턴스의 IP 주소로 port 80을 통해 들어오는 모든 URL을 연결시켜주는 것이다.
root 행에는 아까 Git을 통해 가져온 프로젝트 내부의 build 디렉토리 경로를 입력한다.

자 우선 위에서 #####.conf => [자신의 프로젝트 명].conf 로 이해하고 입력하자. 또 /etc/nginx/sites-available/#####.conf 파일에 입력할 때 위에 적어둔대로 자기의 상황에 맞게 입력하자.


3-4. sites-enabled > symlink 생성 및 Nginx 설정 테스트

  $ 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

위와 같은 내용이 출력되면 설정의 문법이 정상적이라는 것이다.

위와 같이 안뜬다면 지금까지 흐름에서 주석을 달 때, } 를 몇개 빠뜨렸다거나 프로젝트 루트 설정이 잘못되었다거나 그럴 가능성이 높다. 꼼꼼하게 작성해보자. 추가로 아래엔 기본적이지만 도움이 될 리눅스 명령어를 조금만 적어두겠다.

$ cd ~~ //~~경로로 이동
$ ls  //현재 경로에 존재하는 모든 파일 및 디렉토리 표시
$ pwd //현재 경로를 출력
$ mkdir ~~ //현재 경로에 ~~이름을 가진 디렉토리(폴더) 만들기
$ touch ~~ //현재 경로에 ~~이름을 가진 파일 만들기
$ rm ~~ //현재 경로에 ~~이름을 가진 파일 삭제(디렉토리를 삭제하고 싶으면 $ rm -rf ~~)

3-5. Nginx 동작
이제 Nginx를 동작시키고, 웹 브라우저에서 AWS EC2 인스턴스 IP 주소를 입력하면 build한 React 앱으로 연결되는 것을 확인할 수 있다.
(AWS EC2 인스턴스 IP 주소로 바로 연결할 때 https로 들어가지는데, 현재는 http만 설정했기 때문에, http로 수정하면 들어가질 것이다.)

$ sudo systemctl start nginx

만약, 500 Internal Server Error가 발생한다면, build까지의 경로로 접근할 때 거치는 디렉토리들에 대해 외부에서의 실행 권한이 없어서 발생하는 문제일 가능성이 높으므로, 홈 디렉토리인 /home/ec2-user의 권한을 others의 실행 권한을 포함한 711로 설정한다.

$ chmod 711 /home/ec2-user

위에서 이상이 없었다면 정상적으로 본인의 프로젝트의 빌드 파일이 출력될 것이다. 그게 안된다면 프로젝트 빌드 루트를 적었던 etc/nginx/sites-available/#####.conf 파일에 오타나 잘못된 내용은 없어는지 살펴보자.


현재 내 빌드 된 웹사이트 - 해당 주소를 통해 누구나 접속 할 수 있지만, 비용절감을 위해 EC2를 사용하지 않을 때는 중지 상태로 두는데 이걸 다시 켜면 IP주소가 바뀌더라. 나중에 고정 도메인을 구해서 그걸 등록해보겠다.

[참고 링크]

profile
누구나 할 수 있지만 아무나 못하는 일을 하자

0개의 댓글