ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 원티드 프리온보딩 챌린지 - CSR / SSR with Next.js
    Next 2023. 7. 4. 16:44

    1. CSR이란 무엇이며, 그것의 장단점에 대하여 설명해주세요

    CSR(Client-side-rendering)이란

    CSR은 브라우저에서 자바스크립트로 페이지를 직접 렌더링하는 것을 의미한다.
    즉 모든 로직과 데이터 패칭, 템플릿과 라우팅등을 서버가 아닌 클라이언트에서 처리하는 렌더링 방식을 말한다.
    이러한 렌더링 방식으로 인해 서버에서 사용자 기기로 더 많은 정보를 전달할 수 있지만 그에따른 단점도 존재한다.

    반대로 SSR(Server-side-rendering) 방식은 서버에서 페이지 전체의 HTML을 생성하여 브라우저에서 렌더링 하는 방식이다.

    장점

    1. 향상된 사용자의 경험
      CSR은 렌더링시 최소한의 자바스크립트와 CSS 파일이 포함된 HTML을 받아와 클라이언트에 전달해준 후 클라이언트는 스크립트를 동적으로 생성하고 렌더링 과정을 이어받게 됩니다
      그렇기 때문에 CSR은 서버가 모든 요청을 처리할 때까지 기다릴 필요가 없으므로 사용자와의 상호작용이 더 빠르게 이루어져 사용자의 경험이 향상된다.
    2. 빠른 페이지 로드
      클라이언트 측은 필요한 자바스크립트와 CSS 파일이 포함된 서버에서 최소한의 HTML 파일만 받아오기 때문에 페이지가 더 빠르게 로드될 수 있습니다.
      그렇기 때문에 대역폭이 제한된 모바일에서 유용할 수 있습니다.
    3. 확장의 용이성
      트래픽이 많은 웹 사이트에서 CSR은 최소한의 자바스크립트와 CSS 파일이 포함된 HTML파일을 받아와 사용자의 기기에서 렌더링을 담당하기 때문에 서버는 전체 HTML파일을 만들지 않아도 되어 서버의 워크로드가 줄어들게 됩니다.
      그로인해 서버는 클라이언트로 전송을 최적화하는데 초점을 맞춰 확장할 수 있게 됩니다.

    단점

    1. SEO의 문제
      CSR은 콘텐츠가 브라우저에서 동적으로 생성되는 특성상 초기의 HTML파일이 최소한으로 있거나 콘텐츠가 아예 없을 수도 있기 때문에 검색 엔진 크롤러가 콘텐츠를 크롤링하는데 어려움을 겪을 수 있습니다.
    2. 성능 문제
      애플리케이션의 성장에 따라 필요한 자바스크립트 양이 많아지면서 느린 디바이스나 대량의 데이터에서 성능 문제를 일으킬 수 있습니다.
    3. 특히 성능을 위해 렌더링 전 처리하기 위한 라이브러리나 폴리필등의 코드가 추가됨으로 써 로드 시간이 길어지고, 사용자 인터페이스의 반응이 저하될 수 있습니다.
    4. 초기 페이지 로드 시간
      페이지를 렌더링하기 전 브라우저는 HTML구조, 자바스크립트와 CSS등 필요한 리소스를 다운로드해야 하는데 이로인해 초기 로딩시간이 길어져 사용자가 콘텐츠를 보는데 지연이 발생하여 초기 페이지 로드시간이 느려질 수 있습니다.

    2.SPA(Single Page Application)로 구성된 웹 앱에서 SSR(Server-side Rendering)이 필요한 이유에 대하여 설명해주세요.

    SPA(Single page Application)란?

    단일 페이지 애플리케이션의 약자로 서버에서 새로운 페이지를 로드하는 대신 현재 페이지를 동적으로 업데이트하는 웹 애플리케이션의 아키텍처입니다.
    SPA는 초기 HTML,JS,CSS를 서버에서 로드하고 이후 업데이트는 클라이언트 측에서 처리하게 됩니다.
    그렇기 때문에 기존의 MPA(Multi Page Application)는 업데이트가 발생하면 서버에서 새로운 HTML을 받아오기 때문에 페이지 전환 속도가 느려져 사용자의 경험이 저하되게 됩니다.

    먼저 설명에 앞서 SSR과 CSR의 차이점과 SPA와 MPA의 차이점에 대해서 간단히 이야기해보면 아래와 같다.

    • SSR의 경우에는 서버측에서 콘텐츠가 완전히 렌더링 된 HTML파일을 받아오는 반면에 CSR은 최소한의 HTML,JS,CSS 파일만 받아온 후 클라이언트 측에서 자바스크립트를 실행하여 콘텐츠를 구성하게 된다.
    • 과거에 사용되었던 MPA 아키텍처는 콘텐츠가 업데이트가 되면 서버에서 새로운 HTML을 받아와 렌더링하기 때문에 이 과정에서 지연이 발생하여 사용자의 경험을 저하시키게 된다. 그래서 이를 해결하기 위해 SPA 아키텍처가 나오게 되었다. SPA는 초기에 최소한의 리소스만 받아오기 때문에 MPA에서 발생하는 문제점을 해결하게 된다.

    SPA로 루성된 웹 앱에서 CSR을 사용할 경우에 최소한의 파일만 받아오고 클라이언트 측에서 렌더링을 이어나가기 때문에 초기 로딩속도가 느려질 수 있으며,
    콘텐츠가 완전히 없거나, 최소한의 콘텐츠만 있는 경우에는 검색 엔진 크롤러가 접근하는데 불리하기 때문에 SEO에서도 문제점이 발생하게 된다.

    이러한 점을 해결하기 위해 SSR을 사용하게 되는데 SSR을 사용할 경우에는 서버에서 콘텐츠가 완전히 렌더링 된 HTML파일을 받아오기 때문에 초기에 콘텐츠를 페인팅하는 시간을 단축하게 되고, 콘텐츠가 모두 존재하기 때문에 검색 엔진 크롤러가 콘텐츠게 접근하는데 보다 유리하기 때문에 SEO에서도 향상되게 된다.

    또한 CSR의 경우에는 클라이언트 측 자바스크립트를 실행하여 사용자의 기기에 전적으로 의존하기 때문에 기기의 성능에 따라 성능 저하를 발생할 수 있지만 SSR의 경우에는 서버에서 처리하기 때문에 기기에 부담을 완화하는데 도움이 됩니다.

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

    우선 npm run start를 하기 위해서는 이전에 build가 우선되어야 한다고 공식 문서에도 작성되어 있다.
    만약 build를 하지 않고 npm run start를 실행하게 된다면 에러가 발생하는 것을 볼 수 있다.

    Error: Could not find a production build in the '/Desktop/my-app/.next' directory. Try building your app with 'next build' before starting the production server.

    이때 올바르지 않은 명령어나 에러가 발생한다면 아래 코드에서 막혀 발생한 log를 보여주는 코드가 실행된다.

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

    그후 프로젝트가 시작되는 디렉토리와 호스트, 포트 번호, keepAliveTimeoutArg등의 값을 확인하는 코드가 실행된다.

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

    만약 아래와 같이 조건문에 음수, 무한대값, 숫자가 아닌 값을 입력하면 조건문에 걸려 종료되게 된다.

    npx next start --keepAliveTimeout -70000 //exit

    이후 loadConfig를 통해 프로젝트의 설정을 완료한 후 해당 값을 바탕으로 startServer 함수에 지금까지 생성된 값을 전달하여 함수를 실행하게 된다.

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

    이때 startServer함수는 서버를 실행하는 함수로 전달받은 값을 바탕으로 프록시 서버를 설정하여 실행하는 과정을 갖게 된다.

    'Next' 카테고리의 다른 글

    NextJS에서 Firebase 사용하기  (0) 2023.02.22
    NextJS에서 제공하는 <Image/> 를 왜 써야할까?  (0) 2023.02.13
    getStaticProps와 getServerSideProprs  (0) 2023.02.12
Designed by Tistory.