블록 메이커는 Beta(베타) 기능이에요!
•
Beta 기간에는 사용된 문법의 하위 호환이 보장되지 않아요.
•
Beta 기간에 개발된 블록들의 경우 추후 문법 변경에 의해서 수정이 요청될 수 있어요.
기본 개념
사용자
웹사이트
•
에디터를 통해서 제작된 사이트이며, 방문자(및 구매자)가 사이트를 방문하여 컨텐츠를 보거나 상품을 구매해요.
•
웹사이트는 쇼핑 기능이 없는 ‘홈페이지’와 쇼핑 기능을 포함하는 ‘쇼핑몰’ 모두를 포함해요.
에디터
•
웹사이트를 제작하기 위한 툴이에요.
•
사용자는 에디터를 활용하여 사이트와 페이지를 구성 및 디자인하고 발행(공개)해요.
•
웹사이트를 제작하는 과정에서 프리뷰(Preview)를 통해 발행하기 전에 미리 구성과 디자인을 확인할 수 있어요.
블록
•
블록은 하나의 행(Row)를 모두 차지하게 삽입될 수도 있고, 하나의 행 내의 열(Column)에 삽입될 수도 있어요.
•
블록 메이커
•
블록을 제작하는 툴이에요.
세팅 빌더
•
특정 블록을 선택하여 나오는 코드 수정 창에서 [세팅 빌더] 탭을 눌러서 사용할 수 있어요.
“안녕 블록 메이커!” — 기본 문법 소개
<style>
h1 {
color: red;
font-size: 24px;
}
</style>
<template>
<h1>안녕 블록 메이커!</h1>
<ul>
<li>제목 색상: red</li>
<li>제목 사이즈: 24px</li>
</ul>
<button>설명 보기</button>
</template>
<script>
const container = bm.container;
const context = bm.context;
function clicked(e) {
e.preventDefault();
if (e.target.matches('button')) {
alert(`제목 색상은 red이고 사이즈는 24px 이에요!`);
}
}
container.addEventListener('click', clicked, true);
</script>
HTML
복사
블록을 만들기 위해서는 HTML/CSS/JavaScript에 대한 기본적인 지식이 필요해요!
간단한 블록을 만들기 위해서는 HTML/CSS 정도로도 구현이 가능하지만, 동작 복잡도가 있는 블록을 만들기 위해서는 기본적인 HTML/CSS/JavaScript 지식이 필요해요.
예시 코드는 빨간색의 “안녕 블록 메이커” 텍스트를 포함하는 <h1> 태그를 그리고 <button>을 클릭 시 설명을 출력하는 블록의 예시에요.
기본 블록 문법 설명
•
하나의 블록은 하나의 코드 파일로 구성돼요.
•
하나의 블록은 크게 3개의 최상위 HTML 태그인 <style> , <template> , <script> 태그로 구성될 수 있고, 태그별로 하나만 최상위 태그로 가질 수 있어요.
◦
<style>: 구현하려는 블록의 Style(CSS)을 입력할 수 있어요.
◦
<template>: 구현하려는 블록의 기본적인 템플릿(HTML)을 입력할 수 있어요.
◦
<script>: 구현하려는 블록의 JavaScript 코드를 입력할 수 있어요.
“{{property.myHelloPhrase}} 블록 메이커!“ — 사용자가 설정할 수 있는 블록 만들기
{
"property": {
"myHelloPhrase": "🖐🏻",
"myColor": "blue",
"myFontSize": 36,
}
}
JavaScript
복사
세팅 빌더를 통해 정의된 설정들(property)과 각 설정의 값들을 포함한 컨텍스트(Context) 객체 예시
<style>
h1 {
color: {{property.myColor}};
font-size: {{property.myFontSize}}px;
}
</style>
<template>
<h1>{{property.myHelloPhrase}} 블록 메이커!</h1>
<ul>
<li>제목 색상: {{property.myColor}}</li>
<li>제목 사이즈: {{property.myFontSize}}px</li>
</ul>
<button>설명 보기</button>
</template>
<script>
const container = bm.container;
const context = bm.context;
function clicked(e) {
e.preventDefault();
if (e.target.matches('button')) {
const myColor = context.property.myColor;
const myFontSize = context.property.myFontSize;
alert(`제목 색상은 ${myColor}이고 사이즈는 ${myFontSize}px 이에요!`);
}
}
container.addEventListener('click', clicked, true);
</script>
HTML
복사
이제 사용자는 <h1> 의 색상과 글자 크기를 설정할 수 있고, “안녕”이라는 문구를 고쳐 쓸 수 있어요.
갑자기 주어진 상황!
•
블록을 제작하는 중에 블록의 사용자가 <h1> 태그 내 “색상, 글자 크기나 컨텐츠 일부를 직접 수정할 수 있도록 지원”해달라는 요청이 왔어요.
•
사용자는 아쉽게도 코드를 직접 수정하지 못하는 분이어서, 컨텐츠와 디자인을 바꾸고 싶을 때마다 항상 코드 수정을 위해 연락이 와요.
사용자가 설정할 수 있는 블록
1.
세팅 빌더를 통해 블록에서 지원하려는 설정 가능한(커스터마이징 가능한) 값들(변수명, 타입, …)을 정의.
2.
컨텍스트(Context)
•
컨텍스트(Context)는 블록의 UI를 그리거나 블록 동작에 참고 및 활용할 수 있는 데이터를 담고 있는 일종의 JSON 객체(Object)에요.
•
블록을 만드는 과정에서 세팅 빌더를 통해서 정의한 설정과 설정의 값(디폴트 값 혹은 사용자가 설정한 값)들이 컨텍스트 객체 내 property 라는 객체 내에 키와 값이 전달돼요.
•
세팅 빌더와 컨텍스트 객체 내 property 를 활용하여 블록을 제작하면, 한 번 제작한 블록에서 코드 수정 없이도 사용자가 UI나 동작을 에디터에서 설정할 수 있도록 블록을 제작할 수 있어요.
•
컨텍스트 객체는 <style> , <template> , <script> 모든 태그 내에서 접근해 활용할 수 있어요.
◦
◦
◦
<script>: bm.context를 통해서 컨텍스트 객체에 접근할 수 있어요.
Handlebars.js 문법이 어려워 보이는데 혹시 다 알아야 할까요?
사용자가 설정한 값을 HTML/CSS에서 단순히 읽어서 사용하시는 경우에는 모든 문법을 자세히 알 필요 없이 property 값에 접근하기 위한 {{property.*}} 문법만 기억해도 괜찮아요!
<style> 태그
<style>
h1 {
color: red;
/* Handlebars.js 문법으로 컨텍스트 객체 내 property 값에 접근 */
font-size: {{property.myFontSize}}px;
}
</style>
HTML
복사
CSS 및 Handlebars.js 로 작성된 스타일 예시
•
블록에 적용될 CSS 코드를 입력할 수 있어요.
•
입력된 CSS 코드는 웹사이트에 삽입된 각 블록 별로 격리되어 적용돼요.
•
•
•
기본 HTML 디자인이 이상해요!
블록 메이커를 통해 제작되는 블록들은 다양한 기기에서 여러 테마에 적용되어도 최대한 동일한 블록 UI를 제공할 수 있도록 브라우저에서 기본 적용되는 디폴트 CSS 스타일이 대부분 초기화(Reset)되어 있어요.
<template> 태그
<template>
<h1>Hello Block Maker!</h1>
<!-- Handlebars.js 문법으로 컨텍스트 객체 내 property 값에 접근 -->
<p>{{property.myDescription}}</p>
</template>
HTML
복사
HTML 및 Handlebars.js 로 작성된 템플릿 예시
<!-- 블록 컨테이너(Block Container) 영역 -->
<div>
<!-- 템플릿의 HTML은 블록 컨테이너 안에 그려져요. -->
<h1>Hello Block Maker!</h1>
<p>블록 메이커에 대한 설명이에요.</p>
</div>
HTML
복사
작성된 템플릿이 웹사이트에 그려진 예시
•
블록의 기본이 되는 HTML 템플릿을 입력할 수 있어요.
•
•
•
•
블록 컨테이너
•
입력한 블록 템플릿을 감싸고 내부에 실제로 그리게 되는 HTML DOM 컨테이너에요.
•
블록 컨테이너는 하나의 블록당 1개만 존재하고, 작성한 HTML 템플릿의 부모(Parent) 컨테이너로 볼 수 있어요.
•
<script> 태그
<script> 태그 사용 시 주의 사항
•
Beta(베타) 기간에는 <script> 태그의 문법적 제약이 거의 없지만, 추후 특정 문법을 사용하는 경우 제약될 수 있어요.
•
외부 라이브러리(jQuery 등)를 사용하는 경우 공통 코드를 설정하여 <script> 태그 내에서 활용할 수 있지만, 꼭 필요한 경우가 아니라면 사이트의 속도 저하의 원인이 될 수 있으니 순수 JavaScript(Vanilla JavaScript) 사용을 지향해요.
<script>
const container = bm.container;
const context = bm.context;
container.addEventListener('click', e => {
e.preventDefault();
if (e.target.matches('h1')) {
// <h1> 태그를 클릭시 사용자가 에디터에 설정한 메세지를 출력
alert(context.property.myAlertMessage);
}
}, true);
</script>
HTML
복사
블록에서 접근 가능한 bm 변수와 스크립트 예시
•
<script> 태그 내에 JavaScript 코드를 작성해서 블록의 동작을 제어할 수 있어요.
•
작성한 <script> 코드는 <template> 과 <style> 이 그려진 뒤에 실행돼요.
•
bm
•
<script> 태그 내에서 bm 이라는 변수에 접근할 수 있고, bm 을 통해 해당 블록과 관련된 정보에 접근할 수 있어요.
•
bm 변수는 웹사이트에 삽입된 블록별로 격리되어 있어요.
bm.context
•
컨텍스트(Context) 객체에 접근해 블록의 기능이나 UI 구성에 활용할 수 있어요.
•
<script> 태그에서 컨텍스트(Context) 객체를 활용한 블록 제작 시에는 bm.onContextChange 와 에디터 내 프리뷰(Preview) 지원 내용을 함께 참고해 주세요.
bm.container
•
블록 컨테이너의 DOM 객체에요.
•
일반적으로 DOM 이벤트(마우스 클릭 등)를 걸거나 블록 컨테이너 내 HTML을 찾는(Query) 용도로 사용해요.
bm.onContextChange
•
컨텍스트(Context) 객체의 변화가 생긴 경우 실행되는 콜백 함수를 정의할 수 있는 공간이에요.
bm.onContextChange 문법의 특이 사항
•
현재에는 제작하시게 되는 블록의 <script> 태그에서 컨텍스트(Context) 객체를 활용한 경우에 에디터 내 프리뷰(Preview) 지원을 자연스럽게 하는 경우에만 사용돼요.
•
<script> 태그 사용 — Good vs. Bad
<!-- Good -->
<script>
// bm, bm.context 와 별도로 필요한 변수를 관리하고 사용
let myCounter = 0;
bm.container.addEventListener('click', e => {
e.preventDefault();
myCounter = myCounter + 1;
});
</script>
<!-- Bad -->
<script>
// bm.context에 변수를 할당하고 사용
bm.context.myCounter = 0;
bm.container.addEventListener('click', e => {
e.preventDefault();
bm.context.myCounter = bm.context.myCounter + 1;
});
</script>
HTML
복사
bm 및 bm.context 객체 내부의 값을 JavaScript 코드를 통해 직접 수정하지 말아 주세요.
•
추후bm 혹은 bm.context 를 코드에서 더 활용할 수 있는 문법을 추가 제공할 예정이어서, bm 혹은 bm.context 를 직접 수정하면 추후 예기치 않은 사이드 이펙트가 발생할 수 있어요.
<!-- Good -->
<script>
bm.container.innerHTML = '<h1>안녕하세요!</h1>';
// 블록 컨테이너에 DOM 이벤트를 위임하고 분기
bm.container.addEventListener('click', e => {
e.preventDefault();
if (e.target.matches('h1')) {
alert('<h1> 태그가 클릭되었어요.');
}
}, true);
// 1초 뒤 <h1> 태그를 새로 생성
setTimeout(() => {
bm.container.innerHTML = '<h1>☺️클릭하면 창이 떠요!</h1>';
}, 1000);
</script>
<!-- Bad -->
<script>
bm.container.innerHTML = '<h1>안녕하세요!</h1>';
// 블록 컨테이너에 그려진 HTML 요소에 직접 DOM 이벤트를 바인딩
const h1 = bm.container.querySelector('h1');
h1.addEventListener('click', e => {
e.preventDefault();
alert('<h1> 태그가 클릭되었어요.');
});
// 1초 뒤 <h1> 태그를 새로 생성
setTimeout(() => {
bm.container.innerHTML = '<h1>😢클릭해도 창이 안떠요...</h1>';
}, 1000);
</script>
HTML
복사
UI 클릭 등 DOM에 이벤트를 거는(Binding) 경우, 상위 컨테이너인 블록 컨테이너(bm.container)에 이벤트를 걸고 콜백 함수(Callback)에서 분기 처리하는 패턴이 좋아요.
•
블록 컨테이너 내부의 HTML 구조나 내용물이 바뀌는 상황에도 DOM 이벤트를 다시 걸어줄 필요가 없어요.
•
제작하는 블록에서 <script> 태그를 활용해 UI를 동적으로 수정하는 경우에도 상위 컨테이너인 블록 컨테이너를 활용하는 방식이 사이드 이펙트가 덜 발생해요.
◦
에디터 내 프리뷰(Preview) 지원 시 자연스러운 동작에 도움이 돼요.
에디터 내 프리뷰(Preview) 지원
<style>
h1 {
/* 사용자가 블록의 설정 값(property.myColor)을 에디터에서 변경하면 프리뷰에 자동 반영돼요. */
color: {{property.myColor}};
}
</style>
<template>
<!-- 사용자가 블록의 설정 값(property.myHelloPhrase)을 에디터에서 변경하면 프리뷰에 자동 반영돼요. -->
<h1>{{property.myHelloPhrase}} 블록 메이커!</h1>
<p></p>
</template>
<script>
const container = bm.container;
const context = bm.context;
const p = container.querySelector('p');
// 처음 한 번은 반영되지만, 사용자가 블록의 설정 값(property.myContents)을 에디터에서 변경해도 자동 반영되지 않아요.
p.innerHTML = context.property.myContents;
</script>
HTML
복사
•
사용자가 설정할 수 있는 블록은 사용자가 에디터에서 블록을 삽입한 뒤, 블록이 정의한 설정 값(컨텍스트(Context) 객체의 property)들을 패널을 통해서 설정하는 과정을 거치게 돼요.
•
사용자가 에디터에서 블록을 설정하게 되면, 사용자는 설정한 값들이 블록에 바로 반영되어 프리뷰에 나오기를 기대해요.
에디터 프리뷰 내 태그별 특징
•
<template> 태그와 <style> 태그에서 사용 중인 컨텍스트(Context) 객체의 property 값들은 에디터에서 자동으로 변경을 감지하고 반영하여 에디터 프리뷰에서 바로 확인할 수 있어요.
•
<script> 태그도 <template> , <style> 태그와 동일하게 제일 처음에는 <script> 태그가 동작하면서 프리뷰에 반영돼요.
•
다만 <script> 태그는 <template> , <style> 태그와는 다르게, 별도의 문법 처리를 해주지 않으면 사용자가 블록의 설정값을 변경하였을 때 자동으로 프리뷰에 반영하지 않아요.
•
...
<script>
const container = bm.container;
const context = bm.context;
const p = container.querySelector('p');
// 최초 실행시 설정 값(property.myContents)을 반영
p.innerHTML = context.property.myContents;
// 이후 사용자가 블록의 설정 값(property.myContents)을 변경한 경우 반영 처리
bm.onContextChange = () => {
const p = container.querySelector('p');
p.innerHTML = context.property.myContents;
};
</script>
HTML
복사
<script> 태그에서 프리뷰 지원하기
•
사용자가 블록이 정의한 설정 값(컨텍스트(Context) 객체의 property)들을 설정하여 property 값에 변화가 생기면, 블록 메이커는 컨텍스트(Context) 객체에 변화가 생겼다고 판단하고 bm.onContextChange에 정의한 함수를 실행해요.
•
bm.onContextChange에 콜백(Callback) 함수를 정의하고, property 값의 변화가 발생한 경우 블록의 UI와 동작에 반영하는 코드를 작성하면 프리뷰에서도 잘 반영되는 블록을 제작할 수 있어요.
bm.onContextChange 문법의 특이 사항
•
현재에는 제작하시게 되는 블록의 <script> 태그에서 컨텍스트(Context) 객체를 활용한 경우에 에디터 내 프리뷰(Preview) 지원을 자연스럽게 하는 경우에만 사용돼요.
•
Handlebars.js 문법
•
<style>, <template> 태그에서는 일반적인 HTML/CSS와 다르게 Handlebars.js 문법 일부를 지원해요.
•
Handlebars.js 문법을 활용하면 <style>, <template> 태그 내에서 {{…}} 문법으로 컨텍스트(Context) 객체의 값에 접근하고 활용해서 사용자가 설정할 수 있는 블록을 제작할 수 있어요.
•
{{property.mySetting}}
{{property.myNested.mySetting}}
HTML
복사
<style>
{{#if property.showWelcome}}
p {
color: green;
}
{{/if}}
</style>
<template>
{{#if property.showWelcome}}
<p>만나서 반가워요!</p>
{{else}}
<p>인사는 생략할게요...</p>
{{/if}}
</template>
HTML
복사
{{#if}} {{else}} 문법 (+{{#unless}})
•
{{#if}} {{else}} 구문으로 아주 간단한 분기 처리를 할 수 있어요.
•
{{#if}} 가 있으면 {{/if}} 로 항상 닫혀야 해요.
•
{{else}} 구문은 필요한 경우에만 중간에 끼워서 사용할 수 있어요.
•
{{#if}} 구문에서는 false, undefined, null, "", 0, [] 값들은 모두 거짓 값(Falsy)으로 취급돼요.
•
아직은 {{#if}} 구문에서 비교 연산자(동일성 비교, 부등호 비교 등)를 지원하지 않고 있어요.
•
{{#if}} 와 비슷하지만 논리 연산이 반대인 문법으로 {{#unless}} 도 있어요.