nginx 개념 잡기

박상하·2025년 3월 20일

1년차

목록 보기
9/26

EC2와 nginx

우리 서비스 중 웹 뷰(Next.js)는 EC2 nginx pm2 로 서버를 구축했다.

사실 필자가 위 내용을 이해하지 못했던 이유는 경험 부족 때문이다.

React 로 개발 후 Vercel 배포 경험

사실 Vercel이나 Netlify 와 같은 SaaS(Software as a Service ) 플랫폼인
정적 웹 호스팅 서비스를 사용하다보면 배포의 흐름을 이해하기 어려울 수있다.

왜냐면 연동된 Github 와 연동하여 간단하게 배포가 가능하기 때문이다.
CI/CD, 서버 관리, HTTPS 등 다양한 기능을 제공한다.

그런데 문득 학습 순서가 잘못되었음을 인지했다.

사실 CI/CD, 서버를 직접 관리, HTTPS로 배포 등의 학습을 마친 후 위 서비스를 사용했다면
더 좋았을 거 같다.

앞으로 게시글은 이러한 학습 내용을 하나씩 실습해보며 그 내용을 정리해보겠다.

이번 게시글에서는 EC2 와 nginx를 다룬다.

nginx

nginx 는 웹 서버이다.

이전에 서버의 개념을 이렇게 잡아놓으면 편하다.

서버는 컴퓨터, 특히 주는 서버
클라이언트는 다운로드 받는다.

서버는 그냥 컴퓨터이다. 그런데 뭔가를 주는 컴퓨터이다.
그리고 프론트엔드 입장에서 클라이언트는 다운로드를 받는 녀석이다.

우리가 개발자 도구의 network 탭을 켜고 "네이버"에 들어가면 이렇게 나온다.

아~~주 많은 파일들을 "다운로드" 해온다

이 많은 파일을 누가 준 것일까??

바로 "웹 서버"이다.

웹 서버

웹 서버란 정적 파일들을 서빙하는 역할을 한다.

정적 파일: (html, js, css, img 등 빌드 시점에 미리 생성되어 변하지 않는 파일)
동적 파일: (서버에서 실시간으로 처리되어 매 요청마다 생성되거나 변할 수 있는 파일)

사실 프론트엔드에서 동적파일을 사용하지 않는다면 대부분 이 웹 서버만으로 배포가 가능하다.

웹 서버에서 가장 중요한건

웹 서버는 머리통이 없어 === 생각 안해 😛

웹 서버는 뭔가 연산을 하거나 계산하지 않는다. 정말 서빙만 담당한다.
만약 연산이 필요한 실시간으로 뭔가 처리해야하거나 하는 작업은 WAS에서 떠맡긴다.

Web Application Server(WAS)

WAS는 연산을 할 수 있는 서버이다. 웹 서버로부터 요청을 받아 동적 콘텐츠를 처리하고 웹 서버에게 전달해주는 역할을 한다. 예를 들어 was가 로그인 정보를 처리하고 인증된 사용자에게 맞춤형 콘텐츠를 반환할 수 있다.

WAS === API 서버??

필자는 이게 헷갈렸었다.

결론은 아니다.

WAS !== API 서버 !!

WAS는 동적 콘텐츠를 처리하고 반환한다.
API 서버는 클라이언트에서 즉, 브라우저에서 직접 요청한다.
fetch라는 JavaScript Web API를 사용하여 데이터를 클라이언트에서 직접 받아온다.
웹 서버를 거쳐 동적 콘텐츠를 처리 하는 것이 WAS이다.

nginx는 웹 서버

nginx 공식 홈페이지

nginx는 http 웹 서버, 역방향 프록시, 콘텐츠 캐시, 로드 밸런서, TCP/UDP 프록시 서버, 메일 프록시 서버입니다.

http 웹 서버 라는 말에 주목해보자.

우리는 어떤 스토리지 (S3, EC2 등)에 우리가 개발한 서비스를 올려놓을 수 있다. (빌드 파일)
이때, 정적 파일인 경우 해당 정적 파일을 읽는 주체는 누구일까?

"브라우저" 이다.

그럼 흐름은 이렇게 된다.

브라우저 -> Domain(네이버) -> DNS를 통해 nginx가 설치된 웹 서버 IP주소 ->
Nginx -> 네이버 서버 (정적 리소스가 담겨 있는곳) -> Nginx(서빙중) -> 브라우저

nginx는 정적 파일 서빙을 담당한다. 그런데 이 서빙의 방법이나 캐싱 그리고 위치에 따라서
reverse proxy, contents cache, TCP/UDP proxy server 등으로서 역할을 하는 것이다.
기능이 굉장히 많다.

우리 서비스는 간단하게 프록시 서버로만 이용을 하고있다.

코드로 살펴보자.

배포 코드로 살펴보는 nginx

package.json

"farmer-prod-publish": "yarn build:farmer-prod && sh script/farmer_deploy_prod.sh && sh script/record_deployment_info.sh",
"build:farmer-prod": "env-cmd -f .env.farmer.production next build",

빌드 하면 .env.farmer.production 파일을 환경변수 파일로 저장하여 build 한다.

next.config.js 파일을 살펴보자

const nextConfig = {
  reactStrictMode: false,
  output: 'standalone',
  /* config options here */
  compiler: {
      // ssr and displayName are configured by default
      styledComponents: true,
  },
};

output: 'standalone'
을 사용했다는 건 동적 배포를 진행한다는 것이다.
독립 실행형으로 빌드.

이렇게 빌드를 하면 다음과 같이 빌드 파일이 형성된다.

standalone에 server.js가 생성되는데 이를 node를 통해 읽어주면 독립적으로 next.js를 실행할 수 있다. 동적으로 배포가 가능하다는 것이다.

동적 배포: 요청이 왔을 때 그때그때 서버에서 요청을 처리하고 동적으로 콘텐츠를 생성할 수 있다.

그 다음 명령어 sh script/farmer_deploy_prod.sh

    chmod -R 400 $PEM
    cp -r .next/static/ .next/standalone/.next
    tar -cf build.tar -C .next/standalone .
    scp -ri "$PEM" build.tar farmerhelp@ec2-$IP.ap-northeast-2.compute.amazonaws.com:/opt/$DIR
    ssh -i "$PEM" farmerhelp@ec2-$IP.ap-northeast-2.compute.amazonaws.com <<EOF

    export NVM_DIR="\$HOME/.nvm"
    source "\$NVM_DIR/nvm.sh"
    export PATH="\$HOME/.npm-global/bin:\$PATH"

    cd /opt/$DIR
    nvm use $NODE_VERSION
    tar -xf build.tar
    rm -rf build.tar
    ls -al | grep server.js
    sed -i 's/const currentPort = parseInt(process.env.PORT, 10) || .*/const currentPort = 3002;/g' server.js
    pm2 restart $DIR

대략적으로 읽어보면

static 폴더는 standalone 으로 빌드를 했을 때 들어가지 않기 때문에
static 폴더를 standalone에 저장하고 build.tar에 압축한 후 이 파일을 서버 ec2로 복사한다.

그 후 ssh 통신을 통해 해당 ec2로 접속하고 node를 설치한 후 해당 build.tar를 해제하여
필요한 파일을 원하는 폴더에 둔다.

그후 모든 포트를 3002로 맞춰준다. 그리고 pm2 로 시작한다.

여기서 핵심은 포트이다. 어쨌든 이 ec2 즉, next.js가 실행되는 ec2의 포트는 3002 번이다

이제 nginx 파일을 살펴보자.

nginx는 어디에 설치되어 있을까? 당연 ec2에 설치되어있다.

nginx.conf 파일을 살펴보자

위에서 부터 읽어보면

80 포트로 prod.webview.TESTPROD.co.kr 로 들어오면

루트 하위 (/ 이후) 로 모든 요청에 한해서 http://localhost:3002로 프록시한다.
즉, 흐름은 이렇게 된다.

모바일 -> 상세페이지(웹뷰로 개발됨) 요청 -> prod.webview.TESTPROD.co.kr ->
nginx는 ec2:3002 포트에서 실행중인 next.js로 부터 완성된 HTML을 받아온다 ->
모바일로 전달

사실 이 사례는 nginx와 was의 사례

필자가 생각하기에 이 사례는 nginx(웹 서버)와 WAS의 사례로 인지되었다.
nginx가 클라이언트로 부터 요청을 받았지만 그 요청은 동적 자료다. 그렇기 때문에
next.js가 실행중인 포트로 재요청을 보낸 것이다.

만약 정적 자료 요청을 받았다면 nginx가 바로 원하는 폴더에서 정적 자료를 보내줬을것이다..

그렇기에 위 사례는 nginx의 프록시 서버로서 사용 사례이자 웹 서버와 was의 연결 사례

이렇게 nginx가 서버 내에 실행되고 있다면 nginx.conf 기반으로 실행이 되는 것이기 때문에
nginx.conf 파일을 작성하는 방법을 배우는 것이 중요하다.

여기서는 프록시 서버로서만 사용하고 있지만 로드밸런싱, ssl 적용 등 다양하게 사용할 수 있다.
이는 nginx로 직접 실습해보며 작성해보겠다.

0개의 댓글