본문 바로가기

Frontend/React

3. Component와 Props 그리고 React Developer Tools

Component

리액트는 컴포넌트를 통해 UI를 재사용 가능한 개별적인 여러 조각으로 나누고, 각 조각을 분리해서 생각해 볼 수 있게 해준다.

component 를 정의하는 방법은 이전 포스팅에서 설명했던 것과 같이 함수형과 클래스형이 있다.

 

주의: 컴포넌트의 이름은 항상 대문자로 시작
React는 소문자로 시작하는 컴포넌트를 DOM 태그로 처리한다. 예를 들어 <div />는 HTML div 태그를 나타내지만, <Welcome />은 컴포넌트를 나타내며 범위 안에 Welcome이 있어야 한다.

 

 

 

 

1) 함수형

function Welcome (){
  return <h1>Happy Coding!</h1>
}

function App() {
  return (
    <div className="App">
      <Welcome></Welcome> // 위의 웰컴함수의 내용 <h1>Happy Coding!</h1>이 나타남
    </div>
  );
}

 

 

 

2) 클래스형

class Subject extends Component {
  render () {
    return (
      <header>
            <h1>WEB</h1>
            world wide web!
      </header>
    );
  }
}

class TOC extends Component {
  render () {
    return (
      <nav>
          <ul>
              <li><a href="1.html">HTML</a></li>
              <li><a href="2.html">CSS</a></li>
              <li><a href="3.html">JavaScript</a></li>
          </ul>            
      </nav>
    );
  }
}

class Content extends Component {
  render () {
    return (
      <article>
        <h2>HTML</h2>
        HTML is HyperText Markup Language.
      </article>
    );
  }
}

class App extends Component  {
  render () {
    return (
    <div className="App">
      <Subject></Subject> // 리액트가 위에 적어준 헤더 클래스 내용을 가져옴 => 결과 : <h1>WEB</h1> World wide web이 나타남
      <TOC></TOC> // 리액트가 위에 적어준 TOC클래스 내용을 가져옴 => 결과 : HTML, CSS, JavaScript a link가 생김
      <Content></Content> // 리액트가 위에 적어준 Content클래스 내용을 가져옴 => 결과 : <h2>HTML</h2> HTML is HyperText Markup Language.가 나타남
    </div>
    );
  }    
}

 

이렇게 함으로써 개발자는 컴포넌트 이름에만 집중하면 되기 때문에 코드의 복잡도가 현저하게 줄었다. 하지만 만약 클래스가 많고 같은 내용이 반복된다면.. 즉 자식클래스 급일때도 그 때마다 새로운 클래스를 선언하고 이름도 새로 지어줘야되나? 라는 생각이 든다.

 

 

 

Props

프로퍼티(properties)의 줄임말로 React에서 props는 사용자가 컴포넌트에 전달해서 보관하길 원하는 데이터이다. 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달할 때 사용되는데, 이 props는 컴포넌트에서 사용하는 데이터의 변경이 불가능하다. 즉, 컴포넌트 내에서 데이터가 보관되면, 이 데이터는 수정되지 않고 보존되어야 한다. 

 

1)함수형

function App() {
  return (
    <div className="App">
      <Intro name="Yuni" subname="everyone"></Intro> 
      <Intro name="LiveCoding" subname="Thank you"></Intro>
      <Welcome></Welcome>
    </div>
  );
}


function Intro (props) {
  return <h2>Hello, {props.name} and {props.subname}.</h2>        
}

function Welcome (){
  return <h1>Happy Coding!</h1>
}

 

 

결과화면 

 

 

2)클래스형

<div className="App">
      <Subject title="WEB" sub="world wide web!"></Subject>
      <Subject title="React" sub="For UI"></Subject>
      <TOC></TOC>
      <Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
      <Welcome></Welcome>
      <Intro name="yuni"></Intro> //여기서 subname을 설정하지 않으면 어떻게 될까?
    </div>
    );
  }    
}

class Intro extends Component {
  render () {
    return (
      <h2>Hello, {this.props.name} and {this.props.subname}.</h2>
    );
  }
}

class Welcome extends Component {
  render () {
    return (
      <h1>Happy Coding!</h1>
    );
  }
}

 

 

결과화면

크게 문제는 없다. 오류는 나지 않고 그냥 빈칸으로 나온다. 

 

 

props 렌더링 과정

  1. <Intro name="yuni" /> 엘리먼트로 ReactDOM.render()를 호출한다.
  2. React는 {name: 'yuni'}를 props로 하여 Intro 컴포넌트를 호출한다.
  3. Intro 컴포넌트는 결과적으로 <h1>Hello, yuni and {props.subname}.</h1> 엘리먼트를 반환한다.
  4. React DOM은 <h1>Hello, yuni and {props.subname}.</h1> 엘리먼트와 일치하도록 DOM을 효율적으로 업데이트한다.

 

 

좋다. props를 이용하니까 클래스 이름을 매번 새로 정의해주고 코드를 새로 쓸 필요가 없다. 근데 그래도 클래스들이 많아지면 App.js에서 그 클래스를 유지보수 하는 것도 힘들 것 같다. 좀 더 쪼갤 수 있을까? 있다. 더 쪼개서 관리할 수 있다. 자바에서 썼던 방법과 굉장히 유사하다.

 

 

 

directory(=folder)이용해서 Component 파일로 분리하기

src에서 디렉토리를 생성한후 그 디렉토리에 해당 컴포넌트를 파일별로 정리해주면 된다. 위의 클래스형으로 예시를 들어보겠다. 사실 저 코드가 이미 반정도는 분리가 된 상황이긴 하다.

 

Intro, Welcome 클래스를 App.js에서 분리해 새로 생성한 디렉토리로 옮겨주기.

 

 

이렇게 생성해주고 아래와 같이 구성해주면 된다. 틀은 똑같다. 

 

import { Component } from 'react';

class 내용

export default class이름; 

 

1) Welcome.js

import { Component } from 'react';

class Welcome extends Component {
    render () {
      return (
        <h1>Happy Coding!</h1>
      );
    }
}

export default Welcome;  

2)Intro.js

import { Component } from 'react';

class Intro extends Component {
    render () {
      return (
        <h2>Hello, {this.props.name} and {this.props.subname}.</h2>
      );
    }
  }

export default Intro;    

 

 

3) App.js 

import { Component } from 'react';
import TOC from './components/TOC';
import Content from './components/Content';
import Subject from './components/Subject';
import Intro from './components/Intro';
import Welcome from './components/Welcome';

class App extends Component  {
  render () {
    return (
    <div className="App">
      <Subject title="WEB" sub="world wide web!"></Subject>
      <Subject title="React" sub="For UI"></Subject>
      <TOC></TOC>
      <Content title="HTML" desc="HTML is HyperText Markup Language."></Content>
      <Welcome></Welcome>
      <Intro name="yuni"></Intro>
    </div>
    );
  }    
}

export default App;

이렇게나 깔끔해진 모습을 볼수가 있다. 주의해야할 것은 import를 해와야 쓸 수 있으므로 클래스 import 해주는 것 잊지말기!

 

 

 

 

 

 

번외)

 

Chrome 개발자 도구로 볼때 리액트의 컴포넌트들은 나오지 않고 그냥 html 태그로만 나와 불편했었는데.. React Developer Tools라는게 있었다. 사용하면 이렇게 컴포넌트를 볼 수 있다. 리액트는 배우면 배울수록 와.. 혁명이네.. 라는 감탄을 금치못함.

 

chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en

 

 

 

 

 


참고

 

생활코딩 React 11-14

www.youtube.com/watch?v=FWVnIe_9-1w&list=PLuHgQVnccGMCRv6f8H9K5Xwsdyg4sFSdi&index=14

ko.reactjs.org/docs/components-and-props.html

trustyoo86.github.io/react/2017/11/18/props-state-react.html

velog.io/@kyusung/