본문 바로가기

Next.js : npx next start

Next.js : npx next start

npx next start

 

npx next start CLI는 Next.js 애플리케이션이 프로덕션 모드로 시작할 수 있게 하는 명령어다.

  • Next.js 프로젝트에서 해당 스크립트를 실행했을 때 실행되는 코드를 Next.js Github 레포지토리에서 찾으면 아래와 같다.
  • 즉, npx next start를 실행했을 때 어떤 코드가 작동하는 지를 찾아보려고 한다.

 

찾아가는 과정

  • 사실 npm run start? yarn start 와 같이 프로덕션 모드로 시작하게 해주는 Next.js 스크립트를 먼저 찾아야 했다.
  • 따라서 가장 기본 문서인 getting-started의 installation에서 start와 관련한 설명을 찾았다. 

 

next.js/docs/01-getting-started/01-installation.mdx
- `dev`: runs [`next dev`](/docs/app/api-reference/next-cli#development) to start Next.js in development mode.
- `build`: runs [`next build`](/docs/app/api-reference/next-cli#build) to build the application for production usage.
- `start`: runs [`next start`](/docs/app/api-reference/next-cli#production) to start a Next.js production server.
- `lint`: runs [`next lint`](/docs/app/api-reference/next-cli#lint) to set up Next.js' built-in ESLint configuration.

 

  • 해당 경로를 찾아가 보았다. (아래의 내용은 Next.js 공식 문서의 내용이기도 하다.)
next.js/docs/02-app/02-api-reference/08-next-cli.mdx
## Production

`next start` starts the application in production mode. The application should be compiled with [`next build`](#build) first.

The application will start at `http://localhost:3000` by default. The default port can be changed with `-p`, like so:

```bash filename="Terminal"
npx next start -p 4000
```

Or using the `PORT` environment variable:

```bash filename="Terminal"
PORT=4000 npx next start
```

> **Good to know**:
>
> -`PORT` cannot be set in `.env` as booting up the HTTP server happens before any other code is initialized.
>
> - `next start` cannot be used with `output: 'standalone'` or `output: 'export'`.

 

 

  • yarn으로 프로젝트를 시작하는 경우, 혹은 공식 문서를 참고하여 수동으로 package.json을 작성하는 경우 아래와 같이 scripts를 작성해주면 된다.
  • 아래의 코드를 예를 들면, yarn으로 프로젝트를 시작했을 때 yarn start를 실행하면 아래의 next start 명령어가 실행된다.
"scripts": {
  "dev": "next dev",
  "build": "next build",
  "start": "next start",
  "lint": "next lint"
}

 

  • 아래 경로에서 npx next start를 실행했을 때 작동하는 코드를 찾았다.

 

 

next.js/packages/next/src/cli/next-start.ts
  • 아래의 코드는 nextStart라는 비동기 함수로 CliCommand 타입으로 작성되어 있다.
  • 해당 함수는 Next.js 애플리케이션을 프로덕션 모드로 시작하는 작업을 수행한다.
  • (코드에 대한 설명은 주석으로 작성)
#!/usr/bin/env node

import arg from 'next/dist/compiled/arg/index.js'
import { startServer } from '../server/lib/start-server'
import { getPort, printAndExit } from '../server/lib/utils'
import isError from '../lib/is-error'
import { getProjectDir } from '../lib/get-project-dir'
import { CliCommand } from '../lib/commands'
import { resolve } from 'path'
import { PHASE_PRODUCTION_SERVER } from '../shared/lib/constants'
import loadConfig from '../server/config'

const nextStart: CliCommand = async (argv) => {
  const validArgs: arg.Spec = { // 명령줄 인수의 유효한 옵션을 정의 (유형과 별칭)
    // Types
    '--help': Boolean,
    '--port': Number,
    '--hostname': String,
    '--keepAliveTimeout': Number,

    // Aliases
    '-h': '--help',
    '-p': '--port',
    '-H': '--hostname',
  }
  let args: arg.Result<arg.Spec>
  try {
    args = arg(validArgs, { argv })  // args에 validArgs를 사용하여 명령줄 인수를 파싱한 결과를 저장
  } catch (error) {
    if (isError(error) && error.code === 'ARG_UNKNOWN_OPTION') {
      return printAndExit(error.message, 1)
    }
    throw error
  }
  if (args['--help']) { // --help 옵션이 주어진 경우, 도움말 메시지를 출력하고 프로세스를 종료
    console.log(`
      Description
        Starts the application in production mode.
        The application should be compiled with \`next build\` first.

      Usage
        $ next start <dir> -p <port>

      <dir> represents the directory of the Next.js application.
      If no directory is provided, the current directory will be used.

      Options
        --port, -p          A port number on which to start the application
        --hostname, -H      Hostname on which to start the application (default: 0.0.0.0)
        --keepAliveTimeout  Max milliseconds to wait before closing inactive connections
        --help, -h          Displays this message
    `)
    process.exit(0)
  }

  const dir = getProjectDir(args._[0])  // args._[0]에서 프로젝트 디렉토리 경로를 가져옴
  const host = args['--hostname']       // args['--hostname']에서 호스트 이름을 가져옴
  const port = getPort(args)            // getPort 함수를 사용하여 포트 번호를 가져옴

 // args['--keepAliveTimeout']에서 --keepAliveTimeout 옵션의 값(밀리초)을 가져옴
  const keepAliveTimeoutArg: number | undefined = args['--keepAliveTimeout']
  
  // 값이 유효한지 확인하고, 유효하지 않은 경우 오류 메시지를 출력하고 프로세스를 종료
  if (
    typeof keepAliveTimeoutArg !== 'undefined' &&
    (Number.isNaN(keepAliveTimeoutArg) ||
      !Number.isFinite(keepAliveTimeoutArg) ||
      keepAliveTimeoutArg < 0)
  ) {
    printAndExit(
      `Invalid --keepAliveTimeout, expected a non negative number but received "${keepAliveTimeoutArg}"`,
      1
    )
  }

// keepAliveTimeoutArg 값이 주어진 경우, 
// 해당 값을 반올림하여 할당하고, 그렇지 않은 경우 undefined로 설정
  const keepAliveTimeout = keepAliveTimeoutArg
    ? Math.ceil(keepAliveTimeoutArg)
    : undefined

// loadConfig 함수를 사용하여 프로덕션 서버 설정을 로드
  const config = await loadConfig(
    PHASE_PRODUCTION_SERVER,
    resolve(dir || '.'),
    undefined,
    undefined,
    true
  )

// startServer 함수를 사용하여 서버를 시작
  await startServer({
    dir,
    isDev: false,
    hostname: host,
    port,
    keepAliveTimeout,
    useWorkers: !!config.experimental.appDir,
  })
}

// nextStart 함수를 다른 파일에서 사용할 수 있도록 내보냄

export { nextStart }

// 🟣 즉, nextStart 함수는 Next.js 애플리케이션을 프로덕션 모드로 시작하는 데 필요한 
// 명령줄 인수를 파싱하고 설정을 로드한 다음 서버를 시작하는 역할

 

next.js/packages/next/src/server/lib/start-server.ts
  • startServer 함수는 아래와 같이 작성되어 있다. (일부)
 let targetHost = hostname

  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}`

      Log.ready(
        `started server on ${normalizedHostname}${
          (port + '').startsWith(':') ? '' : ':'
        }${port}, url: ${appUrl}`
      )
      resolve()
    })
    server.listen(port, hostname)
  })

 

 

레퍼런스

 

728x90
⬆︎