Frontend ๐Ÿ“š/React

[์ฝ”๋”ฉ์• ํ”Œ] ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ Part6 - Redux

leejaejae 2023. 10. 23. 20:38

๐Ÿ’‍โ™€๏ธ ์žฅ๋ฐ”๊ตฌ๋‹ˆ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

// Cart.js

import { Table } from 'react-bootstrap'

let state = useSelector((state)=> state)

<Table>
  <thead>
    <tr>
      <th>#</th>
      <th>์ƒํ’ˆ๋ช…</th>
      <th>์ˆ˜๋Ÿ‰</th>
      <th>๋ณ€๊ฒฝํ•˜๊ธฐ</th>
    </tr>
  </thead>
  <tbody>
    {
      state.cart.map((a, i)=>
        <tr key={i}>
          <td>1</td>
          <td>{state.cart[i].name}</td>
          <td>{state.cart[i].count}</td>
          <td>์•ˆ๋…•</td>
        </tr>
       )
     }
  </tbody> 
</Table>

 

โœ๏ธ Redux

โœ๏ธ Redux ์“ฐ๋ฉด ์ข‹์€ ์ 
- props ์—†์ด ํŽธ๋ฆฌํ•˜๊ฒŒ state ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
! ๊ฐ„๋‹จํ•œ ๊ฑฐ ๋งŒ๋“ค ๋•Œ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ช‡ ๊ฐœ ์—†์„ ๋•Œ → props ์“ฐ๋Š”๊ฒŒ ๋” ์ด๋“์ž„

- ์ด๊ฑฐ ์„ค์น˜ํ•˜๋ฉด js ํŒŒ์ผ ํ•˜๋‚˜์— state๋“ค์„ ๋ณด๊ด€ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๊ฑธ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ง์ ‘ ๊บผ๋‚ด์“ธ ์ˆ˜ ์žˆ์Œ.
- ๊ทธ๋ž˜์„œ ๊ท€์ฐฎ์€ props ์ „์†ก์ด ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค. 

โœ๏ธ Redux ์„ค์น˜

npm install @reduxjs/toolkit react-redux

- redux toolkit์€ redux์˜ ๊ฐœ์„  ๋ฒ„์ „(๋ฌธ๋ฒ•์ด ์ข€ ๋” ์‰ฌ์›Œ์ง„๋‹ค)
- package.json์—์„œ "react", "react-dom" ๋ฒ„์ „์ด 18.1.x ์ด์ƒ์ด๋ฉด ์‚ฌ์šฉ๊ฐ€๋Šฅ(์•„๋‹˜ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฉด ํŒŒ์ผ ์ €์žฅํ•˜๊ณ  ํ„ฐ๋ฏธ๋„์—์„œ npm install ๋ˆŒ๋Ÿฌ๋„ ๋จ)

โœ๏ธ Redux ์…‹ํŒ…

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: { }
})

1. ์•„๋ฌด๋ฐ๋‚˜ store.js ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์œ„ ์ฝ”๋“œ๋ฅผ ๋ณต๋ถ™ํ•ด์ค€๋‹ค. (state๋“ค์„ ๋ณด๊ด€ํ•˜๋Š” ํŒŒ์ผ)

import { Provider } from "react-redux";
import store from './store.js'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

2. index.js ํŒŒ์ผ ๊ฐ€์„œ Provider ๋ผ๋Š” ์ปดํฌ๋„ŒํŠธ์™€ ์•„๊นŒ ์ž‘์„ฑํ•œ ํŒŒ์ผ์„ import ํ•ด์˜จ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ฐ‘์— <Provider store={import ํ•ด์˜จ๊ฑฐ} ์ด๊ฑธ๋กœ <App/>์„ ๊ฐ์‹ธ๋ฉด ๋œ๋‹ค.

โœ๏ธ Redux store์— state ๋ณด๊ด€ํ•˜๋Š” ๋ฒ•
- store.js ํŒŒ์ผ์„ ์—ด์–ด์„œ ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ์งœ๋ฉด state ํ•˜๋‚˜ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
step 1. createSlice()๋กœ state ๋งŒ๋“ค๊ณ 
step 2. configureStore() ์•ˆ์— ๋“ฑ๋ก

import { configureStore, createSlice } from '@reduxjs/toolkit'

let user = createSlice({
  name : 'user',
  initialState : 'kim'
})

export default configureStore({
  reducer: {
    user : user.reducer
  }
})

1. createSlice() ์ƒ๋‹จ์—์„œ import ํ•ด์˜จ ๋‹ค์Œ์— { name : 'state์ด๋ฆ„', initialState : 'state๊ฐ’' } ์ด๊ฑฐ ๋„ฃ์œผ๋ฉด state ํ•˜๋‚˜ ์ƒ์„ฑ๊ฐ€๋Šฅ(createSlice( ) ๋Š” useState( ) ์™€ ์šฉ๋„๊ฐ€ ๋น„์Šทํ•˜๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.)

2. state ๋“ฑ๋ก์€ configureStore( ) ์•ˆ์— ํ•˜๋ฉด ๋œ๋‹ค. { ์ž‘๋ช… : createSlice๋งŒ๋“ ๊ฑฐ.reducer } ์ด๋Ÿฌ๋ฉด ๋“ฑ๋ก ๋. ์—ฌ๊ธฐ ๋“ฑ๋กํ•œ state๋Š” ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉ๊ฐ€๋Šฅ.

โœ๏ธ Redux store์— ์žˆ๋˜ state ๊ฐ€์ ธ๋‹ค์“ฐ๋Š” ๋ฒ•

// Cart.js

import { useSelector } from "react-redux"

function Cart(){
  let a = useSelector((state) => { return state } )  
  // let a = useSelector((state) => state.user ) ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋” ํŽธ๋ฆฌํ•  ์ˆ˜๋„?! ํŽธํ•œ ๊ฑธ๋กœ ใ„ฑใ„ฑ
  console.log(a)

  return (์ƒ๋žต)
}

- ์•„๋ฌด ์ปดํฌ๋„ŒํŠธ์—์„œ  useSelector((state) => { return state } ) ์“ฐ๋ฉด store์— ์žˆ๋˜ ๋ชจ๋“  state๊ฐ€ ๊ทธ ์ž๋ฆฌ์— ๋‚จ๋Š”๋‹ค. ({ user : 'kim' } ์ด๋Ÿฐ๊ฑฐ ์ถœ๋ ฅ๋ ๋“ฏ)

โœ๏ธ store์˜ state ๋ณ€๊ฒฝํ•˜๋Š” ๋ฒ• 
- state ์ˆ˜์ •ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ถ€ํ„ฐ store.js์— ๋งŒ๋“ค์–ด๋‘๊ณ 
๊ทธ๊ฑธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์›ํ•  ๋•Œ ์‹คํ–‰ํ•˜๋Š” ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ง ๋‹ค.
1. store.js ์•ˆ์— state ์ˆ˜์ •ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ถ€ํ„ฐ ๋งŒ๋“ ๋‹ค

let user = createSlice({  // ํ•จ์ˆ˜ ์ž‘๋ช… ์ž์œ ๋กญ๊ฒŒ
  name : 'user',  // ํŒŒ๋ผ๋ฏธํ„ฐ ํ•˜๋‚˜ ์ž‘๋ช…ํ•˜๋ฉด ๊ทธ๊ฑด ๊ธฐ์กด์˜ state๊ฐ€ ๋œ๋‹ค
  initialState : 'kim',
  reducers : {
    changeName(state){
      return 'john ' + state  // return ์šฐ์ธก์— ์ƒˆ๋กœ์šด state ์ž…๋ ฅํ•˜๋ฉด ๊ทธ๊ฑธ๋กœ ๊ธฐ์กด state๋ฅผ ๊ฐˆ์•„์น˜์›€
    }
  }
})

// ์ด์ œ changeName() ์“ธ ๋•Œ๋งˆ๋‹ค 'kim' -> 'john kim' ์ด๋ ‡๊ฒŒ ๋ณ€ํ•จ

- slice ์•ˆ์— reducers : { } ์—ด๊ณ  ๊ฑฐ๊ธฐ ์•ˆ์— ํ•จ์ˆ˜ ๋งŒ๋“ค๋ฉด ๋œ๋‹ค.

2. ๋‹ค๋ฅธ ๊ณณ์—์„œ ์“ฐ๊ธฐ ์ข‹๊ฒŒ export ํ•ด๋‘๊ธฐ

export let { changeName } = user.actions

- ์ด๋Ÿฐ ์ฝ”๋“œ๋ฅผ store.js ๋ฐ‘์— ์ถ”๊ฐ€
- slice์ด๋ฆ„.actions ๋ผ๊ณ  ์ ์œผ๋ฉด state ๋ณ€๊ฒฝํ•จ์ˆ˜๊ฐ€ ์ „๋ถ€ ๊ทธ ์ž๋ฆฌ์— ์ถœ๋ ฅ๋จ
- ๊ทธ๊ฑธ ๋ณ€์ˆ˜์— ์ €์žฅํ–ˆ๋‹ค๊ฐ€ export ํ•˜๋ผ๋Š” ๋œป์ผ ๋ฟ

3. ์›ํ•  ๋•Œ import ํ•ด์„œ ์‚ฌ์šฉ, ๊ทผ๋ฐ dispatch()๋กœ ๊ฐ์‹ธ์„œ ์จ์•ผํ•จ
- ์˜ˆ๋ฅผ ๋“ค์–ด Cart.js ์—์„œ ๋ฒ„ํŠผ๊ฐ™์€๊ฑฐ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ  ๊ทธ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด state๋ฅผ 'kim' -> 'john kim' ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์œผ๋ฉด

 

// Cart.js

import { useDispatch, useSelector } from "react-redux"  //useDispatch ๋ผ๋Š” ๊ฒƒ๋„ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๊ฐ€์ ธ์˜ค๊ณ 
import { changeName } from "./../store.js"  // store.js์—์„œ ์›ํ•˜๋Š” state๋ณ€๊ฒฝํ•จ์ˆ˜ ๊ฐ€์ ธ์˜ค๊ณ 

(์ƒ๋žต) 

<button onClick={()=>{
  dispatch(changeName())  //dispatch( state๋ณ€๊ฒฝํ•จ์ˆ˜() ) ์ด๋ ‡๊ฒŒ ๊ฐ์‹ธ์„œ ์‹คํ–‰ํ•˜๋ฉด state ์ง„์งœ๋กœ ๋ณ€๊ฒฝ
}}>๋ฒ„ํŠผ์ž„</button>

- ์ด๋ ‡๊ฒŒ ์ฝ”๋“œ ์งœ๋ฉด ๋œ๋‹ค.

๐Ÿค” ๋ณต์žกํ•œ ๊ฒƒ ๊ฐ™์€๋ฐ์š”?

store ์•ˆ์— ์žˆ๋Š” state ์ˆ˜์ •ํ•˜๊ณ  ์‹ถ์œผ๋ฉด
- state ์ˆ˜์ •ํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋ฅผ store.js์— ๋งŒ๋“ค์–ด๋‘๊ณ 
- ์ปดํฌ๋„ŒํŠธ๋Š” ๊ทธ๊ฑธ ๋ถ€๋ฅด๊ธฐ๋งŒ ํ•˜๋Š” ์‹์œผ๋กœ state ์ˆ˜์ •ํ•˜๊ฒŒ ๋˜์–ด์žˆ์Œ

! ์ปดํฌ๋„ŒํŠธ์—์„œ state ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ฉด ํŽธํ•˜์ง€ ์•Š๋‚˜
- ๋‹น์žฅ์€ ํŽธํ•  ์ง€ ๋ชฐ๋ผ๋„ ๋‚˜์ค‘์— ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง€๋ฉด ์‹ฌ๊ฐํ•œ ๋‹จ์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

- ์ปดํฌ๋„ŒํŠธ 100๊ฐœ์—์„œ ์ง์ ‘ 'kim' ์ด๋ผ๋Š” state ๋ณ€๊ฒฝํ•˜๋‹ค๊ฐ€ ๊ฐ‘์ž๊ธฐ 'kim'์ด 123์ด ๋˜์–ด๋ฒ„๋ฆฌ๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ๋ฒ”์ธ ์ฐพ์œผ๋ ค๊ณ  ์ปดํฌ๋„ŒํŠธ 100๊ฐœ๋ฅผ ๋‹ค ๋’ค์ ธ์•ผํ•œ๋‹ค.

- ๊ทผ๋ฐ state ์ˆ˜์ •ํ•จ์ˆ˜๋ฅผ store.js์— ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด๋‘๊ณ  ์ปดํฌ๋„ŒํŠธ๋Š” ๊ทธ๊ฑฐ ์‹คํ–‰ํ•ด๋‹ฌ๋ผ๊ณ  ๋ถ€ํƒ๋งŒ ํ•˜๋Š” ์‹์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์งœ๋†“์œผ๋ฉด 'kim'์ด 123์ด ๋˜์–ด๋ฒ„๋ฆฌ๋Š” ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ๋ฒ”์ธ์ฐพ๊ธฐ๊ฐ€ ์ˆ˜์›”ํ•˜๋‹ค. ๋ฒ”์ธ์€ ๋ฌด์กฐ๊ฑด store.js์— ์žˆ๊ธฐ ๋•Œ๋ฌธ! (์ˆ˜์ •ํ•จ์ˆ˜๋ฅผ ์ž˜ ๋งŒ๋“ค์–ด๋†จ๋‹ค๋ฉด)

โœ๏ธ redux state๊ฐ€ array/object์ธ ๊ฒฝ์šฐ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด
- ๋Œ€์ถฉ {name : 'kim', age : 20} ์ด๋ ‡๊ฒŒ ์ƒ๊ธด ์ž๋ฃŒ๋ฅผ state๋กœ ๋งŒ๋“ค์–ด๋ณด์ž
- ๊ทผ๋ฐ ์ €๊ธฐ์„œ 'kim' -> 'park' ์ด๋ ‡๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์œผ๋ฉด state ๋ณ€๊ฒฝํ•จ์ˆ˜ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค์–ด์•ผํ• ๊นŒ

let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    changeName(state){
      return {name : 'park', age : 20}
    }
  }
})

- ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด return ์˜ค๋ฅธ์ชฝ์— ์ ์€๊ฑธ๋กœ ๊ธฐ์กด state๋ฅผ ๋ณ€๊ฒฝ์‹œํ‚ค๋Š” ๊ผด์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ changeName() ์‚ฌ์šฉ์‹œ ๋ณ€๊ฒฝ๋œ๋‹ค.

let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    changeName(state){
      state.name = 'park'
    }
  }
})

- ๊ทผ๋ฐ state๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ผ๊ณ ํ•ด๋„ ๋ณ€๊ฒฝ ์ž˜ ๋œ๋‹ค.
- ๊ทธ ์ด์œ ๋Š” mmer.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ state ์‚ฌ๋ณธ์„ ํ•˜๋‚˜ ๋” ์ƒ์„ฑํ•ด์ค€ ๋•๋ถ„์ธ๋ฐ Redux ์„ค์น˜ํ•˜๋ฉด ๋”ธ๋ ค์™€์„œ ๊ทธ๋ ‡๋‹ค. 

- ๊ทธ๋ž˜์„œ ๊ฒฐ๋ก ์€ array/object ์ž๋ฃŒ์˜ ๊ฒฝ์šฐ state๋ณ€๊ฒฝ์€
state๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•ด๋ฒ„๋ ค๋„ ์ž˜ ๋˜๋‹ˆ๊นŒ ์ง์ ‘ ์ˆ˜์ •ํ•˜๋ผ! 
- ์ฐธ๊ณ ) ๊ทธ๋ž˜์„œ state ๋งŒ๋“ค ๋•Œ ๋ฌธ์ž๋‚˜ ์ˆซ์žํ•˜๋‚˜๋งŒ ํ•„์š”ํ•ด๋„
redux์—์„  ์ผ๋ถ€๋Ÿฌ object ์•„๋‹ˆ๋ฉด array์— ๋‹ด๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. ์ˆ˜์ •์ด ํŽธ๋ฆฌํ•ด์ง€๊ธฐ ๋•Œ๋ฌธ

โœ๏ธ state ๋ณ€๊ฒฝํ•จ์ˆ˜๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ํ•„์š”ํ•˜๋ฉด
- ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ age๊ฐ€ +10, +100 ์”ฉ ์ฆ๊ฐ€ํ•˜๊ธธ ์›ํ•  ๋•Œ, +10 ํ•˜๋Š” ํ•จ์ˆ˜ ๋งŒ๋“ค๊ณ  +100 ํ•˜๋Š” ํ•จ์ˆ˜ ๋งŒ๋“ค ํ•„์š” X → ํŒŒ๋ผ๋ฏธํ„ฐ๋ฌธ๋ฒ• ์ด์šฉ

let user = createSlice({
  name : 'user',
  initialState : {name : 'kim', age : 20},
  reducers : {
    increase(state, a){  // increase(10) ํ•˜๋ฉด +10, increase(100) ํ•˜๋ฉด +100
      state.age += a.payload 
    }
  }
})

 

๐Ÿ’‍โ™€๏ธ ์ˆ˜๋Ÿ‰ +1 ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

let cart = createSlice({
  name : 'cart',
  initialState : [
    {id : 0, name : 'White and Black', count : 2},
    {id : 2, name : 'Grey Yordan', count : 1}
  ],
  reducers : {
    addCount(state, action){
      let ๋ฒˆํ˜ธ = state.findIndex((a)=>{ return a.id === action.payload })  // findIndex() ์‚ฌ์šฉํ•ด์„œ ๊ฐ™์€ id ๊ฐ€์ง„ ์ƒํ’ˆ ์ฐพ์•„์„œ +1
      state[๋ฒˆํ˜ธ].count++
    }
  }
})
// Cart.js

import { createSlice } from '@reduxjs/toolkit'

<tbody>
  {
    state.cart.map((a, i)=>
      <tr key={i}>
        <td>{state.cart[i].id}</td>
        <td>{state.cart[i].name}</td>
        <td>{state.cart[i].count}</td>
        <td>
          <button onClick={()=>{ dispatch(addCount(state.cart[i].id)) }}>+</button>  <!-- ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ์˜†์— ์žˆ๋˜ ์ƒํ’ˆ id๋ฅผ payload๋กœ ์ „์†ก -->
          <!-- ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ๋ฒ„ํŠผ ์˜†์— ์žˆ๋Š” ์ƒํ’ˆ id ๊ฐ€์ ธ์™€์„œ ์ด๊ฑฐ๋ž‘ ๋˜‘๊ฐ™์€ id๋ฅผ ๊ฐ€์ง„ ์ƒํ’ˆ์„ state์—์„œ ์ฐพ์•„์„œ ๊ทธ๊ฑธ +1 -->
        </td>
      </tr>
     )
   }
</tbody>

 

๐Ÿ’‍โ™€๏ธ ์ฃผ๋ฌธ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ์žฅ๋ฐ”๊ตฌ๋‹ˆ state์— ์ƒˆ๋กœ์šด ์ƒํ’ˆ ์ถ”๊ฐ€

let cart = createSlice({
  name : 'cart',
  initialState : [
    {id : 0, name : 'White and Black', count : 2},
    {id : 2, name : 'Grey Yordan', count : 1}
  ],
  reducers : {
    addCount(state, action){
      state[action.payload].count++
    },
    addItem(state, action){  // addItem( {id : 2, name : 'Grey Yordan', count : 1} ) ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด{id : 2, name : 'Grey Yordan', count : 1} ์ด ์ƒํ’ˆ์ด state์— ์ถ”๊ฐ€
      state.push(action.payload)
    }
  }
})
// Detail.js

import { createSlice } from '@reduxjs/toolkit' 

<div className="col-md-6">
  <h4 className="pt-5">{์ฐพ์€์ƒํ’ˆ.title}</h4>
  <p>{์ฐพ์€์ƒํ’ˆ.content}</p>
  <p>{์ฐพ์€์ƒํ’ˆ.price}์›</p>
  <button className="btn btn-danger" onClick={()=>{
    dispatch(addItem( {id : 1, name : 'Red Knit', count : 1} ))
  }}>์ฃผ๋ฌธํ•˜๊ธฐ</button>
  </div>
</div>

๋ณธ ํฌ์ŠคํŒ…์€ << React ๋ฆฌ์•กํŠธ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ๊นŒ์ง€! >> ๊ฐ•์˜๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.