개발 서버 실행 및 기본 설정
개발 서버의 코드 감시와 오류 표시를 확인하고 포트·이미지·엄격 모드·환경 변수의 기본 설정을 조정합니다.
Next.js 프로젝트의 구조를 이해하셨다면, 이제 개발의 핵심적인 부분인 개발 서버(Development Server)를 좀 더 자세히 살펴보고, 기본적인 설정을 통해 개발 환경을 최적화하는 방법을 알아보겠습니다.
개발 서버는 여러분이 작성하는 코드를 실시간으로 브라우저에 반영하여, 빠르게 결과를 확인하며 개발할 수 있도록 돕는 매우 중요한 도구입니다.
개발 서버 다시 실행하기
2장 2절에서 이미 개발 서버를 한 번 실행해 보셨겠지만, 다시 한번 그 과정을 상기하고 몇 가지 유의할 점을 짚어보겠습니다.
프로젝트 디렉터리(my-next-app 또는 여러분이 지정한 프로젝트 이름)로 이동한 후, 다음 명령어를 터미널에 입력합니다.
아래 cd는 프로젝트의 상위 폴더에 있을 때 실행합니다. 앞 절을 따라 이미 my-next-app 안에 있다면 npm run dev부터 실행합니다. 앞 절의 서버가 계속 실행 중이면 그 서버에서 일반 소스 변경을 확인하고, 설정을 바꿔 재시작할 때는 해당 터미널에서 먼저 Ctrl + C로 종료합니다.
cd my-next-app
npm run dev또는 yarn을 사용한다면:
cd my-next-app
yarn dev명령이 성공하면 접속 URL이 출력됩니다. 아래는 로그 형식의 예시이며, Next.js 버전과 실행 환경에 따라 실제 문구가 달라집니다.
ready - started server on 0.0.0.0:3000, url: http://localhost:3000이 메시지는 Next.js 개발 서버가 http://localhost:3000 주소에서 실행 중임을 의미합니다.
웹 브라우저를 열고 해당 주소로 접속하면, Next.js의 기본 환영 페이지를 볼 수 있습니다.
개발 서버의 특징
- 자동 새로 고침 (Hot Module Replacement, HMR): 개발 서버가 실행 중인 상태에서 코드를 수정하고 저장하면, 브라우저가 자동으로 새로고침되거나 변경된 모듈만 교체되어 화면에 즉시 반영됩니다. 이는 개발 효율성을 크게 높여주는 기능입니다.
- 에러 오버레이: 개발 중에 문법 오류나 런타임 오류가 발생하면, 브라우저 화면에 에러 메시지 오버레이가 나타나 문제를 쉽게 파악하고 해결할 수 있도록 돕습니다.
- 성능 최적화 미적용: 개발 서버는 빠른 피드백을 위해 성능 최적화가 최소화되어 있습니다. 따라서 실제 프로덕션 환경에서의 성능과는 차이가 있을 수 있습니다.
개발 서버를 종료할 때는 Windows, macOS, Linux 모두 실행 중인 터미널에서 Ctrl + C를 누릅니다.
기본 포트 변경하기
간혹 3000번 포트가 다른 애플리케이션에 의해 사용 중이거나, 다른 포트에서 개발하고 싶은 경우가 있을 수 있습니다.
이럴 때는 npm run dev 명령어를 실행할 때 PORT 환경 변수를 지정하여 포트를 변경할 수 있습니다.
# Windows (명령 프롬프트)
set PORT=3001 && npm run dev
# Windows (PowerShell)
$env:PORT=3001; npm run dev
# macOS/Linux
PORT=3001 npm run dev위 명령어를 실행하면 http://localhost:3001으로 개발 서버가 시작되는 것을 확인할 수 있습니다.
PORT는 서버를 시작하는 셸 환경에 지정합니다. .env.local에 PORT=3001만 적는 방법은 포트 설정으로 사용하지 않습니다. HTTP 서버의 시작이 .env 로딩보다 먼저 일어나기 때문입니다. 실행 후에는 지정한 번호뿐 아니라 터미널에 실제 출력된 주소를 확인합니다. 공식 포트 옵션
next.config.ts 파일 살펴보기 및 기본 설정
next.config.ts 파일은 Next.js 애플리케이션의 전반적인 동작 방식을 설정하는 중요한 파일입니다.
프로젝트의 루트 디렉터리에 위치하며, create-next-app으로 프로젝트를 생성했다면 기본적으로 다음과 같은 내용으로 생성되어 있을 것입니다.
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {};
export default nextConfig;이 파일은 타입 검사를 받는 설정 객체를 기본 export합니다.
nextConfig 객체 안에 다양한 설정 옵션을 추가하여 Next.js의 동작을 커스터마이징할 수 있습니다.
몇 가지 유용한 기본 설정 옵션을 살펴보겠습니다.
아래의 완결된 next.config.ts 예시는 각 옵션을 따로 설명합니다. 한 파일에 세 예시를 차례로 붙여 세 개의 default export를 만드는 방식이 아닙니다. 여러 옵션을 함께 사용한다면 하나의 nextConfig 객체 안에 images와 reactStrictMode 같은 속성을 모으고 한 번만 내보냅니다.
images 설정: 이미지 최적화
Next.js는 이미지 최적화를 위한 <Image> 컴포넌트를 제공합니다.
로컬 이미지는 별도 설정 없이 사용할 수 있고, 외부 이미지는 next.config.ts의 remotePatterns로 허용 범위를 명시합니다.
외부 도메인에서 이미지를 로드할 때 필요합니다.
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'assets.example.com',
pathname: '/my-bucket/**',
},
],
},
};
export default nextConfig;위 remotePatterns는 HTTPS, 정확한 호스트, /my-bucket/ 아래 경로를 함께 검사합니다. 예를 들어 https://assets.example.com/my-bucket/cat.png는 이 조건에 맞지만, http://assets.example.com/my-bucket/cat.png는 프로토콜이 다르고 https://assets.example.com/other/cat.png는 경로가 다릅니다. 이 예시에는 port와 search 조건이 없으므로 포트와 쿼리 문자열까지 제한했다고 설명하지 않습니다. 필요한 제한은 별도 속성으로 명시합니다. 공식 remotePatterns 규칙
reactStrictMode 설정: React 엄격 모드
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
reactStrictMode: true, // true 또는 false
};
export default nextConfig;App Router는 기본적으로 Strict Mode를 사용하므로 보통 이 옵션을 직접 적을 필요가 없습니다.
개발 중 일부 로직이 두 번 실행되는 것처럼 보인다면 Strict Mode를 끄기보다, effect 정리 함수와 부수 효과가 안전하게 반복되는지 먼저 확인합니다.
.env.local: 환경 변수 관리
애플리케이션에서 민감한 정보(API 키 등)나 환경별로 달라지는 값(백엔드 API 주소)을 관리할 때 환경 변수를 사용합니다.
프로젝트 루트의 .env.local에 서버 전용 값과 브라우저 공개 값을 구분해 작성합니다. 이 교재의 구조에서도 src/.env.local이 아니라 package.json 옆에 둡니다. 예시 DB 주소는 값을 읽는 방법을 설명하며 실제 데이터베이스를 생성하거나 연결하지 않습니다.
# 서버 컴포넌트와 Route Handler에서만 읽습니다.
DATABASE_URL=postgresql://user:password@localhost:5432/app
# 브라우저 번들에 공개해도 되는 값에만 접두사를 붙입니다.
NEXT_PUBLIC_API_ORIGIN=https://api.example.comNEXT · CH2-4
공개 변수는 빌드된 브라우저 코드에 남습니다
이름·접근 방식·읽는 시점을 함께 확인합니다. 일반 서버 환경 변수와 공개 변수, next.config의 env는 노출 경로가 다릅니다.
서버 전용 · DATABASE_URL
서버 코드에서 process.env.DATABASE_URL을 읽습니다. 브라우저에 자동 제공하지 않습니다.
별도 노출 경로: 응답이나 props에 직접 넣으면 공개됩니다. 서버에서도 빌드 중 읽는지 요청 중 읽는지에 따라 값이 출력에 남는 시점이 다릅니다.
공개 · NEXT_PUBLIC_API_ORIGIN
process.env.NEXT_PUBLIC_API_ORIGIN처럼 변수명으로 직접 접근하면 빌드 시 공개 값으로 치환됩니다.
빌드 후: 배포 환경값만 바꾸어도 기존 브라우저 번들의 값은 바뀌지 않습니다.
설정 객체 · next.config의 env
접두사와 무관하게 번들에 포함할 값을 설정하는 경로입니다. 비밀값을 넣지 않습니다.
접근 방식: process.env[name] 같은 동적 조회는 공개 변수의 정적 치환 대상이 아닙니다.
공개 여부는 NEXT_PUBLIC_ 이름만 보고 끝내지 않고 실제 응답·props·번들 경로를 함께 확인합니다.
예시
NEXT_PUBLIC_API_ORIGIN을 https://stage.example.com으로 두고 빌드한 브라우저 코드를 같은 산출물 그대로 운영에 옮겼다고 가정합니다. 운영 서버의 환경값만 https://prod.example.com으로 바꾸어도 기존 브라우저 코드의 공개 값은 stage 주소입니다. 변수명을 직접 읽는 공개 값은 빌드 시 치환되므로 운영 값을 사용하려면 해당 값으로 다시 빌드하거나, 별도로 설계한 런타임 공개 설정 계약을 사용해야 합니다.
DATABASE_URL은 접두사가 없어 브라우저에 자동 치환되지 않습니다. 하지만 서버가 그 문자열을 응답이나 Client Component의 props에 넣으면 직접 공개한 것입니다. 이름과 실제 전달 경로를 함께 확인합니다. 공식 환경 변수 안내
독립 판단
서버에서 DB 연결 문자열을 읽어 제품 목록을 조회한 뒤 { title: 제품명, debug: 연결문자열 }을 브라우저로 반환했습니다. 연결 문자열에 NEXT_PUBLIC_ 접두사가 없으니 비공개라고 말할 수 있을까요? 위 이미지 설정에서 https://assets.example.com/other/a.png도 허용되는지 따로 판단하세요.
노출 경로와 허용 조건 확인
debug 응답에 넣은 순간 문자열이 브라우저로 전달되므로 비공개라고 말할 수 없습니다. 서버 내부 연결 정보는 반환하지 않고 필요한 제품 데이터만 반환합니다. 이미지 URL은 호스트와 HTTPS 조건이 맞아도 /my-bucket/** 경로 조건이 맞지 않아 이 패턴으로 허용되지 않습니다. 변수의 이름이나 이미지의 호스트 한 조건만 확인해 결론을 내리지 않습니다.
환경 변수의 로드 우선순위와 런타임 읽기 시점은 이후 장에서 더 자세히 다룹니다.
개발 서버 시작 전 최종 확인
모든 설정이 완료되었다면 프로젝트 디렉터리에서 npm run dev를 다시 실행합니다.
실행 전에는 현재 폴더, 포트 충돌, 설정 파일 변경 여부를 함께 확인합니다.