React Material-UI 적용

React는 오픈소스로 구성된 자바스크립트 라이브러리의 하나로서 사용자 인터페이스를 만들기 위해 사용합니다. 사용자 인터페이스를 아름답게 만들수 있게 도와주는 다양한 리액트 기반의 UI 라이브러리가 있습니다.

대표적으로 Material-UI, Semantic-UI-React, Ant-Design, React-Bootstrap, Grommet 등이 있으며 간략하게 소개합니다.

1. Material-UI
https://material-ui.com/?ref=designrevision.com
Google Material Design 을 사용하는 React 컴포넌트를 제공합니다.React 테마와 템플릿을 제공하므로 어플리케이션에 대한 사용자 지정 테마를 가질 수 있습니다.

2. Semantic-UI-React
https://react.semantic-ui.com/?ref=designrevision.com
Semantic UI React 는 Semantic UI 키트의 React 구현 버전입니다. jQuery Free이고 선언적인 API를 제공합니다.Semantic UI React 앱위에 Semantic UI CSS 테마를 로드 할 수 있고 마크업에 완전히 접근 할 수 있어 컴포넌트를 조정 할 수 있습니다.

3. Ant-Design
https://ant.design/docs/react/introduce?ref=designrevision.com
Ant Design React는 고품질 React 구성요소 세트를 특징으로하는 웹 응용 프로그램을 위한 엔터프라이즈급 UI 설계 언어입니다. 데이터 시각화 솔루션에 대한 무한한 가능성을 가지고 있으며 현실적인 디자인 원칙으로 알리바바, 바이두, 엔트파이넨셜 등의 기업에서 사용하고 있습니다.

4. React Bootstrap
https://react-bootstrap.github.io/?ref=designrevision.comReact
Bootstrap은 공식 부트스트랩 4 UI키트를 React로 구현한 버전입니다.각 구성요소의 형식과 기능을 보다 잘 제어 할 수 있도록 Bootstrap의 Javascript를 React로 대체합니다.Bootstrap의 기원과 크게 다른점이 없으므로 개발자는 수천가지 Bootstrap테마를 손쉽게 선택 할 수 있습니다.

5. Grommet
https://v2.grommet.io/
Grommet은 다양한 컴포넌트 라이브러리를 보유하고 있으며 Netflix 및 Boeing 등이 이용하고 있습니다. 반응형 레이아웃을 디자인 할 수 있고 키보드 또는 스크린 리더를 통해 접근성이슈를 해결했습니다.테마 도구는 색상, 유형 및 레이아웃을 사용자 정의하는데 도움이 됩니다.
Apache License 2.0

6. Blueprint
https://blueprintjs.com/
Blueprint는 웹을 위한 React기반 UI툴킷입니다. 테스크톱 애플리케이션을 위한 복잡한 데이터 집약적 인터페이스를 구축하는데 최적화 되어있습니다.

컴포넌트 라이브러리 및 UI툴킷을 사용하면 미리 만들어진 컴포넌트 세트를 사용하여 시간을 절약하고 응용프로그램을 보다 빠르게 작성 할 수 있습니다.

이번 포스팅에서는 Google Material Design에 대해 알아보고 React 어플리케이션에서 Material UI 프레임워크를 사용하는 방법에 대해 알아보도록 하겠습니다.

Material Design

Material Design은 2014년 구글 I/O에서 공개되었으며, 웹과 모바일 어플리케이션에서 큰 인기를 얻고 있는 플랫 디자인 기반의 디자인 메뉴얼입니다.

디자인 및 개발자 지침, 오픈소스 구성 요소, 아이콘, 글꼴 및 리소스를 포함하여 UI를 위한 자료를 구현하는 방법에 대한 지침을 제공합니다.

디자이너와 개발자 간의 협업을 간소화하고 어플리케이션을 신속하게 제작 할 수 있도록 지원하며 Material Theming으로 브랜드 고유의 정체성을 표현 할 수 있습니다.

조명, 서페이스 및 그림자를 활용해 3차원 공간을 표현하는 환경에 나타내며 모든 요소는 x축을 따라 수평, 수직 및 다양한 깊이로 이동합니다.
따라서 여러 요소는 공간의 동일한 지정을 동시에 차지 할 수 없습니다.

Material Design의 레이아웃은 반응형이며 예측 가능하며 일관성이 있습니다.
사용자 장치 및 화면 요소에 따라 반응하고 일관된 격자 라인 및 패딩을 사용하여 일관된UI 영역과 공간적 구성으로 직관적이고 예측 가능한 레이아웃을 사용합니다.

디자인 원칙
빛을 반사하고 그림자를 드리우는 방법을 포함하여 실제 세계와 텍스쳐에서 영감을 얻어 타이포그래피, 격자, 공간, 크기, 색상 및 이미지와 같은 인쇄 디자인 방법에 따라 안내자가 경험에 몰입 할 수 있는 계층구조, 의미 및 초점을 만듭니다.

모션은 미묘한 피드백과 일관된 전환을 통해 주의를 집중시키고 지속성을 유지합니다.
요소는 화면에 나타나므로 상호 작용을 통해 환경을 변형하고 재구성하여 새로운 변형을 만들어냅니다.

컴포넌트, 플러그인 및 디자인 요소를 완벽하게 구현할 수 있는 사용자 정의 코드 기반과 통합되어 있습니다.

Material Design은 Android, IOS및 웹에서 공유 구성 요소를 사용하여 플랫폼간에 동일한 UI를 유지합니다.

색상
컬러시스템은 체계적인 접근방식을 사용하여 브랜드를 나타내기 위해 기본 색상과 보조 색상이 선택됩니다.
기본 테마가 내장되어있으며 배경, 표면, 오류, 타이포그래피 및 아이콘그래피 색상과 같이 UI를 정의하는 추가 색상이 포함되어 있습니다.
이 모든 색상은 프로젝트에 맞춰 커스터마이징이 가능합니다.

  • Primary Color
    주요 색상은 앱화면과 구성요소에서 가장 빈번하게 표시되는 색상으로 기본 색상과 어둡거나 밝은 변형을 사용하여 앱의 색상 테마를 만들수 있습니다.
    UI요소 사이에 대조를 만들기 위해 각 요소에 변형을 사용 할 수 있으며 다양한 변형 및 구성요소 내의 아이콘을 구분하기 위해 변형을 사용 할수도 있습니다.

  • Secondary Color
    보조 색상은 제품을 강조하고 구별하는 더 많은 방법을 제공합니다.
    보조 색상을 지정하는것은 선택사항이며 UI의 선택부분을 강조하기 위해 드물게 적용해야합니다.

    • 링크 및 헤드라인
    • 진행 표시줄
    • 선택한 텍스트 강조표시
    • 슬라이더 및 스위치
    • 떠있는 동작 버튼

Material UI

월 600만 건의 npm 다운로드횟수를 가진 리액트 UI프레임워크중 하나로 Google Material Design을 구현하는 React 구성 요소를 제공합니다.
Material-UI 라이브러리의 컴포넌트를 사용하면 React 웹 또는 모바일 어플리케이션에서 메테리얼 디자인 요소를 쉽게 사용 할  수 있습니다.

https://material-ui.com/ 에서 라이브러리 컴포넌트들을 확인 할 수 있습니다.

CSS Baseline
Material UI는 CSS Baseline 컴포넌트를 제공하여 일관되며 단순한 기준을 구축합니다.
CSS Baseline은 다음과 같이 적용됩니다.

  • Page
    모든 브라우저에서 여백이 제거 되며, 기본 메테리얼 디자인 배경색이 적용되었습니다.
  • Layout
    box-sizing은 html요소에 border-box로 전역설정됩니다.
    *::before 및 *::after를 포함한 모든 요소는 이 속성을 상속 받도록 선언되어 padding 또는 border로 인해 선언된 너비가 초과되지 않습니다.
  • Typography
    html에 기본 폰트크기가 선언되지 않지만, 브라우저 기본값인 16px으로 간주 됩니다. 글꼴 엔티 앨리어신을 사용하면 roboto 글꼴을 더 잘 표시 할 수 있습니다.

React 애플리케이션에서 Material UI를 설정하고 사용하는 방법에 대해 알아보도록 하겠습니다.

React 프로젝트 생성

creact-react-app을 사용하여 새로운 리액트 프로젝트를 생성합니다.

Material UI를 사용하기 위해 npm 또는 yarn 명령어를 이용하여 설치합니다.

js

메테리얼 UI는 roboto 글꼴을 염두에 두고 설계되었으므로 google roboto 글꼴을 public 폴더의 index.html 파일에 추가해줍니다.

<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" />

설치후 프로젝트에서 아래와 같이 적용 할 수 있습니다.

import "typeface-roboto"

폰트 아이콘
사용을 위해서는 아이콘 글꼴을 폰트 적용방법과 동일하게 적용합니다.

<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />

SVG 아이콘
사용을 위해 하단의 명령어를 이용해 설치해줍니다.

React 애플리케이션을 실행합니다.

App.js 파일에서 불필요한 기본 내용을 삭제하고 프로젝트를 준비합니다.

HeaderBar 구현하기
프로젝트에 HeaderBar를 추가하기 위해서 먼저 src 디렉토리에 새 하위폴더 components 를 생성하고 HeaderBar.js 파일을 추가합니다.

AppBar컴포넌트를 사용하기 위해서 @material-ui/core/AppBar에서 import 합니다.
AppBar의 position을 static으로 지정해 줍니다. 내부에 Toolbar 컴포넌트를 넣고 AppBar와 동일하게 import 합니다.
Typography 컴포넌트에서 variant와 color를 지정합니다.

HeaderBar.js

import React from 'react'
import AppBar from '@material-ui/core/AppBar'
import Toolbar from '@material-ui/core/Toolbar'
import Typography from '@material-ui/core/Typography'

export default function HeaderBar() {
    return (
        <div>
            <AppBar position="static">
                <Toolbar>
                    <Typography variant="title" color="inherit">
                        React Material-UI Sample
                    </Typography>
                </Toolbar>
            </AppBar>
        </div>
    );
}

List 컴포넌트를 이용해 nav 요소를  생성해 보도록 하겠습니다.

List 컴포넌트 내부에 ListItem 컴포넌트를 넣고 button으로 지정한 다음, <ListItemText primary="ListItem” /> 에 들어갈 텍스트를 입력해줍니다.

스타일을 적용하는 방법은 몇 가지가 있으며 자세한 설명은 다음 포스팅때 자세히 알아보도록 하겠습니다.

아래와 같은 방법으로 스타일을 적용해 줍니다.

import React from 'react';
import {makeStyles} from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';

const useStyles = makeStyles(theme => ({
    root: {
        width: '100%',
        maxWidth: 260,
        backgroundColor: theme.palette.background.paper,
        minHeight: 'calc(100vh - 64px)',
        borderRight: '1px solid #ddd',
    },
}));

export default function SimpleList() {
    const classes = useStyles();

    return (
        <List component="nav" className={classes.root}>
            <ListItem button>
                <ListItemText primary="REACT 01"/>
            </ListItem>

            <ListItem button>
                <ListItemText primary="REACT 02"/>
            </ListItem>

            <ListItem button>
                <ListItemText primary="REACT 03"/>
            </ListItem>
        </List>
    );
}

App.js 파일에서 Nav 메뉴를 import 하고 적용시켜줍니다.

import React, {Component} from 'react';
import HeaderBar from './components/HeaderBar';
import LeftNav from './components/LeftNav';
import Posts from './components/Posts';
import './App.css';

class App extends Component {
    render() {
        return (
            <div >
                <HeaderBar/>
                <div style={{ display: 'flex'}}>
                    <LeftNav/>
                    <Posts/>
                </div>
            </div>
        )
    }
}

export default App;

Material Design의 Grid System은 12열 그리드 레이아웃을 기반으로 화면 크기와 방향에 적용되는 반응형 레이아웃입니다.
다양한 디자인에서 유연성을 허용하면서 레이아웃간의 일관성을 보장해줍니다.

여백은 8px 을 기준으로 하며, spacing 특성은 0 과 10 사이의 정수입니다.
예를들어, spacing = {1} 은 8px, spacing = {2} 는 16px을 나타냅니다.

Content 영역에 Grid를 이용하여 레이아웃을 잡고 Card 컴포넌트를 배열해 보도록 하겠습니다.

Grid 컴포넌트를 import 하고 원하는만큼의 여백을 지정해 줍니다.

import React from "react";
import {makeStyles} from '@material-ui/core/styles';
import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import Typography from "@material-ui/core/Typography";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import CardMedia from "@material-ui/core/CardMedia";
import Button from "@material-ui/core/Button";
import TrendingFlat from '@material-ui/icons/TrendingFlat';

const useStyles = makeStyles(theme => ({
    root: {
        padding: 30,
    },
}));

function Posts(props) {
    const classes = useStyles();

    return (
        <div className={classes.root}>
            <Grid container spacing={4}>
                {posts.map(post => (
                    <Grid item xs={16} sm={6} md={4} key={post.title}>
                        <Card>
                            <CardActionArea>
                                <CardMedia
                                    component="img"
                                    alt="Post Image"
                                    height="160"
                                    image={post.image}
                                    title="Post Image"
                                />
                                <CardContent>
                                    <Typography variant="subtitle2" color="textSecondary" gutterBottom>
                                        REACT 01
                                    </Typography>
                                    <Typography variant="h5" component="h2" gutterBottom>
                                        {post.title}
                                    </Typography>
                                    <Typography variant="body2" component="p">{post.excerpt}</Typography>
                                </CardContent>
                            </CardActionArea>
                            <CardActions>
                                <Button size="small" color="primary">
                                    Read More <TrendingFlat/>
                                </Button>
                            </CardActions>
                        </Card>
                    </Grid>
                ))}
            </Grid>
        </div>
    );
}

export default Posts;

상단과 같이 작성 후 데이터를 작성해 줍니다.

const posts = [
    {
        title: "Post 01",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=1"
    },

    {
        title: "Post 02",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=2"
    },

    {
        title: "Post 03",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=3"
    },

    {
        title: "Post 04",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=4"
    },

    {
        title: "Post 05",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=5"
    },

    {
        title: "Post 06",
        excerpt: "Lorem ipsum dolor sit amet, est dictas elaboraret te. An vide magna iriure eum, ex eos nibh accusam.",
        image: "https://picsum.photos/200/300?random=6"
    }
]

Material UI 컴포넌트 라이브러리를 사용하면 Google의 Material Design으로 리액트 애플리케이션을 쉽게 생성 할 수 있습니다.
지금까지 React 프로젝트에서 Material UI를 설정하고 사용하는 방법을 살펴 보았습니다.

(어떤 애플리케이션에서든 무조건적으로 Material이 최선의 방법은 아니므로 프로젝트의 사용성과 달성목표에 따라 React UI 라이브러리를 적용하는것을 추천드립니다.)

다음 글에서는 Material UI 의 스타일링 방법에 대해 포스팅 하도록 하겠습니다.

React + MobX
SPA 라이브러리인 React를 MobX state 관리 라이브러리와 함께 배워봅시다.