1. 들어가며
Vercel 같은 플랫폼이 아닌 일반 서버에 Next.js를 배포하는 것은 처음이라 공식 문서와 AI의 도움을 많이 받았다. 배포하면서 내가 네트워크에 대한 지식이 많이 부족하다는 것을 새삼 깨달았다… 시행착오를 겪으며 배운 내용들을 기록 차원에서 정리해보려 한다!
1.1 NCP를 선택한 이유
프로젝트를 진행하면서 네이버 클라우드 플랫폼(NCP)의 무료 크레딧을 받게 되었다.
사실 Next.js 배포라면 Vercel이 가장 간편한 선택지다. 하지만 우리 프로젝트는 GitHub Organization 레포지토리를 사용하고 있었고, Vercel에서 Organization 레포를 무료로 배포하려면 개인 계정으로 fork해야 하는 번거로움이 있었다.
마침 받은 무료 크레딧도 있고, 실제 서버에 직접 배포해보는 경험도 쌓을 겸 NCP를 선택했다.
1.2 Object Storage vs Compute Server
NCP에는 Object Storage라는 정적 호스팅 서비스도 있다. 하지만 Next.js는 단순 정적 사이트가 아니라 Node.js 런타임이 필요한 프레임워크이다. Object Storage에 배포하면 다음과 같은 기능들이 제대로 작동하지 않는다.
- SSR (Server-Side Rendering)
- API Routes
- ISR (Incremental Static Regeneration)
- Middleware
따라서 Next.js의 모든 기능을 사용하려면 Node.js를 실행할 수 있는 서버 환경이 필요하다.
2. 서버 생성하기
2.1 서버 이미지 선택
서버 이미지는 가상 서버를 만들 때 사용할 운영체제와 기본 설정이 포함된 템플릿이다. 이 이미지를 기반으로 새로운 가상 서버 인스턴스가 만들어진다.

NCP에서는 다양한 이미지를 제공한다. 여기에서 순수한 OS만 설치된 Ubuntu 24.04를 선택했다. Ubuntu를 선택한 이유는 다음과 같다.
- Node.js, npm, PM2, Nginx, Git 등 주요 도구들이 Ubuntu에 최적화되어 있다.
- 많은 배포 가이드와 CI/CD 도구들이 Ubuntu를 기본으로 지원한다. (GitHub Actions 등)
- 가볍고 안정적이다.
2.2 서버 설정 (VPC, Subnet, 스펙)
서버 설정에서는 VPC, Subnet, 서버 스펙, 요금제, 네트워크 인터페이스, 공인 IP 등을 설정한다. 아래 문서에서 가이드를 확인할 수 있다.
신규 콘솔 화면으로 Server 생성
guide.ncloud-docs.com

2.2.1. VPC (Virtual Private Cloud)
VPC는 클라우드 안에 만드는 독립된 네트워크 공간이다. 서버들이 들어갈 폐쇄된 네트워크 구역이라고 생각하면 된다. 백엔드에서 이미 VPC를 만들어놨기 때문에 같은 VPC를 사용했다.
2.2.2 Subnet
Subnet은 VPC 안에서 IP 대역을 나누는 것이다.

백엔드 서버가 10.0.1.0/24를 사용하고 있어 10.0.2.0/24로 설정했다.
Next.js 서버를 외부에서 접속해야 하므로 Internet Gateway 전용 여부는 ‘Y’로 설정하고, 간단한 프로젝트이기 때문에 용도는 ‘일반’으로 설정했다.
2.2.3 서버 스펙

기본으로 제시되는 스펙은 Standard s2-g3a (vCPU 2EA, Memory 8GB)로 월 82,240원이다. 공식 가이드에 따르면 일반 웹 용도로는 Standard가 권장되지만, 비용을 고려해 High-CPU c2-g3a (vCPU 2EA, Memory 4GB)로 선택했다.
2.2.4 요금제 및 기타 설정
- 요금제: 월 요금제 (계속 켜둬야 하므로)
- 서버 개수: 1개 (서버 생성시 공인 IP를 함께 생성하려면 서버 개수는 1개여야 한다.)
- Network Interface: 기본값 (IP 자동 할당)
- 공인 IP: 할당 (외부에서 접속을 위해 필수)
2.2.5 스토리지
스토리지는 서버의 하드디스크 용량을 설정하는 것이다. 운영체제, 프로젝트 코드, 빌드 파일 등이 저장되는 공간이다.

- 크기: 30GB (기본 10GB는 부족할 수 있어서 여유롭게 설정했다. 나중에 확장이 가능하다.)
- 타입: CB1 (일반 SSD)
2.3 인증키 및 ACG 설정
2.3.1. 인증키 설정
인증키는 SSH로 서버에 접속할 때 사용하는 보안 키이다. 비밀번호 대신 .pem 파일로 인증한다.

백엔드 서버와 프론트엔드 서버를 구분하기 위해 새로운 인증키를 생성했다. [새로운 인증키 생성]을 선택하면 .pem 파일을 다운로드받을 수 있다. 이 파일은 안전한 곳에 보관해야 한다.
2.3.2 ACG (Access Control Group) 설정

기존에 백엔드 개발자가 만들어둔 ACG를 사용했다. 나중에 필요한 포트는 추가로 열 수 있다.
3. 서버 환경 구축
3.1 SSH 접속하기
서버 생성이 완료되면 SSH를 통해 서버에 접속할 수 있다. macOS는 터미널에서 기본적으로 SSH 접속이 가능하다. Windows는 PowerShell이나 PuTTY를 사용할 수 있다.
3.1.1 접속 명령어
아래 명령어로 접속할 수 있다.
ssh -i ~/Documents/Key/my-key.pem root@서버IP
-i: 인증키 파일 경로 (인증키 설정에서 받은 파일 주소)root: 사용자 이름 (NCP 기본값은 root)서버IP: NCP 콘솔의 Server에서 생성한 서버를 클릭하면 공인 IP를 확인할 수 있다.
3.1.2 권한 오류 해결
첫 접속 시 SSH가 처음 접속하는 서버가 맞는지 확인하는 메시지가 뜨는데, yes를 입력하면 된다. 그리고 접속을 시도하면 이런 오류가 발생할 수 있다.
Warning: Permanently added '서버IP' (ED25519) to the list of known hosts. Permissions 0644 for '~/Documents/Key/my-key.pem' are too open.
키 파일의 권한이 너무 열려있다는 뜻이다. 다음 명령어로 권한을 변경해준다.
chmod 400 ~/Documents/Key/my-key.pem
3.1.3 관리자 비밀번호 확인
이제 다시 SSH 접속을 시도해보면 비밀번호를 요구한다. 비밀번호는 [NCP 콘솔] - [서버 관리 및 설정 변경] - [관리자 비밀번호 확인]에서 인증 키를 첨부하면 확인할 수 있다.

비밀번호를 입력하면 서버에 잘 접속된다!

root 계정은 시스템의 모든 권한을 가지고 있어 위험이 크기 때문에 실제 서비스 운영 시에는 보안을 위해 root 대신 별도 사용자 계정을 생성해서 사용하는 것이 권장된다.
3.2 개발 환경 구축 (Node.js 및 Git 설치)
3.2.1 Node.js 및 npm 설치
서버에 Node.js, npm, Git을 설치한다.
sudo apt install nodejs
node -v # 설치 확인
sudo apt install npm
npm -v # 설치 확인
처음에는 Node.js를 설치하면 npm이 포함되어 있을 거라고 생각해서 npm을 따로 설치하지 않았는데, npm install 명령어가 작동하지 않았다. 일부 리눅스 배포판에서는 Node.js와 npm이 별도 패키지로 분리되어 있다고 한다. npm도 반드시 따로 설치해주어야 한다.
참고로 이렇게 Node.js를 apt로 설치하니 약간 번거로운 점이 있었다. 관련 내용은 이 글에서 확인할 수 있다.
3.2.2 Git 설치
sudo apt install git
git -v # 설치 확인
3.3 프로젝트 클론 및 빌드
3.3.1 프로젝트 클론
# 프로젝트 클론
git clone https://github.com/my-repo/project.git
# 프로젝트로 이동
cd project
.env 파일은 따로 만들어서 환경 변수를 추가해주었다.
3.3.2 의존성 설치 및 빌드/실행
# 의존성 설치
npm install
# 빌드 및 실행
npm run build
npm start
빌드가 완료되고 서버가 실행되면 http://서버IP:3000으로 접속할 수 있다. 하지만 아직 방화벽(ACG)에서 3000번 포트를 열어주지 않았기 때문에 접속이 안 된다.
3.3.4 포트 열기 (ACG 설정)
Next.js는 기본적으로 3000번 포트를 사용한다. 외부에서 접속하려면 ACG 설정에서 3000번 포트를 열어주어야 한다. [NCP 콘솔] - [Server] - [ACG 규칙] - [규칙 설정]에 들어가면 인바운드에서 새로운 포트를 추가할 수 있다.

다음과 같이 인바운드 규칙(들어오는 트래픽)을 추가한다.
- 프로토콜: TCP
- 접근 소스: 0.0.0.0/0 (누구나 접속 가능)
- 허용 포트: 3000
설정을 저장하고 http://서버IP:3000으로 접속하면 Next.js 앱이 잘 뜬다!
4. Next.js 실행하기
4.1 PM2 설치 및 실행
지금까지는 npm start로 서버를 실행했다. 하지만 이 방식에는 큰 문제가 있다. 바로 SSH 접속을 종료하면 서버도 같이 꺼진다는 점이다.
이를 해결하기 위해 PM2라는 도구를 사용할 수 있다. PM2는 Node.js 프로세스를 백그라운드에서 관리해준다. PM2를 사용하면 SSH를 종료해도 서버를 계속 실행할 수 있고, 서버가 에러로 죽거나 재부팅할 때도 자동으로 다시 시작하도록 할 수도 있다.
4.1.1 PM2 설치
기존에 실행 중인 npm start는 종료 후 설치 및 실행한다.
npm install -g pm2
4.1.2 PM2로 실행
--name: PM2에서 관리할 프로세스 이름 지정-- start: npm start 명령어 실행
cd project
pm2 start npm --name "project" -- start
pm2 list로 현재 실행중인 프로세스를 확인하면 정상적으로 표시되어야 한다.
4.1.3 상태 저장 및 자동 시작 설정
# 현재 상태 저장
pm2 save
# 서버 재부팅 시 자동 실행되게 설정
pm2 startup
pm2 startup 입력 시 아래와 같은 명령어가 출력되는데, 이 명령어를 복사해서 실행해야 한다.
sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u root --hp /root
이제 SSH 접속을 종료해도 서버가 계속 실행된다.
4.2 포트 분리 (prod/dev)
운영 배포만 따로 두어도 되지만, 운영 환경은 배포 주기가 길다. 개발자 팀원들은 로컬 환경에서 바로 테스트할 수 있지만, 비개발자 팀원들은 실제 서버에 배포되기까지 오래 기다려야 할 수밖에 없다. 빠른 피드백과 협업을 위해 개발 환경도 별도로 배포하기로 했다.
- main 브랜치 → 3000번 포트 (프로덕션)
- develop 브랜치 → 3001번 포트 (개발)
4.2.1 develop 브랜치 클론
기존 프로젝트는 main 브랜치였으므로 project-prod와 같이 폴더 이름을 변경하고, develop 브랜치를 별도로 클론했다.
# 프로젝트 클론
git clone -b develop https://github.com/my-repo.git project-dev
# 의존성 설치 및 빌드
cd project-dev
npm install
npm run build
4.2.2 3001번 포트 열기
두 환경을 동시에 실행하려면 각각 다른 포트가 필요하므로 ACG 설정에서 3000번 포트를 추가했던 것과 똑같이 3001번 포트도 추가한다.
4.2.3 각각 다른 포트로 PM2 실행
pm2 설정 파일 ecosystem.config.js를 사용하는 방법도 있다.
# main 브랜치 (3000번 포트)
cd ~/project-prod
PORT=3000 pm2 start npm --name "prod" -- start
# develop 브랜치 (3001번 포트)
cd ~/project-dev
PORT=3001 pm2 start npm --name "dev" -- start
pm2 list로 확인하면 두 개의 프로세스가 실행 중인 걸 볼 수 있다.

4.2.4 상태 저장
pm2 save
4.3 코드 수정 후 재배포
나중에 코드를 수정하고 재배포할 때는 다음 명령어만 실행하면 된다.
# SSH 접속하여 프로젝트 디렉토리로 이동 후 업데이트
git pull
npm install
npm run build
pm2 restart prod # 또는 dev
5. 마무리
현재는 단일 서버에만 배포했지만 추후에는 CDN, Object Storage를 활용해서 정적 리소스와 서버를 분리하는 구조도 만들어보고 싶다.
다음 글에서는 Nginx를 이용한 리버스 프록시 설정, HTTPS 적용, 도메인 연결, 간단한 자동 배포 설정 과정을 정리해볼 예정이다!
'DevOps' 카테고리의 다른 글
| nvm으로 Node.js 버전업 후 Nginx 502 문제 해결하기 (0) | 2026.04.19 |
|---|---|
| NCP 서버에 Next.js 배포하기 (2) - 프로덕션 환경 구축하기 (0) | 2026.02.09 |