원티드 프리온보딩 챌린지 - CSR / SSR with Next.js
📝 문제
Assignment) 개인 블로그에 아래 질문에 대한 포스팅을 하고 링크를 제출해주세요.
- CSR(Client-side Rendering)이란 무엇이며, 그것의 장단점에 대하여 설명해주세요.
- SPA(Single Page Application)로 구성된 웹 앱에서 SSR(Server-side Rendering)이 필요한 이유에 대하여 설명해주세요.
- 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 레포지토리)
_document.js
,_app.js
,getServerSideProps
같은 요소들에 대해 설명을 요구하는 과제가 아닙니다. 오히려 Next.js 코드 베이스 내부를 살펴보라는 의미입니다.- 사전과제 여부나 제출된 과제 퀄리티가 수강 가능 여부 및 이후의 과정에 영향을 미치지는 않을 것이나, 3번 과제를 해보는 것이 큰 학습이 될 것이라고 확신합니다. 반드시 한번 살펴보시길 권장드립니다.
- 제출 전 과제가 유효한 Public 한 링크인지 다시 한번 확인 부탁드립니다.
과제 제출
- 수행하신 과제는 챌린지 시작 후 전달될 안내에 따라 링크로 제출해주시고, 학습 수준 파악 및 강의 진행을 위해 사용될 예정입니다.
📝 과제
📌 1번, CSR(Client-side Rendering)이란 무엇이며, 그것의 장단점에 대하여 설명해주세요.
CSR
- CSR은 클라이언트가 웹 렌더링에 필요한 주요 로직들(JS 등)을 초기 접속시 한번에 모두 내려받음
- 사용자의 행동에 따라 이미 다운 받아진 JS 번들을 통해 서버로부터 데이터를 가져오거나, 화면을 렌더링
장점
- 쉬운 페이지 전환
- 서버에 추가적인 요청없이 작동
- 네이티브 애플리케이션과 유사하게 작동
- 브라우저 화면을 새로 고칠 필요없이 다른 페이지로 이동 가능
단점
- 보안 문제
- API 요청/응답을 통해 백엔드 구조 및 민감한 정보가 노출 될 수 있음
- 초기 로딩 시간
- 초기 페이지 로딩시에 주요 번들을 전부 내려받기 때문에, 초기 로딩시에 시간이 소요됨
- SEO최적화 문제
- 일부 검색 엔진(네이버 등)과 같은 곳에서는 CSR로 구성된 웹 사이트를 분석하지 못함
- 호환성 문제
- 구형 브라우저 등에서 번들에 포함된 일부 JS 스펙이 작동되지 않을 수 있음
📌 2번, SPA(Single Page Application)로 구성된 웹 앱에서 SSR(Server-side Rendering)이 필요한 이유에 대하여 설명해주세요.
- 보안
- 중요한 데이터 요청을 서버단에서 처리하여 중요 정보를 감출 수 있음
- 브라우저 호환성
- 대부분의 렌더링을 브라우저에서 처리하고 마크업 파일만 내려주기 때문에, 대부분의 브라우저에서 호환성이 높음
- SEO 성능
- 검색엔진의 크롤러가 작동할 때, 어떤 웹 사이트인지 메타데이터를 포함해서 전달할 수 있음
- 초기 로딩 속도
- 프리렌더링, 캐싱 등의 전략을 통해 처음 웹 사이트에 접속하는 유저의 로딩 시간을 단축시킬 수 있음
- 서버 리소스 활용
- 클라이언트 기기 성능에 영향을 받지 않고, 사이트를 렌더링하여 클라이언트에 내려줄 수 있음
📌 3번, Next.js 프로젝트에서 yarn start(or npm run start)
스크립트를 실행했을 때 실행되는 코드를 Next.js Github 레포지토리에서 찾은 뒤, 해당 파일에 대한 간단한 설명을 첨부해주세요.
nextJS 프로젝트
yarn start는 어떤 명령어인지 찾아보기
"scripts": { // ... "start": "next start" },
yarn start
실행시 →next start
next start
는 어떻게 실행되는가
Vercel/next 레포에서 찾아보기
- https://github.com/vercel/next.js 의
package.json
"workspaces": [ "packages/*" ],
- 모노레포로 구성되어 있으며, 찾고자하는
next
명령어 에 대한 정보는packages/
에 있을 것으로 보임.
packages/
에 속한 다양한 레포- create-next-app
- next
- next-swc
- … 등
packages/next
의package.json
// bin: 패키지내 실행 가능한 명령어 경로 "bin": { "next": "./dist/bin/next" },
packages/next/src/bin/next
에서 찾을 수 있음
packages/next/src/bin/next
next는 어떻게 실행되는 명령어인지 찾아보기
- 주요코드
// 의존성 체크 ;['react', 'react-dom'].forEach((dependency) => { try { // When 'npm link' is used it checks the clone location. Not the project. require.resolve(dependency) } catch (err) { console.warn( `The module '${dependency}' was not found. Next.js requires that you include it in 'dependencies' of your 'package.json'. To add it, run 'npm install ${dependency}'` ) } })
- 명령어 옵션
// 버전 // --version 옵션이 있을 경우, 버전을 출력하고 프로세스를 종료함 if (args['--version']) { console.log(`Next.js v${process.env.__NEXT_VERSION}`) process.exit(0) }
// help if (!foundCommand && args['--help']) { console.log(` Usage $ next <command> Available commands ${Object.keys(commands).join(', ')} Options --version, -v Version number --help, -h Displays this message For more information run a command with the --help flag $ next build --help `) process.exit(0) }
// 그 외 명령어들 commands[command]() .then((exec) => exec(forwardedArgs)) .then(() => { if (command === 'build') { // ensure process exits after build completes so open handles/connections // don't cause process to hang process.exit(0) } })
- 명령어
// next/src/lib/commands.ts export type CliCommand = (argv?: string[]) => void export const commands: { [command: string]: () => Promise<CliCommand> } = { build: () => Promise.resolve(require('../cli/next-build').nextBuild), start: () => Promise.resolve(require('../cli/next-start').nextStart), export: () => Promise.resolve(require('../cli/next-export').nextExport), dev: () => Promise.resolve(require('../cli/next-dev').nextDev), lint: () => Promise.resolve(require('../cli/next-lint').nextLint), telemetry: () => Promise.resolve(require('../cli/next-telemetry').nextTelemetry), info: () => Promise.resolve(require('../cli/next-info').nextInfo), 'experimental-compile': () => Promise.resolve(require('../cli/next-build').nextBuild), 'experimental-generate': () => Promise.resolve(require('../cli/next-build').nextBuild), }
yarn start
그래서 yarn start를 입력하면,
- next/src/lib/commands.ts 에 따라 next/src/cli/next-start’가 실행됨
- next/src/cli/next-start
- next-start에 의해 실행되는 코드
- 주요코드
// .. // 서버 환경 정보 가져오기 const dir = getProjectDir(args._[0]) const host = args['--hostname'] const port = getPort(args) //... // 서버 실행 await startServer({ dir, isDev: false, hostname: host, port, keepAliveTimeout, useWorkers: !!config.experimental.appDir, })
- 구성
- startServer는 node의 http모듈을 활용하여 구성되어 있음 https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction
- 해당 코드에 따라, nextjs를 실행시킬 서버가 작동 됨