Next.js 입문 1일차 (2022.05.19)

RyuSW·2022년 5월 19일
0
post-thumbnail

🏹 Next.js란? React로 만드는 SEO에 최적화된 서버사이드 렌더링 프레임워크


💻 SSR(Server Side Rendering)이 뭔데??

SSR이란 Server Side Rendering의 약자로 사용자가 웹 페이지에 접속했을 때 서버가 사용자에게 랜더링될 HTML을 응답하여 브라우저가 바로 렌더링할 수 있게 만든다. 그 후 CSR과 동일하게 자바스크립트 파일을 다운로드 받고 실행한다.

SSR을 사용하는 이유

  • CSR의 단점을 보완하기 위해서다!

    • CSR(Client Side Rendering)의 경우 모든 JavaScript 파일을 로드하고 사용자는 웹을 보게 되는데 그 때까지 사용자는 오랜 시간을 대기해야 함

    • SEO 문제 : 클라이언트 사이드에서 JavaScript가 로드되지 않으면 아무런 정보를 보이지 않는다. Google 검색엔진의 경우 JavaScript가 로드 안된 페이지를 검색엔진으로 스캔하게 되므로 결론적으로 검색에 아무 페이지도 걸리지 않게 됨.

  • 위 두 가지를 해결하는 것이 서버 사이드 렌더링이다.

    • 서버에서 JavaScript를 로딩함으로 클라이언트 측에서는 스크립트를 로딩하는 시간이 줄어든다.

    • 검색 엔진이 JavaScript를 읽는 것이 아닌 서버 측에서 HTML파일을 만들어 컨텐츠를 직접 업로드한다.


🏓 Next.js가 제공하는 주요 기능

  • Hot Reloading : Dev 모드에서 코드가 수정되면 따로 빌드하지 않아도 자동으로 적용을 시켜준다.

  • Automatic Routing : page 폴더에 있는 파일은 해당 이름으로 라우팅이 된다.

  • Single File Components : style.jsx를 사용해서 컴포넌트 내부에 해당 컴포넌트만 스코프를 가지는 css를 만들 수 있다.

  • Server Randering : 서버 렌더링을 한다. 클라이언트랑 다르게 서버 렌더링을 한 페이지의 소스보기를 클릭하면 내부에 소스가 있다.

  • Code Splitting : 자기가 원하는 페이지에서 원하는 JS와 라이브러리를 렌더링 하는 것이다. 모든 Bundle이 하나로 묶이지 않는다.

  • Intuitive Page-Based Routing Sytstem : Next.js는 Pre-Rendering 뿐만 아니라 페이지 기반 라우팅 시스템도 제공한다. 프로젝트의 가장 바깥 폴더인 /pages폴더에서 컴포넌트를 export하게 되면 폴더명이 페이지 route가 실시된다. (/pages/indext.s -> /, /pages/store/t-shirt -> /store/t-shirt)

    참조 : [Next.js] 기본 개념 : Next.js 란? Next.js를 왜 사용할까? Next.js의 장점은?

  • Link 제공 : a태그를 사용안하고 link 태그를 사용한다. get 요청을 보냈다면, component에서는 /pages/index.js 파일이 props로 내려오게 된다. pages/[value].tsx 왼쪽 페이지 구조의 값은 router.query.값과 동일하다.


🔨 Next.js 실습환경 구축하기


1. 가장 먼저 npx create-next-app [자신이 만들 폴더명] 명령어를 통해서 자신이 실습할 Next.js 개발 환경을 만들어준다.

※ 개꿀팁!! 자신이 만든 next.js 폴더로 이동을 해서 code . 명령어롤 입력하면 VSCode같은 에디터로 폴더가 자동으로 열린다!

2. 아래와 같이 디렉토리가 셋팅되면 Next.js프로젝트가 잘 생성된 것을 확인할 수 있다.

  • package.json의 dependencies들은 잘 설치된 것을 확인할 수 있다. Webpack이나 필수적인 라이브러리들은 next.js가 알아서 잘 관리해주니 걱정할 필요 없다.

  • 아래는 서버 실행 시 사용하게 될 명령어들이다.

    • npm run dev : 개발을 할 때 개발 모드를 띄우는 명령어
    • npm run build : 개발한 내용을 빌드시켜서 production을 할 준비
    • npm run start : production모드로 구동을 해볼 수 있는 명령어
    • npm run lint : 불필요한 코드 정리

  • next.config.js : next에 필요한 설정들을 작성해 주는 파일

  • styles폴더 : css파일들 저장

  • public폴더 : react의 public폴더의 역할과 비슷

  • pages폴더 : 실질적인 코드 파일들을 보관하는 폴더


3. 개발 모드를 실행시키기 위해 ctrl + Tab키를 눌러서 터미널을 열고 npm run dev를 입력해서 실행시킨다.
그 후 url주소에 localhost:3000/을 입력하고 들어가보면 다음과 같은 화면이 나온다.

위 화면과 같이 나오면 잘 따라 온 것이다🙌🙌

위 화면의 내용들은 index.js페이지의 내용들이다.
React의 App.js의 역할을 index.js가 수행한다고 보면 된다!


  • Next.js의 가장 큰 장점 중 하나는 Routing이 상당히 쉽다는 점!!

    • 왜냐하면 page의 파일명이 곧 url의 하위 주소가 되기 때문이다!!

    • index.js에서 제공해주는 <Head>태그는 페이지의 title 설정 역할을 수행한다.

    • 아래와 같이 index.js에서 코드를 작성해주면은

    • 로컬환경에서 다음과 같이 화면에 보여진다.



  • <Head>태그 안에 meta태그를 작성할 수 있다.

    • SEO에 필수적인 요소이다.

    • <meta> 내부에 keyword와 contents를 다음과 같이 작성해보고 소스 코드를 확인해보자.
    • 웹페이지 상에서 바로 소스 코드를 확인하면 코드가 지저분 보일 수 있기 때문에 chrome 웹스토어에
      Quick source viewer를 설치해서 소스 코드를 확인하기를 권하고 있다.
  • 지금은 Chrome 접근 권한 에러로 인해 문제가 계속 발생하므로 지금은 스킵하자!



4. index.js에서 메뉴를 만들어보기

  • 첫 번째 태그는 Home으로 이동하고 두 번째 태그는 Photos로 이동할 수 있는 메뉴를 만들어보자.

    • 첫 번째 태그 url은 /, 두 번째 태그 url은 /photos로 이동할 수 있게 설정

    • <a> 대신 <Link>컴포넌트를 import해서 페이지 이동을 하게 만들어준다.
      이것이 Next.js를 이용하는 데 있어서 큰 메리트 중 하나다!

  • 결과 화면 :

    • 화면 새로고침 했을 때, Home 텍스트를 클릭했을 때

    • Photos 텍스트를 클릭했을 때

5. Photos 페이지 내부에서 다른 페이지로 이동하는 것 메뉴를 구현해보기

  • 어떠한 한 곳에서 관리를 하고 다른 페이지로 이어주기

  • components폴더를 생성해주고 폴더 안에 Layout.js파일을 만들어준다.

    • Layout.js파일을 index.js에 바로 거는 것이 아니라 _app.js으로 import시킨다.
    • component들이 들어갈 수 있도록 props에 children을 넘겨서 component로 나오게 유도
    • index.jsphotos.js파일들이 children props 내부에 들어가게 된다.
  • components폴더 안에 nav.js파일도 하나 만들어준다.

  • Layout.js파일로 돌아가서 Nav컴포넌트를 import해온다.

  • _app.js파일로 이동해서 Layout컴포넌트를 import 하고 return할 때 Component태그를 Layout컴포넌트로 감싸준다.

  • index.js파일은 <Head>태그를 제외하고 나머지 코드는 모두 삭제한다.

  • 그러면 다음과 같이 Home 화면에서 Photos 링크로 이동하는 과정이 _app.js파일 하나에서 관리가 될 수 있다는 것을 확인할 수 있다.

  • 여기서 알아야 할 점!!

    • 페이지에 어떤 내용을 적던 간에 _app.js에서 실질적인 컨텐츠가 들어가게 된다.
    • 컨텐츠를 Layout으로 감싸고 Layout 안에 children으로 실질적인 컴포넌트를 props로 넘겨받아서 화면에 보여주는 것이다.
  • Layout.js에서 모든 페이지들의 관리를 할 수 있기 때문에 중복을 피하기 위해서 index.js 또는 photos.js에 있는 <Head>태그들은 모두 Layout.js파일에 작성하자!

6. <Head>태그를 컴포넌트화 시켜서 관리를 해보자.

  • Components폴더 안에 HeadInfo.js를 만들고 Head 태그의 내용들을 넣어주자!

  • 넘겨받은 타이틀이나 컨텐츠들과 같은 메타정보들은 props로 넘겨받자.

  • Props의 default값들도 미리 설정해주자!

  • photos.js파일에 HeadInfo.js를 import하고 title을 따로 지정해주자.


  • module.css를 사용해서 Nav.js에 스타일을 입혀보자!

    • styles폴더에 Nav.module.css파일을 만들어주기

    • list형식 옆에 붙는 까만색 점을 없애주기 위해 globals.css에 아래 구문 추가

      ul {
         list-style: none;
       }
    • Nav.js의 className에 스타일 부여



❗❗ SSR, SSG를 위해서 Fetch를 실시해야 한다!

  • index.js에서 다음과 같은 구문을 입력한다.

https://jsonplaceholder.typicode.com/ ← 다양한 무료 API를 제공해주는 사이트

※ POST를 불러오고 갯수가 많기 때문에 0번부터 10번까지만 불러온다.

https://jsonplaceholder.typicode.com/posts?_start=0&_end=10

  • props로 posts를 return한다.

  • props자리에 posts를 넣고 console.log로 데이터가 잘 출력되었는 지 확인해본다.

  • 위와 같이 데이터가 잘 출력되었음을 확인할 수 있다.

    getServerSideProps를 사용하면 SSR(Server Side Rendering)을 하게 되는데 해당 페이지에 들어올 때마다 서버에 요청을 해서 데이터를 받아오는 역할을 한다.

    ★ 서버에서 만든 HTML파일을 그 때 그 때 보여주는 방식



  • getServerSideProps 대신에 getStaticProps를 사용한다면?

    • SSG(Static Side Generation)가 일어나게 된다.

    • 두 방식의 차이점을 직관적으로 확인하기 위해 다음과 같은 방법들을 사용해보자!

      1. dev로 구동되는 터미널 실행을 종료하고 npm run build를 입력한다.

    1. next 프로젝트가 들어있는 폴더에 local-api라는 폴더를 만들고 폴더를 열어준다.

      • 여기서 우리만의 api를 생성해볼 예정
    2. local-api 폴더 안에서 app.js파일을 만들고 터미널을 실행해서 expresscors을 설치한다.

      npm install express cors

    3. 간단한 Node.js 서버를 만들어본다.

      • app.js에서 아래와 같이 코드를 작성하고 node app.js로 서버를 실행시킨다.
    4. data.js파일을 만들고 jsonplaceholder페이지에서 받아왔던 0부터 10까지의 JSON형태의 데이터들을 복사하고 붙여넣기한다.

      module.exports = {
        posts : [
            {
              "userId": 1,
              "id": 1,
              "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
              "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
            },
            {
              "userId": 1,
              "id": 2,
              "title": "qui est esse",
              "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
            },
            {
              "userId": 1,
              "id": 3,
              "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
              "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
            },
            {
              "userId": 1,
              "id": 4,
              "title": "eum et est occaecati",
              "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
            },
            {
              "userId": 1,
              "id": 5,
              "title": "nesciunt quas odio",
              "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
            },
            {
              "userId": 1,
              "id": 6,
              "title": "dolorem eum magni eos aperiam quia",
              "body": "ut aspernatur corporis harum nihil quis provident sequi\nmollitia nobis aliquid molestiae\nperspiciatis et ea nemo ab reprehenderit accusantium quas\nvoluptate dolores velit et doloremque molestiae"
            },
            {
              "userId": 1,
              "id": 7,
              "title": "magnam facilis autem",
              "body": "dolore placeat quibusdam ea quo vitae\nmagni quis enim qui quis quo nemo aut saepe\nquidem repellat excepturi ut quia\nsunt ut sequi eos ea sed quas"
            },
            {
              "userId": 1,
              "id": 8,
              "title": "dolorem dolore est ipsam",
              "body": "dignissimos aperiam dolorem qui eum\nfacilis quibusdam animi sint suscipit qui sint possimus cum\nquaerat magni maiores excepturi\nipsam ut commodi dolor voluptatum modi aut vitae"
            },
            {
              "userId": 1,
              "id": 9,
              "title": "nesciunt iure omnis dolorem tempora et accusantium",
              "body": "consectetur animi nesciunt iure dolore\nenim quia ad\nveniam autem ut quam aut nobis\net est aut quod aut provident voluptas autem voluptas"
            },
            {
              "userId": 1,
              "id": 10,
              "title": "optio molestias id quia eum",
              "body": "quo et expedita modi cum officia vel magni\ndoloribus qui repudiandae\nvero nisi sit\nquos veniam quod sed accusamus veritatis error"
            }
        ]
      }
    5. const { posts } = require('./data.js');로 posts를 호출하고 res.json()posts를 인자로 기입힌다. 그 후 실행하고 있던 터미널을 종료하고 다시 실행시켜준다.

    6. url창에 localhost:8080/api/posts를 입력한다.
      아래와 같이 나오면 우리는 JSON 데이터가 나오는 api를 작성한 것이다.

    7. next.js 프로젝트index.js로 돌아와서 getServerSideProps의 fetch에 기입했던 링크를 url창에 적었던 주소로 바꿔준다.

      • 그리고 다시 터미널에서 npm run build를 실행해서 빌드를 해준다.
      • 그러고 나서 npm start를 입력하여 production 모드로 접속을 할 준비를 해준다.

      • 바뀐 주소로도 api에 있던 내용들을 잘 불러오는 것을 볼 수 있다.


⭕ 위 과정에서 알 수 있는 SSRSSG의 차이


  1. loca1-api에서 1번의 title 내용을 바꾼 다음에 node를 다시 구동시킨다.
    그리고 실행 중인 next.js 서버에서 새로고침을 실행시킨다.

  • 위와 같이 첫 번째 줄 내용이 바뀐 것을 볼 수 있음.


  1. Next.js에서는 getStaticsideProps를 사용하는 것을 추천하는 편임
    index.js에서 getServerSideProps를 주석처리하고 아래와 같이 코드를 입력하고 npm run buildnpm start를 차례차례 실행시켜 본다.

  • 그리고 결과를 확인해본다.

  • api의 내용을 고치고 다시 구동하고 서버를 새로고침했을 때 내용 변화가 일어나지 않았다!

미리 파일 생성을 해서 접근을 바로 해서 데이터를 바로 조회하는 것이 아닌 이미 생성된 데이터를 보여주는 방식이 getStaticSideProps다.

revalidate 속성을 주어서 설정해놓은 시간이 지나면 갱신된 새로운 데이터를 regeneration시킬 수 있도록 하는 명령어 옵션을 준다.

  • 20초 뒤에 사이트가 regeneration이 된 것을 확인할 수 있다.

  • 이것이 SSG(Static Side Generation)의 작동 방식을 보여준다.

  • 페이지가 긴급하게 변화가 일어나지 않아도 된다고 하면 이 방식을 통해서 미리 html을 만들어놓고 이 html만 보여주면 상당히 빠른 렌더링과 처리 속도를 보여준다. 설정된 값을 통해서 regeneration시키면 빠른 동기화도 보여줄 수 있다.



📷 Image 태그 사용해보기


  • photos.js로 다시 돌아오기 전에 서버 종료를 하고 npm run dev로 다시 개발 서버를 열고 node.js 서버도 종료시켜준다.

  • fetch()안에 넣어주었던 url도 get방식의 url로 다시 돌려준다.

    https://jsonplaceholder.typicode.com/photos?_start=0&_end=10

    • 이번에는 props였던 posts 대신 photos를 넣어본다.

    • 이번에는 Next.js에서 제공해주는 <Image>태그를 사용해볼 것이다.

    • 다음과 같은 에러가 발생한다 왜일까?

      • 썸네일 url이 외부 url이기 때문에 접근할 때 문제가 발생하는 것이다.

      • 따라서, next.config.js에서 설정을 해주어야 한다.

      • 그 후, npm run dev 개발 모드를 다시 실행시켜준다.

      • 이미지 링크 접근은 허용되었으나 response에서 문제가 생겨서 일단 문제 해결 전까지 보류



🚝 Next.js 프로젝트 배포하기


  • 오류가 해결되지 않으므로 더 진도를 나가는 의미가 없다 이제 vercel 사이트에 next.js 프로젝트를 빌드해보려고 한다.

    • Vercel 사이트에 로그인해서 다음과 같이 들어간다.

    • 다음과 같이 로그인한 상태로 본인의 next-js 프로젝트를 github에 푸시한다.

      • 터미널에서 git init 입력

      • 본인 github에 새로운 Repository 생성

      • add → commit → remote → push 순으로 진행시킨다.

      • 위와 같이 정상적으로 push가 된 상황

    • 프로젝트 생성하는 곳으로 돌아와서 github의 프로젝트를 연결시켜주면 다음과 같은 화면이 뜬다.

    • 파란색 버튼의 Import를 눌러주고 연결을 진행하고 Deploy를 하면 프로젝트가 연결이된다.

    • 그 후, deploy가 완료되면 사이트가 제공되고 배포가 가능해진다.

      https://next-practice.vercel.app/ ← 해당 홈페이지를 통해 서비스 확인 가능


일단 이렇게 끝~ 다음에 더 공부하고 더 기록해볼 예정이다😁

휴면 상태에 있던 내 벨로그 계정 되살린 것도 덤으로

profile
배운 것은 항상 그 때 문서화하자!

0개의 댓글