5단계: 웹에서 이미지 추가

이 단계에서 학습할 내용은 다음과 같습니다.

  • 앱 외부에서 리소스를 로드하고 XHR 및 ObjectURL을 통해 DOM에 추가하는 방법

이 단계를 완료하는 데 필요한 예상 시간: 20분
이 단계에서 완료할 작업을 미리 보려면 이 페이지 하단으로 이동 ↓하세요.

CSP가 외부 리소스 사용에 미치는 영향

Chrome 앱 플랫폼은 앱이 콘텐츠 보안 정책 (CSP)을 준수하도록 강제합니다. Chrome 앱 외부에서 이미지, 글꼴, CSS와 같은 DOM 리소스를 직접 로드할 수 없습니다. 패키지에서 찾을 수 있습니다.

앱에 외부 이미지를 표시하려면 XMLHttpRequest를 통해 요청해야 합니다. Blob으로 변환하고 ObjectURL을 만듭니다. 이 ObjectURL을(를) 다음 항목에 추가할 수 있습니다. DOM을 사용하는 이유는 앱 컨텍스트에서 메모리 내 항목을 참조하기 때문입니다.

할 일 항목의 썸네일 이미지 표시

todo 항목에서 이미지 URL을 찾도록 앱을 변경해 보겠습니다. URL이 이미지( .png, .jpg, .svg, .gif로 끝나는 경우 위에서 언급한 프로세스를 적용하여 이미지 썸네일을 클릭합니다.

권한 업데이트

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 요청

지정된 이미지 URL에서 XMLHttpRequest를 실행하는 _requestRemoteImageAndAppend() 메서드를 추가합니다.

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를 만들고 <img> 요소를 추가합니다. 이 ObjectURL를 DOM에 전달합니다.

todo 항목의 이미지 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;
}

완성된 할 일 앱 실행

5단계가 완료되었습니다. 앱을 새로고침하고 온라인으로 호스팅되는 이미지에 대한 URL과 함께 todo 항목을 추가합니다. 다소 유용함 사용할 수 있는 URL: http://goo.gl/nqHMF#.jpg 또는 http://goo.gl/HPBGR#.png

추가 정보

이 단계에서 도입된 일부 API에 관한 자세한 내용은 다음을 참조하세요.

다음 단계를 진행할 준비가 되셨나요? 6단계 - todos를 파일 시스템으로 내보내기 »로 이동합니다.