[ReactJS] react 실전 프로젝트 - react 기초

react로 mac의 미리 알림 앱 만들기

Posted by [ReactJS] react 실전 프로젝트 - react 기초 on May 07, 2018

이번에 회사를 그만두고 구인을 하게 되면서, 많은 회사에서 react를 선택하고 사용하고 있음을 느꼈다. 실무해서 사용해본 경험도 벌써 1년이나 지났고, 그동안 엄청난 버전업을 하였기에 이번 기회에 간단한 앱을 만들면서 다시 한번 react에 대해 복습하고 그 과정을 포스팅하고자 한다.

What is React?

React는 페이스북이 개발한 UI 라이브러리이다. React의 핵심은 재사용 가능한 UI의 생성이다. 이 재사용 가능한 UI를 컴포넌트화 하여 더 복잡한 UI 화면을 구성한다. 일반적인 MVC, MV* 패턴에서 View만 담당한다. 이외의 모델이나 다른 부분은 다른 라이브러리를 가져와 조합하여 사용해도 무방하다.

1. Virtual DOM

React는 DOM을 Virtual DOM을 이용해 표현하다. React는 모델이 업데이트 되면, 화면을 re-render 한다. 일반적으로 jQuery를 이용해 DOM을 업데이트하는 상황을 생각해보자. 모델이 업데이트됨으로써 모델이 영향을 미치는 DOM 부분만 선택자를 통해 업데이트 한다. 하지만 React는 해당 부분을 모두 다시 re-render 해버린다. 이렇게 되면 당연히 reflow, repaint상황이 더 많이 발생할 테고, 이에 따른 성능 문제는 없을까?

ReactVirtual DOM을 사용하여 이러한 걱정을 해소한다. 후술한 JSX를 사용하여 최종 결과물(업데이트된 모델이 반영된 UI)에 대해서만 선언적으로 기술한다. 이후 모델의 업데이트가 발생하면 실제 DOM 트리에 반영하는 것이 아닌 가상 DOM 트리에만 적용한 뒤 최종적으로 이 두 DOM 트리를 비교하여 변경된 부분만 실제 DOM에 반영한다. 따라서 DOM을 직접 조작할 때 발생할 수 있는 reflow, repaint에 의한 성능 문제는 걱정하지 않아도 된다.

2. Component

React의 핵심은 재사용 가능한 UI의 생성이라고 했다. 모든 UI는 컴포넌트화 하여 구성한다. 아래의 코드는 여러개의 컴포넌트를 조합하여 하나의 어플리케이션을 구성하는 예제이다.


    import React, { Component } from 'react';
    
    class Header extends Component {
      render() {
        return (
            <div>
                <h1>Hello world!</h1>
            </div>
        );
      }
    }
    
    export default Header;
    

    import React, { Component } from 'react';
    
    class Content extends Component {
      render() {
        return (
            <div>
                content...
            </div>
        );
      }
    }
    
    export default Content;
    

    import React, { Component } from 'react';
    
    class Footer extends Component {
      render() {
        return (
            <div>
                footer
            </div>
        );
      }
    }
    
    export default Footer;
    

    import React, { Component } from 'react';
    import Header from './Header';
    import Content from './Conent';
    import Footer from './Footer';
    
    class App extends Component {
      render() {
        return (
            <div>
                <Header></Header>
                <Content></Content>
                <Footer></Footer>
            </div>
        );
      }
    }
    
    export default App;
    

각각 Header, Content, Footer 라는 컴포넌트를 만들어, App에서 사용하도록 하였다. 이렇게 컴포넌트화 하면 필요한 곳에서 얼마든지 재사용할 수 있다. 심화 내용은 실제 프로젝트 포스트를 작성하면서 소개하도록 하겠다.

3. JSX

JSX는 Javscript와 XML을 결합한 확장 문법이라고 볼 수 있다. 이 문법을 사용하여 자바스크립트 코드에서 마크업을 할 수 있고, 손쉽게 변수나 함수를 태그 안에 바인딩 할 수 있다. JSX는 필수 사항이 아니지만, 왠만하면 사용하기를 권장한다. (초심자라면 특히.. 인터넷에 돌아다니는 거의 모든 react 예제는 JSX로 작성되어 있다.)

이번 포스트에서는 JSX를 어떻게 사용하는지 간단하게 알아보고, 심화 내용은 실제 프로젝트 포스트를 작성하면서 소개하도록 하겠다.


    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        return (
            <div></div>
        );
      }
    }
    
    export default App;
    

먼저 다른 코드는 다 무시하고 render() 내부의 return 구문만 살펴보자. return내부에 HTML 마크업이 되어 있는 것을 확인할 수 있다. 기본적으로, 기존과 동일하게 render 함수에서 원하는 UI를 마크업하여 return값으로 지정하면 된다. (참 쉽죠?) 유의해야 할 점은, JSX에서 마크업을 할 때 몇가지 지켜야 할 규칙이 있다.

감싸진 Element

JSX는 무조건 하나의 요소로 감싸야 한다. 즉 최상위 요소는 1개여야만한다.


    // 이 코드는 에러가 발생합니다.!!
    
    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        return (
            <div></div>
            <div></div>
        );
      }
    }
    
    export default App;
    

위 코드와 같이 최상위에 요소가 2개 있는 경우 에러를 발생한다.


    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        return (
            <div>
                <div></div>
                <div></div>
            </div>
        );
      }
    }
    
    export default App;
    

위 코드와 같이 하나의 요소로 감싸야한다. css와 같은 스타일 가이드가 미리 나와서 다른 요소로 감싸기 곤란한 상황이라면, <Fragments> 태그를 사용한다.


    import React, { Component } from 'react';
    
    class App extends Component {
      render() {
        return (
            <Fragments>
                <div></div>
                <div></div>
            </Fragments>
        );
      }
    }
    
    export default App;
    

자바스크립트 표현식

JSX를 사용하면 변수나 함수를 손쉽게 바인딩 할 수 있다고 했다. 아래 코드를 살펴보자.


    import React, { Component } from 'react';
    
    class App extends Component {
        
        clickButton(e){
            console.log('clicked');
        }
    
        render() {
        
            const name = 'dohee';
            
            return (
                <div>
                    <h1>Hello {name}!</h1>
                    <button onClick={this.clickButton}>click me</button>
                </div>
            );
        }
    }
    
    export default App;
    

{ }로 표현된 부분을 자세히 보자. { }를 사용하면 자바스크립트 표현식을 사용 할 수 있다. 이 표현식을 가지고 조건부 렌더링 또한 가능하다.


    import React, { Component } from 'react';
    
    class App extends Component {
        
        render() {
        
           let condition = true;
            
            return (
                <div>
                    {
                        condition ? 
                        <div>true</div>
                        <div>false</div>
                    }
                </div>
            );
        }
    }
    
    export default App;
    

주의해야 할 점은, if문은 사용할 수 없다는 것이다. 위와 같이 삼항 연산식을 사용하거나 즉시실행함수(IIFE)를 사용해야한다.

Inline Style

태그 내부에 Style 속성을 사용하게 될 경우, 아래와 같이 사용해야한다.


    import React, { Component } from 'react';
    
    class App extends Component {
        
        render() {
        
            const style = {
                marginTop: 10,
                color: 'blue'
            };
            
            return (
                <div style={style}>inline style</div>
            );
        }
    }
    
    export default App;
    

3. One-way Data Flow

React에서는 데이터가 부모 컴포넌트에서 자식컴포넌트로 한 방향으로만 흐른다. two-way data bind를 사용하는 AngularJs를 경험해본 개발자라면, 이 개념에 적응하는데 시간이 좀 걸릴 수 있다. React의 단방향 데이터의 흐름에서 다음과 같은 두가지 개념을 사용한다.

Props

부모 컴포넌트에서 자식 컴포넌트로 전달하는 값이다. 이 Props는 전달받을수만 있고 수정은 불가능하다.


    import React, { Component } from 'react';
    import Child from './Child';
    
    class Parent extends Component {
        
        render() {
            
            const name = 'dohee';
            
            return (
                <Child data={name}></Child>
            );
        }
    }
    
    export default Parent;

위와 같이 Parent 컴포넌트에서 name이라는 PropsChild컴포넌트에 전달하였다.


    import React, { Component } from 'react';
    
    class Child extends Component {
        
        render() {
            
            
            return (
                <div>{this.props.name}</div>
            );
        }
    }
    
    export default Child;

Child 컴포넌트에서 전달받아 사용하는 코드이다. this.props로 접근하여 사용할 수는 있지만, 값을 변경할 수는 없다.

State

Props와는 달리 State는 변경 가능한 컴포넌트의 상태값이다. 이 State가 변경되면, 컴포넌트의 re-render가 발생한다.


    import React, { Component } from 'react';
    
    class App extends Component {
    
        state = {
            name : ''
        }
        
        clickButton(){
            this.setState({name: 'dohee'});
        }
        
        render() {
            
            
            return (
                
                <div>
                    name: {this.state.name}
                    <button onClick={this.clickButton.bind(this)}>change name</button>
                </div>
            );
        }
    }
    
    export default App;

버튼을 클릭하면, setState를 호출하여 state값을 변경하는 코드이다. clickButton 함수에 의해 state값이 변경되고 나면, render()함수가 호출되고 컴포넌트가 re-render되어 변경된 이름이 출력될 것이다.

. . .

여기까지 기본적인 React의 기초와 특징에 대해서 포스팅하였다. 다음 포스팅부터는 mac의 미리 알림 앱을 React로 구현하는 프로젝트를 위주로 구성해보려고 한다. 이 포스팅은 아래의 링크를 참고하여 작성하였다.