Regular Motion

개발자가 상팔자

Author: REGULARMOTION (page 1 of 59)

Small Tips When You Develop Chrome Extension

  • Content Scripts가 Inject되는 타이밍을 정의 할 수 있다.
    manifest.json의 content_scripts의 속성 중 run_at 속성으로 content_scripts 파일이 Inject되는 시점을 정의 할 수 있다. run_at의 값으로는 document_start, document_end, document_idle 세가지가 올 수 있다. 기본으로 document_idle이 적용되며 Inject되는 시점은 아래와 같다.

      • document_start: DOM이 생성되기전 또는 다른 Script들이 실행되기전에 Script가 Inject 된다. Inject하려는 Script가 1빠로 실행되어야 하면 이 타이밍을 노려보자.
      • document_end: DOM 생성이 완료 된 후, Script가 Inject된다.
      • document_idle: document_idle은 시점이 불명확한데, document_end 이벤트와 window.onload 이벤트가 Fire된 직후 그 사이에 Script가 Inject 된다. 따라서 document_idle로 Inject되는 경우 window.onload 이벤트를 받지 못 할 수 있다.

    * 예전에 Supreme 자동구매 봇을 만든적이 있는데, (참고로 Supreme의 인기 신상은 1~2초 싸움이다) run_at:document_idle에서 제품을 담고, 결제하도록 했을 때와 run_at:document_end:에서 제품을 담고, 결제하도록 했을 때의 성공 확률이 크게 차이났었다.

 

  • Content Scripts는 Web Pages의 DOM에 접근 및 제어가 가능하나, JavaScript Context는 별도로 존재한다.
    Web Pages와 Content Scripts는 각각 별도의 JavaScript Scope를 갖기 때문에, Content Script에서 Web Pages의 변수나 함수를 사용 할 수 없고, Web Pages에서도 Contents Scripts의 변수나 함수에 접근 할 수 없다.  허나  Content Scripts에서 Web Pages의 DOM에 접근 및 제어가 가능하다.  DOM을 제어 할 수 있다는 사실은 실로 대단한 가능성을 내포하고 있다.

 

  • Content Scripts는 Chrome Extension의 Popup과 Background Scripts와 localStorage를 공유하지 않는다.
    localStorage도메인 별로 독립된 저장공간을 사용한다. Content Scripts는 Web Pages와 같은 도메인에서 실행되고, Popup과 Background Scripts는 chrome-extension://으로 시작하는 도메인에서 실행된다.  따라서 Content Scripts와 Popup, Background Scripts는 localStorage를 통해 데이터를 공유 할 수 없다.
    * 글로 적으면 당연한 사실인데 만들다보면 왠지 공유가 될 것 같다. 희망은 이성을 초월하는 것 같다.만약 반드시 Content Scripts와 Popup, Background Scripts간 데이터를 저장/공유해야 한다면 localStorage 대신 chrome.storage를 사용해야 한다. * 알 수 없는 이유로 10분을 허비하기 싫으면, manifest.json의 permissions에 storage 추가하는 것을 잊지 말자.
    사용법은 https://developer.chrome.com/extensions/storage#property-sync 링크를 참고하면 쉽다;localStorage와 다르게 개발자 도구에서 Inspect/Edit를 제공하지 않는다. (2017/05 기준) 만약 chrome.storage를 Heavy하게 사용 할 예정이라면, Storage Area Explorer를 설치해서 사용해야 한다. 아직 정품이 없다.

 

  • Again, Content Script는 Web Pages의 DOM에는 접근/제어가 가능하나, JavaScript Scope는 별도로 존재한다.
    만약, Web Pages에서 필요한 JavaScript 코드가 있다면 Script Element를 이용해 File 또는 Text를 Inject 하는게 제일 편하다.아래의 코드를 통해 File 또는 Text를 Inject 할 수 있고, Inject 하려는 파일은 manifest.json의 web_accessible_resources에 선언되어야 한다. web_accessible_resources에 선언된 파일에 한해 Web Pages에서 접근 가능하다.

     

디자인의 디자인

디자인의 디자인

디자인의 디자인

 

하라 켄야의 디자인의 디자인이라는 책을 읽었다.

디자이너가 디자인을 통해 사회에 어떤 영향을 미칠 수 있는지 작가의 시각에서 정리된 책이다.  그리고 그 시각이 문장을 통해 선명하게 전달된다.

개인적으로 책에서 가장 인상적이었던 문장은, 예술과 디자인의 차이를 설명한 문장이다.

아트는 개인이 사회를 마주 보는 개인적인 의사표명으로 발생의 근원이 매우 사적이다. 한편 디자인은 기본적으로 그 동기가 개인의 자기 표출 의사에 있는 것이 아니라 사회에 있다

 

이 외에도 디자인에 대한 작가의 다양한 시각을 엿볼 수 있는 문장들을 곳곳에서 찾을 수 있다.

사람이 살아 있어야 환경이다. 그것을 냉정하게 관찰하는 시선 저편에 테크놀로지의 미래나 디자인의 미래가 있다. 그것들이 교차되는 부분에서 모더니즘의 미래를 내다볼 수 있을 것이다.

인간이 살아가는 것, 생활하는 것의 의미를 물건 만들기의 과정을 통해 해석하고자하는 의욕이 디자인이다.

화장지를 감는 종이심을 사각형으로 만듦으로써 그곳에 저항이 발생한다. 이런 완만한 저항의 발생이 곧 ‘자원 절약’의 기능을 발휘하기도 하지만 거기에는 자원을 절약하자는 메시지도 함께 담겨 있다.

마카로니는 구축적인데 비해 스파게티는 비구축적이다. 극단적으로 말하면 마카로니에는 형태가 있으나 스파게티에는 형태가 없다.

메이커의 기능이 생산 기술보다는 상품 개발 능력으로 집약될 때 더욱 중요해지는 것이 마케팅과 디자인이다.

포장 테이프를 미디어로 바라본 발상이다.

‘정보의 질’이란 실제로 그래픽 디자이너의 궁극적인 주제라고 할 수 있다.

‘그래픽 디자인’이라는 말을 과거의 것으로 돌리지 말고 그 내용을 진화시키는 것이 중요하다. 그것은 동시에 ‘그래픽 디자이너’ 자신의 진화를 의미하는 것이기도 하다.

 

AWS S3 Transfer Accelerator

AWS의 S3는 Static한 파일을 저장/배포하기에 매우 훌륭한 저장소지만, 버킷의 Region이 접속지역과 멀리 떨어진 경우 응답시간과 전송시간 모두 사용자들의 인내심을 테스트하게 만드는 단점이 있다. 사실 다운로드의 경우 CDN(CloudFront)을 이용해 개선 할 수 있지만, 업로드는 방법이 없다.

현재 회사에서 운영중인 서비스는 유럽에 위치한 주요 고객(이라 적고 갑이라 읽는다)을 위해 대부분의 버킷을 eu-west-1에 위치시키고 있다.  eu-west-1의 버킷의 경우 100KB의 파일을 업로드/다운로드하는데 1~3초, 5MB 정도의 파일은 수십초가 소요된다.  (편리함의 대가로 시간을 지불하고 있었던 것이다).

매일같이 시간을 지불하고 있던 어느날, S3에 Transfer Acceleration을 활용하면 적게는 2~3배에서 많게는 10배 정도 업로드/다운로드 속도가 빨라진다는 글을 접하게 됐다.  평소 의심이 많고, 두눈으로 보기전엔 믿지 않는 분들은 AWS에서 제공하는 속도비교 페이지에 접속해보시기 바란다.  7번 정도 확인을 해봤는데 eu-west-1의 경우 6~21배 정도 속도차이가 있었다.

이제 Transfer Acceleration의 효과를 봤으니, 1) 속도 개선이 어떻게 이루어지고 2) 적용 방법은 어떻게 되며 가장 중요한 그래서 3) 얼마를 더 내야 되는지 알아보자.

Overview

공식 설명은 ‘S3 Transfer Acceleration은 AWS S3로 데이터를 전송 할 때, AWS의 Edge 인프라와 네트워크 프로토콜을 최적화하여 전송 속도를 개선하는 기능’ 이라고 되어 있습니다.

사용자가 S3 Bucket에 데이터를 전송 할 때, 직접 Origin 서버로 전송하는게 아니라 AWS의 Edge 인프라를 활용하여 사용자는 가장 가까운 Edge 서버로 데이터를 전송하고, Edge 서버에서 Origin 서버로 최적화된 네트워크 프로토콜과 전용회선을 활용하여 데이터를 전송함으로써 속도를 개선합니다. 그림으로 표현하면 아래와 같습니다.

Before

After

자칫 복잡해 보일 수 있는 아래의 방식이 5~10배 이상 빠르다는건 Edge 서버와 S3 사이의 네트워크 프로토콜과 데이터 이동이 최적화되었다는 반증일겁니다. 실제로 Edge 인프라를 활용하기 위해 Transfer Acceleration을 사용하는 요청은 Endpoint가 기존과 다릅니다.

  • Original Endpoint: https://{your-bucket}.s3.amazonaws.com/
  • Accelerated Endpoint: https://{your-bucket}.s3-accelerate.amazonaws.com/

 

버킷에서 Transfer Acceleration 설정

Transfer Acceleration은 Bucket 레벨에서 적용할 수 있는 기능이기 때문에, 적용을 원하는 버킷의 속성에서 Transfer Acceleration을 활성화(Enable)해주면 됩니다.  활성화 방법은 아래 세가지 방법 중 평소 본인이 흠모하던 방법으로 하시면 됩니다. 자세한 방법은 링크를 참고하시는게 글을 쓰는 사람과 읽는 사람 모두의 정신건강에 이로울 것 같아 링크로 대체합니다.

Transfer Acceleration 활용

아쉽게도, 버킷에서 Transfer Acceleration 속성을 활성화하는 것으로 갑자기 빨라지는 건 아니고, 버킷에 파일을 업로드/다운로드를 하는 부분도 약간의 수정을 해야 합니다. SDK를 사용하고 있었다면 Flag를 활성화하는 수준이고, REST API를 사용하고 있었다면 Endpoint를 대체하는 수준으로 가능합니다. (역시나 우리 모두의 정신 건강을 위해 링크로 대체합니다)

Transfer Acceleration 비용

저장 비용에는 변화가 없으며, Transfer Acceleration을 이용한 전송에 추가 비용이 발생합니다. GB당 추가로 $0.04가 부과됩니다. (스벅에서 카페라떼 한잔을 참으면 약 100GB를 빠르게 전송 할 수 있습니다. 반대로 100GB를 느긋하게 전송하면 카페라떼를 한잔 사먹을 수 있습니다)

Benchmark Test

평소 의심이 많던 저는 AWS의 속도 비교 페이지를 온전히 믿지 못하고, 직접 벤치마크 테스트를 해봤습니다. 아래 표는 eu-west-1 버킷에 CLI를 이용하여 파일을 업로드/다운로드한 결과입니다. 파일의 크기가 크면 클수록 속도 개선이 드라마틱하게 이루어짐을 알 수 있습니다. 15MB 정도되는 파일의 경우 평균 43초 정도 소요되던 다운로드 속도가 4.7초로 개선된 것을 확인 할 수 있습니다.

 

주의사항
  • 설정 후 반영까지 최대 30분정도가 소요 될 수 있습니다.

Common Design Patterns for Android

이 글은 https://www.raywenderlich.com에 소개된 글을 저자의 동의를 얻고 번역한 것임을 알려드립니다.

개발자로서 일하며 행복을 유지하기 위해서는 고객과 사장님도 만족시켜야 하지만, 미래의 나 또한 만족시켜야 한다.  (행복한 닭이 더 맛있는 달걀을 낳는다고 하지 않던가)

미래의 나는 과거의 내가 작성한 코드를 이어받게 될 것이고, 아마 왜 이렇게 코드를 작성했는지 궁금해 할 것이다.  헷갈리는 주석을 왕창 달아 놓는 것보다, 많이 사용되는 디자인 패턴을 적용하여 코드를 읽기 쉽고, 구조화 시켜 놓는게 미래의 나를 위해 훨씬 나은 방법일 것이다.

이 글은 안드로이드 개발을 하며 많이 사용하는 디자인 패턴을 소개 할 것이다. 디자인 패턴이란 일반적인 소프트웨어 개발시 마주 할 수 있는 문제들을 해결 할 수 있는 재사용 가능한 해결책이라고 할 수 있다. 이 글에서는 많은 디자인 패턴을 소개하지는 않을 예정이지만, 시작점으로 좋은 글이 될 것이라고 생각한다.

Getting Started

“동일한 수정을 여러 곳에 적용해야 할 부분이 이 프로젝트에 있나요?” – Future You

미래의 당신은 아마 추측하거나 추론하며 프로젝트의 의존성을 찾는 시간을 최소화하고 싶을 것이다. 그러기 위해 프로젝트는 최대한 재사용 가능하며, 읽기도 쉽고, 이해하기 쉬워야 할 것이다.  하나의 클래스부터 전체 프로젝트에 이르기까지 위 목표를 달성하기 위해, 패턴을 다음의 카테고리로 나눌 수 있다.

  • Creational patterns: how you create objects.
  • Structural patterns: how you compose objects.
  • Behavioral patterns: how you coordinate object interactions.

당신은 아마 각각의 패턴을 지칭하는 이름을 모른채 몇 종류의 패턴들은 사용하고 있을지도 모른다. 이제 각각의 카테고리에 어떤 패턴이 있으며 실제로 Android에 어떻게 구현/적용 할 수 있는지 알아보자.

Creational

  • Builder
  • Dependency Injection
  • Singleton

Structural

  • Adapter
  • Facade

Behavioral

  • Command
  • Observer
  • Model View Controller
  • Model View ViewModel

Creational Patterns

“복잡한 오브젝트가 여러곳에서 필요할 때는 어떻게 하죠?” – Future You

미래의 당신은 위 물음에 “동일한 코드가 필요할 때마다 Copy and Paste하면 되잖아요?” 라는 말을 듣고 싶지는 않을 것이다.  대신 Creational Pattern으로 오브젝트의 생성을 단순하게 유지하고 쉽게 반복 가능하도록 만들 수 있습니다.

Builder

단골 샌드위치 가게의 주문서에 빵의 종류와 재료 그리고 양념을 펜으로 선택한다. 주문서의 이름이 “Build my own”이지만 실제로 샌드위치를 직접 만들지는 않고 입맛에 맞게 각각의 재료들을 선택한 뒤 직원에게 넘겨 줄 뿐이다.

이와 비슷하게 Builder pattern은 Object의 복잡한 생성과정(빵을 익히고 자르고, 재료를 넣고, … )을 Object(샌드위치)에서 분리한 것이다. 이와 같은 방법을 통해 동일한 프로세스로 다른 Object(샌드위치)를 쉽게 만들어 낼 수 있다.

Android의 AlertDialog.Builder와 같은 오브젝트에 Builder pattern이 사용된다.

위의 AlertDialog를 Build하는 과정은 단계적으로 진행되며, AlertDialog의 요소 중 수정하고 싶은 부분만 수정 할 수 있도록 해준다.  AlertDialog.Builder 문서를 보면, Alert을 만들 때 매우 제한적인 요소만 설정 할 수 있다는 것을 알 수 있다.

위 코드는 아래와 같은 Alert을 생성한다.

please_use_the_spicy_mustard

Dependency Injection

Dependency Injection은 빌트인 가구가 갖춰진 아파트로 이사하는 것과 비슷하다. 필요한게 이미 있기 때문에; IKEA 홈페이지에 접속해서 가구를 주문하고 배달을 할 필요가 없다.

소프트웨어 측면에서 보자면, Dependency Injection은 새로운 Object를 생성하는 시점에 필요한 Object들을 제공해준다. 따라서 새로 생성되는 Object는 필요한 Object들을 만들 필요가 없다.

안드로이드에서는 앱의 다양한 Activity 또는 Fragment에서 Network Client나 Image Loader, SharedPreferences와 같은 다양한 Object들에 접근 할 필요가 있다. Dependency Injection을 활용하면 이러한 Object들을 Activity나 Fragment들에 Inject 한 뒤, 필요한 시점에 바로 사용 할 수 있도록 해준다.

Dagger 2는 Google과 Square가 협업하여 개발한 Framework으로, Android에서 가장 유명한 Dependency Injection Framework이다. 클래스에 @Module 어노테이션을 추가한 뒤, @Provides 어노테이션으로 필요한 모듈을 제공하도록 할 수 있다.

위 모듈은 Object 생성과 필요한 설정을 수행한다. 규모가 있는 앱을 위한 Best practice로는, 여러 모듈을 함수로 구분하여 생성 할 수도 있다. Component interface를 만든 뒤, Inject가 필요한 모듈과 클래스를 나열한다.

Component는 dependency들이 어디서 와야(module coming from) 되고 어디로 가야(injection point) 되는지를 판단하여 묶어 주는 역할을 한다.

마지막으로 @Inject 어노테이션을 사용해서 Dependency가 필요한 곳에 삽입 할 수 있다.

* Dagger에 대한 간소화된 개요이기 때문에, 자세한 내용은 Dagger 문서를 참조하기 바란다.

Singleton

Singleton 패턴은 클래스의 인스턴스가 오직 하나만 생성되도록 해준다. 모델링하는 Object가 실제로 단 하나의 인스턴스만 갖을 때, Singleton 패턴은 잘 동작한다.

위 ExampleSingleton 클래스는 객체의 생성자를 static 함수인 getInstance() 함수 안으로 숨겨서, 객체가 하나만 생성되도록 보장한다. Singleton 객체에 접근이 필요할 때는 아래와 같이 getInstance() 함수로 접근 할 수 있다.

Singleton은 이해하기 가장 쉬운 패턴 중 하나지만, 오/남용되기 가장 쉬운 패턴이기도 하다.  복수의 객체에서 동일한 Singleton 인스턴스에 접근 할 수 있기 때문에 예상치 못한 Side Effect가 발생하기 쉽고, 원인을 파악하기 어려운 경우도 많다.  따라서 사용하기 전에 패턴을 정확히 이해하고 사용하는 것이 중요하다.

 

Structural Patterns

미래의 당신은 전형적인 작업(typical task)을 수행하는 클래스와 오브젝트들을 익숙한 형태로 정리 할 수 있도록 도와준 Structural Pattern을 의심의 여지없이 고마워 할 것이다. AdapterFacade는 안드로이드에서 가장 많이 사용되는 패턴이다.

Adapter

Apollo 13에서 엔지니어들이 네모난 마개를 ‘Round Hole’에 맞추는 유명한 장면이 있다. 이 장면은 Adapter의 역할을 은유적으로 보여준다. Adapter 패턴은 Class의 Interface를 변환하여 사용자가 예상하는 다른 Class의 Interface에 맞출 수 있도록 해준다.
(By converting the interface of a class into another interface the client expects).

당신 앱의 비즈니스 로직은 제품이 될수도, 사용자 또는 건조틀이 될 수도 있다. 그게 뭐가됐든, RecyclerView는 모든 Android App에서 공통으로 사용되는 ‘Round Hole’ 이다.

RecyclerView는 Star Trek의 에피소드를 하나도 본적이 없기 때문에 Tribble이 뭔지 모른다.  하지만 데이터를 처리하고, ViewHolder에 데이터를 올바르게 전달해주는 Adapter의 역할을 한다.

Facade

Facade 패턴은 인터페이스들의 모음을 사용하기 쉽게 하기 위한 Higher-level 인터페이스를 제공한다. 아래 다이어그램은 이를 더 자세히 설명해준다.

만약 Activity에서 도서 목록이 필요하다면, 내부 저장소나 캐시 그리고 API 클라이언트의 내부 로직에 대한 이해 없이도 요청 할 수 있어야 한다.  이는 Activity와 Fragment의 코드를 깨끗하고 간결하게 유지하는 것을 넘어 Activity에 영향을 주지 않고, API 구현에 대한 변경사항을 적용 할 수 있도록 해준다.

SquareOne의 Retrofit은 Facade 패턴을 구현할 수 있도록 도와주는 Open Source Android 라이브러리다. API data를 제공하는 Interface를 아래와 같이 생성하면,

Client에서는 listBooks()을 호출하는 것 만으로 도서 목록을 얻어 올 수 있다.  RequestInterceptor 또는 OkClient의 설정을 수정(customize)하는 것 만으로 Client의 변경없이 캐시 동작 방식을 제어 할 수 있다.

Behavioral Patterns

Behavioral 패턴은 앱의 기능에 책임을 부여 할 수 있도록 해준다. Behavioral 패턴을 통해 프로젝트의 구조나 설계를 파악하는데 도움을 얻을 수 있다. 이 패턴의 Scope는 두 객체간의 관계에서 부터 전체 어플리케이션의 구조에 이르기까지 다양하게 나뉜다. 다양한 Behavioral 패턴이 하나의 앱에 사용되는게 일반적이다.

Command

인도 음식점에서 ‘Saag Paneer’를 주문했을 때, 음식이 만들어지는 과정은 알 필요가 없다. 종업원에게 주문을 알려주기만 하면 된다.

이와 비슷하게 Command 패턴은 Request를 수신하는 곳에 대한 정보없이 발행 할 수 있도록 해준다.

Greenrobot의 EventBus는 Command 패턴이 아래와 같이 동작할 수 있도록 해주는 Android Framework다.

EventBus-Publish-Subscribe

EventBus의 실제 동작방식은 링크를 참고하기 바란다.

Observer

Observer 패턴은 Objects간의 1 대 多 의존성을 정의 한 뒤, Object의 상태가 변경됐을 때, 이에 의존적인 Object들에게 내용이 전달되고, 자동으로 갱신된다.

Observer 패턴은 활용도가 높아, API Call이나 사용자 입력에 대한 반응과 같이 종료시간을 예측하기 어려운 작업에는 모두 적용 할 수 있다.

RxAndroid Framework은 아래와 같은 방식으로 Observer 패턴을 앱에 적용 할 수 있게 해준다.

 

Getting Literal with Template Strings.

최근 개발하고 있는 기능 중, JavaScript에서 XML String을 생성하는 부분이 있다.  해당 코드는 Template화된 XML String에서, 필요한 값들을 replace하는 방식으로 구현되어 있었다.
문제는 Template에 replace 해야 할 값들이 많을 수록 코드의 미적인 부분과 성능적인 부분이 함께 추락하는 방식이었다.
아래의 코드는 위의 예시와 72% 정도 유사하다.

생성해야 할 XML Template을 String으로 선언한 뒤, 변수로 치환되어야 할 값들을 String.prototype.replace()를 통해 치환하는 구조다.  쉽고, 나름 직관적이다.  사실 크게 문제가 있는 코드라고 보기는 어렵다. 하지만 위에서 언급했듯 치환되어야 할 값들이 늘어나면 replace chaining이 늘어나며 뭔가 문제가 생길 것 같은 불안감을 내포하는 코드다.

그래서 위 코드를 깔끔하게 개선하고 싶어 약간의 조사를 해보니 ES6의 Template Strings을 활용하면 매우/훨씬 깔끔한 코드로 수정 가능 할 것 같았다.  (정말 약간의 조사로 알게되어 애초에 왜 저렇게 구현했나 자괴감이 들었다)

실제로 위 코드를 ES6의 Template Strings을 활용하여 수정한 코드는 아래와 같다.

문장을 감싸는 부호를 single quotes(‘)에서 back-ticks(´)으로 대체했고, 값들을 치환하는 replace() chaining 구문이 사라졌다. (JavaScript 엔진에 의해 자동으로 치환된다는 의미다.)
코드가 간결해졌다는 것은 시력이 0.2 이상인 사람은 모두 육안으로 확인 가능하고, 성능이 빨라졌다는 것은 간단한 Benchmark를 통해 증명 가능하다.  (https://jsfiddle.net/6xnutcsd/)
* 위의 예제는 크롬에서 7~10배 정도의 성능 향상이 있으며, 치환되어야 할 값들이 많을수록 성능 개선 효과도 크게 나타났다.

 

예제로 글을 시작했으니, 이제 문법과 활용 범위에 대해 알아보자.
(글 끝부분의 Reference 링크를 참고하시는게 더 낫다)

Syntax
Template String은 일반적으로 String을 감쌀 때 사용하던 single quote(‘)나 double quote(“) 대신 back-ticks(`)을 사용하면된다.  쉽다;


String Substitution
문자열에 JavaScript Expression을 삽입 할 수 있는 String Substitution은 Template String의 가장 큰 장점이라고 할 수 있다. 심지어, 거의 모든 JavaScript Expression이 허용되며,  치환/처리가 필요한 Expression을 중괄호{}로 감싼 뒤, 앞에 달러($)를 붙여주기만 하면 된다. (아, 이놈의 자본주의, 그놈의 돈돈돈)

Expression에는 단순히 변수의 이름이나, 간단한 수식은 물론이고, Instance의 property나 method등 일반적인 JavaScript Expression 대부분 허용된다. (개발자한테 참 좋은데, 설명할 방법이 없다.)

Tagged Templates
Tagged Templates은 함수를 이용하여 Template String의 출력을 변형하기 위한 목적으로 사용 할 수 있다. 사용법은 함수의 이름 뒤에 Template String을 선언하면 된다. 그러면 함수의 첫번째 인자로 Template String의 문자열이 Array 형태로 전달되고, Expression이 순서대로 함수의 인자로 전달된다.

상상력이 미천한건지 아직까지 Tagged Templates의 활용할 코드는 발견하지 못했다.

 

References

 

Older posts

© 2017 Regular Motion

Theme by Anders NorenUp ↑