프로그래밍/Frontend

[React] React.js 튜토리얼 2- 주요 개념 살펴보기(JSX, Component, Props, State)

돔돔이 2023. 12. 9. 00:08
728x90
반응형

 

 

이전 포스팅을 보려면 아래 링크를 눌러주세요.

[React] React.js 튜토리얼 1- 프로젝트 생성 및 실행하기

 

 

이미지출처: https://velog.io/@hyejeong/%EC%99%9C-React%EB%A5%BC-%EC%8D%A8%EC%95%BC%ED%95%A0%EA%B9%8C

 

 

 

 

간단한 React 예제 프로젝트를 만들어보기 앞서, 알아둬야하는 React의 개념과 특징들을 살펴봅시다.

.

React로 구현된 애플리케이션은 일반적으로 하나의 루트 DOM 노드가 있습니다.

이 안에 들어가는 모든 엘리먼트를 React DOM에서 관리합니다.

엘리먼트를 렌더링하기 위해서는 ReactDOM.createRoot()에 엘리먼트를 전달한 다음, root.render()에 전달해야 합니다.

 

튜토리얼1에서 만들어보았던 프로젝트의 index.js를 열어보면 다음과 같이 작성되어 있습니다.

root.render에 App.js에 만들어놓은 App 엘리먼트가 전달된 것을 알 수 있습니다.

 

root.render 안에 들어있는 React.StrictMode는 잠재적인 문제를 알아내기 위해,

자식들에 대한 검사와 경고를 활성화하는 도구라고 합니다.

 

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

 

 

 

다음으로, React는 JSX라는 문법을 사용합니다.

JSX가 무엇인지에 대해서는 reactjs 홈페이지에 잘 나와있는데요.

https://ko.legacy.reactjs.org/docs/introducing-jsx.html

 

JSX 소개 – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

 

 

JSX는 html과 javascript가 혼합된 형태처럼 보이는, javascript를 확장한 문법이라고 합니다.

위의 JSX 소개 페이지에 작성되어있는 JSX 표현식을 같이 살펴봅시다!

 

1. JSX에 표현식 포함하기

아래 예시에서는 name이라는 변수를 선언한 후 중괄호로 감싸 JSX 안에 사용하였습니다.

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

 

 

JSX의 중괄호 안에는 유효한 모든 javascript 표현식을 넣을 수 있습니다.

아래 예시에서는 javascript 함수 호출 결과인 formatName(user) 을 <h1> 엘리먼트에 포함했습니다.

 

function formatName(user) {
  return user.firstName + ' ' + user.lastName;
}

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);
반응형

 

 

 

 

어트리뷰트에 따옴표를 이용해 문자열 리터럴을 정의할 수 있습니다.

const element = <a href="https://www.reactjs.org"> link </a>;

// 중괄호를 사용한 javascript 표현식 삽입
const element = <img src={user.avatarUrl}></img>;

// 태그가 비어있다면 />를 이용해 닫아줌
const element = <img src={user.avatarUrl} />;

 

 

 

JSX 태그는 자식 엘리먼트를 포함할 수 있습니다.

class는 className으로 작성합니다.

 

const element = (
  <div className="w-full">
    <h1>Hello!</h1>
    <h2>Good to see you here.</h2>
  </div>
);
728x90

 

 

 

 

다음으로 Props와 State에 대해서 알아봅시다.

https://ko.legacy.reactjs.org/docs/components-and-props.html

 

Components와 Props – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

 

 

 

2. Component와 Props, State 객체

 

컴포넌트에는 함수 컴포넌트와 클래스 컴포넌트가 있습니다.

컴포넌트를 정의하는 가장 간단한 방법은 javascript 함수를 작성하는 것입니다.

이렇게 가장 간단한 방법인 javascript 함수로 만들어진 컴포넌트를 말 그대로 "함수 컴포넌트"라고 호칭합니다.

// javascript 함수로 작성한 함수컴포넌트
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// ES6 class를 사용한 컴포넌트
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

 

 

이전까지는 DOM 태그만을 사용해 React 엘리먼트를 나타냈으나,

아래처럼 사용자정의 컴포넌트로도 나타낼 수 있습니다.

컴포넌트의 이름은 항상 대문자로 시작해야 합니다.

예를들어 <div />는 HTML div 태그를 나타내지만, <Welcome />은 컴포넌트를 나타냅니다.

 

// DOM 태그 사용
const element = <div />;

// 사용자정의 컴포넌트
const element = <Welcome name="Sara" />;

 

 

 

React가 사용자정의 컴포넌트로 작성한 엘리먼트를 발견하면

JSX 어트리뷰트와 자식을 해당 컴포넌트에 단일 객체로 전달합니다.

 

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const root = ReactDOM.createRoot(document.getElementById('root'));
const element = <Welcome name="Sara" />;
root.render(element);

 

 

 

 

Welcome을 여러번 렌더링하는 App 컴포넌트도 만들 수 있습니다.

 

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

 

 

 

추가적으로, 컴포넌트를 여러 개의 작은 컴 포넌트로 쪼개서 사용하는 것이 재사용하기에도 좋습니다.

아래와 같은 컴포넌트는 구성요소들이 모두 중첩구조로 이루어져있어 변경하기 어려울 수 있습니다.

 

// 중첩구조로 만들어진 컴포넌트
function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

 

 

 

 

아래와 같이 작은 컴포넌트로 쪼개서 사용합니다.

 

// 쪼개진 작은 컴포넌트
function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

// Avatar 옆에 사용자 이름을 렌더링하는 컴포넌트
function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}

// 작은 컴포넌트들을 사용
function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

 

 

 

이제 컴포넌트에 사용되는 props와 state객체에 대해서 알아봅시다.

props는 읽기전용 객체로, 입력값을 바꾸려하지 않고 항상 동일한 입력값에 대해 동일한 결과를 반환합니다.

다음과 같이 sum 함수는 자신의 입력값(a,b)을 바꾸지 않고 결과를 반환합니다.

이런 함수들을 순수함수라고 호칭합니다.

function sum(a, b) {
  return a + b;
}

 

 

반면에 다음 함수는 자신의 입력값을 변경하기 때문에 순수 함수가 아닙니다.

function withdraw(account, amount) {
  account.total -= amount;
}

 

 

시간과 같이, 동적이며 시간에 따라 변하는 객체는 state로 자신의 출력값을 변경할 수 있습니다.

아래는 Clock 함수 컴포넌트입니다.

여기서 Clock이 스스로 업데이트되도록 만들기 위해서는 clock 컴포넌트에 "state"를 추가해야합니다.

 

const root = ReactDOM.createRoot(document.getElementById('root'));

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  root.render(<Clock date={new Date()} />);
}

setInterval(tick, 1000);

 

 

 

이를 클래스컴포넌트를 사용하여 변경해봅니다.

Clock이 처음 DOM에 렌더링 될때마다 타이머를 설정하는 것을 "마운팅"이라고 하고,

Clock에 의해 생성된 DOM이 삭제될 때마다 타이머를 해제하는 것을 "언마운팅"이라고 합니다.

컴포넌트가 마운트되거나 언마운트될 때 일부코드를 작동할 수 있습니다.

이러한 메서드들을 "생명주기 메서드"라고 부릅니다.

 

 

class Clock extends React.Component {
  // 초기 this.state를 지정하는 class constructor를 추가 (this.state를 지정할 수 있는 유일한 공간)
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
  
  // 마운팅
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
  
  // 언마운팅
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
  
  // 매초 시계가 작동하도록 하는 메서드. 
  tick() {
    this.setState({
      date: new Date()
    });
  }
  
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));

// <Clock /> 요소에서 date prop을 삭제함
root.render(<Clock />);

 

 

 

위의 코드를 보면, 매초 시계가 작동하도록 하는 메서드 tick에서 state를 업데이트하기 위해 this.setState()를 사용한 것을 볼 수 있습니다.

직접 State를 수정하지 않고, setState()를 사용해야 컴포넌트를 다시 렌더링 할 수 있습니다.

// 잘못된 State 변경
this.state.comment = 'Hello';

// 올바른 State 변경
this.setState({comment: 'Hello'});

 

 

 

setState는 컴포넌트를 렌더링하지만, 렌더링 업데이트는 비동기적일 수도 있습니다.

React는 성능을 위해 여러 setState() 호출을 단일 업데이트로 한꺼번에 처리할 수 있습니다.

 

// 업데이트에 실패될 수 있음
this.setState({
  counter: this.state.counter + this.props.increment,
});

// 업데이트 적용
this.setState(function(state, props) {
  return {
    counter: state.counter + props.increment
  };
});

 

 

 

state는 다양한 독립적인 변수를 포함할 수 있습니다.

constructor(props) {
    super(props);
    this.state = { // 다양한 변수 포함
      posts: [],
      comments: []
    };
  }
  
  componentDidMount() {
    fetchPosts().then(response => {
      this.setState({
        posts: response.posts
      });
    });

    fetchComments().then(response => {
      this.setState({
        comments: response.comments
      });
    });
  }

 

 

 

 

여기까지 React의 JSX, Component, props, state에 대해서 알아보았습니다.

 

다음 포스팅을 보려면 아래 링크를 눌러주세요.

 

[React] React.js 튜토리얼 3- 이벤트 처리하기

 

[React] React.js 튜토리얼 3- 이벤트 처리하기

이전 포스팅을 보려면 아래 링크를 눌러주세요. [React] React.js 튜토리얼 1- 프로젝트 생성 및 실행하기 [React] React.js 튜토리얼 1- 프로젝트 생성 및 실행하기 먼저 react를 개발하기 앞서 react는 node.js

domdom.tistory.com

 

 

 

 

 

 

 

 

728x90
반응형