본문으로 건너뛰기

Next.js 프로젝트 배포하기 (Docker, AWS S3)

Next.js Is

Next.js is a flexible React framework that gives you building blocks to create fast web applications. (Next.js 공식문서 발췌)

Next.js는 React 라이브러리의 프레임워크이며, 가장 큰 특징으로는 SEO 향상과 SSR(Server-Side Rendering)을 가능케 한다는 것이다. 리액트는 기본적으로 CSR(Client-Side Rendering)을 지원하는데 Next.js를 이용하면 pre-render를 통해 미리 데이터가 렌더링된 페이지를 가져올 수 있게 할 뿐 아니라 검색엔진에도 노출이 잘 되기 때문에 제품의 SEO 향상에도 큰 도움이 된다.

Docker Is

Docker는 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼입니다. Docker는 소프트웨어를 컨테이너라는 표준화된 유닛으로 패키징하며, 이 컨테이너에는 라이브러리, 시스템 도구, 코드, 런타임 등 소프트웨어를 실행하는 데 필요한 모든 것이 포함되어 있습니다. (AWS Docker 설명에서 발췌)

Docker를 검색하면 가장 처음 보는 단어는 이미지, 컨테이너, 배포이다. 이미지는 컨테이너 실행에 필요한 파일과 설정값들을 포함한 것이며, 컨테이너는 격리된 공간에서 프로세스가 동작하는 기술이다. 처음엔 나도 잘 이해가 되지 않았다. 코드 블록이 이미지라니? 컨테이너는 또 뭐야? 여러번 읽고 나서도 이해가 잘 가지 않아 Adobe Illustrator와 비교해서 이해하기로 했다.

DockerAdobe Illustrator
이미지아트보드
컨테이너파일

일러스트레이터(서버) 안에서 여러개의 작업 파일(컨테이너)를 작동할 수 있고, 각 파일에는 여러개의 아트보드(이미지)가 포함된다고 이해하니 도커가 어떤 방식으로 작동되는지 전보다 쉽게 이해할 수 있었다.

Docker + EC2로 배포하기

처음 백엔드 개발자분과 얘기했을 때는 서로의 환경에서 배포가 어떻게 진행되는지 전혀 알 수 없었기 때문에 시행착오가 많았다.(이전 기수분들의 인수인계 때 vercel을 이용해서 배포하면 쉽다고 했는데 그걸 이해했을 땐 Doker로 이미 배포가 완료된 상태였다.)

해당 기업에서는 테스트 서버 배포를 원하였으므로 git clone을 받아 EC2로 배포하기로 협의헀다. 배포방법은 다른 포스트에도 많아 자세히 다루지 않겠지만 내가 경험한 배포 순서를 간단히 정리하자면 아래와 같다.

1. dockerfiledp env-cmd 패키지를 다운로드하는 명령어를 추가
2. package.json의 build에 env-cmd -f ~/.env.dev 명렁어를 추가
3. root에 .env.dev를 생성

이렇게 프론트 테스트 서버가 성공적으로 끝난 줄 알았지만 배포 후 백엔드 개발자님께서 배포 방식이 잘못됨을 언급, S3로 재배포해야 한다고 하셨다. (사실 경험이 없어 어떤 배포 방법이 더 좋은지 알지 못 했고, 이 부분은 전적으로 백엔드 개발자님의 의견을 따르기로 했다.)

S3로 재배포하기

S3로의 재배포는 백엔드 개발자님이 미리 배포를 위한 준비를 해주신 상태였고, 나는 준비해둔 bucket에 프로젝트를 업로드만 하면 되는 상태였다. 배포는 프로젝트를 build하면 프로젝트 폴더에 out이라는 폴더가 생기는데 이 때 out 폴더 안에 있는 모든 폴더 및 파일을 업로드해주면 끝이다. Docker로 했을 때보다 더욱 심플했다. 다만 build시 sessionStorage 혹은 localStorage is no defined라는 경고 문구가 뜨면서 build가 되지 않은 문제를 겪을 것이다.

Next.js는 CSR을 실행하기 전에 SSR을 실행하는데, Next.js에서 제공하는 SSR에서는 window나 document와 같은 전역 객체 사용이 불가능하다. 따라서 페이지가 client에 로드되고 전역객체가 정의되기 전까지는 sessionStorage 혹은 localStorage에 접근할 수 없다!

이럴 땐 페이지가 client에 마운트 될 때까지 기다린 후 스토리지에 접근해야 하는데 이를 해결할 수 있는 방법은 아래와 같다.

if (typeof window !== 'undefined') {
// Perform localStorage action
const item = localStorage.getItem('key');
}

스토리지를 이용한 코드블럭에 위와 같이 수정 후 빌드하니 이상없이 빌드가 완료되고, 성공적으로 S3에 업로드 할 수 있었다.

회고

배포를 맡기로 했을 땐 사용하는 플랫폼이나 언어의 특징, 그리고 수많은 오류들이 걱정이 되었다. 그러나 백엔드 개발자님과 함께 Docker로 먼저 배포를 해보며 오류를 맞이하는 것에 대한 두려움이 많이 줄어들었고, 이 또한 나를 성장시킬 수 있는 양분이 된다고 생각하니 오류를 해결하는 것이 진짜 개발자 같이 느껴져 재밌어지기 시작했다. 하지만 예상했던 것보다 더 많은 오류와 시행착오로 시간이 많이 소요되었다. '프론트엔드니까 배포는 중요하지 않겠지?'라는 마인드로 임했던 과거의 나를 반성하는 계기가 되었다.