이 단계에서 학습할 내용은 다음과 같습니다.
- 앱 외부에서 리소스를 로드하고 XHR 및 ObjectURL을 통해 DOM에 추가하는 방법
이 단계를 완료하는 데 걸리는 예상 시간: 20분
이 단계에서 완료할 작업을 미리 보려면 이 페이지 하단으로 이동 ↓합니다.
CSP가 외부 리소스 사용에 미치는 영향
Chrome 앱 플랫폼은 앱이 콘텐츠 보안 정책 (CSP)을 완벽히 준수하도록 강제합니다. Chrome 앱 패키지 외부에서 이미지, 글꼴, CSS와 같은 DOM 리소스를 직접 로드할 수는 없습니다.
앱에 외부 이미지를 표시하려면 XMLHttpRequest를 통해 요청하고 Blob으로 변환한 후 ObjectURL을 만들어야 합니다. 이 ObjectURL
는 앱의 컨텍스트에서 메모리 내 항목을 참조하므로 DOM에 추가할 수 있습니다.
할 일 항목의 썸네일 이미지 표시
할 일 항목에서 이미지 URL을 찾도록 앱을 변경해 보겠습니다. URL이 이미지처럼 보이는 경우 (예: .png, .jpg, .svg, .gif로 끝남) 위에 설명된 절차를 적용하여 URL 옆에 이미지 썸네일을 표시합니다.
권한 업데이트
Chrome 앱에서는 매니페스트에 도메인을 지정하는 한, 어떤 URL로든 XMLHttpRequest를 호출할 수 있습니다. 사용자가 입력할 이미지 URL을 미리 알 수 없으므로 "<all_urls>"
에 요청할 권한을 요청합니다.
manifest.json에서 '
"permissions": ["storage", "alarms", "notifications",
"webview", "<all_urls>"],
ObjectURL 만들기 및 삭제
controller.js에서 _createObjectURL()
메서드를 추가하여 Blob에서 ObjectURL을 만듭니다.
Controller.prototype._createObjectURL = function(blob) {
var objURL = URL.createObjectURL(blob);
this.objectURLs = this.objectURLs || [];
this.objectURLs.push(objURL);
return objURL;
};
ObjectURL은 메모리를 보유하므로 ObjectURL이 더 이상 필요하지 않으면 취소해야 합니다. 이를 처리하려면 이 _clearObjectURL()
메서드를 controller.js에 추가합니다.
Controller.prototype._clearObjectURL = function() {
if (this.objectURLs) {
this.objectURLs.forEach(function(objURL) {
URL.revokeObjectURL(objURL);
});
this.objectURLs = null;
}
};
XHR 요청
_requestRemoteImageAndAppend()
메서드를 추가하여 지정된 이미지 URL에서 XMLHttpRequest를 실행합니다.
Controller.prototype._requestRemoteImageAndAppend = function(imageUrl, element) {
var xhr = new XMLHttpRequest();
xhr.open('GET', imageUrl);
xhr.responseType = 'blob';
xhr.onload = function() {
var img = document.createElement('img');
img.setAttribute('data-src', imageUrl);
img.className = 'icon';
var objURL = this._createObjectURL(xhr.response);
img.setAttribute('src', objURL);
element.appendChild(img);
}.bind(this);
xhr.send();
};
XHR 로드 시 이 메서드는 XHR의 응답에서 ObjectURL
를 만들고 이 ObjectURL
를 사용하여 <img>
요소를 DOM에 추가합니다.
할 일 항목에서 이미지 URL 파싱
이제 아직 처리되지 않은 모든 링크를 찾아 이미지를 확인하는 _parseForImageURLs()
메서드를 추가합니다. 이미지처럼 보이는 각 URL에 대해 _requestRemoteImageAndAppend()
를 실행합니다.
Controller.prototype._parseForImageURLs = function () {
// remove old blobs to avoid memory leak:
this._clearObjectURL();
var links = this.$todoList.querySelectorAll('a[data-src]:not(.thumbnail)');
var re = /\.(png|jpg|jpeg|svg|gif)$/;
for (var i = 0; i<links.length; i++) {
var url = links[i].getAttribute('data-src');
if (re.test(url)) {
links[i].classList.add('thumbnail');
this._requestRemoteImageAndAppend(url, links[i]);
}
}
};
할 일 목록에서 썸네일 렌더링
이제 showAll()
, showActive()
, showCompleted()
에서 _parseForImageURLs()
를 호출합니다.
/**
* An event to fire on load. Will get all items and display them in the
* todo-list
*/
Controller.prototype.showAll = function () {
this.model.read(function (data) {
this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
this._parseForImageURLs();
}.bind(this));
};
/**
* Renders all active tasks
*/
Controller.prototype.showActive = function () {
this.model.read({ completed: 0 }, function (data) {
this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
this._parseForImageURLs();
}.bind(this));
};
/**
* Renders all completed tasks
*/
Controller.prototype.showCompleted = function () {
this.model.read({ completed: 1 }, function (data) {
this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
this._parseForImageURLs();
}.bind(this));
};
editItem()
에서도 동일한 작업을 실행합니다.
Controller.prototype.editItem = function (id, label) {
...
var onSaveHandler = function () {
...
if (value.length && !discarding) {
...
label.innerHTML = this._parseForURLs(value);
this._parseForImageURLs();
} else if (value.length === 0) {
...
}
표시되는 이미지 크기 제한
마지막으로 _bowercomponents/todomvc-common/base.css에 CSS 규칙을 추가하여 이미지 크기를 제한합니다.
.thumbnail img[data-src] {
max-width: 100px;
max-height: 28px;
}
완성된 Todo 앱을 실행합니다.
5단계를 완료했습니다. 앱을 새로고침하고 온라인으로 호스팅되는 이미지의 URL과 함께 할 일 항목을 추가합니다. 사용할 수 있는 일부 URL: http://goo.gl/nqHMF#.jpg 또는 http://goo.gl/HPBGR#.png
추가 정보
이 단계에서 도입된 일부 API에 관한 자세한 내용은 다음을 참고하세요.
다음 단계로 진행할 준비가 되셨나요? 6단계 - 파일 시스템으로 할 일 목록 내보내기 »로 이동합니다.