1. 소개
머티리얼 구성요소(MDC)를 통해 개발자는 머티리얼 디자인을 구현할 수 있습니다. Google의 엔지니어와 UX 디자이너로 구성된 팀에서 만든 MDC는 아름답고 기능적인 수십 가지의 UI 구성요소가 특징이며 Android, iOS, 웹, Flutter.material.io/develop에서 제공됩니다. |
MDC Web은 Material Design 원칙을 준수하면서 모든 프런트엔드 프레임워크에 통합되도록 설계되었습니다. 다음 Codelab에서는 MDC Web을 기반으로 하는 React 구성요소를 빌드하는 방법을 안내합니다. 이 Codelab에서 배운 원칙은 모든 JavaScript 프레임워크에 적용할 수 있습니다.
MDC 웹 빌드 방법
MDC Web의 JavaScript 레이어는 구성요소당 3개의 클래스(Component, Foundation, Adapter)로 구성됩니다. 이 패턴을 통해 MDC 웹은 프런트엔드 프레임워크와 유연하게 통합할 수 있습니다.
Foundation에는 Material Design을 구현하는 비즈니스 로직이 포함되어 있습니다. Foundation은 HTML 요소를 참조하지 않습니다. 이렇게 하면 HTML 상호작용 로직을 어댑터로 추상화할 수 있습니다. Foundation에는 어댑터가 있습니다.
어댑터는 인터페이스입니다. 어댑터 인터페이스는 Material Design 비즈니스 로직을 구현하기 위해 Foundation에서 참조합니다. Angular 또는 React와 같은 다양한 프레임워크에서 Adapter를 구현할 수 있습니다. 어댑터의 구현은 DOM 구조와 상호작용합니다.
구성요소에는 기초가 있으며, 그 역할은
- 프레임워크 외 JavaScript를 사용하여 어댑터를 구현합니다.
- Foundation의 메서드에 프록시하는 공개 메서드를 제공합니다.
MDC Web에서 제공하는 기능
MDC 웹의 모든 패키지는 구성요소, 기초, 어댑터와 함께 제공됩니다. 구성요소를 인스턴스화하려면 루트 요소를 구성요소의 생성자 메서드에 전달해야 합니다. 구성요소는 DOM 및 HTML 요소와 상호작용하는 어댑터를 구현합니다. 그런 다음 구성요소는 Foundation을 인스턴스화하고 Adapter 메서드를 호출합니다.
MDC 웹을 프레임워크에 통합하려면 해당 프레임워크의 언어/구문으로 자체 구성요소를 만들어야 합니다. 프레임워크 구성요소는 MDC Web의 어댑터를 구현하고 MDC Web의 Foundation을 사용합니다.
빌드할 항목
이 Codelab에서는 Foundation 로직을 사용하여 Material Design React 구성요소를 구현하는 맞춤 어댑터를 빌드하는 방법을 보여줍니다. 프레임워크에 통합에 있는 고급 주제를 다룹니다. 이 Codelab에서는 React를 프레임워크의 예로 사용하지만 이 접근 방식은 다른 모든 프레임워크에 적용할 수 있습니다.
이 Codelab에서는 상단 앱 바를 빌드하고 상단 앱 바 데모 페이지를 다시 만듭니다. 상단 앱 바 작업을 시작할 수 있도록 데모 페이지 레이아웃이 이미 설정되어 있습니다. 상단 앱 바에는 다음이 포함됩니다.
- 탐색 아이콘
- 작업 항목
- 짧은 변형, 항상 접히는 변형, 고정, 눈에 띄는 변형의 4가지 변형을 사용할 수 있습니다.
필요한 항목:
- 최신 버전의 Node.js (JavaScript 패키지 관리자인 npm과 번들로 제공됨)
- 샘플 코드 (다음 단계에서 다운로드)
- HTML, CSS, JavaScript, React에 대한 기본 지식
웹 개발 경험 수준을 평가해 주세요.
2. 개발 환경 설정
시작 Codelab 앱 다운로드
시작 앱은 material-components-web-codelabs-master/mdc-112/starter
디렉터리에 있습니다.
...또는 GitHub에서 클론
이 Codelab을 GitHub에서 클론하려면 다음 명령어를 실행하세요.
git clone https://github.com/material-components/material-components-web-codelabs
cd material-components-web-codelabs/mdc-112/starter
프로젝트 종속 항목 설치
시작 디렉터리 material-components-web-codelabs/mdc-112/starter
에서 다음을 실행합니다.
npm install
많은 활동이 표시될 것이며 최종적으로 터미널에 설치가 완료된 것으로 표시됩니다.
시작 앱 실행
동일한 디렉터리에서 다음을 실행합니다.
npm start
webpack-dev-server
이(가) 시작됩니다. 브라우저에서 http://localhost:8080/에 접속하여 페이지를 확인합니다.
완료되었습니다. 상단 앱 바 React 데모 페이지의 시작 코드가 브라우저에서 실행 중이어야 합니다. lorem ipsum 텍스트, 컨트롤 상자 (오른쪽 하단), 완성되지 않은 상단 앱 바가 표시됩니다.
코드 및 프로젝트 살펴보기
코드 편집기를 열면 프로젝트 디렉터리가 다음과 같이 표시됩니다.
App.js
파일을 열고 <TopAppBar>
구성요소가 포함된 render
메서드를 확인합니다.
App.js
render() {
const {isFixed, isShort, isRtl, isProminent, isAlwaysCollapsed, shouldReinit} = this.state;
return (
<section
dir={isRtl ? 'rtl' : 'ltr'}
className='mdc-typography'>
{
shouldReinit ? null :
<TopAppBar
navIcon={this.renderNavIcon()}
short={isShort}
prominent={isProminent}
fixed={isFixed}
alwaysCollapsed={isAlwaysCollapsed}
title='Mountain View, CA'
actionItems={this.actionItems}
/>
}
<div className={classnames('mdc-top-app-bar--fixed-adjust', {
'mdc-top-app-bar--short-fixed-adjust': isShort || isAlwaysCollapsed,
'mdc-top-app-bar--prominent-fixed-adjust': isProminent,
})}>
{this.renderDemoParagraphs()}
</div>
{this.renderControls()}
</section>
);
}
이는 애플리케이션의 TopAppBar
진입점입니다.
render
메서드가 있는 맨 React Component
클래스인 TopAppBar.js
파일을 엽니다.
TopAppBar.js
import React from 'react';
export default class TopAppBar extends React.Component {
render() {
return (
<header>
TOP APP BAR
</header>
);
}
}
3. 구성요소 구성
React에서 render
메서드는 구성요소의 HTML을 출력합니다. 상단 앱 바 구성요소는 <header />
태그를 렌더링하며 다음과 같은 두 가지 주요 섹션으로 구성됩니다.
- 탐색 아이콘 및 제목 섹션
- 작업 아이콘 섹션
상단 앱 바를 구성하는 요소에 관해 궁금한 점이 있으면 GitHub의 문서를 참고하세요.
TopAppBar.js
의 render()
메서드를 다음과 같이 수정합니다.
render() {
const {
title,
navIcon,
} = this.props;
return (
<header
className={this.classes}
style={this.getMergedStyles()}
ref={this.topAppBarElement}
>
<div className='mdc-top-app-bar__row'>
<section className='mdc-top-app-bar__section mdc-top-app-bar__section--align-start'>
{navIcon ? navIcon : null}
<span className="mdc-top-app-bar__title">
{title}
</span>
</section>
{this.renderActionItems()}
</div>
</header>
);
}
이 HTML에는 두 개의 섹션 요소가 있습니다. 첫 번째 요소에는 탐색 아이콘과 제목이 포함되어 있습니다. 두 번째에는 작업 아이콘이 포함되어 있습니다.
다음으로 renderActionItems
메서드를 추가합니다.
renderActionItems() {
const {actionItems} = this.props;
if (!actionItems) {
return;
}
return (
<section className='mdc-top-app-bar__section mdc-top-app-bar__section--align-end' role='toolbar'>
{/* need to clone element to set key */}
{actionItems.map((item, key) => React.cloneElement(item, {key}))}
</section>
);
}
개발자는 TopAppBar
를 React 애플리케이션으로 가져와 TopAppBar
요소에 작업 아이콘을 전달합니다. App.js
에서 TopAppBar
를 초기화하는 예시 코드를 확인할 수 있습니다.
render
메서드에서 사용되는 getMergedStyles
메서드가 누락되었습니다. TopAppBar
클래스에 다음 JavaScript 메서드를 추가하세요.
getMergedStyles = () => {
const {style} = this.props;
const {style: internalStyle} = this.state;
return Object.assign({}, internalStyle, style);
}
this.classes
도 render
메서드에서 누락되었지만 나중에 다룹니다. 누락된 getter 메서드 this.classes
외에도 상단 앱 바가 올바르게 렌더링되기 전에 구현해야 하는 TopAppBar
의 일부가 아직 있습니다.
상단 앱 바에서 여전히 누락된 React 구성요소는 다음과 같습니다.
- 초기화된 기반
- 기반에 전달할 어댑터 메서드
- JSX 마크업
- 변형 관리 (고정됨, 짧음, 항상 접힘, 눈에 띄게 표시됨)
접근 방식
- Adapter 메서드를 구현합니다.
componentDidMount
에서 기초를 초기화합니다.componentWillUnmount
에서 Foundation.destroy 메서드를 호출합니다.- 적절한 클래스 이름을 결합하는 getter 메서드를 통해 변형 관리를 설정합니다.
4. 어댑터 메서드 구현
프레임워크 외 JS TopAppBar
구성요소는 다음 어댑터 메서드를 구현합니다 (여기에 자세히 나열됨).
hasClass()
addClass()
removeClass()
registerNavigationIconInteractionHandler()
deregisterNavigationIconInteractionHandler()
notifyNavigationIconClicked()
setStyle()
getTopAppBarHeight()
registerScrollHandler()
deregisterScrollHandler()
registerResizeHandler()
deregisterResizeHandler()
getViewportScrollY()
getTotalActionItems()
React에는 합성 이벤트와 다양한 권장 코딩 관행 및 패턴이 있으므로 어댑터 메서드를 다시 구현해야 합니다.
어댑터 getter 메서드
TopAppBar.js
파일에서 TopAppBar
에 다음 JavaScript 메서드를 추가합니다.
get adapter() {
const {actionItems} = this.props;
return {
hasClass: (className) => this.classes.split(' ').includes(className),
addClass: (className) => this.setState({classList: this.state.classList.add(className)}),
removeClass: (className) => {
const {classList} = this.state;
classList.delete(className);
this.setState({classList});
},
setStyle: this.setStyle,
getTopAppBarHeight: () => this.topAppBarElement.current.clientHeight,
registerScrollHandler: (handler) => window.addEventListener('scroll', handler),
deregisterScrollHandler: (handler) => window.removeEventListener('scroll', handler),
registerResizeHandler: (handler) => window.addEventListener('resize', handler),
deregisterResizeHandler: (handler) => window.removeEventListener('resize', handler),
getViewportScrollY: () => window.pageYOffset,
getTotalActionItems: () => actionItems && actionItems.length,
};
}
스크롤 및 크기 조절 이벤트 등록을 위한 어댑터 API는 프레임워크 외 JS 버전과 동일하게 구현됩니다. React에는 스크롤 또는 크기 조절을 위한 합성 이벤트가 없으며 네이티브 DOM 이벤트 시스템을 사용하기 때문입니다. 또한 getViewPortScrollY
는 React의 API가 아닌 window
객체의 함수이므로 네이티브 DOM을 따라야 합니다. 어댑터 구현은 프레임워크마다 다릅니다.
get adapter
메서드에서 호출하는 this.setStyle
가 누락되었을 수도 있습니다. TopAppBar.js
파일에서 누락된 JavaScript 메서드를 TopAppBar
클래스에 추가합니다.
setStyle = (varName, value) => {
const updatedStyle = Object.assign({}, this.state.style);
updatedStyle[varName] = value;
this.setState({style: updatedStyle});
}
어댑터를 구현했습니다. 이 시점에서 전체 구현이 아직 완료되지 않았으므로 콘솔에 오류가 표시될 수 있습니다. 다음 섹션에서는 CSS 클래스를 추가하고 삭제하는 방법을 안내합니다.
5. 구성요소 메서드 구현
변형 및 클래스 관리
React에는 클래스를 관리하는 API가 없습니다. 네이티브 JavaScript의 추가/삭제 CSS 클래스 메서드를 모방하려면 classList
상태 변수를 추가합니다. TopAppBar
에는 CSS 클래스와 상호작용하는 세 가지 코드가 있습니다.
className
속성을 통한<TopAppBar />
구성요소addClass
또는removeClass
를 통한 어댑터 메서드<TopAppBar />
React 구성요소 내에 하드 코딩되어 있습니다.
먼저 TopAppBar.js
상단의 기존 가져오기 아래에 다음 가져오기를 추가합니다.
import classnames from 'classnames';
그런 다음 TopAppBar
구성요소의 클래스 선언 내에 다음 코드를 추가합니다.
export default class TopAppBar extends React.Component {
constructor(props) {
super(props);
this.topAppBarElement = React.createRef();
}
state = {
classList: new Set(),
style: {},
};
get classes() {
const {classList} = this.state;
const {
alwaysCollapsed,
className,
short,
fixed,
prominent,
} = this.props;
return classnames('mdc-top-app-bar', Array.from(classList), className, {
'mdc-top-app-bar--fixed': fixed,
'mdc-top-app-bar--short': short,
'mdc-top-app-bar--short-collapsed': alwaysCollapsed,
'mdc-top-app-bar--prominent': prominent,
});
}
...
}
http://localhost:8080으로 이동하면 이제 컨트롤 체크박스가 DOM에서 클래스 이름을 켜거나 끌 수 있습니다.
이 코드를 사용하면 많은 개발자가 TopAppBar
를 사용할 수 있습니다. 개발자는 CSS 클래스의 구현 세부정보에 관해 걱정하지 않고 TopAppBar
API와 상호작용할 수 있습니다.
이제 어댑터를 구현했습니다. 다음 섹션에서는 기초를 인스턴스화하는 방법을 설명합니다.
구성요소 마운트 및 마운트 해제
Foundation 인스턴스화는 componentDidMount
메서드에서 발생합니다.
먼저 TopAppBar.js
의 기존 가져오기 뒤에 다음 가져오기를 추가하여 MDC 상단 앱 바 기반을 가져옵니다.
import {MDCTopAppBarFoundation, MDCFixedTopAppBarFoundation, MDCShortTopAppBarFoundation} from '@material/top-app-bar';
다음으로 TopAppBar
클래스에 다음 JavaScript 코드를 추가합니다.
export default class TopAppBar extends React.Component {
...
foundation_ = null;
componentDidMount() {
this.initializeFoundation();
}
componentWillUnmount() {
this.foundation_.destroy();
}
initializeFoundation = () => {
if (this.props.short) {
this.foundation_ = new MDCShortTopAppBarFoundation(this.adapter);
} else if (this.props.fixed) {
this.foundation_ = new MDCFixedTopAppBarFoundation(this.adapter);
} else {
this.foundation_ = new MDCTopAppBarFoundation(this.adapter);
}
this.foundation_.init();
}
...
}
한 가지 좋은 React 코딩 방법은 propTypes 및 defaultProps를 정의하는 것입니다. TopAppBar.js의 기존 가져오기 뒤에 다음 가져오기를 추가합니다.
import PropTypes from 'prop-types';
그런 다음 TopAppBar.js
하단의 구성요소 클래스 뒤에 다음 코드를 추가합니다.
import PropTypes from 'prop-types';
TopAppBar.propTypes = {
alwaysCollapsed: PropTypes.bool,
short: PropTypes.bool,
fixed: PropTypes.bool,
prominent: PropTypes.bool,
title: PropTypes.string,
actionItems: PropTypes.arrayOf(PropTypes.element),
navIcon: PropTypes.element,
};
TopAppBar.defaultProps = {
alwaysCollapsed: false,
short: false,
fixed: false,
prominent: false,
title: '',
actionItems: null,
navIcon: null,
};
이제 상단 앱 바 React 구성요소를 구현했습니다. http://localhost:8080으로 이동하면 데모 페이지를 사용할 수 있습니다. 데모 페이지는 MDC 웹의 데모 페이지와 동일하게 작동합니다. 데모 페이지는 다음과 같이 표시됩니다.
6. 마무리
이 튜토리얼에서는 React 애플리케이션에서 사용할 수 있도록 MDC Web의 Foundation을 래핑하는 방법을 다뤘습니다. GitHub 및 npm에는 프레임워크에 통합에 설명된 대로 MDC 웹 구성요소를 래핑하는 라이브러리가 몇 가지 있습니다. 여기에 있는 목록을 사용하는 것이 좋습니다. 이 목록에는 React 외에도 Angular, Vue와 같은 다른 프레임워크도 포함되어 있습니다.
이 튜토리얼에서는 MDC 웹 코드를 기초, 어댑터, 구성요소의 세 부분으로 나누기로 한 결정을 집중적으로 다룹니다. 이 아키텍처를 사용하면 구성요소가 모든 프레임워크에서 작동하는 동안 공통 코드를 공유할 수 있습니다. Material Components React를 사용해 주셔서 감사합니다. 새로운 라이브러리인 MDC React를 확인해 보세요. 이 Codelab에 만족하셨길 바랍니다.