SlideShare ist ein Scribd-Unternehmen logo
1 von 57
Downloaden Sie, um offline zu lesen
컴포넌트 관점에서 개발하기
2017 프론트엔드 트렌드&인사이트
주우영
프런트엔드 개발 시작하기
네이버는 이렇게 한다!, 위키북스
JavaScript Promise
한빛 eBook, 한빛미디어
페이스북 프론트엔드개발 그룹 운영
https://www.facebook.com/groups/webfrontend/
레진엔터테인먼트 프론트엔드개발팀
오늘, 새로운 기술과
기능을 나열하기 보다
현대 UI 개발에 있어 중요히
여기는 부분에 대해 이야기합니다.
현대 프레임워크의 공통된 접근법
컴포넌트 단위로 사고하고 디자인
import {Component} from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h1>Welcome to {{title}}</h1>
`,
styles: [`
h1 {
font-size: 4em;
}
`]
})
export class AppComponent {
title = 'app';
}
import {Component} from 'react';
const style = {
fontSize: '4em'
};
class HelloMessage extends Component {
static defaultProps = {
title: 'React'
};
render() {
return (
<h1 style={style}>
Welcome to {this.props.title}
</h1>
);
}
}
<style scoped>
h1 {
font-size: 4em;
}
</style>
<template>
<h1>Welcome to {{title}}</h1>
</template>
<script type="text/babel">
export default {
data () {
return {
title: 'Vue'
}
}
}
</script>
<dom-module id="hello-element">
<template>
<style>
h1 {font-size: 4em}
</style>
<h1>Welcome to {{title}}</h1>
</template>
<script>
class HelloElement extends Polymer.Element {
static get is() {return "hello-element";}
constructor() {
super();
this.title = "Polymer";
}
}
customElements.define(HelloElement.is, HelloElement);
</script>
</dom-module>
WHY
COMPONENT?
하나의 문제를 잘 해결하는
COMPONENT
프로그램
새로운 방법이 아닌
예로부터 모든 공학 분야의
공학자가 자주 사용해 오던
문제 해결 방법
Unix Philosophy
Write programs that do one thing and do it well.
Write programs to work together.
Doug Mcllroy, Unix pipeline inventor
The UNIX Philosophy in 9 paramount precepts
Mike Gancarz (a member of the team that designed the X Window System)
Small is beautiful.
Make each program do one thing well.
Write programs handle text streams, because that is a universal interface.
$ ps -ef
Processes Status
Report a snapshot of the current processes
$ grep gradle
Globally search a regular expression and print
Searching plain-text data sets for lines that match a regular expression
$ ps -ef | grep gradle
사고의 분산을 막고 하나의 문제에 집중함으로써
효율적으로 개발할 수 있다
설계의 오류를 쉽게 파악할 수 있고
상대적으로 테스트하기 쉽다
이식성을 높일 수 있고
변경에 유연하게 대체할 수 있다
API
UI는 자주적으로 동작하는 또 다른 프로그램,
그것을 API로 제어한다는 사고로 접근
자바스크립트를 개발할 때 우리는
_changeTabs() {
const fragment = this._parseFragment();
if (fragment === null) {
return;
}
_.each(fragment, (value, key) => {
const target = $(_.find(this.$sections, i => {
return $(i).dataset('type') === key);
});
// 선택한 탭으로 변경한다.
target.find('.cs-tab li').removeClass('is-on');
target.find('.cs-tab li')
.has(`a[href='#${value}']`).addClass('is-on');
// 탭에 해당하는 목록으로 변경한다.
target.find('.cs-body').removeClass('is-on');
target.find(`.cs-body#cs-${key}-${value}`)
.addClass('is-on');
});
}
_changeTabs() {
const fragment = this._parseFragment();
if (fragment === null) {
return;
}
_.each(fragment, (value, key) => {
const target = $(_.find(this.$sections, i => {
return $(i).dataset('type') === key);
});
// 선택한 탭으로 변경한다.
target.find('.cs-tab li').removeClass('is-on');
target.find('.cs-tab li')
.has(`a[href='#${value}']`).addClass('is-on');
// 탭에 해당하는 목록으로 변경한다.
target.find('.cs-body').removeClass('is-on');
target.find(`.cs-body#cs-${key}-${value}`)
.addClass('is-on');
});
}
DOM을 직접 핸들링, 장황하고 UI의 형태를 한눈에
파악하기 힘듦
_changeTabs() {
const fragment = this._parseFragment();
if (fragment === null) {
return;
}
_.each(fragment, (value, key) => {
const target = $(_.find(this.$sections, i => {
return $(i).dataset('type') === key);
});
// 선택한 탭으로 변경한다.
target.find('.cs-tab li').removeClass('is-on');
target.find('.cs-tab li')
.has(`a[href='#${value}']`).addClass('is-on');
// 탭에 해당하는 목록으로 변경한다.
target.find('.cs-body').removeClass('is-on');
target.find(`.cs-body#cs-${key}-${value}`)
.addClass('is-on');
});
}
상태를 class나 data attr에 설정 및 사용하여
전체적인 상태 흐름을 알기 힘듦
_changeTabs() {
const fragment = this._parseFragment();
if (fragment === null) {
return;
}
_.each(fragment, (value, key) => {
const target = $(_.find(this.$sections, i => {
return $(i).dataset('type') === key);
});
// 선택한 탭으로 변경한다.
target.find('.cs-tab li').removeClass('is-on');
target.find('.cs-tab li')
.has(`a[href='#${value}']`).addClass('is-on');
// 탭에 해당하는 목록으로 변경한다.
target.find('.cs-body').removeClass('is-on');
target.find(`.cs-body#cs-${key}-${value}`)
.addClass('is-on');
});
}
DOM API의 비용은 비쌈. 상태 변화를 위해 

DOM API 호출이 남용됨
_changeTabs() {
const fragment = this._parseFragment();
if (fragment === null) {
return;
}
_.each(fragment, (value, key) => {
const target = $(_.find(this.$sections, i => {
return $(i).dataset('type') === key);
});
// 선택한 탭으로 변경한다.
target.find('.cs-tab li').removeClass('is-on');
target.find('.cs-tab li')
.has(`a[href='#${value}']`).addClass('is-on');
// 탭에 해당하는 목록으로 변경한다.
target.find('.cs-body').removeClass('is-on');
target.find(`.cs-body#cs-${key}-${value}`)
.addClass('is-on');
});
}
UI 상태 변화를 위한 render 외의 부가적 메서드
다량 정의
프리젠테이션 로직은 크고 복잡.
테스트하고 유지보수하기 괴롭다
Functional Programming
컴포넌트 접근법은 함수형 프로그래밍하고도 관련이 깊다
부작용(Side effect)없이 하나의 일을 잘 수행하는 함수
그러한 함수를 조합 / 구성함으로써 큰 문제를 해결
F2 F3 F4 F5F1
{

“type”: “oval”,

“size”: 32

}
Functional Programming and UI Component
View = Function(state)
function Header({title, desc}) {
return (
<header className="header">
<div className="header__inner">
<h1 className="header__title">{title}</h1>
<p className="header__description">{desc}</p>
</div>
</header>
);
}
View = Function(state)
REMEMBER
Header({
title: 'Hello World!',
desc: 'This is Awesome.'
});
<header class="...">
<div class="...">
<h1 class="...">Hello World!</h1>
<p class="...">This is Awesome.</p>
</div>
</header>
<header class="...">
<div class="...">
<h1 class="...">Hello World!</h1>
<p class="...">This is Awesome</p>
</div>
</header>
<header class="...">
<div class="...">
<h1 class="...">Welcome</h1>
<p class="...">This is Awesome</p>
</div>
</header>
Equal?
<header class="...">
<div class="...">
<h1 class="...">Hello World!</h1>
<p class="...">This is Awesome</p>
</div>
</header>
<header class="...">
<div class="...">
<h1 class="...">Welcome</h1>
<p class="...">This is Awesome</p>
</div>
</header>
Equal?
<header class="...">
<div class="...">
<h1 class="...">Hello World!</h1>
<p class="...">This is Awesome</p>
</div>
</header>
<header class="...">
<div class="...">
<h1 class="...">Welcome</h1>
<p class="...">This is Awesome</p>
</div>
</header>
Equal? FAIL
Snapshot Testing with Jest
HTML(TMPL), CSS, 자바스크립트를 분리하는게
당연한 관심사의 분리라고 생각
과거 우리는.
Templates separate technologies, not concerns.
템플릿은 기술의 분리일 뿐 관심사의 분리가 아니다.
Pete Hunt, React developer
페이트 헌트, 리액트 개발자
“
”
KingCard Component
중요한건 해결하고자 하는 문제
같은 문제를 해결한다면 관심사는 같다
이때, 분리된 환경 보다
한 곳에 있는 경우가 훨씬 수월하다
관심사가 같다면 수정 시,
함께 수정해야 할 확률이 높다
HTML, CSS를 어떻게든 셋팅한 후
자바스크립트를 이어서 테스트
UI 테스트에 대한 자원 준비 없이
곧바로 컴포넌트를 테스트
Test IconText Component
it('iconDirection 속성에 left를 지정하면 아이콘이 좌측에 배치된다.', () => {
// Given
// When
const wrapper = shallow(
<IconText
label="친구초대"
icon="add-friend"
iconDirection="left"
/>
);
// Then
const children = wrapper.children('.icon-text__inner').children();
expect(children.first()).to.have.className('icon-text__icon');
expect(children.last()).to.have.className('icon-text__label');
});
"## Header
$ "## Header.js
$ "## Header.test.js
$ %## style.scss
"## TallCard
$ "## TallCard.js
$ "## TallCard.test.js
$ %## style.scss
"## KingCard
$ "## KingCard.js
$ "## KingCard.test.js
$ %## style.scss
%## StickyBar
"## StickyBar.js
"## StickyBar.test.js
%## style.scss
따라서 관련있는 것은
최대한 가까이에 두는
구조가 현재 유행
const Button = (props) => (
<button className={'large' in props && 'large'}>
{props.children}
<style jsx>{`
button {
padding: 20px;
background: #eee;
color: #999
}
.large {
padding: 50px
}
`}</style>
</button>
);
또는 하나의 파일 내 모든 관심사를
작성하는 방식도 선호
뭘 좀 만들어 봅시다.
이런 UI를 개발해 달라고 했을때
가장 먼저 한가지 일을 수행하는
최소 단위를 분석
뭘 좀 만들어 봅시다.
이런 UI를 개발해 달라고 했을때
가장 먼저 한가지 일을 수행하는
최소 단위를 분석
뭘 좀 만들어 봅시다.
이런 UI를 개발해 달라고 했을때
가장 먼저 한가지 일을 수행하는
최소 단위를 분석
뭘 좀 만들어 봅시다.
이런 UI를 개발해 달라고 했을때
가장 먼저 한가지 일을 수행하는
최소 단위를 분석
<TallCard/>
를 만들어 봅시다.
BEM(Block, Element, Modifier)
컴포넌트와 어울리게 마크업하기
Block
애플리케이션의 구성 요소로서 독립된 존재
Element
블록을 구성하는 작은 단위 또는 자식 개체
Modifier
블록이나 요소의 테마, 동작을 표현
Block
TallCard
Element
Information
Modifier
BadgeUp
Thumbnail
tall-card
tall-card__badge
tall-card__badge-up
tall-card__thumbnail
tall-card__image
tall-card__information
tall-card__title
tall-card__meta
tall-card__meta-key
tall-card__meta-value
BEM tree
BEM(Block, Element, Modifier)
컴포넌트와 어울리게 마크업하기
<div class="tall-card tall-card_badge_up">
<div class="tall-card__badge">
<i class=“tall-card__badge-up">
<span class="blind">UP</span>
</i>
</div>
<div class="tall-card__thumbnail">
<img class="tall-card__image" src="" alt=""/>
</div>
<div className="tall-card__information">
<h5 className="tall-card__title">레바툰</h5>
<dl class="tall-card__meta">
<dt class=“tall-card__meta-key">장르</dt>
<dd class=“tall-card__meta-value">개그 / 일상</dd>
<dt class=“tall-card__meta-key">작가</dt>
<dd class=“tall-card__meta-value">레바</dd>
</dl>
</div>
</div>
Markup with BEM
const TallCard = ({title, image, badge, metadata = []}) => (
<div className={`tall-card ${badge === 'up' ? ‘tall-card_badge_up' … `}>
<div className="tall-card__badge">
<i className=“tall-card__badge-up”/>
</div>
<div className="tall-card__thumbnail">
<img className="…" src={image} alt={`${title}의 썸네일`}/>
</div>
<div className="tall-card__information">
<h5 className="tall-card__title">{title}</h5>
{metadata.length > 0 ? (
<dl className=“tall-card__meta">
${metadata.map(({key, value}) => ([
<dt className=“tall-card__meta-key">{key}</dt>,
<dt className=“tall-card__meta-key">{value}</dt>
]))}
</dl>
) : null}
</div>
</div>
);
Create React Component
$module: 'icon-text';
.#{$module} {
&__badge {
/*...*/
&__up {/*...*/}
}
&__thumbnail {
/*...*/
&__image {/*...*/}
}
&__information {/*...*/}
&__title {/*...*/}
&__meta {/*…*/}
&__meta-key {/*...*/}
&__mata-value {/*...*/}
}
Styling with SASS
SASS의 interpolation은
컴포넌트 접근법과 잘 어울린다
스타일링 영역을 문법적으로
명확히 표현할 수 있다
"## TallCard
"## TallCard.js
%## TallCard.scss
"## TallCard
"## TallCard.js
"## TallCard.html
%## TallCard.scss
File structure
마크업 코드를 템플릿으로 분리한 경우
마크업을 자바스크립트에 포함한 경우
Context Free
<CardGroup/><SquareCard/> type = subscriptions
상위 컴포넌트 스타일이 하위 컴포넌트 스타일에 영향을 주면 안된다
컴포넌트는 어떤 문맥에서든 자유로워야 한다
badge = up sensational = true
만약 특정 문맥에서 컴포넌트가 변화한다면 해당 컴포넌트에
Context Free
<SquareCard/>
badge = new
새로운 변환자(Modifier)를 추가한다
Context Free
<CardGroup/>
CardList 컴포넌트는 badge가 up인 SquareCard 컴포넌트를
자식 컴포넌트로 포함하고 있을 뿐이다
type = subscriptions
타인의 잣대에 얽매이면 행복할 수 없듯
컴포넌트 역시 특정 문맥에 얽매이면
행복할 수 없다
감사합니다.

Weitere ähnliche Inhalte

Was ist angesagt?

개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님
NAVER D2
 

Was ist angesagt? (20)

Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까? Facebook은 React를 왜 만들었을까?
Facebook은 React를 왜 만들었을까?
 
Introduction to ReactJS
Introduction to ReactJSIntroduction to ReactJS
Introduction to ReactJS
 
reactJS
reactJSreactJS
reactJS
 
Tech Talk on ReactJS
Tech Talk on ReactJSTech Talk on ReactJS
Tech Talk on ReactJS
 
Introduction to React JS
Introduction to React JSIntroduction to React JS
Introduction to React JS
 
파이썬 플라스크 이해하기
파이썬 플라스크 이해하기 파이썬 플라스크 이해하기
파이썬 플라스크 이해하기
 
React Js Simplified
React Js SimplifiedReact Js Simplified
React Js Simplified
 
Reactjs Basics
Reactjs BasicsReactjs Basics
Reactjs Basics
 
새해 일어난 일
새해 일어난 일새해 일어난 일
새해 일어난 일
 
React JS - Introduction
React JS - IntroductionReact JS - Introduction
React JS - Introduction
 
Intro to React
Intro to ReactIntro to React
Intro to React
 
Introduction à React JS
Introduction à React JSIntroduction à React JS
Introduction à React JS
 
개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님개발을잘하고싶어요-네이버랩스 송기선님
개발을잘하고싶어요-네이버랩스 송기선님
 
Webpack Introduction
Webpack IntroductionWebpack Introduction
Webpack Introduction
 
Introduction to Node.js
Introduction to Node.jsIntroduction to Node.js
Introduction to Node.js
 
IBM JVM 소개 - Oracle JVM 과 비교
IBM JVM 소개 - Oracle JVM 과 비교IBM JVM 소개 - Oracle JVM 과 비교
IBM JVM 소개 - Oracle JVM 과 비교
 
An introduction to Vue.js
An introduction to Vue.jsAn introduction to Vue.js
An introduction to Vue.js
 
Rethinking Best Practices
Rethinking Best PracticesRethinking Best Practices
Rethinking Best Practices
 
ReactJs
ReactJsReactJs
ReactJs
 
Learn react-js
Learn react-jsLearn react-js
Learn react-js
 

Andere mochten auch

JavaScript 2014 프론트엔드 기술 리뷰
JavaScript 2014 프론트엔드 기술 리뷰JavaScript 2014 프론트엔드 기술 리뷰
JavaScript 2014 프론트엔드 기술 리뷰
Kenu, GwangNam Heo
 

Andere mochten auch (13)

비전공자의 자바스크립트 도전기
비전공자의 자바스크립트 도전기비전공자의 자바스크립트 도전기
비전공자의 자바스크립트 도전기
 
퍼블리셔, 디자인을 퍼블리싱하다
퍼블리셔, 디자인을 퍼블리싱하다퍼블리셔, 디자인을 퍼블리싱하다
퍼블리셔, 디자인을 퍼블리싱하다
 
퍼블리셔, 디자인을 퍼블리싱하다
퍼블리셔, 디자인을 퍼블리싱하다퍼블리셔, 디자인을 퍼블리싱하다
퍼블리셔, 디자인을 퍼블리싱하다
 
하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기하코사세미나_캔버스 파이그래프 만들기
하코사세미나_캔버스 파이그래프 만들기
 
JavaScript 2014 프론트엔드 기술 리뷰
JavaScript 2014 프론트엔드 기술 리뷰JavaScript 2014 프론트엔드 기술 리뷰
JavaScript 2014 프론트엔드 기술 리뷰
 
Jquery핵심노토
Jquery핵심노토Jquery핵심노토
Jquery핵심노토
 
나의 jQuery 실력 향상기
나의 jQuery 실력 향상기나의 jQuery 실력 향상기
나의 jQuery 실력 향상기
 
프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트 프론트엔드 개발자의 자바스크립트
프론트엔드 개발자의 자바스크립트
 
JavaSript Template Engine
JavaSript Template EngineJavaSript Template Engine
JavaSript Template Engine
 
퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다퍼블리셔, 프론트엔드개발을 시작하다
퍼블리셔, 프론트엔드개발을 시작하다
 
알아봅시다, Polymer: Web Components & Web Animations
알아봅시다, Polymer: Web Components & Web Animations알아봅시다, Polymer: Web Components & Web Animations
알아봅시다, Polymer: Web Components & Web Animations
 
웹 Front-End 실무 이야기
웹 Front-End 실무 이야기웹 Front-End 실무 이야기
웹 Front-End 실무 이야기
 
[토크아이티] 프런트엔드 개발 시작하기 저자 특강
[토크아이티] 프런트엔드 개발 시작하기 저자 특강 [토크아이티] 프런트엔드 개발 시작하기 저자 특강
[토크아이티] 프런트엔드 개발 시작하기 저자 특강
 

Ähnlich wie 컴포넌트 관점에서 개발하기

(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
탑크리에듀(구로디지털단지역3번출구 2분거리)
 

Ähnlich wie 컴포넌트 관점에서 개발하기 (20)

ABC: 다시 생각하는 컴포넌트
ABC: 다시 생각하는 컴포넌트ABC: 다시 생각하는 컴포넌트
ABC: 다시 생각하는 컴포넌트
 
react-ko.pdf
react-ko.pdfreact-ko.pdf
react-ko.pdf
 
Django를 Django답게, Django로 뉴스 사이트 만들기
Django를 Django답게, Django로 뉴스 사이트 만들기Django를 Django답게, Django로 뉴스 사이트 만들기
Django를 Django답게, Django로 뉴스 사이트 만들기
 
Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005Working Effectively With Legacy Code - xp2005
Working Effectively With Legacy Code - xp2005
 
Java script 강의자료_ed13
Java script 강의자료_ed13Java script 강의자료_ed13
Java script 강의자료_ed13
 
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
[React-Native-Seoul] React-Native 초심자를 위한 실습위주의 간단한 소개 및 구현법 안내
 
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
애자일 테스트 프랙티스와 사례들 (부제: 협업의 힘)
 
ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는ReactJS | 서버와 클라이어트에서 동시에 사용하는
ReactJS | 서버와 클라이어트에서 동시에 사용하는
 
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 TestOkjsp 13주년 발표자료: 생존 프로그래밍 Test
Okjsp 13주년 발표자료: 생존 프로그래밍 Test
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
개발이 테스트를 만났을 때(Shift left testing)
개발이 테스트를 만났을 때(Shift left testing)개발이 테스트를 만났을 때(Shift left testing)
개발이 테스트를 만났을 때(Shift left testing)
 
김윤환_포트폴리오
김윤환_포트폴리오김윤환_포트폴리오
김윤환_포트폴리오
 
Express framework tutorial
Express framework tutorialExpress framework tutorial
Express framework tutorial
 
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
(스프링프레임워크 강좌)스프링부트개요 및 HelloWorld 따라하기
 
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기 GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
GDG DevFest 2017 Seoul 프론트엔드 모던 프레임워크 낱낱히 파헤치기
 
디자인 시스템 디자인하기
디자인 시스템 디자인하기디자인 시스템 디자인하기
디자인 시스템 디자인하기
 
[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱[114]angularvs react 김훈민손찬욱
[114]angularvs react 김훈민손찬욱
 
워드프레스 For 플러그인
워드프레스 For 플러그인워드프레스 For 플러그인
워드프레스 For 플러그인
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
XECon2015 :: [2-3] 홍성범 - XE3 Theme 제작 소개
XECon2015 :: [2-3] 홍성범 - XE3 Theme 제작 소개XECon2015 :: [2-3] 홍성범 - XE3 Theme 제작 소개
XECon2015 :: [2-3] 홍성범 - XE3 Theme 제작 소개
 

Mehr von 우영 주

아재가 젊은이에게 사랑받는 마크업을 하는 방법
아재가 젊은이에게 사랑받는 마크업을 하는 방법아재가 젊은이에게 사랑받는 마크업을 하는 방법
아재가 젊은이에게 사랑받는 마크업을 하는 방법
우영 주
 
Introduce Guetzli
Introduce GuetzliIntroduce Guetzli
Introduce Guetzli
우영 주
 
스코프와 실행문맥
스코프와 실행문맥스코프와 실행문맥
스코프와 실행문맥
우영 주
 
좋은 기능을 만드는 방법
좋은 기능을 만드는 방법좋은 기능을 만드는 방법
좋은 기능을 만드는 방법
우영 주
 
서비스를 성공적으로 만드는 방법
서비스를 성공적으로 만드는 방법서비스를 성공적으로 만드는 방법
서비스를 성공적으로 만드는 방법
우영 주
 
다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!
우영 주
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
우영 주
 
명세부터 깨우치는 FILEAPI
명세부터 깨우치는 FILEAPI명세부터 깨우치는 FILEAPI
명세부터 깨우치는 FILEAPI
우영 주
 

Mehr von 우영 주 (18)

스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리스트리밍과 디지털 권리 관리
스트리밍과 디지털 권리 관리
 
스트리밍과 플레이어
스트리밍과 플레이어스트리밍과 플레이어
스트리밍과 플레이어
 
프런트엔드개발, 지금과 다음
프런트엔드개발, 지금과 다음프런트엔드개발, 지금과 다음
프런트엔드개발, 지금과 다음
 
아재가 젊은이에게 사랑받는 마크업을 하는 방법
아재가 젊은이에게 사랑받는 마크업을 하는 방법아재가 젊은이에게 사랑받는 마크업을 하는 방법
아재가 젊은이에게 사랑받는 마크업을 하는 방법
 
Introduce Guetzli
Introduce GuetzliIntroduce Guetzli
Introduce Guetzli
 
스코프와 실행문맥
스코프와 실행문맥스코프와 실행문맥
스코프와 실행문맥
 
좋은 기능을 만드는 방법
좋은 기능을 만드는 방법좋은 기능을 만드는 방법
좋은 기능을 만드는 방법
 
서비스를 성공적으로 만드는 방법
서비스를 성공적으로 만드는 방법서비스를 성공적으로 만드는 방법
서비스를 성공적으로 만드는 방법
 
다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!다함께, FluxUtils 한바퀴!
다함께, FluxUtils 한바퀴!
 
BEM을 깨우치다.
BEM을 깨우치다.BEM을 깨우치다.
BEM을 깨우치다.
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
명세부터 깨우치는 FILEAPI
명세부터 깨우치는 FILEAPI명세부터 깨우치는 FILEAPI
명세부터 깨우치는 FILEAPI
 
[Toolcon2014] WebStorm에서 자바스크립트 리팩토링하기
[Toolcon2014] WebStorm에서 자바스크립트 리팩토링하기[Toolcon2014] WebStorm에서 자바스크립트 리팩토링하기
[Toolcon2014] WebStorm에서 자바스크립트 리팩토링하기
 
진보한 개발 환경에서 품질 좋은 코드 생산 (WebStorm)
진보한 개발 환경에서 품질 좋은 코드 생산 (WebStorm)진보한 개발 환경에서 품질 좋은 코드 생산 (WebStorm)
진보한 개발 환경에서 품질 좋은 코드 생산 (WebStorm)
 
Javascript Test Double Sinon.js
Javascript Test Double Sinon.jsJavascript Test Double Sinon.js
Javascript Test Double Sinon.js
 
LESS와 EMMET
LESS와 EMMETLESS와 EMMET
LESS와 EMMET
 
HTML5 BOILERPLATE를 소개합니다.
HTML5 BOILERPLATE를 소개합니다.HTML5 BOILERPLATE를 소개합니다.
HTML5 BOILERPLATE를 소개합니다.
 
이클립스로 GIT 사용하기
이클립스로 GIT 사용하기이클립스로 GIT 사용하기
이클립스로 GIT 사용하기
 

Kürzlich hochgeladen

Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
Wonjun Hwang
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
Wonjun Hwang
 

Kürzlich hochgeladen (6)

A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
 

컴포넌트 관점에서 개발하기

  • 1. 컴포넌트 관점에서 개발하기 2017 프론트엔드 트렌드&인사이트
  • 2. 주우영 프런트엔드 개발 시작하기 네이버는 이렇게 한다!, 위키북스 JavaScript Promise 한빛 eBook, 한빛미디어 페이스북 프론트엔드개발 그룹 운영 https://www.facebook.com/groups/webfrontend/ 레진엔터테인먼트 프론트엔드개발팀
  • 4. 현대 UI 개발에 있어 중요히 여기는 부분에 대해 이야기합니다.
  • 5. 현대 프레임워크의 공통된 접근법 컴포넌트 단위로 사고하고 디자인
  • 6. import {Component} from '@angular/core'; @Component({ selector: 'my-app', template: ` <h1>Welcome to {{title}}</h1> `, styles: [` h1 { font-size: 4em; } `] }) export class AppComponent { title = 'app'; }
  • 7. import {Component} from 'react'; const style = { fontSize: '4em' }; class HelloMessage extends Component { static defaultProps = { title: 'React' }; render() { return ( <h1 style={style}> Welcome to {this.props.title} </h1> ); } }
  • 8. <style scoped> h1 { font-size: 4em; } </style> <template> <h1>Welcome to {{title}}</h1> </template> <script type="text/babel"> export default { data () { return { title: 'Vue' } } } </script>
  • 9. <dom-module id="hello-element"> <template> <style> h1 {font-size: 4em} </style> <h1>Welcome to {{title}}</h1> </template> <script> class HelloElement extends Polymer.Element { static get is() {return "hello-element";} constructor() { super(); this.title = "Polymer"; } } customElements.define(HelloElement.is, HelloElement); </script> </dom-module>
  • 11. 하나의 문제를 잘 해결하는 COMPONENT 프로그램
  • 12. 새로운 방법이 아닌 예로부터 모든 공학 분야의 공학자가 자주 사용해 오던 문제 해결 방법
  • 13. Unix Philosophy Write programs that do one thing and do it well. Write programs to work together. Doug Mcllroy, Unix pipeline inventor The UNIX Philosophy in 9 paramount precepts Mike Gancarz (a member of the team that designed the X Window System) Small is beautiful. Make each program do one thing well. Write programs handle text streams, because that is a universal interface.
  • 14. $ ps -ef Processes Status Report a snapshot of the current processes $ grep gradle Globally search a regular expression and print Searching plain-text data sets for lines that match a regular expression $ ps -ef | grep gradle
  • 15. 사고의 분산을 막고 하나의 문제에 집중함으로써 효율적으로 개발할 수 있다
  • 16. 설계의 오류를 쉽게 파악할 수 있고 상대적으로 테스트하기 쉽다
  • 17. 이식성을 높일 수 있고 변경에 유연하게 대체할 수 있다
  • 18. API UI는 자주적으로 동작하는 또 다른 프로그램, 그것을 API로 제어한다는 사고로 접근 자바스크립트를 개발할 때 우리는
  • 19. _changeTabs() { const fragment = this._parseFragment(); if (fragment === null) { return; } _.each(fragment, (value, key) => { const target = $(_.find(this.$sections, i => { return $(i).dataset('type') === key); }); // 선택한 탭으로 변경한다. target.find('.cs-tab li').removeClass('is-on'); target.find('.cs-tab li') .has(`a[href='#${value}']`).addClass('is-on'); // 탭에 해당하는 목록으로 변경한다. target.find('.cs-body').removeClass('is-on'); target.find(`.cs-body#cs-${key}-${value}`) .addClass('is-on'); }); }
  • 20. _changeTabs() { const fragment = this._parseFragment(); if (fragment === null) { return; } _.each(fragment, (value, key) => { const target = $(_.find(this.$sections, i => { return $(i).dataset('type') === key); }); // 선택한 탭으로 변경한다. target.find('.cs-tab li').removeClass('is-on'); target.find('.cs-tab li') .has(`a[href='#${value}']`).addClass('is-on'); // 탭에 해당하는 목록으로 변경한다. target.find('.cs-body').removeClass('is-on'); target.find(`.cs-body#cs-${key}-${value}`) .addClass('is-on'); }); } DOM을 직접 핸들링, 장황하고 UI의 형태를 한눈에 파악하기 힘듦
  • 21. _changeTabs() { const fragment = this._parseFragment(); if (fragment === null) { return; } _.each(fragment, (value, key) => { const target = $(_.find(this.$sections, i => { return $(i).dataset('type') === key); }); // 선택한 탭으로 변경한다. target.find('.cs-tab li').removeClass('is-on'); target.find('.cs-tab li') .has(`a[href='#${value}']`).addClass('is-on'); // 탭에 해당하는 목록으로 변경한다. target.find('.cs-body').removeClass('is-on'); target.find(`.cs-body#cs-${key}-${value}`) .addClass('is-on'); }); } 상태를 class나 data attr에 설정 및 사용하여 전체적인 상태 흐름을 알기 힘듦
  • 22. _changeTabs() { const fragment = this._parseFragment(); if (fragment === null) { return; } _.each(fragment, (value, key) => { const target = $(_.find(this.$sections, i => { return $(i).dataset('type') === key); }); // 선택한 탭으로 변경한다. target.find('.cs-tab li').removeClass('is-on'); target.find('.cs-tab li') .has(`a[href='#${value}']`).addClass('is-on'); // 탭에 해당하는 목록으로 변경한다. target.find('.cs-body').removeClass('is-on'); target.find(`.cs-body#cs-${key}-${value}`) .addClass('is-on'); }); } DOM API의 비용은 비쌈. 상태 변화를 위해 
 DOM API 호출이 남용됨
  • 23. _changeTabs() { const fragment = this._parseFragment(); if (fragment === null) { return; } _.each(fragment, (value, key) => { const target = $(_.find(this.$sections, i => { return $(i).dataset('type') === key); }); // 선택한 탭으로 변경한다. target.find('.cs-tab li').removeClass('is-on'); target.find('.cs-tab li') .has(`a[href='#${value}']`).addClass('is-on'); // 탭에 해당하는 목록으로 변경한다. target.find('.cs-body').removeClass('is-on'); target.find(`.cs-body#cs-${key}-${value}`) .addClass('is-on'); }); } UI 상태 변화를 위한 render 외의 부가적 메서드 다량 정의
  • 24. 프리젠테이션 로직은 크고 복잡. 테스트하고 유지보수하기 괴롭다
  • 25. Functional Programming 컴포넌트 접근법은 함수형 프로그래밍하고도 관련이 깊다 부작용(Side effect)없이 하나의 일을 잘 수행하는 함수 그러한 함수를 조합 / 구성함으로써 큰 문제를 해결 F2 F3 F4 F5F1
  • 26. {
 “type”: “oval”,
 “size”: 32
 } Functional Programming and UI Component View = Function(state)
  • 27. function Header({title, desc}) { return ( <header className="header"> <div className="header__inner"> <h1 className="header__title">{title}</h1> <p className="header__description">{desc}</p> </div> </header> ); } View = Function(state) REMEMBER
  • 28. Header({ title: 'Hello World!', desc: 'This is Awesome.' }); <header class="..."> <div class="..."> <h1 class="...">Hello World!</h1> <p class="...">This is Awesome.</p> </div> </header>
  • 29. <header class="..."> <div class="..."> <h1 class="...">Hello World!</h1> <p class="...">This is Awesome</p> </div> </header> <header class="..."> <div class="..."> <h1 class="...">Welcome</h1> <p class="...">This is Awesome</p> </div> </header> Equal?
  • 30. <header class="..."> <div class="..."> <h1 class="...">Hello World!</h1> <p class="...">This is Awesome</p> </div> </header> <header class="..."> <div class="..."> <h1 class="...">Welcome</h1> <p class="...">This is Awesome</p> </div> </header> Equal?
  • 31. <header class="..."> <div class="..."> <h1 class="...">Hello World!</h1> <p class="...">This is Awesome</p> </div> </header> <header class="..."> <div class="..."> <h1 class="...">Welcome</h1> <p class="...">This is Awesome</p> </div> </header> Equal? FAIL
  • 33. HTML(TMPL), CSS, 자바스크립트를 분리하는게 당연한 관심사의 분리라고 생각 과거 우리는.
  • 34. Templates separate technologies, not concerns. 템플릿은 기술의 분리일 뿐 관심사의 분리가 아니다. Pete Hunt, React developer 페이트 헌트, 리액트 개발자 “ ”
  • 35.
  • 36.
  • 37. KingCard Component 중요한건 해결하고자 하는 문제 같은 문제를 해결한다면 관심사는 같다
  • 38. 이때, 분리된 환경 보다 한 곳에 있는 경우가 훨씬 수월하다 관심사가 같다면 수정 시, 함께 수정해야 할 확률이 높다
  • 39. HTML, CSS를 어떻게든 셋팅한 후 자바스크립트를 이어서 테스트 UI 테스트에 대한 자원 준비 없이 곧바로 컴포넌트를 테스트
  • 40. Test IconText Component it('iconDirection 속성에 left를 지정하면 아이콘이 좌측에 배치된다.', () => { // Given // When const wrapper = shallow( <IconText label="친구초대" icon="add-friend" iconDirection="left" /> ); // Then const children = wrapper.children('.icon-text__inner').children(); expect(children.first()).to.have.className('icon-text__icon'); expect(children.last()).to.have.className('icon-text__label'); });
  • 41. "## Header $ "## Header.js $ "## Header.test.js $ %## style.scss "## TallCard $ "## TallCard.js $ "## TallCard.test.js $ %## style.scss "## KingCard $ "## KingCard.js $ "## KingCard.test.js $ %## style.scss %## StickyBar "## StickyBar.js "## StickyBar.test.js %## style.scss 따라서 관련있는 것은 최대한 가까이에 두는 구조가 현재 유행
  • 42. const Button = (props) => ( <button className={'large' in props && 'large'}> {props.children} <style jsx>{` button { padding: 20px; background: #eee; color: #999 } .large { padding: 50px } `}</style> </button> ); 또는 하나의 파일 내 모든 관심사를 작성하는 방식도 선호
  • 43. 뭘 좀 만들어 봅시다. 이런 UI를 개발해 달라고 했을때 가장 먼저 한가지 일을 수행하는 최소 단위를 분석
  • 44. 뭘 좀 만들어 봅시다. 이런 UI를 개발해 달라고 했을때 가장 먼저 한가지 일을 수행하는 최소 단위를 분석
  • 45. 뭘 좀 만들어 봅시다. 이런 UI를 개발해 달라고 했을때 가장 먼저 한가지 일을 수행하는 최소 단위를 분석
  • 46. 뭘 좀 만들어 봅시다. 이런 UI를 개발해 달라고 했을때 가장 먼저 한가지 일을 수행하는 최소 단위를 분석 <TallCard/> 를 만들어 봅시다.
  • 47. BEM(Block, Element, Modifier) 컴포넌트와 어울리게 마크업하기 Block 애플리케이션의 구성 요소로서 독립된 존재 Element 블록을 구성하는 작은 단위 또는 자식 개체 Modifier 블록이나 요소의 테마, 동작을 표현
  • 49. <div class="tall-card tall-card_badge_up"> <div class="tall-card__badge"> <i class=“tall-card__badge-up"> <span class="blind">UP</span> </i> </div> <div class="tall-card__thumbnail"> <img class="tall-card__image" src="" alt=""/> </div> <div className="tall-card__information"> <h5 className="tall-card__title">레바툰</h5> <dl class="tall-card__meta"> <dt class=“tall-card__meta-key">장르</dt> <dd class=“tall-card__meta-value">개그 / 일상</dd> <dt class=“tall-card__meta-key">작가</dt> <dd class=“tall-card__meta-value">레바</dd> </dl> </div> </div> Markup with BEM
  • 50. const TallCard = ({title, image, badge, metadata = []}) => ( <div className={`tall-card ${badge === 'up' ? ‘tall-card_badge_up' … `}> <div className="tall-card__badge"> <i className=“tall-card__badge-up”/> </div> <div className="tall-card__thumbnail"> <img className="…" src={image} alt={`${title}의 썸네일`}/> </div> <div className="tall-card__information"> <h5 className="tall-card__title">{title}</h5> {metadata.length > 0 ? ( <dl className=“tall-card__meta"> ${metadata.map(({key, value}) => ([ <dt className=“tall-card__meta-key">{key}</dt>, <dt className=“tall-card__meta-key">{value}</dt> ]))} </dl> ) : null} </div> </div> ); Create React Component
  • 51. $module: 'icon-text'; .#{$module} { &__badge { /*...*/ &__up {/*...*/} } &__thumbnail { /*...*/ &__image {/*...*/} } &__information {/*...*/} &__title {/*...*/} &__meta {/*…*/} &__meta-key {/*...*/} &__mata-value {/*...*/} } Styling with SASS SASS의 interpolation은 컴포넌트 접근법과 잘 어울린다 스타일링 영역을 문법적으로 명확히 표현할 수 있다
  • 52. "## TallCard "## TallCard.js %## TallCard.scss "## TallCard "## TallCard.js "## TallCard.html %## TallCard.scss File structure 마크업 코드를 템플릿으로 분리한 경우 마크업을 자바스크립트에 포함한 경우
  • 53. Context Free <CardGroup/><SquareCard/> type = subscriptions 상위 컴포넌트 스타일이 하위 컴포넌트 스타일에 영향을 주면 안된다 컴포넌트는 어떤 문맥에서든 자유로워야 한다
  • 54. badge = up sensational = true 만약 특정 문맥에서 컴포넌트가 변화한다면 해당 컴포넌트에 Context Free <SquareCard/> badge = new 새로운 변환자(Modifier)를 추가한다
  • 55. Context Free <CardGroup/> CardList 컴포넌트는 badge가 up인 SquareCard 컴포넌트를 자식 컴포넌트로 포함하고 있을 뿐이다 type = subscriptions
  • 56. 타인의 잣대에 얽매이면 행복할 수 없듯 컴포넌트 역시 특정 문맥에 얽매이면 행복할 수 없다