본문 바로가기

React

[Tutorial]3.개요



※ React.org의 공식문서( https://reactjs.org/tutorial/tutorial.html ) 번역본입니다. ※

1. React는 무엇인가?

2. tic-tac-toe 초기 코드 분석

3. Props로 데이터 전달

4. 컴포넌트에 기능 만들기

5. 개발도구

  



1. React는 무엇인가?


  - React는 유저 인터페이스 개발을 위한 선언적, 효과적, 유연한 자바스크립트 라이브러리다. "컴포넌트"라고 부르는 작고 독립된 코드조각으로 복잡한 UI를 구성할 수 있다. React는 몇가지 종류의 컴포넌트를 갖고 있으며 지금은 React.Component부터 시작하겠다. XML 형태의 태그를 사용할 것이다. 우리는 화면에 보여줄 것을 React에게 전달하기 위해 컴포넌트들을 사용한다. 데이터가 변경될 때 React는 효과적으로 업데이트하고 그 컴포넌트를 다시 그린다. 


 여기 ShoppingList라는 React 컴포넌트 클래스(React 컴포넌트 타입)가 있다. 컴포넌트는 props(properties 줄임)라고 부르는 매개변수를 받아들일 수 있고 render 함수를 통해서 화면에 보여줄 React element를 리턴하고 이것은 화면에 그려질 것에 대한 작은 용량의 기술된 내용(JSX : html 문법과 흡사하나 조금 다름)이다.

 

 class ShoppingList extends React.Component{
    render(){
      return (
        <div className="shopping-list">
          <h1>Shopping List for {this.props.name}</h1>
          <ul>
            <li>Instagram</li>
            <li>WhatsApp</li>
            <li>Oculus</li>
          </ul>
        </div>
      );
    }
  }



 대부분의 React 개발자들은 "JSX"라고 불리는 특별한 구문을 사용한다. 이는 React Element 구조들을 더 쉽게 작성할 수 있다. JSX의 구문인 <div />는 사실 빌드 타임에 React.createElement('div')로 변경된다. 아래 복잡한 코드는 위의 예시와 동일하다.

 

 class ShoppingList extends React.Component{
    render(){
      return React.createElement('div',{className:'shopping-list'},
        React.createElement('h1',null,"Shopping List for ",props.name),
        React.createElement('ul',null
          ,React.createElement('li',null,'instagram')
          ,React.createElement('li',null,'WhatsApp')
          ,React.createElement('li',null,'Oculus'))
      );
    }
  } 


createElement() 함수가 궁금하다면 API reference 에서 자세히 살펴볼 수 있다. tutorial에서는 JSX만 사용하고 이는 더 다루지 않을 것이다. 

 JSX는 Javascript의 모든 기능을 지원한다. 어떤 JavaScript 표현식도 JSX 안의 {}안에서 사용할 수 있다. 각 React element는 프로그램 안에서 변수에 저장하거나 사용할 수 있는 JavaScript 객체다. 

 ShoppingList 컴포넌트는 <div />나 <li /> 같은 기본 DOM만 화면에 표시한다. 그러나 필요하다면 확장된 React 컴포넌트 역시 사용 가능하다. 예를 들어, ShoppingList 컴포넌트는 이제 <ShoppingList />로 사용할 수 있다. 각각의 React 컴포넌트는 캡슐화 되어 있어서 독립적으로 동작한다. 이것이 간단한 컴포넌트들로 복잡한 UI를 만들 수 있는 비결이다.


2. tic-tac-toe 초기 코드 분석


 브라우저에서 이 tutorial을 수행하고 있다면, 이 코드를 열어주길 바란다. PC에 개발환경을 설치해서 tutorial을 진행하고 있다면 src/index.js 파일을 열어주길 바란다. 이 초기 코드는 우리가 만들어야 할 것의 기본을 담고 있다. CSS 파일도 같이 제공되었기 때문에 React의 학습과 tic-tac-toe 게임의 프로그래밍에만 초점을 두면 된다. 

 이제 코드를 살펴보면 3가지 React 컴포넌트를 볼 수 있다.

    - Suqare

    - Board

    - Game

Square 컴포넌트는 하나의 <button>을 화면에 그리고, Board 컴포넌트는 9개의 Square 컴포넌트를 그린다. Game 컴포넌트는 물론 나중에 수정될 1개의 Board 컴포넌트를 화면에 그린다. 아직은 기능이 동작하는 컴포넌트는 없다.


3. Props로 데이터 전달


  맛만 보기 위해 데이터를 Board 컴포넌트에서 Square 컴포넌트로 전달해 보겠다. Baord 클래스의 renderSquare 함수 안에서 "value"로 정의된 props를 전달하도록 아래와 같이 코드를 수정한다.

 

class Board extends React.Component {
    renderSquare(i) {
      return <Square value={i}/>;
    }


Square 클래스의 render 함수에서 전달받은 "value"를 보여줄 수 있도록 {/* TODO */} 부분을 {this.props.value}로 수정한다.

 

class Square extends React.Component {
    render() {
      return (
        <button className="square">
          {this.props.value}
        </button>
      );
    }
  }



 Before

 After :  화면에 그려진 각각 Square에 숫자를 확인할 수 있다.


                        



여기까지가 부모 컴포넌트에서 자식 컴포넌트로 props를 전달하는 방법이다. props 전달은 React app에서 데이터가 어떻게 흘러가는지 볼수 있게 한다.


4. 컴포넌트에 기능 만들기


 Square 컴포넌트를 클릭할 때 X가 표시되도록 해보자. 먼저, 버튼 태그를 바꿔 Square 컴포넌트의 render 함수가 아래와 같게 한다.

 

class Square extends React.Component {
    render() {
      return (
        <button className="square" onClick={function(){ alert('click'); }}>
          {this.props.value}
        </button>
      );
    }
  }


이제 Square 를 클릭하면 알림 메세지를 볼 수 있다.


 

  Note

 typing 시간과 this객체 사용의 혼동을 회피하기 위해 arrow 함수 구분을 사용할 것이다. 위의 컴포넌트에 기능 만들기를 arrow 함수로 변경하면 아래와 같다.


class Square extends React.Component {
    render() {
      return (
        <button className="square" onClick={function(){ alert('click'); }}>
          {this.props.value}
        </button>
      );
    }
  }


 onClick={() => alert('click')} 함수를 onClick이라는 prop으로 전달한다. 클릭된 후에 이 이벤트는 발생하며 컴포넌트가 다시 그려질 때마다 이벤트가 적용된다.

 


다음 단계로 Square 컴포넌트가 클릭되었다는 것을 기억하게 하기 위해 X를 표시한다. "기억"하게 하기 위해 컴포넌트는 state를 사용한다. React 컴포넌트는 생성자 안에서 this.state를 설정해 줌으로써 state를 갖는다. this.state React 컴포넌트에서 private하게 작성되어야 한다. Square의 현재 값을 this.state에 저장하고 Square가 클릭될 때 변경해보자.

 우선, state를 초기화할 수 있는 생성자를 추가하자.

 

class Square extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button className="square" onClick={()=>alert('click')}>
        {this.props.value}
      </button>
    );
  }
}




 

  Note

 JavaScript에서 자식클래스의 생성자를 정의할 때 항상 super를 콜해야 한다. 생성자를 갖는 모든 React 컴포넌트는 super(props)를 콜하는 것부터 시작해야 한다.



이제 Square의 rener 함수를 수정해서 클릭할 때 현재 상태를 보여줄 수 있게 하자.

  • button 태그 안의 this.props.value를 this.state.value로 수정한다.
  • () => alert() 이벤트 핸드러를 () => this.setState({value: 'X'})로 수정한다.
  • className과 onClick props를 가독성을 위해 각각 다른 줄에 표시한다.

수정하면 Square의 render 함수는 아래와 같은 button 태그를 리턴할 것이다.


 

class Square extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      value: null,
    };
  }
    render() {
      return (
        <button 
          className="square" 
          onClick={()=>this.setState({value:'X'})}>
          {this.state.value}
        </button>
      );
    }
  }



Square의 render 함수 안에 있는 onClick 핸들러의 this.setState를 호출함으로써 React는 버튼이 클릭될 때마다 Square를 다시 그린다. state가 변경된 다음 this.state.value는 'X'가 되고 화면에 그렇게 표시되는 것을 볼 수 있다. 어떤 Square를 클릭하던 'X'가 보일 것이다. 컴포넌트의 setState를 호출하면 React는 자동으로 자식 컴포넌트의 구성 역시 업데이트한다.


5. 개발도구


 React 개발도구로 크롬파이어폭스에서 확장기능을 제공한다. 브라우저 개발자 도구에서 React 컴포넌트 트리를 검사할 수 있다.

React 개발도구를 통해서 props와 React 컴포넌트의 state를 확인해 볼 수 있다. React 개발도구를 설치한 다음 화면의 React 컴포넌트에 마우스 우클릭한 다음 "검사" 항목을 선택하면 개발자 도구가 열리고 React 탭이 추가된 것을 확인할 수 있다.


CodePen을 통해 이를 확인하려면 몇가지 해야 할 일이 더 있다.

  1) 로그인, 회원가입 후 이메일을 등록한다.

  2) Fork 버튼을 클릭한다.

  3) Change View를 클릭 후 Debug Mode를 선택한다.

  4) 이제 개발도구에서 React 탭을 볼 수 있다.


'React' 카테고리의 다른 글

[Tutorial]6.마무리  (0) 2019.02.15
[Tutorial]5.Time Trave 기능 추가  (0) 2019.02.15
[Tutorial]4.게임 완성하기  (0) 2019.02.15
[Tutorial]2.Tutorial 환경설정  (0) 2019.02.15
[Tutorial]1.Tutorial을 시작하면서...  (0) 2019.02.15