Next.js CSR ,SPA , SSR , Next.js 프로젝트에서 yarn start 에 대해

임동현·2023년 7월 1일
0


1. CSR(Client-side Rendering)이란 무엇이며, 그것의 장단점에 대하여 설명해주세요.
2. SPA(Single Page Application)로 구성된 웹 앱에서 SSR(Server-side Rendering)이 필요한 이유에 대하여 설명해주세요.
3. Next.js 프로젝트에서 yarn start(or npm run start) 스크립트를 실행했을 때 실행되는 코드를 Next.js Github 레포지토리에서 찾은 뒤, 해당 파일에 대한 간단한 설명을 첨부해주세요.
https://nextjs.org/docs/getting-started (Next.js 세팅 가이드)
https://github.com/vercel/next.js/ (Next.js Github 레포지토리)

CSR 이란?

Client Side Rendering , Next.js 에서 CSR 은 기본적으로 Javascript 를 이용해 브라우저에서 페이지를 동적으로 생성하게 됩니다. 이를 통해 웹사이트는 사용자와 상호작용하면서 원활하게 업데이트 될 수 있습니다.

CSR 의 경우 모든 데이터가 로드가 되고 , Javascript 가 실행되어야 페이지가 완전히 렌더링되므로 쵝 로딩 시간이 상대적으로 느릴 수 있습니다. 그리고 검색 엔진 최적화(SEO) 에 있어서는 서버사이드 렌더링(SSR) 이나 정적사이트 생성(SSG) 방식에 비해 불리할 수 있습니다. 왜냐하면 CSR 의 경우 크롤러가 페이지를 인덱싱하기 전에 모든 자바스크립트가 로드 되어야 하기 때문입니다.
따라서, CSR 은 사용자의 인터랙션에 따라 콘텐츠가 자주 바뀌는 웹 사이트나 애플리케이션에 적합합니다.

SPA 로 구성된 웹 앱에서 SSR(server side rendering ) 이 필요한 이유

SPA(single Page Application) 는 모든 콘텐츠를 한 페이지에 로드하여 사용자와 상호작용을 통해 필요한 부분만 업데이트 합니다. 이렇게 되면 , 페이지 전환 없이 빠르고 부드러운 사용자 경험이 가능합니다. 하지만 단점이 존재합니다.

  1. SEO (검색 엔진 최적화)문제 : SPA 는 자바스크립트를 통해 동적으로 콘텐츠를 로드하기 때문에 , 검색엔진이 페이지를 제대로 크롤링 하지 못하고 , 따라서 사이트의 검색 엔진 순위가 낮아질 수 있습니다.
  2. 초기 로딩시간: SPA 는 처음에 모든 자바스크립트를 로드해야 하기 때문에 초기 로딩 시간이 길어질수 있습니다.

이러한 문제들을 해결하기 위해 Next.js 는 SSR 을 제공합니다. SSR 은 서버에서 페이지를 렌더링 하고 완전히 렌더링 된 페이지를 클라이언트에 전달하는 방식입니다. 이 방식을 사용하면 다음과 같은 이점이 있습니다.

  1. SEO 개선: SSR 을 사용하면 서버에서 완전히 렌더링된 페이지를 클라이언트에게 보내주기 때문에 검색 엔진이 콘텐츠를 쉽게 크롤링 하고 인덱싱 할 수 있습니다. 이로 인해 검색 엔진의 순위가 향상될 수 있습니다.
  2. 초기 로딩 시간 감소: 클라이언트는 서버에서 렌더링된 HTML 을 바로 받아 볼 수 있으므로 , 사용자가 빠르게 페이지의 콘텐츠를 볼 수 있습니다.

따라서 , SSR 은 SPA 의 SEO 문제와 초기 로딩 시간 문제를 해결해주는 중요한 도구 입니다. 그러나 모든 상황에 SSR 이 필요한 상황은 아니며 , 애플리케이션의 필요에 따라 적절한 렌더링 전략을 잘 선택해야합니다!!

Next.js 프로젝트에서 yarn start(or npm run start) 스크립트를 실행했을 때 실행되는 코드를 Next.js Github 레포지토리에서 찾은 뒤, 해당 파일에 대한 간단한 설명

보통은 package.json 파일에

  "scripts": {
    "dev": "next dev -p 3000",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },

yarn dev , yarn start 이전에 프로젝트 사용시 웹팩을 이용해서 https:// 개발환경을 만들면서 script 코드를 수정해본적이 있었지만 start 가 어떻게 실행되는지에 대해서 이번 온보딩 사전 과제를 통해서 공부하는 계기가 되었다.

파일위치

next.js/packages/next/src/cli/next-start.ts

#!/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 })
  } catch (error) {
    if (isError(error) && error.code === 'ARG_UNKNOWN_OPTION') {
      return printAndExit(error.message, 1)
    }
    throw error
  }
  if (args['--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])
  const host = args['--hostname']
  const port = getPort(args)

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

  const keepAliveTimeout = keepAliveTimeoutArg
    ? Math.ceil(keepAliveTimeoutArg)
    : undefined

  const config = await loadConfig(
    PHASE_PRODUCTION_SERVER,
    resolve(dir || '.'),
    undefined,
    undefined,
    true
  )

  await startServer({
    dir,
    isDev: false,
    hostname: host,
    port,
    keepAliveTimeout,
    useWorkers: !!config.experimental.appDir,
  })
}

export { nextStart }

전체적인 코드가 이렇게 구성 되어져 있다.

1. 유효한 옵션 명시 및 확인

 const validArgs: arg.Spec = {
    // Types
    '--help': Boolean,
    '--port': Number,
    '--hostname': String,
    '--keepAliveTimeout': Number,

    // Aliases
    '-h': '--help',
    '-p': '--port',
    '-H': '--hostname',
  }

1) validArgs 는 인자들의 이름과 타입 , 그리고 단축키를 정의합니다.
2) arg 함수는 사용자가 입력한 인자를 파싱하고 args 에 저장합니다.
3) 만약 알수 없는 인자가 입력 되면 , 오류를 출력하고 프로그램을 종료합니다.

2. --help 옵션이 있는 경우

if (args['--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)
  }

사용자가 "--help' 옵션을 사용해 명령어를 실행했을 때 도움말 메시지를 출력하고 프로그램을 종료하는 역할을 합니다.

'args['--help']' 가 참이면 즉 ,'--help' 옵션이 주어졌다면 , 'console.log' 를 통해 도움말 메시지를 출력합니다. 이 메시지는 'next start' 명령어의 사용 방법과 옵션들에 대한 설명을 제공합니다.

마지막으로 'process.exit(0)' 를 호출하여 프로그램을 종료합니다 '0 은 ' 정상 종료를 뜻합니다.

3. 사용자가 제공한 명령줄 인자를 바탕으로 서버를 설정하는 부분

const dir = getProjectDir(args._[0] ) 
  const host = args['--hostname'] 
  const port = getPort(args)

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

  const keepAliveTimeout = keepAliveTimeoutArg
    ? Math.ceil(keepAliveTimeoutArg)
    : undefined

1 ) getProjectDir(args.[0] ) 사용자가 제공한 프로젝트 디렉토리를 가져오고 인자로 'args.[0]' 를 사용합니다. 이 위치는 인자가 'next start' 명령어에 전달한 프로젝트 디렉토리 입니다.
2 ) args['--hostname'] : 사용자가 제공한 호스트 이름을 가져옵니다.
3 ) getPort(args) 사용자가 제공한 포트를 가져옵니다.
4 ) keepAliveTimeoutArg : 사용자가 제공한 keep-alive 타임아웃을 가져옵니다. 이 값은 서버가 비활성 연결을 닫기 전에 대기할 최대 시간을 밀리초로 설정합니다. 만약 사용자가 유효하지 않은 값을 제공하면 , 오류 메시지를 출력하고 프로그램을 종료합니다. keepAliveTimeout : keepAliveTimeoutArg 값을 반올림한 결과를 저장합니다. 사용자가 제공하지 않으면 이 값은 undefined 가 나옵니다.

이 코드를 통해 Next.js는 사용자가 제공한 인자를 바탕으로 서버를 설정할 수 있습니다.

4. 이 코드는 Next.js의 설정을 로드하고 서버를 시작하는 부분입니다.

const config = await loadConfig(
    PHASE_PRODUCTION_SERVER, 
    resolve(dir || '.'),
    undefined,
    undefined,
    true
  )

  await startServer({
    dir,
    isDev: false,
    hostname: host,
    port,
    keepAliveTimeout,
    useWorkers: !!config.experimental.appDir,
  })

1) loadConfig : next.js 의 설정을 로드하는 함수 입니다. 첫 번째 인자로 프로덕션 서버의 단계를 나타내는 PHASE_PRODUCTION_SERVER, 를 넘겨줍니다.
두번째 인자는 사용자가 입력한 또는 기본적으로 현재 디렉토리를 나타내고 있는 dir 을 넘겨줍니다. 프로젝트의 설정을 반환!

2 ) startServer 이 함수는 서버를 시작하는 역할을 합니다. 사용자가 입력한 설정들 과 함께 서버를 시작합니다. 개발모드가 아닌 프로덕션 모드를 서버로 시작하고 useWorkers: !!config.experimental.appDir, 설정에 따라 워커를 사용할지 여부를 결정합니다. 간단히 말하면 Next.js 애플리케이션의 설정을 로드하고 , 해당 설정에 따라 서버를 시작하는 작업을 수행합니다.

profile
프론트엔드 공부중

0개의 댓글