Next/Image에 대해 얼만큼 알아?

jjyung·2022년 4월 16일
29

글을 쓰게된 계기

최근 next.js를 공부하면서 직접 구현해보며 깊이 이해한 부분이 있어 글로 남겨보고자 합니다.
아무래도 이미지를 화면에 출력하게 되는데 next.js에서는 이미지를 최적화시켜 주어 따로 처리하지 않아도 되도록 해줍니다 (이런 편리한 기능이 많기 때문에 대부분의 회사에서 next를 사용하는거겠죠?)

그렇다면 img 태그와 다른 점이 무엇인지, 그리고 어떻게 활용할 수 있을지를 알아봅시다.

next/image

next를 사용하면 img태그가 아닌 next에서 import해 온 next/image 의 Image태그를 사용하라고 알려주는데, 그 이유는 next에서는 이미지를 최적화 시켜주기 때문입니다.

그래서 이걸 왜 사용하는데?

  • Loader을 통해서 url을 커스터마이징할 수 있습니다.
  • 자동으로 Lazy Loading을 통해 이미지 최적화를 지원해주지만, pre loading을 원하는 경우 취소를 할 수 있습니다.
  • 자동 스켈레톤 UI(placeholder통해서), CLS 방지도 가능합니다.
  • 이미지 캐싱도 자동으로 해주고 expiration time 설정도 가능합니다.
  • next.config.js를 통해 지정된 곳에서만 이미지를 받아오며 악의적인 유저로부터 앱을 보호할 수 있습니다.

이렇게 장점이많은 next/image인데요, 그럼 어떤 props를 필수로 받아와야하며 optional한 props에는 어떤 것들이 있는지 알아봅시다.

필수 props

  1. src
  • 정적 import된 이미지 파일
  • 외부 url (해당 경우는 next.config.js의 domain에 추가해두어야 해당 사이트에서 이미지를 받아올때 보안에 신경쓸 수 있습니다)
  1. width, height
  • layout이 fill 또는 정적으로 import 해오는 이미지(내부 이미지 폴더)의 경우를 제외하고는 모두 필수로 지정해주어야 합니다.

옵셔널 props

  1. layout
  • 앞서 설명한것 처럼 이미지를 뷰포트 기준으로 어떤 사이즈로 출력할지 지정하게 됩니다.
  • intrinsic은 default값으로 container의 width에 fit하기 위해 축소시킵니다.
  • layout이 responsivefill 인 경우를 사용하기 위해 부모 요소에 따로 설정이 필요합니다.
    - responsive : display: block
    • fill : position:relative
  1. loader
  • URL을 커스텀할 수 있는 함수를 가질 수 있습니다. loader의 경우 src, width, quality를 props로 받아 url에 포함시킨 후 return 하게 됩니다.
  1. quality
  • 1부터 100 사이의 숫자를 지정할 수 있으며, 숫자는 높아질수록 높은 퀄리티를 뜻합니다.
  • default 는 75입니다.
  1. priority
  • next/image의 장점은 LazyLoading을 자동 지원한다는 것입니다. 하지만 Lazy Loading을 사용할 필요가 없는 경우는 priority를 true로 줌으로써 lazy loading을 취소시킬 수 있습니다.

  • 이 priority는 LCP(Largest Contentful Paint)와 관련있습니다. LCP란 사용자가 화면에 렌더링 되는 콘텐츠를 보기까지 얼마나 시간이 걸리냐를 말하는데 렌더링을 완료한 시점을 결정하는 데 사용할 수 있습니다.즉, LCP가 발생하면 응답 시간이나 리소스 로드 시간이 느리다고 판단됩니다. 그럼 언제 사용해야할까요? pre-loading이 필요한 경우, 예를 들어 KV인 경우가 가장 대표적이라고 볼 수 있습니다.

  1. placeholder
  • image가 로딩되기 이전에 상태를 지정가능하고 blur, empty중 설정 가능합니다.
  • empty(default)인 경우 그냥 빈 space를 보여주지만, blur을 설정한경우 blurDataURL 을 통해 정적/동적 이미지 지정이 가능합니다. 해당 이미지는 10px 이하의 사이즈 이미지를 추천하고 로딩이 성공적으로 되기 이전까지 보여줍니다.

스타일링 방식

  • next/image는 정말 장점이 많지만 스타일링이 아주 귀찮다는 단점이 있습니다. Styled component, emotion이 사용가능하지만 항상 원하는대로 스타일링이 반영되지 않아 많은 스트레스를 받았습니다 (저 뿐만 아니라 많은 stackoverflow에서도 저와 비슷한 고민을 가진분들이 많았습니다).

그 이유는 next/image자체에서 default로 지정된 스타일이 있는데 그것이 우선반영되다보니 제가 스타일링을 했을때 원치 않는 방향으로 흘러가는 경우가 있습니다.

해결 방법은 다음과 같습니다.

  1. Styled.component내부에 스타일링을 해주되, 제대로 반영되지 않는 스타일링의 경우 !important를 사용하여 스타일링에 우선순위를 부여합니다. 하지만 important를 사용했을 때 side effect가 발생할 수 있기때문에 유의해야 합니다. !important를 많이 사용해야하는 경우라면 다음 해결 방법을 권해드립니다.

  2. next/image를 span으로 감싼 후 부모 요소(span)에 className을 지정해줍니다. 그 후 css를 통해 스타일링을 해줄 수 있습니다.

동작 방식

제가 next/image를 사용했을때는 loader을 사용해주었고, 동작 방식은 다음과 같습니다.

  1. imageLoader에서 src, width, quality를 받아 원하는 url로 변환시켜 반환합니다. 저는 따로 quality는 옵셔널하게 받을 수 있도록하며 기본값은 75로 지정합니다.
const myLoader = ({ src, width, quality=75 }) => {
  return `https://example.com/${src}?w=${width}&q=${quality}`
}
  1. 변환된 url을 next/image태그에서 받습니다. 그리고 next/image에서는 사이즈, lazy loading 여부, 스켈레톤 UI의 여부를 지정하면 해당 이미지를 최적화한 후 화면에 보여줍니다.

느낀점

이미지를 다루면서 next의 장점을 많이 깨달았지만 동시에 css의 어려움 + next/image의 단점인 스타일링에 고민을 많이 했습니다. 다른 글에서도 nightmare이라고 표현할 정도로 next/image의 스타일링은 은근한 스트레스를 주었던 것 같습니다. 하지만 그 이외 장점이 있기 때문에 사용하는구나를 느꼈고, 컴포넌트를 만드는데 즐거움을 느꼈습니다. 빨리 개발을 더 잘하고 싶다는 욕심이 드는 하루네요.. 오늘도 즐거운 주말 보내세요!

참고 자료

  1. Web.dev
  2. next/image
profile
🏃‍♀️movin' forward, developer

1개의 댓글

comment-user-thumbnail
2023년 6월 13일

진짜 글 하나 하나 다 잘보고 갑니다. 응원합니다. 너무 멋지세요~

답글 달기