NgOptimizedImage 디렉티브를 활용하면 이미지를 다루는 모범 사례를 간단하게 도입할 수 있습니다.
이 디렉티브는 아래 작업을 통해 가장 큰 컨텐츠 페인트(Largest Contentful Paint, LCP) 성능을 끌어올립니다:
<img>태그에fetchpriority어트리뷰트를 자동으로 설정합니다.- 기본적으로 이미지는 지연 로딩합니다.
- document 헤더에 사전 연결 링크 태그를 자동으로 생성합니다.
srcset어트리뷰트를 자동으로 생성합니다.- SSR이 적용된 앱이라면 사전 로딩 힌트를 생성합니다.
NgOptimizedImage는 LCP 이미지 로딩을 최적화하는 것 외에도, 이미지를 다루는 모범 사례를 제공합니다:
- 이미지 최적화를 위해 이미지 CDN URL을 사용합니다.
width와height를 강제해서 레이아웃 변경을 방지합니다.width값이나height값이 잘못되면 경고를 표시합니다.- 이미지를 렌더링할 때 왜곡이 발생할 것 같으면 경고를 표시합니다.
CSS 파일로 배경 이미지를 지정하고 있다면 여기부터 참고하세요.
참고: NgOptimizedImage 디렉티브는 Angular 15 버전부터 정식으로 도입되었지만, 하위 버전에도 백포팅되어 Angular 13.4.0이나 14.3.0에서도 사용할 수 있습니다.
시작하기
-
NgOptimizedImage디렉티브 불러오기@angular/common패키지에서NgOptimizedImage디렉티브를 불러옵니다:import {NgOptimizedImage} from '@angular/common';그리고 독립 컴포넌트나 NgModule의
imports배열에 추가합니다:imports: [ NgOptimizedImage, // ... ], -
(선택) 로더 설정하기
NgOptimizedImage를 활용할 때 이미지 로더를 정하는 것이 필수 는 아니지만, 성능 향상을 위해서라면 이미지 엘리먼트에
srcset을 설정하고 이미지 CDN을 활용하는 것이 좋습니다.이미지 로더를 어떻게 설정하는지 간단하게 알아보려면 이미지 로더 설정하기 섹션을 참고하세요.
-
디렉티브 활성화하기
NgOptimizedImage디렉티브를 활성화하기 위해, 이미지 엘리먼트의src어트리뷰트를ngSrc로 변경합니다.<img ngSrc="cat.jpg" />내장 서드 파티 로더를 사용하고 있다면,
src를 지정할 때 베이스 URL 경로는 제외하세요. 베이스 주소는 이미지 로더가 직접 적용합니다. -
이미지에
priority설정하기화면에서 LCP 이미지는
priority를 설정해서 로딩 우선순위를 높이세요.<img ngSrc="cat.jpg" width="400" height="200" priority />이미지 엘리먼트에
priority를 적용하면 이런 최적화가 수행됩니다:fetchpriority=high가 설정됩니다. 사용할 수 있는 옵션은 여기를 참고하세요.loading=eager가 설정됩니다. 기본 지연 로딩은 여기를 참고하세요.- 서버에서 렌더링하는 경우라면 사전로드 링크 엘리먼트를 자동으로 생성합니다.
LCP 엘리먼트에
priority어트리뷰트가 설정되어 있지 않으면 Angular는 경고를 표시합니다. 화면에 표시되는 LCP 엘리먼트는 사용자 화면 해상도 등 여러 가지 요인에 따라 다르게 표시될 수 있기 때문에,priority를 이미지 여러 개에 지정해야 할 수도 있습니다. 자세한 내용은 웹 바이탈을 위한 CSS를 참고하세요. -
너비, 높이 지정하기
이미지 때문에 레이아웃이 변경되는 것을 방지하기 위해, NgOptimizedImage는 이미지의 너비와 높이 입력을 강제합니다:
<img ngSrc="cat.jpg" width="400" height="200" />뷰포트 크기에 따라 크기가 변경되거나 화면에서 없어지는 반응형 이미지(responsive images) 를 사용한다면,
width값과height값은 이미지 파일의 원래 크기로 지정하세요. 반응형 이미지는sizes값을 설정하는 것도 중요합니다.고정 크기 이미지(fixed size images) 는 화면에 표시하려는
width값과height값을 지정하면 됩니다. 화면에 표시되는 가로-세로 비율은 이미지 자체의 가로-세로 비율과 같아야 합니다.참고: 이미지의 크기를 정확하게 알지 못한다면, 부모 컨테이너를 채우는 "fill 모드" 사용을 고려해 보세요.
fill 모드 사용하기
이미지를 엘리먼트에 가득 채우고 싶다면 fill 어트리뷰트를 사용하면 됩니다.
이 방식은 이미지를 배경 이미지처럼 지정하려고 할 때 유용합니다.
그리고 이미지 자체의 너비와 높이는 모르지만, 부모 컨테이너의 크기를 알고 있을 때에도 활용할 수 있습니다.
이미지에 fill 어트리뷰트를 지정하면 width나 height를 지정할 수 없습니다.
예제 코드를 봅시다:
<img ngSrc="cat.jpg" fill />
이미지를 컨테이너 가득 채울 때는 object-fit CSS 프로퍼티를 사용할 수도 있습니다.
object-fit: "contain" 라고 지정하면 이미지는 비율을 유지한 채로 엘리먼트 범위를 넘지 않는 정도로 엘리먼트를 채웁니다.
그리고 object-fit: "cover" 라고 지정하면 이미지는 비율을 유지한 채로 레터박스가 없게 엘리먼트를 채웁니다.
엘리먼트 크기를 넘는 부분은 잘려 보일 수 있습니다.
어떻게 다른지 직접 확인해보려면 MDN object-fit 문서를 참고하세요.
이렇게 이미지를 채우는 경우 object-position 프로퍼티를 지정해서 이미지가 표시되는 위치를 지정할 수 있습니다.
중요: 이미지에 fill 어트리뷰트를 적용할 때는, 부모 엘리먼트에 position: "relative", position: "fixed", position: "absolute" 중에 하나가 반드시 설정되어야 합니다.
배경 이미지 마이그레이션하기
background-image를 NgOptimizedImage로 마이그레이션하는 과정을 간단하게 살펴봅시다.
다음 단계에서 이미지 배경이 들어가는 엘리먼트를 "컨테이너 엘리먼트"라고 하겠습니다:
- 컨테이너 엘리먼트에서
background-image스타일을 제거합니다. - 컨테이너 엘리먼트에
position: "relative",position: "fixed",position: "absolute"중에 하나가 지정되어 있는지 확인하세요. - 컨테이너 엘리먼트의 자식으로 이미지 엘리먼트를 선언하고
ngSrc어트리뷰트를 붙여서NgOptimizedImage디렉티브를 연결합니다. - 이미지 엘리먼트에
fill어트리뷰트를 지정합니다.height나width는 지정하지 마세요. - 이 이미지가 LCP 엘리먼트라면, 이미지 엘리먼트에
priority어트리뷰트를 지정합니다.
배경 이미지가 컨테이너를 어떻게 채울지 지정하려면 fill 모드 사용하기 섹션을 참고하세요.
플레이스홀더(placeholder) 사용하기
자동 플레이스홀더
이미지 크기를 자동으로 제공하는 CDN이나 이미지 호스팅 서비스를 사용한다면 NgOptimizedImage로 저해상도 플레이스 홀더를 자동으로 표시할 수 있습니다.
이미지 엘리먼트에 placeholder 어트리뷰트만 추가하면 됩니다:
<img ngSrc="cat.jpg" width="400" height="200" placeholder />
이 어트리뷰트를 추가하면 NgOptimizedImage 디렉티브는 지정된 이미지 로더를 사용해서 저해상도 플레이스홀더를 자동으로 요청합니다.
이렇게 불러오는 이미지는 CSS 블러(blur) 효과가 적용된 background-image 스타일로 실제 이미지가 로드될 때까지 사용됩니다.
이미지 로더가 지정되지 않으면, 플레이스홀더를 불러올 수 없기 때문에 오류가 발생합니다.
플레이스홀더의 기본 너비는 30px 입니다.
이 기본 크기는 IMAGE_CONFIG 프로바이더를 사용해서 변경할 수 있습니다:
providers: [
{
provide: IMAGE_CONFIG,
useValue: {
placeholderResolution: 40
}
},
],
플레이스홀더 주변이 흐릿하게 표시되는 것을 방지하려면, 컨테이너 엘리먼트 <div>에 overflow: hidden 스타일을 지정하면 됩니다.
width: fit-content 스타일을 지정해서 이미지와 <div> 엘리먼트의 크기가 동일한 경우에는, 플레이스홀더의 흐릿한 가장자리가 표시되지 않습니다.
데이터 URL 플레이스홀더
플레이스홀더에는 이미지 로더 대신 base64 데이터 URL을 사용할 수도 있습니다.
이 데이터 url은 data:image/[imagetype];[data] 형식이며, [imagetype] 자리에는 이미지의 형식이 들어가는데, png와 같이 들어갑니다.
그리고 [data] 자리에는 base64로 인코딩된 이미지가 들어갑니다.
이미지 인코딩은 커맨드라인이나 JavaScript로도 실행할 수 있습니다.
자세한 내용은 MDN 문서를 참고하세요.
데이터 URL은 아래와 같이 사용하면 됩니다:
<img ngSrc="cat.jpg" width="400" height="200" placeholder="data:image/png;base64,iVBORw0K..." />
그런데, 데이터 URL의 크기가 커지면 Angular 빌드 결과물의 크기가 함께 커지기 때문에 페이지 로딩이 느려질 수 있습니다. 이미지 로더를 사용하지 못하는 경우에는 base64 플레이스홀더 이미지를 권장하지만, 이 크기는 최대 4KB를 넘지 않을 것을 권장합니다. 플레이스홀더의 크기를 줄일 수 없다면 이미지의 형식이나 변수를 조정해서 이미지의 크기를 줄이는 것도 고려할 만합니다. 해상도가 낮은 이미지라면 이런 변수 조정이 파일 크기에 큰 영향을 미칠 수 있습니다.
흐리게 처리되지 않는 플레이스홀더
기본적으로 NgOptimizedImage는 이미지 플레이스 홀더에 CSS 블러 효과를 적용합니다.
플레이스홀더에 흐림 효과를 적용하지 않으려면 placeholderConfig 인자를 사용해서 blur 프로퍼티 값을 false로 지정하면 됩니다:
<img ngSrc="cat.jpg" width="400" height="200" placeholder [placeholderConfig]="{blur: false}" />
이미지 스타일 조정하기
이미지 엘리먼트에 width, height 어트리뷰트를 추가하면 이미지가 다르게 렌더링될 수 있습니다.
이런 경우 이미지 비율이 왜곡되면 NgOptimizedImage가 경고를 표시합니다.
일반적으로는 height: auto, width: auto를 사용하면 이 문제를 방지할 수 있습니다.
자세한 내용은 web.dev의 <img> 태그 문서를 참고하세요.
width, height 어트리뷰트 때문에 이미지를 원하는 대로 조정할 수 없다면, 이미지 엘리먼트에 fill 모드를 적용하고 부모 엘리먼트 스타일 조정을 고려해 보세요.
성능 향상
NgOptimizedImage는 앱 성능 향상을 위한 기능도 다양하게 제공합니다. 어떤 기능을 제공하는지 알아봅시다.
리소스 힌트 추가
LCP 이미지를 최대한 빠르게 로드하려면 preconnect 리소스 힌트를 사용하면 됩니다.
사전 연결 링크는 로더에 인자로 전달되는 도메인에 대해 자동으로 생성됩니다.
이미지의 출처를 자동으로 감지할 수 없는 경우에는, LCP 이미지라고 해도 사전 연결 링크가 생성되지 않으며, 개발 서버에서는 NgOptimizedImage가 경고를 표시합니다.
이런 경우는 index.html에 리소스 힌트를 직접 추가하면 됩니다.
아래 예제 코드와 같이 도큐먼트의 <head>에 link 태그를 추가하고 rel="preconnect"를 지정하면 됩니다:
<link rel="preconnect" href="https://my.cdn.origin" />
사전 연결 경고를 무시하려면 PRECONNECT_CHECK_BLOCKLIST 토큰을 의존성으로 주입하면 됩니다:
providers: [
{provide: PRECONNECT_CHECK_BLOCKLIST, useValue: 'https://your-domain.com'}
],
자동으로 생성되는 사전 연결 힌트에 대해 알아보려면 이 섹션을 참고하세요.
이미지를 원하는 사이즈로 요청하기: srcset
srcset 어트리뷰트를 지정하면 사용자의 뷰포트에 맞는 이미지를 적절하게 로드할 수 있기 때문에, 불필요하게 큰 이미지를 다운로드하지 않아도 됩니다.
NgOptimizedImage는 sizes 어트리뷰트 값에 따라 srcset을 자동으로 생성합니다.
크기가 고정된 이미지
이미지의 크기가 사용자 기기에 관계없이 동일하고 픽셀 해상도만 다르다면, sizes 어트리뷰트를 설정할 필요가 없습니다.
이 경우에는 이미지의 너비와 높이에 따라 srcset이 자동으로 생성됩니다:
<img ... srcset="image-400w.jpg 1x, image-800w.jpg 2x" />
반응형 이미지
뷰포트 크기에 따라 이미지가 작아지거나 커지는 경우라면, sizes 어트리뷰트를 지정해서 srcset을 생성해야 합니다.
sizes를 사용해본 적이 없다면, 뷰포트를 기준으로 설정하는 것이 좋습니다.
CSS에서 이미지가 뷰포트 100%를 채우는 경우에는, sizes를 100vw로 설정하면 브라우저가 픽셀 해상도를 고려하여 적절한 크기의 srcset 이미지를 선택합니다.
그리고 사이드바와 같이 화면의 최대 반 정도를 채우는 이미지라면 sizes를 50vw로 설정하면 브라우저가 더 작은 이미지를 선택해서 로드합니다.
여기까지 읽고 더 원하는 내용이 있다면, sizes 고급 활용 섹션을 참고하세요.
NgOptimizedImage는 지연 로딩되는 이미지의 sizes 값 앞에 "auto"를 자동으로 추가합니다.
이 경우 브라우저가 sizes="auto"를 지원한다면 srcset에 맞게 적절한 이미지를 로드할 수 있으며, sizes="auto"를 지원하지 않는 브라우저에서는 무시됩니다.
priority 이미지처럼 지연 로딩되지 않는 이미지는 지정한 sizes 값을 그대로 유지합니다.
기본적으로 반응형 레이아웃의 기준점은 다음과 같이 나눕니다:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
이 기준점을 변경하려면 IMAGE_CONFIG 프로바이더를 지정하면 됩니다:
providers: [
{
provide: IMAGE_CONFIG,
useValue: {
breakpoints: [16, 48, 96, 128, 384, 640, 750, 828, 1080, 1200, 1920]
}
},
],
만약 srcset 어트리뷰트를 수동으로 지정하려면 ngSrcset 어트리뷰트를 지정하면 됩니다:
<img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w" />
ngSrcset 어트리뷰트가 존재하면 NgOptimizedImage는 이 어트리뷰트에 지정된 크기를 기준으로 srcset 어트리뷰트를 설정합니다.
이때 ngSrcset에 이미지 파일 이름을 포함하지 마세요.
이 정보는 디렉티브가 ngSrc를 활용해서 추론합니다.
NgOptimizedImage 디렉티브는 100w와 같은 너비 설명자와, 1x와 같은 밀도 설명자를 모두 지원합니다.
<img ngSrc="hero.jpg" ngSrcset="100w, 200w, 300w" sizes="50vw" />
srcset 자동 생성 비활성화
srcset 자동 생성을 비활성화하려면 이미지 엘리먼트에 disableOptimizedSrcset 어트리뷰트를 추가하면 됩니다:
<img ngSrc="about.jpg" disableOptimizedSrcset />
이미지 지연로딩 비활성화
NgOptimizedImage는 priority가 지정되지 않은 모든 이미지 파일에 loading=lazy를 지정합니다.
그런데 이미지들의 우선순위가 따로 없다면 이 기능을 비활성화할 수 있습니다.
loading 어트리뷰트에 eager, auto, lazy를 활용하면 됩니다.
자세한 내용은 표준 이미지 loading 어트리뷰트에 대한 문서를 참고하세요.
<img ngSrc="cat.jpg" width="400" height="200" loading="eager" />
이미지 디코딩 지정
NgOptimizedImage는 모든 이미지에 decoding="auto"를 지정합니다.
이 동작은 브라우저가 이미지 파일을 로드한 후에 디코딩하는 방식을 지정하기 위한 것입니다.
만약 이미지 파일에 priority가 지정되어 있다면, Angular는 해당 이미지 엘리먼트에 decoding="sync"를 지정해서 최대 컨텐츠 페인트(Largest Contentful Paint, LCP)가 최대한 빨리 표시될 수 있도록 합니다.
priority가 지정되지 않은 이미지는 decoding 어트리뷰트를 직접 지정해서 기본값인 auto를 변경할 수 있습니다.
priority 이미지는 항상 decoding="sync"를 사용합니다.
자세한 내용은 표준 이미지 decoding 어트리뷰트 문서를 참고하세요.
<!-- 기본값: 디코딩 방식은 'auto' 입니다. -->
<img ngSrc="gallery/landscape.jpg" width="1200" height="800" />
<!-- 메인 스레드 블로킹을 방지하기 위해 이미지 디코딩을 비동기로 수행합니다. -->
<img ngSrc="gallery/preview.jpg" width="600" height="400" decoding="async" />
<!-- 우선순위가 높은 이미지는 decoding="sync"가 지정됩니다. -->
<img ngSrc="awesome.jpg" width="500" height="625" priority />
<!-- decoding="sync"를 지정하면 메인 스레드를 잠시 막더라도 즉시 디코딩합니다. -->
<img ngSrc="hero.jpg" width="1600" height="900" decoding="sync" />
사용할 수 있는 값
auto(기본값): 브라우저가 최적의 방식을 선택하도록 맡깁니다.async: 이미지를 비동기로 디코딩합니다. 메인 스레드 중단을 피할 수 있습니다.sync: 이미지를 즉시 디코딩합니다. 렌더링이 잠시 멈출 수 있지만 이미지는 즉시 표시됩니다.
sizes 고급 활용
다양한 화면 크기에 따라 이미지를 다양한 크기로 표시해야 하는 경우가 있습니다.
모바일 장치에서는 그리드나 칼럼 기반 레이아웃에서 한 칸으로 표시하던 것을, 화면이 더 큰 장치에서는 두 칸으로 표시하는 경우가 일반적인 경우일 것입니다.
이런 경우는 다음과 같이 "미디어 쿼리" 문법을 사용해서 sizes 어트리뷰트를 지정하면 됩니다:
<img ngSrc="cat.jpg" width="400" height="200" sizes="(max-width: 768px) 100vw, 50vw" />
이렇게 작성하면, "화면 크기가 768px보다 작으면 이미지는 100% 너비로 표시하고, 화면 크기가 768px보다 크다면 화면 전체 너비의 50%로 표시한다"는 것을 의미합니다.
sizes 어트리뷰트에 대해 자세하게 알아보려면 web.dev나 mdn 문서를 참고하세요.
NgOptimizedImage용 이미지 로더 설정하기
로더(loader)는 이미지 파일을 이미지 URL로 변환하는 함수를 의미합니다.
NgOptimizedImage는 이미지의 크기, 형식, 이미지 품질을 지정합니다.
NgOptimizedImage는 변환을 수행하지 않는 제네릭 로더를 제공하며, 서드 파티 이미지 로더도 제공하고, 사용자 지정 로더를 직접 지정할 수도 있습니다.
| 로더 타입 | 동작 |
|---|---|
| 제네릭 로더 | 제네릭 로더를 통해 변환되는 URL은 언제나 src에 지정된 것과 같습니다. 다르게 표현하면, 이 로더는 URL 변환을 수행하지 않습니다. Angular를 사용해서 이미지를 제공하는 웹사이트에서 주로 사용합니다. |
| 서드 파티 이미지 로더 | 서드 파티 이미지 서비스에서 지정하는 대로 URL을 변환합니다. |
| 커스텀 로더 | 개발자가 원하는 대로 URL을 변환합니다. NgOptimizedImage에서 제공하는 기능 외에 다른 기능이 필요한 경우에 사용합니다. |
Angular 애플리케이션과 함께 사용되는 이미지 서비스들은 NgOptimizedImage가 사전에 로더를 준비해서 제공합니다:
| 이미지 서비스 | Angular API | 문서 |
|---|---|---|
| Cloudflare Image Resizing | provideCloudflareLoader |
문서 |
| Cloudinary | provideCloudinaryLoader |
문서 |
| ImageKit | provideImageKitLoader |
문서 |
| Imgix | provideImgixLoader |
문서 |
| Netlify | provideNetlifyLoader |
문서 |
제네릭 로더 를 사용한다면 코드를 변경할 필요가 없습니다. 기본 설정은 제네릭 로더입니다.
내장 로더
서드 파티 이미지 서비스 용 로더를 사용하려면 프로바이더 팩토리를 providers 배열에 추가하면 됩니다.
예를 들어 Imgix 로더를 사용하는 경우는 이렇습니다:
providers: [
provideImgixLoader('https://my.base.url/'),
],
이때 이미지 파일들이 존재하는 기본 URL이 프로바이더 팩토리에 인자로 전달되어야 합니다. 보통은 다음과 같은 패턴입니다:
정확한 기본 URL 구조는 CDN 프로바이더 안내를 참고하세요.
커스텀 로더
커스텀 로더 를 사용하려면 IMAGE_LOADER DI 토큰에 로더 함수를 등록하면 됩니다.
아래 예제 코드는 URL 인자로 전달되는 src, width, height에 https://example.com을 붙이는 커스텀 로더 함수입니다.
providers: [
{
provide: IMAGE_LOADER,
useValue: (config: ImageLoaderConfig) => {
return `https://example.com/images?src=${config.src}&width=${config.width}&height=${config.height}`;
},
},
],
NgOptimizedImage 디렉티브용 로더 함수는 @angular/common 패키지로 제공되는 ImageLoaderConfig 타입을 인자로 받고 이미지 리소스의 절대 주소를 반환합니다.
그리고 ImageLoaderConfig 객체에는 src 프로퍼티가 존재하며, width, height, loaderParams 프로퍼티는 옵션 인자입니다.
참고: width 프로퍼티가 항상 존재하는 것은 아니지만, 커스텀 로더는 ngSrcset이 제대로 작동할 수 있도록 다양한 너비용 이미지를 로드하기 위해 해당 기능을 지원해야 합니다.
loaderParams 프로퍼티
NgOptimizedImage 디렉티브가 지원하는 loaderParams 추가 어트리뷰트가 있는데, 이 어트리뷰트는 커스텀 로더에서 주로 사용됩니다.
loaderParams 어트리뷰트는 객체를 인자로 받는데, 객체의 형식은 제한되지 않습니다.
loaderParams 안에 있는 데이터는 ImageLoaderConfig 객체에 추가되어 커스텀 로더로 전달되어, 커스텀 로더 로직으로 활용됩니다.
보통은 CDN 기능을 활용할 때 사용합니다.
내장 로더로 transform 프로퍼티 활용하기
내장 로더는 Cloudinary, Cloudflare, ImageKit, Imgix를 지원하며, loaderParams로 transform 프로퍼티를 지정할 수 있습니다.
이 프로퍼티를 사용하면 CDN을 통해 이미지를 변환할 수 있습니다.
transform 프로퍼티에는 두 가지 형식을 사용할 수 있습니다:
문자열 형식
쉼표로 구분하는 문자열 형식을 사용할 수 있습니다:
<img
ngSrc="my-image.jpg"
width="400"
height="300"
[loaderParams]="{transform: 'e_grayscale,r_10'}"
/>
객체 형식
키-값 쌍으로 객체 형식을 사용할 수 있습니다:
<img
ngSrc="my-image.jpg"
width="400"
height="300"
[loaderParams]="{transform: {e: 'grayscale', r: 10}}"
/>
참고: transform 프로퍼티는 Netlify 로더를 지원하지 않기 때문에, Netlify CDN에는 변환 인자를 전달할 수 없습니다.
커스텀 로더 예제
아래 코드는 커스텀 로더 함수입니다.
이 함수는 src와 width, height 를 조합하면서 가장자리 곡선 처리를 위해 loaderParams 인자를 활용합니다:
const myCustomLoader = (config: ImageLoaderConfig) => {
let url = `https://example.com/images/${config.src}?`;
let queryParams = [];
if (config.width) {
queryParams.push(`w=${config.width}`);
}
if (config.height) {
queryParams.push(`h=${config.height}`);
}
if (config.loaderParams?.roundedCorners) {
queryParams.push('mask=corners&corner-radius=5');
}
return url + queryParams.join('&');
};
위에서 다룬 코드처럼 roundedCorners 프로퍼티는 커스텀 로더의 기능을 확장하는 용도로 활용됩니다.
다음과 같이 사용하면 됩니다:
<img ngSrc="profile.jpg" width="300" height="300" [loaderParams]="{roundedCorners: true}" />
자주 묻는 질문
NgOptimizedImage는 background-image CSS 프로퍼티를 지원하나요?
NgOptimizedImage는 background-image CSS 프로퍼티를 직접 지원하지 않지만, 다른 엘리먼트의 배경으로 이미지를 지정하는 경우는 쉽게 처리할 수 있습니다.
background-image를 NgOptimizedImage로 단계별 마이그레이션하려면 배경 이미지 마이그레이션하기 섹션을 참고하세요.
왜 NgOptimizedImage에 src를 사용할 수 없나요?
ngSrc 어트리뷰트는 브라우저에서 이미지가 효율적으로 로드되는 기능을 제공하기 위해 NgOptimizedImage의 트리거로 선택되었습니다.
NgOptimizedImage는 loading 어트리뷰트를 프로그램으로 변경하는데, 브라우저가 이런 변경사항을 반영하기 전에 src 속성을 발견하면 이미지 파일을 즉시 다운로드하기 시작하고 loading 어트리뷰트 변경은 무시됩니다.
이미지 도메인에 사전 연결 엘리먼트가 연결되지 않는 이유는 무엇일까요?
사전 연결 생성은 애플리케이션의 정적 분석을 기반으로 수행됩니다. 이 말은, 이미지 도메인이 로더의 인자에 다음과 같이 지정되어야 한다는 것을 의미합니다:
providers: [
provideImgixLoader('https://my.base.url/'),
],
도메인 문자열을 변수로 로더에 전달하거나 이미지 로더를 사용하지 않으면, 정적 분석기가 이미지의 도메인을 판단할 수 없게 되고 사전 연결 링크는 생성되지 않습니다. 이런 경우는 도큐먼트 헤드에 리소스 힌트를 직접 추가하면 됩니다.
한 화면에서 이미지 도메인을 2개 사용할 수 있나요?
이미지 로더 프로바이더 패턴은 컴포넌트에서 단일 이미지 CDN 활용을 최적화하기 위해 도입되었습니다. 하지만 프로바이더가 하나라도 이미지 CDN을 여러 개 활용하는 것도 가능합니다.
이런 경우라면, 커스텀 이미지 로더를 정의하고 loaderParams 프로퍼티를 전달받아 원하는 이미지 CDN을 선택하는 방식으로 구현하면 됩니다.
제가 자주 사용하는 CDN용 로더를 추가해 줄 수 있나요?
유지보수상의 이유로 Angular 저장소에 내장 로더를 추가할 계획은 현재 없습니다. 대신 추가 이미지 로더를 서드파티 패키지로 배포하는 것을 권장합니다.
<picture> 태그를 사용할 수 있나요?
아니요, 하지만 로드맵에 포함되어 있으니 조금만 기다려 주세요.
이 기능을 기다리고 있다면 Github 이슈에 투표해 주세요.
Chrome 개발자도구에서 LCP 이미지를 어떻게 찾을 수 있나요?
Chrome 개발자도구에서 Performance 탭으로 이동한 후에 왼쪽 위에 있는 "start profiling and reload page" 버튼을 클릭하세요. 새로고침 아이콘과 비슷하게 생겼습니다.
버튼을 클릭하면 Angular 애플리케이션의 프로파일링 스냅샷을 분석합니다.
프로파일링 결과가 나오면 타이밍 섹션에서 "LCP"를 선택합니다.
아래쪽 패널에서 요약 정보를 확인할 수 있습니다. "related node"라고 표시된 엘리먼트가 LCP 엘리먼트입니다. 이 엘리먼트를 클릭하면 실제 어떤 엘리먼트인지 Elements 패널로 이동하면서 확인할 수 있습니다.
참고: 이 방식은 테스트 중인 뷰포트에서 LCP 엘리먼트를 찾는 방법일 뿐입니다. 작은 화면의 장치에서 LCP를 확인하려면 모바일 장비 에뮬레이션 사용을 권장합니다.