[NextJS] NextJS로 blog 만들어보기 - (1) Link, Image Tag

yongkini ·2023년 6월 22일
1

NextJS

목록 보기
1/4

동기

: react를 쓰면서 SEO 등에 대한 처리와(CSR의 한계 중에 하나인) SSR이 가진 장점 등을 좀 더 쉬운 방법으로 이용할 수 없을까? 라는 생각이 들었었다. 물론 React만을 가지고도 모듈이나 스킬을 써서 어느정도는 가능하게 만들 수 있지만, 프레임워크라는게 특정 목적을 가진 개발자에게 체계화된 구조를 제공하는 역할을 하는 것으로 그러한 역할을 하는 nextJS를 써봐야겠다는 생각이 들었다. 이에 따라 nextJS를 배울겸 간단한 blog를 만들어보고자 한다.

프로젝트 생성

yarn create next-app blog --example "https://github.com/vercel/next-learn/tree/master/basics/learn-starter"
import Link from 'next/link'

<h1 className={styles.title}>Read this Post {` `}
  <Link href="/posts/first-post">첫번째 글(Link tag)</Link>
</h1>
<h1 className={styles.title}>Read this Post {` `}
  <a href="/posts/first-post">첫번째 글(a tag)</a>
</h1>
     

둘의 차이가 궁금해서 해봤다. 결과는 A를 Link 태그 B를 a tag라고 해보겠다.
A 에서 링크를 클릭해서 이동하면

_devPagesManifest.json
first-post.js

이렇게 두개의 파일만 새로 fetching 해온다.
하지만, B에서 링크를 클릭해서 이동하면
이전에 네트워크 탭에 있던 파일들(fetching 해온 리스트)을 다시 한번 받아온다.
즉, refresh를 하고 페이지를 이동하는 형태로 동작한다.
따라서, 만약에 index.js -> first-post.js 로 이동하는 중에 persist 와 같은 state 유지 스킬을 쓰지 않는다면, 새로고침이 됐기 때문에 user state 같은게 있었다면 다 날아간 채로 페이지 이동이 됐을 것이다. 그리고 당연하게도 굳이 이미 fetching 한 파일을 다시 받으면서 페이지 이동한다는 것 자체가 의도한게 아니라면 낭비이다.
결론적으로 Link 태그는 JS를 가지고 있는 채로 추가적으로 해당 페이지에 필요한 파일을 불러오는 방식으로 동작한다(자동으로 최적화를 하고 있는 것)

이를 용어로 표현하면 Client Side Navigate 라고 한다. browser에서 url을 직접 쳐서 이동하는 것과 달리 JS 상에서 page 컴포넌트를 교체하는 개념이다.

실제로 앞서 말한 state나 css 파일들이 유지 된채로 컴포넌트만 교체되는지를 알아보기 위해
body의 css 속성으로

background-color: yellow;

를 개발자 도구의 element 탭에서 임의로 준 다음에 Link, a tag를 통해 이동해보면,
Link 태그로 이동한 경우 css 속성도 그대로 유지된 채로 가기 때문에 배경이 노란색으로 유지되는 반면 a tag로 이동한 경우 개발자 도구의 element 탭에 임의로 써놓은 css 속성은 새로고침되면서 날아간다.

결론 :

모든 데이터를 새로 받는 개념(a) vs 사용자에게 특정 페이지에서 필요한 파일만 가져오기(Link)

Code Splitting

: NextJS는 Automatic Code Splitting 을 제공한다. 리액트에서 사이즈가 큰 모듈을 쓰거나 할 때, 해당 페이지에 접근하는 경우가 아니면, 혹은 그 페이지에 접근하는 상황이 돼야 그 페이지 혹은 모듈이 속한 컴포넌트를 임포트해오는 스킬로 Suspense, React.lazy 등을 썼었는데, 그걸 nextJS는 자동으로 해준다는 것 같다.

  • 특정 페이지에 접근할 때는 해당 페이지를 그릴 때 필요한 chunk만 로드
  • 페이지 이동을 할 땐 목적지 페이지에 필요한 chunk만 추가 로드

이렇게 최적화를 한다.

Prefetching

: 프론트엔드 서버(S3에 띄워질수도 있고, 어쨌든 서버에 띄워진 그 프로젝트 파일)를 브라우저로 request 하면 오는 파일 중에 chunk.js 등의 파일이 있다. 이 때, 그 chunk 파일도 크기가 클 수 있다. 크기가 큰 이미지를 렌더링 할 때 유저가 그 이미지를 viewport 상에 스크롤을 내리던 어떤 행동을 해서 이미지를 볼 때쯤 import 하는 최적화 스킬이 있는데(리액트를 쓸 때), 그것처럼 nextJS 의 Link 태그도, viewport 상에 Link 컴포넌트가 노출 됐을 때 chunk 파일을 가져온다고 한다(자동 최적화). 정확히는 href로 연결된 페이지의 chunk를 로드한다고 한다.

실제로 테스트 해보면(이 때, dev mode로 하면 안되고, build 하고 start한 다음에 테스트 해봐야한다).

first-post-e77ded26550f4754.js

해당 링크가 viewport에 보이는 순간 위 파일을 fetching 해온다(생각보다 더 친절하잖아,,?).
유저의 화면에 이 버튼이 보이니까 누를 수 있겠다 -> 하니까 가져온 것
=> 본래는 개발자가 이걸 예상해서 최적화를 했는데, 자동으로 해준다..
순수 리액트로도 구현할 수 있는 기능이지만, 이걸 자동으로 최적화 해준다는게
프레임워크의 장점이 아닌가 싶다(nextJS의).

: Link 태그에 className을 주고 스타일을 바꿔도 적용이 안된다는 것. 따라서,

<Link>
  <a className="href">태그명</a>
</Link>

여기까지

: Link 태그가 해줄 수 있는 최적화 기능에 대해 알아봤다. 이전에 react 를 하면서 intersectionObserver 등을 써서 이미지 렌더링 최적화, font-size 최적화 등등을 직접 했었는데, 일단 이미지 쪽도 최적화를 지원하는 것 같고(images), Link 태그처럼 코드 스플리팅도 자동으로 해준다는 점에서 점점 개발자가 고민해야할 것들을 쉽게쉽게 해주는 쪽으로 나아가고 있구나 생각이든다. 근데 한편으론 예전에는 이런거 혼자 고민해서 처리하면서 나만의 뿌듯함을 느꼈는데,, 자동화라니..! 라는 생각도 든다.

public 폴더

  • 정적 리소스를 nextjs로 서빙하기 위한 디렉토리
  • 주로 static 한 자료들을 넣어놓는 폴더(react에선 여기에 images 도 넣고, index.html도 들어가고 그랬다).

Image Component

: 위에서 Link vs a 였는데, 이번엔 img vs image 이다(이런 자동 최적화 아주 칭찬해...).

<img
   className={styles.profile}
   src="/images/profile.jpg"
   alt="yongkini"
/>

실제로 해보기전에 Link 태그를 통해 기대해본점

  • viewport에 닿으면 fetching
  • Link 태그로 이동한 페이지에 해당 이미지가 바로 보인다고 했을 때 그 Link 태그가 보이면 data fetching 이되는건가 아니면 이건 또 페이지 가서 viewport에 보이면 fetching 하는걸까?

: 일단 위에처럼 일반 img 태그를 쓰면 당연하게도 해당 페이지를 가져올 때 img 파일도 바로 가져온다.

<Image
	className={styles.profile}
	src="/images/profile.jpg"
	alt="yongkini"
	width={0}
	height={0}
	sizes="100vw"
/>

이번엔 Image 태그를 써봤다.
결과는 ?
img tag : profile.jpg 라는 jpeg 형태의 이미지 파일을 페이지 로드시에 fetching 해온다(파일 크기 : 217B)
image tag : webp type으로 컨버팅돼서 페이지 로드시에 fetching 해온다(파일 크기 : 123KB)

예상한대로 자동으로 viewport 상에 보이면 import 해오는 정도의 최적화는 아니었다. 하지만, 자동으로 webp로 컨버팅하여 파일 크기를 줄여서 가져오는 최적화를 해준다..(이정도도 갓..) 다른 옵션들도 있는데, blur 처리를 해놓고 viewport 에 노출되면 제대로 파일을 가져오는 등의 옵션도 있다(사실상 내가 찾던거).
** webp : jpg보다 가벼우면서도 더 좋은 화질로 제공하는 구글쪽에서 만든 이미지 포맷

사실 webp로 바꾸는 것도 react 로 작업할 때 직접 해봤던거지만, 디자인 팀에게 부탁하지 않는 이상 직접 포매팅 해주는 사이트 들어가서 이미지 컨버팅하고, 세팅을 해줘야하는 번거로움이 있는데 이걸 자동으로 해준다는 것 자체도 좋다고 생각된다.

chrome에서 개발자 도구로 모바일 크기로 스크롤 하면서 이미지 부분에 닿는 인터랙팅을 해보니까 lazy loading도 지원하는걸 알 수 있었다.

  • Resizing(responsive 사이즈)
  • Lazy load(viewport에 들어오면 로드)
  • 그 외 optimization(webp 형태)
  • CLS(Cumulative Layout Shift) 방지 : 누적 레이아웃 이동을 막아주고자 함 => 그래서 width, height 를 주지 않아도 파일 사이즈로 예측하고 미리 준비한다고 함.

다른 옵션들은 https://nextjs.org/docs/pages/api-reference/components/image 해당 링크를 통해 학습하면서 적용해보면 될 것 같다. 사실상 nextJS의 Image 태그가 이미지 관련한 최적화를 대부분 커버한다고 생각된다.

profile
완벽함 보다는 최선의 결과를 위해 끊임없이 노력하는 개발자

0개의 댓글