React

[02] 컴포넌트 이해하기

BGK97 2024. 4. 15. 17:46

디렉터리를 하나 생성하고, 이전에 사용했던 data와 prettier를 복사해온다.

컴포넌트

  • 객체지향 언어의 원조인 스몰토크에서 유래
  • 화면 UI를 처리하는 클래스를 의미
  • MVC 설계지침에 따라 구현되어야 함
  • 리액트 16.8버전 이후, 리액트 훅이라는 새로운 메커니즘을 통해 객체지향만의 클래스가 아닌 단순한 함수 형태로도 구현이 가능하게 되었음

-> 가능한 함수컴포넌트와, 리액트 훅을 사용하라고 권장 됨

리액트 컴포넌트와 사용자 컴포넌트

  • 리액트 컴포넌트
    • 리액트 프레임워크가 제공하는 리액트 제공 컴포넌트
    • div, h1 ...
  • 사용자 컴포넌트
    • 사용자가 직접 지정하는 컴포넌트
    • MyChild, MyComponent...
    • 처음 글자는 무조건 대문자(카멜 케이스)

리액트 컴포넌트

  • 컴포넌트를 React.createElement로 생성할 때, 컴포넌트 타입에는 h1과 같이 문자열을 입력해야 함
const h1 = <h1>Hello world!</h1> //h1는 리액트 컴포넌트

const h1 = React.createElement('h1', null, 'Hello World')
  • 이렇게 하면, HTML5 태그에 해당하는 컴포넌트 이름을 일일이 임포트 하지 않아도 됨

사용자 컴포넌트

  • 리액트 컴포넌트로 구현하면 JSX 코드 때문에 내용이 복잡해보임
import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <ul>
      <li>
        <a href='http://www.google.com'>
          <p>go to Google</p>
        </a>
      </li>
    </ul>
  );
}

export default App;
  • 기존 작성했던 index.tsx의 내용을 App.tsx에 옮기고 하면
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") as HTMLElement
);
root.render(<App />);
  • index.tsx는 이렇게 간편해짐
  • 사용자 컴포넌트의 용도는, React.createElement나 JSX문으로 생성하는 가상 DOM 생성 코드를 사용자 컴포넌트로 옮겨 코드를 간결하게 하는데에 목적

클래스 컴포넌트 만들기

  • 리액트에는 클래스 기반 컴포넌트와 함수형 컴포넌트가 존재
  • 클래스기반 컴포넌트는 항상 react패키지의 Component클래스를 상속
  • 또한, render 메서드를 포함해야하며, 이때 null, createElement로 얻은 반환값 혹은 JSX문으로 가상 DOM 객체를 반환 해야 함

App.tsx를 클래스 컴포넌트 방식으로 바꾸기

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

export default class App extends Component{
  render(): React.ReactNode {
    return (
      <ul>
        <li>
          <a href='http://www.google.com'>
            <p>go to Google</p>
          </a>
        </li>
      </ul>
    );    
  }

}
  • 컴포넌트 개념 도입시 render 메서드에 JSX구문 뿐 아니라 다양한 로직을 TypeScript코드로 구현 가능

컴포넌트 render 부분을 ClassComponent로 옮기기

  • 먼저 src 폴더에 ClassComponent를 생성
  • 그 이후 해당 코드 작성
import { Component, ReactNode } from "react";

export default class ClassComponent extends Component {
  render(): ReactNode {
    return (
      <li>
        <a href="http://www.google.com">
          <p>go to Google</p>
        </a>
      </li>
    );
  }
}
  • 그 다음 App.tsx에 가서, 해당 컴포넌트를 사용만 하면 됨

속성이란?

  • 객체지향 관점에서 클래스의 멤버 변수를 의미
  • 컴포넌트 또한, 화면 UI를 담당하므로 속성을 가질 수 있음
  • 클래스의 속성은 값이 수시로 바뀔 수 있는데, 이를 가변이라고 하고, 바뀌지 않는 것을 불변 이라 함

리액트 프레임워크에서의 속성

  • 부모 컴포넌트가 자식 컴포넌트 쪽에 정보를 전달하는 용도로 사용
  • 위의 코드에서 부모 컴포넌트App은 자식 컴포넌트 ClassComponent 쪽에 href와 text 속성 전달
  • 매개변수 props에서 타입제약({})이 걸려있으면, 이는 리액트 속성이 객체여야 하고 선택 속성이란 의미를 가짐
  • 리액트에서 객체지향관점의 속성은 상태(State)라고 함
  • 속성이 값이 변할 시, 재 렌더링도 된다.(재 렌더링 + 객체지향관점의 속성)

JSX 속성 설정 구문

  • XML언어 이므로 모든 속성은 작은 따옴표(' ')로 감싸야 함
    <Person name='Jack' />
  • 다른 타입의 언어(정수 형 같은...)는 중괄호({})로 감싸주어야 함
    <Person name='Jack' age={22} />
  • 속성 설정값이 객체인 경우, 중괄호 두개를 사용하여 내부는 객체, 외부는 JSX 설정 구문을 의미한다.
    <Person person={{name='Jack', age=22}} />

ClassComponent에 속성 구현하기

  • 리액트 관점에서는 href와 text가 유효한 속성이름인지 알 수 없음
  • 그래서 Component 타입에 속성 이름과 타입을 기입하여 Props와 같이 속성 타입을 만들어서 함께 보내주어야 함
import { Component } from 'react'

type ClassComponentProps =  {
    href: string
    text: string
}

export default class ClassComponent extends Component<ClassComponentProps>{
    render() {return null}
}
  • type으로 지정을 해주면, 나중에 컴포넌트 내부에서 this.props의 형태로 사용이 가능하다
  • (참고) 모든 타입의 부모인 Component는 props라는 이름의 속성을 제공함
import { Component, ReactNode } from "react";

export type ClassComponentProps = {
  href: string;
  text: string;
}

export default class ClassComponent extends Component<ClassComponentProps> {
  render(){
    const {href, text} = this.props;
    return (
      <li>
        <a href={href}>
          <p>{text}</p>
        </a>
      </li>
    );
  }
}
  • 해당 코드를 작성 후 href 및 text에 알맞은 단어를 쓰면 됨

함수 컴포넌트 만들기

  • 함수형 컴포넌트란
    • render 부분을 간단하게 함수로 만든 것
    • react는 render메서드를 구현할 수 있게 해주는 프로그래밍 언어의 코드와, render메서드로 구성됨
  • 함수 컴포넌트는 상용구 코드가 없어 컴포넌트를 간결하게 구현이 가능
  • 함수형 컴포넌트를 만드는 방식에는 Arrow와 function 방식이 존재

function 키워드 방식

  • 클래스 컴포넌트의 역할
    • render 메서드를 통해 리액트 프레임워크가 가상 DOM 객체를 생성해 전달
    • 함수 컴포넌트는 자신의 반환 값으로 가상 DOM 객체를 생성하여 전달
  • function App() { return ... } 방식으로 사용한다.

Arrow 키워드 방식

  • 이름을 가질 수 없는 익명 함수
  • 따라서.. (App 기준) App이라는 변수에 익명 함수를 설정하는 방식으로 구현
  • 이 때, export default 구문을 가지지 못하므로 함수가 끝난 뒤 export default (함수 명)구문이 필요함

import type과 import의 차이

  • import type
    • 자바스크립트로 컴파일할 때만 필요한 정보일 때, 사용
    • 컴파일 한 후 데이터가 완전히 사라짐
  • import
    • 클래스는 물리적으로 동작하는 메서드와 속성이 있기 때문에, import를 사용
    • 컴파일을 해도 데이터가 사라지지 않음

함수형 컴포넌트의 타입

  • FC
    • FunctionComponent
  • CP
    • ClassComponent

화살표 함수 방식 구현

import type { FC } from "react";

export type ArrowComponentProps = {
  href: string;
  text: string;
};

const ArrowComponent: FC<ArrowComponentProps> = (props) => {
  const { href, text } = props;
  return (
    <li>
      <a href={href}>
        <p>{text}</p>
      </a>
    </li>
  );
};

export default ArrowComponent;
  • 이후 App.tsx에서, ClassComponent를 했던 때와 같이 값을 입력하면 똑같이 실행이 된다.