React - 2

Dearยท2025๋…„ 4์›” 21์ผ

TIL

๋ชฉ๋ก ๋ณด๊ธฐ
10/74

๐Ÿ’™์ปดํฌ๋„ŒํŠธ

๋ฆฌ์—‘ํŠธ์—์„œ "UI ์กฐ๊ฐ"์„ ๋งŒ๋“œ๋Š” ๋‹จ์œ„์ด๋‹ค.
๋ฒ„ํŠผ, ํ—ค๋”, ํ”„๋กœํ•„ ์นด๋“œ, ํŽ˜์ด์ง€ ๋“ฑ ํ•˜๋‚˜์˜ ํ™”๋ฉด ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜์ด๋‹ค.

  • ํ•จ์ˆ˜๋กœ UI๋ฅผ ๋งŒ๋“ ๋‹ค.
  • ๋ฐ์ดํ„ฐ(props)๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ View(state) ์ƒํƒœ์— ๋”ฐ๋ผ DOM Node(UI)๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • UI๋ฅผ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฐœ๋ณ„์ ์ธ ์—ฌ๋Ÿฌ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์กฐ๊ฐ์„ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋‚˜๋ˆ„์–ด ์ฝ”๋”ฉํ•œ๋‹ค.
// ํ…์ŠคํŠธ ์ƒ์„ฑ ํ•จ์ˆ˜
function sayHello(name) {
  return `์•ˆ๋…•, ${name}`;
}

// ํ…์ŠคํŠธ ๋Œ€์‹  UI (ํ™”๋ฉด ์š”์†Œ)๋ฅผ ์ƒ์„ฑ 
function Hello(props) {
  return <h1>์•ˆ๋…•, {props.name}</h1>;
}

// ์‚ฌ์šฉ
<Hello name="chori" />

// ๋ธŒ๋ผ์šฐ์ €์— ์ถœ๋ ฅ๋œ ๋ชจ์Šต
<h1>์•ˆ๋…•, chori</h1>

์˜ˆ์ œ

// HTML
<div class="profile">
  <img src="profile.jpg" />
  <h2>chori</h2>
</div>

// ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ
// Profile.js
import React from 'react';

const Profile = () => {
  return (
    <div className="profile">
      <img src="profile.jpg" />
      <h2>chori</h2>
    </div>
  );
};

export default Profile;

// ์œ„์˜ Profile.js ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉ ์•„๋ž˜์ฒ˜๋Ÿผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
import Profile from './Profile';

const App = () => {
  return (
    <div>
      <h1>๋‚ด ํŽ˜์ด์ง€</h1>
      <Profile />
    </div>
  );
};

์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ ์ด์œ 

  1. ํ™”๋ฉด์„ ์ชผ๊ฐœ์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฝ๋‹ค.
    ์˜›๋‚  ๋ฐฉ์‹
    HTML / CSS / JS ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ์„ž์–ด ์“ฐ๊ธฐ -> ๋ณต์žก, ์œ ์ง€๋ณด์ˆ˜ ํž˜๋“ฆ

    ๋ฆฌ์•กํŠธ
    ํ™”๋ฉด์„ ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ ๋‚˜๋ˆ ์„œ ๊ด€๋ฆฌ
    `ํ—ค๋”, ๋ฒ„ํŠผ, ๊ฒŒ์‹œ๊ธ€, ๋Œ“๊ธ€ ์„ ๊ฐ๊ฐ ์ปดํฌ๋„ŒํŠธ
    -> ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. ์žฌ์‚ฌ์šฉ์ด ์‰ฝ๋‹ค.
    ํ•œ ๋ฒˆ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ๋ฐ˜๋ณตํ•ด์„œ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

    ๊ฐ™์€ UI ํ‹€์„ ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ์— ๋งž๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์–ด ํšจ์œจ์ ์ด๋‹ค.

  3. ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์„ ์˜ฌ๋ ค์ค€๋‹ค.
    ์ž…๋ ฅ -> ์ถœ๋ ฅ ๊ตฌ์กฐ๊ฐ€ ๋ผ์„œ ์ฝ๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋‹ค.

  4. ์ƒํƒœ(state)๋‚˜ ์ด๋ฒคํŠธ๋„ ํ•จ์ˆ˜ ์•ˆ์—์„œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ

    UI + ๋™์ž‘ + ๋ฐ์ดํ„ฐ ์ƒํƒœ๋ฅผ ํ•œ ํ•จ์ˆ˜(์ปดํฌ๋„ŒํŠธ) ์•ˆ์—์„œ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•ด์„œ ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ ์ •๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’™props

์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๋Š” ๊ฐ’(๋ฐ์ดํ„ฐ)

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ค„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
props์˜ ๊ฐ’์€ ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฐ’์œผ๋กœ ์ฝ๊ธฐ ์ „์šฉ์ด๋‹ค.
-> ์ˆ˜์ • ๋ถˆ๊ฐ€, ํ•ญ์ƒ ๊ฐ™์€ ๊ฐ’ ์œ ์ง€
๋‹ค๋ฅธ props์˜ ๊ฐ’์œผ๋กœ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๋ฉด ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜์—ฌ ์ƒˆ๋กœ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.


// ๋ถ€๋ชจ
function App() {
  return (
    <div>
      <Greeting name="chori" />
    </div>
  );
}

// ์ž์‹
function Greeting(props) {
  return <h1>์•ˆ๋…•, {props.name}!</h1>;
}

// ๊ฒฐ๊ณผ
// ์•ˆ๋…•, chori!

// ๊ตฌ์กฐ ๋ถ„ํ•ด ๊ฐ€๋Šฅ ( ๊ฐ์ฒด๋‚˜ ๋ฐฐ์—ด์—์„œ ๊ฐ’๋งŒ ๊น”๋”ํ•˜๊ฒŒ ๊บผ๋‚ด๋Š” ๋ฌธ๋ฒ•)
function Greeting({ name }) {
  return <h1>์•ˆ๋…•, {name}!</h1>;
}

// ์ปดํฌ๋„ŒํŠธ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ
<Greeting name="์ฒ ์ˆ˜" /> // ์•ˆ๋…•, ์ฒ ์ˆ˜!
<Greeting name="์˜ํฌ" /> // ์•ˆ๋…•, ์˜ํฌ!

๐Ÿ’™ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ

ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ

class ํ‚ค์›Œ๋“œ๋กœ ์ •์˜ํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋กœ state ๊ธฐ๋Šฅ ๋ฐ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์ž„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
render ํ•จ์ˆ˜๊ฐ€ ๊ผญ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๋ณด์—ฌ์ค˜์•ผํ•  JSX๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผํ•œ๋‹ค.
React์—์„œ ์žฌ๊ณตํ•˜๋Š” Component๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•ด์„œ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Class ์—๋Š” ์ƒํƒœ, ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” state ๋ผ๋Š” ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋“ค์–ด์žˆ๋‹ค. state์˜ ๋‚ด์šฉ์ด ์—…๋ฐ์ดํŠธ ๋  ๋•Œ๋งˆ๋‹ค render ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉฐ ์—…๋ฐ์ดํŠธ๋œ ๋‚ด์šฉ์„ ๋ณด์—ฌ์ค€๋‹ค.
๋ผ์ดํ”„ ์‚ฌ์ดํด์— ๋”ฐ๋ผ ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด ๋†“๊ณ  ๋ฆฌ์•กํŠธ๊ฐ€ ์ด๊ฑธ ์ž๋™์œผ๋กœ ์‹คํ–‰์‹œํ‚จ๋‹ค.

import React, { Component } from 'react';

class MyComponent extends Component {
  render() {
    return <h1>์•ˆ๋…•ํ•˜์„ธ์š”!</h1>;
  }
}

// props๋„ this.props๋กœ ์ ‘๊ทผ
class Hello extends Component {
  render() {
    return <p>์•ˆ๋…•ํ•˜์„ธ์š”, {this.props.name}๋‹˜!</p>;
  }
}

state

์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๊ด€๋ฆฌ๋˜๋Š” ๋ฐ์ดํ„ฐ๋กœ, ์‚ฌ์šฉ์ž์˜ ๋™์ž‘์ด๋‚˜ ์ด๋ฒคํŠธ ๋“ฑ์— ๋”ฐ๋ผ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’์ด๋‹ค.

// ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ ๋งˆ๋‹ค ์ˆซ์ž๊ฐ€ ๋ฐ”๋€Œ๋Š” ๊ฒฝ์šฐ
const [count, setCount] = useState(0);
// count ๊ฐ€ state

// state์— ๋”ฐ๋ผ ์œ ๋™์ ์œผ๋กœ ๋ณ€ํ•˜๋Š”  UI
// state๊ฐ€ ๋ณ€ํ•˜๋ฉด (์‚ฌ์šฉ์ž๊ฐ€ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ์ฒดํฌ ๊ฐ™์€ ์ƒํ˜ธ์ž‘์šฉ ๋“ฑ๋“ฑ) 
// ๊ทธ ๊ฐ’์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ž๋™์œผ๋กœ ํ™”๋ฉด์„ ๋ Œ๋”๋ง
<p>ํ˜„์žฌ ์ˆซ์ž: {count}</p>


import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // count ์ดˆ๊ธฐ๊ฐ’์€ 0

  const increase = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>ํ˜„์žฌ ์นด์šดํŠธ: {count}</p>
      <button onClick={increase}>+1</button>
    </div>
  );
}

/*
useState(0) โ†’ ์ดˆ๊ธฐ๊ฐ’์€ 0

count โ†’ ํ˜„์žฌ ์ƒํƒœ ๊ฐ’

setCount โ†’ ์ƒˆ๋กœ์šด ๊ฐ’์œผ๋กœ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ

setCount()๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด, ์ž๋™์œผ๋กœ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋‹ค์‹œ ๋ Œ๋”๋ง
*/

๐Ÿ’™ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ

์žฅ์ 

  • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค ์„ ์–ธํ•˜๊ธฐ๊ฐ€ ํŽธํ•˜๋‹ค
  • ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋ณด๋‹ค ๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ๋œ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํ”„๋กœ์ ํŠธ ์™„์„ฑํ•˜์—ฌ ๋นŒ๋“œ ํ›„ ๋ฐฐํฌํ•  ๋•Œ์—๋„ ๊ฒฐ๊ณผ๋ฌผ์˜ ํŒŒ์ผ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋” ์ ๋‹ค.

๋‹จ์ 

state์™€ ๋ผ์ดํ”„์‚ฌ์ดํด API ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€ํ•˜๋‹ค.
-> Hook ๊ธฐ๋Šฅ์ด ๋„์ž…๋˜๋ฉด์„œ ํ•ด๊ฒฐ

๐Ÿ’™ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์™€ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ ๋น„๊ต

๐Ÿ’™์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„

ํ•ญ์ƒ ๋Œ€๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•ด์•ผํ•œ๋‹ค.

๐Ÿ’™state

๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ์ƒํƒœ
๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์˜ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ(์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ๊ฐ’)
ํด๋ž˜์Šค ์ปดํฌ๋„ŒํŠธ์˜ ๊ฒฝ์šฐ state๋ฅผ ์ƒ์„ฑ์ž์—์„œ ์ •์˜(state ๋ณ€๊ฒฝํ•  ๋•Œ๋Š” setState()๋ฅผ ์‚ฌ์šฉ)
ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ๋Š” useState()๋ผ๋Š” ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •์˜

ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ์— state๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ ์ƒ์„ฑ์ž(constructor) ๋ฉ”์†Œ๋“œ๋ฅผ ์„ค์ •ํ•œ๋‹ค.
๋ฐ˜๋“œ์‹œ super(props)๋ฅผ ํ˜ธ์ถœํ•ด์ค˜์•ผํ•˜๊ณ , ์ด ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ํ˜„์žฌ ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋Š” ๋ฆฌ์•กํŠธ์˜ ์ปดํฌ๋„ŒํŠธ ํด๋ž˜์Šค๊ฐ€ ์ง€๋‹Œ ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ์ค€๋‹ค.

class Counter extends Component {
  constructor(props) {
    super(props); // ๋ฐ˜๋“œ์‹œ ํ˜ธ์ถœํ•ด์•ผ ํ•จ!

    // this.state ์ดˆ๊ธฐํ™”
    this.state = {
      count: 0
    };
  }

  handleIncrement = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <p>ํ˜„์žฌ ์นด์šดํŠธ: {this.state.count}</p>
        <button onClick={this.handleIncrement}>+1</button>
      </div>
    );
  }
}

๐Ÿ’™useState

React์˜ ํ•จ์ˆ˜ํ˜• ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒํƒœ(state)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” Hook ์ด๋‹ค.
์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์ž๋™์œผ๋กœ ํ™”๋ฉด(UI) ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

import React, { useState } from 'react';

function Counter() {
  // const [ํ˜„์žฌ ์ƒํƒœ ๊ฐ’, ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ํ•จ์ˆ˜] = userState('์ดˆ๊ธฐ๊ฐ’');
  // ์ดˆ๊ธฐ๊ฐ’์€ ๋ชจ๋“  ์ž๋ฃŒํ˜•์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  // ํด๋ž˜์Šคํ˜• ์ปดํฌ๋„ŒํŠธ๋Š” ํ•ญ์ƒ ๊ฐ์ฒด
  const [count, setCount] = useState(0); // ์ƒํƒœ ๋ณ€์ˆ˜ ์„ ์–ธ

  return (
    <div>
      <p>ํ˜„์žฌ ์นด์šดํŠธ: {count}</p>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

๐Ÿ’—Todo

๊ตฌ์กฐ ๋ถ„ํ•ด ๋งŽ์ด ์จ๋ณผ ๊ฒƒ

์ต์ˆ™ํ•˜์ง€ ์•Š์•„์„œ ์ฝ์–ด๋„ ํ•ด์„ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
์˜ˆ์‹œ๋ฅผ ๋งŒ๋“ค๋ผ๊ณ  ํ•ด๋„ ์ž‘์„ฑํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

profile
์นœ์• ํ•˜๋Š” ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€