Accelerated Mobile Pages (AMP)는 빠르고 빠르고 아름다우며 실적이 우수한 웹사이트와 광고를 만들 수 있는 오픈소스 이니셔티브입니다.
AMP를 처음 사용하는 경우 다음 리소스를 통해 간단한 개요를 살펴보세요.
동기
AMP는 이미지 캐러셀 및 라이트박스 같은 UI 구성요소로 풍부하고 역동적인 콘텐츠를 지원합니다. AMP는 AMP 작업을 통해 한 구성요소가 다른 구성요소에서 작업을 트리거하는 간단한 방법을 지원합니다.
하지만 원하는 경우에는 어떻게 해야 할까요?
- AMP 구성요소를 맞춤설정하시겠습니까?
- 예를 들어 이미지 캐러셀에 현재 슬라이드와 총 슬라이드 수를 표시하는 맞춤 라벨을 표시합니다.
- 스테이트풀(Stateful) 동작을 추가하시겠어요?
- 예를 들어 사용자가 선택한 제품의 수량이 현재 재고를 초과하는 경우 '장바구니에 추가' 버튼을 사용 중지합니다.
이전에는 UI 구성요소 간의 강력한 통신 채널이 없고 변경 가능한 공유 상태를 보유할 수 없었기 때문에 AMP에서 이러한 기능을 구현하기가 어려웠습니다. 이러한 사용 사례를 해결하기 위해 AMP에 강력한 새 구성요소를 구축했습니다.
<amp-bind>
<amp-bind>
는 데이터 결합 및 JS와 유사한 표현식을 통해 맞춤 상호작용을 제공하는 새로운 AMP 구성요소입니다. 이 Codelab에서는 <amp-bind>
를 사용하여 풍부한 맞춤 상호작용으로 AMP 페이지를 빌드하는 방법을 안내합니다.
빌드할 항목
이 Codelab에서는 전자상거래 제품 세부정보 페이지를 빌드합니다.
|
학습할 내용
- 데이터 결합과 표현식을 사용하여
<amp-bind>
로 멋진 대화형 AMP 페이지를 빌드하는 방법
필요한 항목
- 원하는 브라우저
- 원하는 텍스트 편집기
- Node.js 및 NPM
- 샘플 코드
- HTML, CSS, 자바스크립트에 대한 기본 지식
코드 다운로드
먼저 Codelab의 시작 코드를 ZIP 파일로 다운로드합니다.
또는 git를 통해 다음을 실행합니다.
git clone https://github.com/googlecodelabs/advanced-interactivity-in-amp.git
설치 종속 항목
필요한 경우 압축 파일을 풀고 디렉토리로 이동합니다. npm install
을 실행하여 종속 항목을 설치합니다.
cd advanced-interactivity-in-amp-codelab npm install
개발 서버 실행
다음과 같이 node.js로 개발 서버를 시작합니다.
node app.js
웹브라우저에서 http://localhost:3000으로 이동하여 실행 중인 AMP 페이지를 확인합니다.
AMP 상용구
AMP 페이지는 안정적인 성능을 제공하기 위한 몇 가지 제한사항이 있는 HTML 페이지입니다. AMP 페이지에는 Google 검색에서 AMP 페이지로 식별되는 약간의 특수 마크업이 있습니다.
기본 AMP 페이지는 다음과 같습니다.
<!doctype html>
<html amp>
<head>
<meta charset="utf-8">
<link rel="canonical" href="hello-world.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>Hello World!</body>
</html>
AMP 구성요소
시작 코드(static/index.html
)는 몇 가지 AMP 구성요소와 함께 페이지 콘텐츠 (이미지, 텍스트 등)가 포함된 기본 AMP 페이지를 기반으로 빌드됩니다.
<script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
<script async custom-element="amp-selector" src="https://cdn.ampproject.org/v0/amp-selector-0.1.js"></script>
AMP 구성요소는 AMP 페이지에 풍부한 상호작용을 더해주는 추가적인 기능과 UI 구성요소를 제공합니다. 시작 코드는 다음과 같은 AMP 구성요소를 사용합니다.
<amp-carousel>
- 제품의 여러 뷰를 표시하는 이미지 캐러셀
<amp-mustache>
- amp-form의 서버 응답을 렌더링하기 위한 템플릿 시스템
<amp-form>
- AMP 페이지에 필요한
<form>
요소의 특수 기능을 추가합니다. <amp-selector>
- 요소 그룹의 하나 이상의 요소를 선택할 수 있는 의미론적 방법을 제공합니다. amp-form의 입력 소스로 사용할 수 있습니다.
기본 상호작용
시작 코드는 몇 가지 기본적인 상호작용을 제공합니다.
- 이미지 캐러셀 (
<amp-carousel>
)은 제품의 여러 뷰를 표시합니다. - 페이지 하단에서 '장바구니에 추가' 버튼을 탭하여 제품을
<amp-form>
(장바구니를 통해)에 추가할 수 있습니다.
이미지 캐러셀을 스와이프하고 '장바구니에 추가' 버튼을 탭하세요.
환경 개선
시작 코드는 매우 기본적인 사용자 환경을 제공합니다. 몇 가지 방법을 통해 사용자 환경을 개선할 수 있습니다.
- 현재 슬라이드와 총 슬라이드 수를 표시하는 표시기를 추가합니다.
- 사용자가 다른 셔츠 색상을 선택하면 이미지 캐러셀을 변경하여 선택한 색상의 셔츠 이미지를 표시합니다.
<amp-bind>
구성요소를 도입하기 전에는 이러한 기능을 추가하는 것이 불가능했습니다. <amp-bind>
실습을 통해 새로운 기능을 샘플 코드에 추가해 보세요.
<amp-bind>
확장 프로그램 설치하기
<amp-bind>
는 데이터 결합 및 JS와 유사한 표현식을 통해 맞춤 상호작용을 제공하는 새로운 AMP 구성요소입니다. <amp-bind>
서비스를 사용하려면 페이지에 설치해야 합니다.
static/index.html
파일을 열고 페이지의 <head>
섹션에서 AMP 구성요소 목록에 다음 스크립트를 추가합니다.
<script async custom-element="amp-bind"
src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
슬라이드 표시기 추가
<amp-bind>
는 요소 속성을 맞춤 표현식에 결합하는 방식으로 작동합니다. 이러한 표현식은 'state"'(변경 가능한 JSON 데이터)를 참조할 수 있습니다. <amp-bind>
에 포함된 <amp-state>
구성요소를 통해 이 상태를 초기화할 수 있습니다.
이제 상태 변수를 초기화하여 이미지 캐러셀에 현재 표시된 슬라이드의 색인을 추적해보겠습니다. static/index.html
을 열고 페이지의 <body>
상단 (헤더 앞)에 다음을 추가합니다.
<amp-state id="selected">
<script type="application/json">
{
"slide": 0
}
</script>
</amp-state>
<amp-state>
요소 내의 데이터는 연결된 ID로 액세스할 수 있습니다. 예를 들어 이 변수를 다음 표현식 프래그먼트로 참조할 수 있습니다.
selected.slide // Evaluates to 0.
다음으로 사용자가 기존 <amp-carousel> 요소에 '작업'을 추가하여 캐러셀의 슬라이드를 변경할 때 이 변수를 업데이트합니다.
<amp-carousel type="slides" layout="fixed-height" height=250 id="carousel"
on="slideChange:AMP.setState({selected: {slide: event.index}})">
이제 <amp-carousel>
가 표시된 슬라이드가 변경될 때마다 AMP.setState
작업이 다음 인수로 호출됩니다.
{
selected: {
slide: event.index
}
}
event.index
표현식이 새 슬라이드 색인으로 평가되고 AMP.setState()
작업은 이 객체 리터럴을 현재 상태로 병합합니다. 이렇게 하면 현재 selected.slide
값이 event.index
값으로 대체됩니다.
다음으로 현재 표시된 슬라이드를 추적하는 이 상태 변수를 활용하여 슬라이드 표시기를 만들어 보겠습니다. 슬라이드 표시기 요소 (<!-- TODO: "Add a slide indicator" -->
이라고 함)를 찾아 다음 바인딩을 하위 요소에 추가합니다.
<!-- TODO: "Add a slide indicator" -->
<p class="dots">
<!-- The <span> element corresponding to the current displayed slide
will have the 'current' CSS class. -->
<span [class]="selected.slide == 0 ? 'current' : ''" class="current"></span>
<span [class]="selected.slide == 1 ? 'current' : ''"></span>
<span [class]="selected.slide == 2 ? 'current' : ''"></span>
</p>
[class]
는 class
속성을 변경하는 결합이며, 이를 사용해 모든 요소에서 CSS 클래스를 추가하거나 삭제할 수 있습니다.
이제 페이지를 새로고침해 보세요. 캐러셀의 슬라이드를 변경하면 다음과 같은 작업이 실행됩니다.
slideChange
이벤트 트리거...AMP.setState
작업을 호출하는 것은...- 상태 변수
selected.slide
를 업데이트합니다. - 그러면 표시기
<span>
요소에서[class]
결합이 업데이트됩니다.
좋아요 이제 슬라이드 표시기가 작동합니다.
<amp-carousel>
에서 이미지 변경
선택된 색상을 변경할 때 다른 셔츠 색상의 이미지가 표시되면 좋습니다. amp-bind를 사용하면 <amp-carousel>
내의 <amp-img>
요소에 [src]
를 바인딩할 수 있습니다.
그러나 먼저 각 색상 셔츠의 이미지 소스 URL로 상태 데이터를 초기화해야 합니다. 새로운 <amp-state>
요소로 그렇게 해 보겠습니다.
<!-- Available shirts. Maps unique string identifier to color and image URL string. -->
<amp-state id="shirts">
<script type="application/json">
{
"1001": {
"color": "black",
"image": "./shirts/black.jpg"
},
"1002": {
"color": "blue",
"image": "./shirts/blue.jpg"
},
"1010": {
"color": "brown",
"image": "./shirts/brown.jpg"
},
"1014": {
"color": "dark green",
"image": "./shirts/dark-green.jpg"
},
"1015": {
"color": "gray",
"image": "./shirts/gray.jpg"
},
"1016": {
"color": "light gray",
"image": "./shirts/light-gray.jpg"
},
"1021": {
"color": "navy",
"image": "./shirts/navy.jpg"
},
"1030": {
"color": "wine",
"image": "./shirts/wine.jpg"
}
}
</script>
</amp-state>
이 <amp-state>
요소에는 셔츠 식별자 문자열 (예: SKU)을 해당 셔츠의 색상 및 이미지 URL에 매핑하는 JSON 객체가 포함되어 있습니다. JSON 배열은 여기에서도 작동하지만 객체를 사용하면 다른 멋진 작업을 할 수 있습니다. 이러한 작업은 곧 제공될 예정입니다.
이제 셔츠 식별자를 통해 이미지 URL에 액세스할 수 있습니다. 예를 들어 shirts['10014'].color
는 "dark green"
로 평가되고 shirts['10030'].image
는 "wine" 셔츠 색상의 이미지 URL을 반환합니다.
선택한 SKU를 추적하는 또 다른 상태 변수를 추가하면 선택한 SKU가 변경될 때 표현식을 <amp-img>
요소에 바인딩하여 src
속성을 업데이트할 수 있습니다. 새 sku
키를 기존 amp-state#selected
요소 JSON에 추가합니다.
<amp-state id="selected">
<script type="application/json">
{
"slide": 0,
"sku": "1001"
}
</script>
</amp-state>
새로운 색상이 선택될 때마다 selected.sku
변수를 업데이트하는 <amp-selector>
에 'quot;' 작업을 추가합니다.
<amp-selector name="color"
on="select:AMP.setState({selected: {sku: event.targetOption}})">
그런 다음 <amp-carousel>
내의 <amp-img>
요소에 바인딩을 추가합니다(<!-- TODO: "Changing images in amp-carousel-->"
참고).
<!-- Update the `src` of each <amp-img> when the `selected.sku` variable changes. -->
<amp-img width=200 height=250 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
<amp-img width=300 height=375 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
<amp-img width=400 height=500 src="./shirts/black.jpg"
[src]="shirts[selected.sku].image"></amp-img>
참고: 실제로 캐러셀의 각 이미지에는 다른 src
가 있을 수 있습니다. 이는 하나의 이미지를 이미지 배열로 대체함으로써 실행할 수 있습니다. 편의를 위해 이 Codelab에서는 다양한 확대 시 단일 이미지를 사용합니다.
이제 페이지를 새로고침하고 셔츠에 다른 색상을 선택하세요. 다른 색상을 선택하면 캐러셀의 이미지가 업데이트되어 선택한 색상의 셔츠가 표시됩니다.
페이지 로드 시 바인딩할 수 있는 데이터가 가져오기에 너무 크거나 복잡한 경우 어떻게 해야 할까요? 또는 각 SKU에 찾는 데 시간이 오래 걸리는 가격이 지정된 경우에는 어떻게 할까요? 표시되지 않는 항목의 SKU 가격을 찾는 것은 헛수고입니다.
셔츠에 사용할 수 있는 사이즈 가져오는 중
Codelab 데이터를 통해 원격 데이터를 가져와 SKU 가격을 확인할 수 있는 기능을 활용해 보겠습니다. app.js
의 Express.js 개발 서버에는 이미 셔츠 SKU가 지정된 각 크기의 사이즈 및 가격을 반환하는 엔드포인트 /shirts/sizes?shirt=<sku>
이 있습니다. 네트워크 지연 시간을 시뮬레이션하기 위해 1초의 인위적인 지연이 있는 응답을 전송합니다.
요청 | 응답 |
|
|
<amp-state>
요소 내의 JSON 데이터와 마찬가지로 이러한 가져오기에서 반환된 원격 데이터는 요소의 id
속성에 병합되고 사용할 수 있습니다. 예를 들어 위의 예제 응답에서 반환되는 데이터는 다음과 같은 표현식에서 액세스할 수 있습니다.
표현식 | 결과 |
|
|
이제 전자상거래 예제에 적용해 보겠습니다. 먼저 새 SKU가 선택되면 이 셔츠 데이터를 가져오게 하겠습니다. amp-state#shirts
요소에 [src]
바인딩을 추가합니다.
<!-- When `selected.sku` changes, update the `src` attribute and fetch
JSON at the new URL. Then, merge that data under `id` ("shirts"). -->
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
다음으로, 특정 SKU의 사용 불가 크기를 명확하게 표시합니다. "unavailable"
CSS 클래스는 요소를 통해 대각선을 추가합니다. amp-selector[name="size"]
에 없는 요소 중 사용할 수 없는 크기에 추가할 수 있습니다.
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<td [class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
<div option="M">M</div>
</td>
<td [class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
<div option="L">L</div>
</td>
<td [class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
이제 페이지를 새로고침해 봅니다. 새 SKU(셔츠 색상)를 선택하면 약간의 지연 후 주문할 수 없는 사이즈에 선이 그어집니다.
여기서 사소한 문제가 생깁니다. 기본으로 선택되는 색상인 검은색 셔츠는 어떻게 해야 할까요? amp-state#shirts
에 검은색 셔츠의 사이즈와 가격 데이터를 추가해야 합니다.
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
<script type="application/json">
{
"1001": {
"color": "black",
"image": "./shirts/black.jpg",
"sizes": {
"XS": 8.99,
"S": 9.99
}
},
<!-- ... -->
관련 요소의 기본 상태도 업데이트합니다.
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<!-- Add the ‘unavailable' class to the next three <td> elements
to be consistent with the available sizes of the default SKU. -->
<td class="unavailable"
[class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
<div option="M">M</div>
</td>
<td class="unavailable"
[class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
<div option="L">L</div>
</td>
<td class="unavailable"
[class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
가변 셔츠 가격
이제 사용 가능한 크기를 올바르게 표시하므로 올바른 가격도 표시되도록 합니다.
AMPPAREL 매장은 특이하게도 색상과 사이즈에 따라 셔츠 가격이 달라집니다. 따라서 사용자가 선택한 사이즈를 추적하기 위해서는 새 변수가 필요합니다. 크기 <amp-selector>
요소에 새 작업을 추가합니다.
<!-- When an element is selected, set the `selectedSize` variable to the
value of the "option" attribute of the selected element. -->
<amp-selector name="size"
on="select:AMP.setState({selectedSize: event.targetOption})">
amp-state#selected
요소를 통해 selectedSize
의 값을 초기화하지는 않습니다. 의도적으로 기본 선택된 사이즈를 제공하지 않고 대신 사용자가 사이즈를 선택하도록 하기 때문입니다.
가격 라벨을 래핑하는 새 <span>
요소를 추가하고 기본 텍스트를 선택하지 않도록 기본 텍스트를 변경합니다.
<h6>PRICE :
<!-- Display the price of the selected shirt in the selected size if available.
Otherwise, display the placeholder text '---'. -->
<span [text]="shirts[selected.sku].sizes[selectedSize] || '---'">---</span>
</h6>
이제 올바른 가격이 표시됩니다. 직접 사용해 보세요.
조건부 사용 설정 버튼
이제 거의 다 끝나갑니다. 이제 선택한 크기를 사용할 수 없을 때 '장바구니에 추가' 버튼을 사용 중지합니다.
<!-- Disable the "ADD TO CART" button when:
1. There is no selected size, OR
2. The available sizes for the selected SKU haven't been fetched yet
-->
<input type="submit" value="ADD TO CART" disabled
class="mdl-button mdl-button--raised mdl-button--accent"
[disabled]="!selectedSize || !shirts[selected.sku].sizes[selectedSize]">
Google은 대화형 JSON 엔드포인트에서 주문형으로 가져오는 각 SKU의 크기와 가격이 다양한 양방향 전자상거래 제품 세부정보 페이지를 제공합니다.
문제가 발생하면 static/final.html
의 전체 솔루션을 확인하세요.
이 Codelab을 통해 <amp-bind>
로 대화형 AMP 페이지를 빌드할 수 있는 강력한 기능과 유연성을 갖추기를 바랍니다. 자세한 내용은 <amp-bind> 문서를 참고하세요.
의견을 보내주시기 바랍니다. 기능 요청, 제안 또는 버그 신고를 보내주세요. 실제 사용자를 대상으로 <amp-bind>
를 테스트해 보려면 원본 체험판을 신청해 보세요.
곧 <amp-bind>
를 출시하고 이 빌드로 무엇을 빌드할 수 있는지 기대하게 되었습니다.