Next.js 프로젝트를 create하고 run할 때 실행되는 script 뜯어봅시다
npx create-next-app@버전 을 통해서 편하게 Next.js project를 만들 수 있다.
하지만 Next 서버가 어떻게 만들어지는지 어떻게 시작되는지는 자세하게 알지 못했다.
Next.js github 을 참고해서 프로젝트를 생성하고 실행할 때 어떻게 동작하는지 알아보았다.
1. Project 생성하기
npx create-next-app@12.3.4 명령어를 이용해서 내가 원하는 디렉토리에 Next.js 프로젝트를 만들었다.
이때 알게된 것은 Next project의 생성 시점이다.
차근차근 보면 먼저 npx 명령어로 버전을 설저한 후 이름을 설정하는 프롬프트가 뜬다.
npx create-next-app@12.3.4
✔ What is your project named? … hj-next-app
여기에 나는 hj-next-app으로 이름을 설정하고 enter를 누르니까
Creating a new Next.js app in /Users/khj/Documents/02_projects/hj-next-app.
이렇게 프로젝트가 만들어졌다.
npx create-next-app 을 쳤을 때가 아니라 이름을 설정해야 비로소 프로젝트가 만들어진다.
그때 Next 스크립트에서는 packages > create-next-app > index.ts > run 함수 가 실행된다.
그 프로세스는 아래에서 알 수 있다.
// packages > create-next-app > index.ts > run 함수
async function run(): Promise<void> {
const conf = new Conf({ projectName: 'create-next-app' })
if (program.resetPreferences) {
conf.clear()
console.log(`Preferences reset successfully`)
return
}
if (typeof projectPath === 'string') {
projectPath = projectPath.trim()
}
if (!projectPath) {
const res = await prompts({
onState: onPromptState,
type: 'text',
name: 'path',
message: 'What is your project named?', // ->
initial: 'my-app',
validate: (name) => {
const validation = validateNpmName(path.basename(path.resolve(name)))
if (validation.valid) {
return true
}
return 'Invalid project name: ' + validation.problems![0]
},
})
if (typeof res.path === 'string') {
projectPath = res.path.trim()
}
}
...
}
이렇게 프로젝트 이름을 설정하고
"... (너무 길다) " 에 있는 try 문을 거치면
packages > create-next-app > create-app.ts > createApp 함수가 실행되고 Next project가 만들어진다.
2. yarn start
그럼 next 앱을 실행하면 어떤 코드가 실행될까?
그런데 yarn start 명령어를 치면 아래 에러가 나온다.
When running `next start` or a custom server in production mode a production build is needed.
그 이유는 프로덕션 모드에서는 next start 스크립트를 실행하는데 프로덕션에서는 빌드된 파일들이 필요하기 때문이다.
(공식문서 내용)
next build생산을 위해 애플리케이션의 최적화된 버전을 생성합니다. 이 표준 출력에는 다음이 포함됩니다.
- getStaticProps또는 자동 정적 최적화를 사용하는 페이지용 HTML 파일
- 전역 스타일 또는 개별 범위 스타일용 CSS 파일
- Next.js 서버에서 동적 콘텐츠를 사전 렌더링하기 위한 JavaScript
- React를 통한 클라이언트 측 상호작용을 위한 JavaScript
https://nextjs.org/docs/pages/building-your-application/deploying
아래는 애러를 성명해주는 공식문서이다. 그래서 프로덕션이 아닌 개발모드에서는 next dev를 사용한다.
https://nextjs.org/docs/messages/production-start-no-build-id
그래서 next start 를 위한 next build를 해주었다면 ,
next start 스크립트를 실행하면 기본적으로 http://localhost:3000/ 서버에서 실행된 프로젝트를 볼 수 있다.
이건 어떻게 실행됐을까?
packages > next > src > server > lib > start-server.ts > startServer 함수
를 보면 알수있다.
Next.js는 node 위에서 동작하는 javascript 기반의 프레임워크임으로 node에서 제공하는 http module을 사용할 수 있다. 그래서 아래 코드를 보면 http 모듈을 이용해서 서버를 생성하고 프로젝트를 보내주는 코드를 확인할 수 있었다.
import type { Duplex } from 'stream'
import type { IncomingMessage, ServerResponse } from 'http'
import type { ChildProcess } from 'child_process'
import http from 'http' // -> 요기! ✅
import { isIPv6 } from 'net'
import * as Log from '../../build/output/log'
import { normalizeRepeatedSlashes } from '../../shared/lib/utils'
import { initialEnv } from '@next/env'
import {
genRouterWorkerExecArgv,
getDebugPort,
getNodeOptionsWithoutInspect,
} from './utils'
...
await new Promise<void>((resolve) => {
server.on('listening', () => {
const addr = server.address()
port = typeof addr === 'object' ? addr?.port || port : port
let host = !hostname || hostname === '0.0.0.0' ? 'localhost' : hostname
let normalizedHostname = hostname || '0.0.0.0'
if (isIPv6(hostname)) {
host = host === '::' ? '[::1]' : `[${host}]`
normalizedHostname = `[${hostname}]`
}
targetHost = host
const appUrl = `http://${host}:${port}`
if (isNodeDebugging) {
const debugPort = getDebugPort()
Log.info(
`the --inspect${
isNodeDebugging === 'brk' ? '-brk' : ''
} option was detected, the Next.js proxy server should be inspected at port ${debugPort}.`
)
}
Log.ready(
`started server on ${normalizedHostname}${
(port + '').startsWith(':') ? '' : ':'
}${port}, url: ${appUrl}`
)
resolve()
})
server.listen(port, hostname)
})
...
}
프로젝트를 create, start, run, build를 간단하게 뜯어보았지만 동작원리를 공부하는데에 큰 도움이 된 것같다.
프레임워크를 그냥 띡 실행해보는게 아니고 앞으로도 이슈를 만났을 때 깊이있게 이해하면서 문제해결을 더 잘할수있도록 접근해야겠다.
-------------------------------------------
Next.js 12.3.4 버전으로 실습해보았습니다.