'집사의 고민' 프론트엔드 인프라 구성 알아보기

Chex·2023년 8월 25일
14

우아한테크코스

목록 보기
15/19
post-thumbnail

집사의고민 프론트엔드 구성도

우테코 레벨3 프로젝트에서, 프론트엔드 인프라 구성은 팀원인 에디가 담당하여 진행하였습니다. 그러던 중, 팀 회의에서 에디 이외의 구성원이 프론트엔드 인프라에 대한 문서화를 맡아 해당 내용을 학습하면 전반적인 프로젝트 이해에 도움이 될 것이라는 의견이 나왔습니다. 이에 따라, 저희 팀 프론트엔드 인프라에 대해 알아보고 구성도를 그려보면서 학습한 내용을 정리해보았습니다.

워크플로우 요약

  • GitHub에서 Merge가 되면 Webhook이 동작하여 zipgo-infra 서버의 젠킨스의 파이프라인이 실행됩니다.
  • 깃허브 레포지토리를 클론하여 패키지를 설치한 후 frontend디렉토리 내의 파일들을 사용하여 도커 이미지를 빌드합니다.
  • 빌드된 이미지를 Docker Hub에 업로드합니다.
  • zipgo-prod 서버에서 도커 이미지를 pull 받은 후 도커 컨테이너를 생성합니다.
  • 도커 컨테이너를 실행(docker run)할 때 호스트 서버의 3000포트와 컨테이너 내부의 3000포트를 바인딩하여 호스트 서버의 3000포트로 들어오는 요청이 컨테이너의 3000포트로 전달되도록 합니다.
  • 도커 컨테이너 내부의 Nginx는 클라이언트로부터 요청을 받았을 때 요청에 맞는 정적 파일을 응답해 주는 HTTP Web Server로서 동작합니다.
  • 클라이언트와 서버 사이에 위치한 Nginx는 외부 IP로 요청이 왔을 때 매핑된 EC2 내부 IP로 요청을 전달하고 이에 대한 응답을 클라이언트에게 반환하는 Proxy Server로서 동작합니다.
  • 배포가 성공하면 Slack으로 배포 성공 / 실패 알림이 옵니다.

📝 젠킨스 프론트엔드 파이프라인

1. 전처리 - 캐싱된 파일 삭제

  • deleteDir 메서드를 통해 이전 빌드의 잔여 데이터나 파일을 제거합니다.

2. Clone Repository

  • 2023-zipgo 깃허브 레포지토리 develop 브랜치를 복사해옵니다.

3. Build

  • npm i -g yarn: Yarn 패키지 매니저를 설치합니다.
  • cd frontend && yarn: frontend 디렉토리로 이동한 후 yarn 명령어를 실행하여 프로젝트에 필요한 패키지를 설치합니다.

4. Docker-Build

  • docker build -t [이미지 이름]:[빌드 번호] ./frontend:
    • docker build 명령어를 통해 도커 이미지를 만듭니다.
    • -t 옵션으로 [이미지 이름]:[빌드 번호]형식으로 도커 이미지의 태그를 설정합니다.
    • ./frontend: frontend 디렉토리를 도커 컨텍스트 경로로 설정하여 이 디렉토리 내의 파일들을 사용하여 이미지를 빌드합니다.

5. Docker-Push

  • Docker Hub에 로그인한 후 [이미지 이름]:latest 태그를 가진 도커 이미지를 Docker Hub에 업로드합니다.

6. Deploy

  • ssh 연결을 생성하여 zipgo-prod 서버(원격 서버)에 원격으로 접속합니다.
  • docker rmi: 원격 서버에서 기존 도커 이미지를 삭제합니다.
  • docker stop: 원격 서버에서 실행되고 있는 기존 컨테이너를 중지합니다.
  • docker rm: 원격 서버에서 기존 컨테이너를 삭제합니다.
  • docker pull: 도커 허브에서 도커 이미지를 가져옵니다.
  • docker run -d -p 3000:3000 --name $CONTAINER_NAME $IMAGE_NAME:latest
    • docker run: 도커 컨테이너를 생성합니다.
    • -d: 컨테이너를 백그라운드 모드로 실행하는 옵션입니다.
    • -p 3000:3000: 호스트 서버의 3000포트와 컨테이너 내부의 3000포트를 매핑하는 옵션으로 이를 통해 호스트 서버의 3000포트로 들어오는 요청이 컨테이너의 3000포트로 전달됩니다.
    • —name: 컨테이너에 이름을 지정하는 옵션입니다.
    • $IMAGE_NAME:latest: 해당 이미지를 사용하여 도커 컨테이너를 생성합니다.

📝 Reverse Proxy로서의 Nginx

Forward Proxy

클라이언트가 서버로 요청할 때 직접 요청하지 않고 먼저 프록시 서버를 통해 요청하는 방식입니다. 서버에게 클라이언트가 누구인지 감추는 역할을 합니다. 서버가 응답받은 IP는 포워드 프록시 서버의 IP이기 때문에 클라이언트가 누군지 알 수 없습니다.

Reverse Proxy

클라이언트가 서버를 호출할 때 리버스 프록시 서버를 호출하게 되고 프록시 서버가 서버에 요청하여 받은 응답을 클라이언트에게 전달하는 방식입니다. 리버스 프록시는 서버가 누구인지 감추는 역할을 합니다. 클라이언트는 리버스 프록시 서버를 먼저 호출하게 되기 때문에 실제 서버의 IP를 알 수 없습니다.

Reverse Proxy로서의 Nginx

클라이언트와 서버 사이에 위치한 Nginxapi.zipgo.pet과 같은 특정 경로로 요청이 왔을 때 실제 백엔드 서버(8080포트)로 요청을 전달하고 응답을 클라이언트에게 반환하는 역할을 하는 Reverse Proxy 서버로 활용합니다.

📝 HTTP Web Server로서의 Nginx

Nginx를 사용하는 이유?

React의 프로덕션 빌드를 생성하면 정적 파일 (HTML, CSS, JavaScript 등)이 생성됩니다. 이때 브라우저에서 액세스할 수 있는 하나의 Index.html만 사용하게 됩니다. 그래서 특정 경로에서 새로고침을 했을 경우 서버가 해당 파일을 찾을 수 없어 404에러메시지를 사용자에게 반환하게 되는 문제가 있습니다.

이를 해결하기 위해 React 웹을 경량 웹 서버인 Nginx를 통하여 실행되도록 만들었습니다.

즉, 위 인프라 구성도에서 도커 컨테이너 내부의 Nginx는 클라이언트로부터 요청을 받았을 때 요청에 맞는 정적 파일을 응답해 주는 HTTP Web Server로 활용합니다.

nginx.conf와 [파일명].conf의 차이

  • nginx.conf: nginx의 기본 설정 파일로 워커 프로세스 설정 또는 로그 저장 위치 등을 작성할 수 있고 다른 server 설정들을 불러오는 역할을 합니다.
  • [파일명].conf: nginx를 통해 구동되는 서버의 설정 값을 작성한 후 /etc/nginx/conf.d 경로에 [파일명].conf라고 저장하면 nginx.conf에서 해당 파일을 import하여 적용합니다.

Nginx컨테이너 라우팅 설정

  • 위 인프라 구성도에서 도커 컨테이너 내부에 있는 Nginx를 말합니다.
  • server {} : 도메인 단위의 1차 라우팅 (https://zipgo.pet이 이에 해당합니다.)
  • location {} : 도메인 내부의 2차 라우팅 (https://zipgo.pet/storybook이 location 라우팅에 해당합니다.)
# /etc/nginx/conf.d/default.conf in Docerk Container

server {
	listen 3000;
    location / {
    	root /usr/share/nginx/html;
        index index.html;
        try_files $uri /index.html;
    }

    location /storybook {
      alias /usr/share/nginx/html/storybook;
      index index.html
      try_files $uri /index.html;
    }
}
  • listen 3000: 3000포트로 들어오는 요청을 해당 server{} 블록의 내용에 맞게 처리합니다.
  • location /: /로 접속했을 경우 /usr/share/nginx/html/index.html을 보여줍니다.
  • location /storybook: /storybook으로 접속했을 경우 /usr/share/nginx/html/storybook/index.html을 보여줍니다.
  • try_files $uri /index.html;: nginx가 해당 경로의 정적 파일을 찾아보고 없으면 index.html을 반환하도록 구성합니다. 이후에는 React Router가 해당 경로를 처리하고 해당 페이지를 표시할 수 있게 됩니다.
    • try_files $uri $uri/ /index.html; 로 설정한 경우,
    • 예를 들어, /about 페이지에 대한 요청이 있을 경우, nginx는 먼저 /about 파일을 찾고 없으면 about이란 폴더로 이동한 뒤 그래도 없으면 index.html을 반환하게 됩니다.

참고

profile
Fake It till you make It!

2개의 댓글

comment-user-thumbnail
2023년 8월 27일

글 잘 보았습니다~ 저희 프로젝트랑 인프라가 비슷하여 복습할 수 있었어요

답글 달기
comment-user-thumbnail
2023년 8월 30일

야무지네요~👍

답글 달기

관련 채용 정보