20. React use
20. React use

20. React use

Authors
Date
Tags
react
Published
Published
Slug
๐Ÿ’ก
์ด ๊ธ€์€ ์ž‘์„ฑ์ž์˜ ๊ฒฌํ•ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ chatgpt์˜ ๋„์›€์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
notion image

โš™๏ธ React์—์„œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ์‹

React๋Š” state ์ค‘์‹ฌ์˜ UI ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.
์ฆ‰, ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์— ํ‘œ์‹œ๋˜๋Š” ๋™์  ๋ฐ์ดํ„ฐ๋Š” ๋ชจ๋‘ state๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌ๋˜๋ฉฐ, ์ด state๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๋งˆ๋‹ค ์ปดํฌ๋„ŒํŠธ๋Š” ๋‹ค์‹œ ๋ Œ๋”๋ง๋œ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์ด๋Ÿฐ ํ๋ฆ„ ์†์—์„œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ• ๊นŒ?
์˜ˆ๋ฅผ ๋“ค์–ด ์„œ๋ฒ„์—์„œ ์ƒํ’ˆ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜จ๋‹ค๊ฑฐ๋‚˜, ์™ธ๋ถ€ API์—์„œ ๋‚ ์”จ ์ •๋ณด๋ฅผ ๋ฐ›์•„์˜ค๋Š” ๋“ฑ์˜ ์ž‘์—…์€ **๋น„๋™๊ธฐ(Promise ๊ธฐ๋ฐ˜)**์ด๋‹ค.
์ด๋Ÿฌํ•œ ๋ฐ์ดํ„ฐ๋ฅผ React์—์„œ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค:
ย 

๐Ÿ”„ useEffect๋ฅผ ํ™œ์šฉํ•œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ

React์˜ ๋Œ€ํ‘œ์ ์ธ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์€ useEffect ํ›…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
'use client'; import { useEffect, useState } from 'react'; import { Product } from '@/libs/types/types'; import { fetchProducts } from '@/libs/fetchProducts'; export function Products() { const [products, setProducts] = useState<Product[]>([]); useEffect(() => { (async () => { const result = await fetchProducts(); setProducts(result); })(); }, []); return ( <ul className="flex flex-col gap-4"> {products.map((product) => ( <li key={product.id} className="border border-green-400"> <strong>{product.title}</strong> </li> ))} </ul> ); }

โœ… ํ๋ฆ„ ์š”์•ฝ

  1. products๋ผ๋Š” ์ดˆ๊ธฐ ์ƒํƒœ๊ฐ’์„ ๋นˆ ๋ฐฐ์—ด๋กœ ์„ค์ •
  1. useEffect ์•ˆ์—์„œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ํ˜ธ์ถœ
  1. setState๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ 
  1. ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฆฌ๋ Œ๋”๋ง๋˜์–ด ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๊ฐ€ ํ™”๋ฉด์— ํ‘œ์‹œ๋จ
์ด ๋ฐฉ์‹์€ ํด๋ผ์ด์–ธํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์ „ํ†ต์ ์ธ ํŒจํ„ด์ด๋ฉฐ, CSR(Client Side Rendering)์—์„œ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
ย 

โ›“๏ธ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ์—์„œ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด?

Next.js๋‚˜ Remix์ฒ˜๋Ÿผ **์„œ๋ฒ„ ์‚ฌ์ด๋“œ ๋ Œ๋”๋ง(SSR)**์„ ์ง€์›ํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š”
์ดˆ๊ธฐ ๋ Œ๋”๋ง ์‹œ์ ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™€ HTML์„ ์™„์„ฑํ•ด์•ผ ํ•˜๋Š” ์š”๊ตฌ๊ฐ€ ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ ์„œ๋ฒ„์—์„œ๋Š” useEffect๋‚˜ useState๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
(์„œ๋ฒ„๋Š” DOM์ด ์—†๊ณ , ๋ฆฌ๋ Œ๋”๋ง์ด๋ผ๋Š” ๊ฐœ๋… ์ž์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ)
๊ทธ๋ž˜์„œ ๋“ฑ์žฅํ•œ ๋ฐฉ์‹์ด ๋ฐ”๋กœ ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ๋‹ค.
ย 

๐Ÿงฉ ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ์™€ Suspense

์ปดํฌ๋„ŒํŠธ ์ž์ฒด๋ฅผ ๋น„๋™๊ธฐ๋กœ ๋งŒ๋“ค๊ณ , Suspense๋ฅผ ํ™œ์šฉํ•ด ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ํŒจํ„ด์ด๋‹ค.
// โŒ ์ž˜๋ชป๋œ ์‚ฌ์šฉ (ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์— async ์‚ฌ์šฉ) 'use client'; import { fetchProducts } from '@/libs/fetchProducts'; export async function Products() { const products = await fetchProducts(); return ( <ul> {products.map((product) => ( <li key={product.id}>{product.title}</li> ))} </ul> ); }
์ด ๋ฐฉ์‹์€ ์ž˜๋ชป๋œ ์‚ฌ์šฉ์ด๋‹ค. async ์ปดํฌ๋„ŒํŠธ๋Š” ์„œ๋ฒ„์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—๋Š” async๋ฅผ ๋ถ™์ผ ์ˆ˜ ์—†๋‹ค.

โœ… ์˜ฌ๋ฐ”๋ฅธ ๊ตฌ์กฐ

// ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ 'use client'; import { Product } from '@/libs/types/types'; export function Products({ products }: { products: Product[] }) { return ( <ul> {products.map((product) => ( <li key={product.id}>{product.title}</li> ))} </ul> ); }
// ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ import { fetchProducts } from '@/libs/fetchProducts'; import { Products } from './products'; export async function ProductsContainer() { const products = await fetchProducts(); return <Products products={products} />; }
์ด๋ ‡๊ฒŒ ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ›์•„์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์— props๋กœ ์ „๋‹ฌํ•˜๋ฉด, ํด๋ผ์ด์–ธํŠธ๋Š” useEffect ์—†์ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ด๋Ÿฐ ๋ฐฉ์‹์€ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•ด ์ปดํฌ๋„ŒํŠธ ์ž์ฒด๊ฐ€ ๋น„๋™๊ธฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋˜์–ด์•ผํ•˜๋ฉฐ, ์ด์— ๋”ฐ๋ผ ์ปดํฌ๋„ŒํŠธ ๊ตฌ์กฐ๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด์•ผ ํ•˜๋Š” ๋ถˆํŽธํ•จ์ด ๋”ฐ๋ฅด๊ธฐ๋„ํ•œ๋‹ค.
ย 

๐Ÿ’ก use ํ›…์˜ ๋“ฑ์žฅ

React 19์—์„œ use(promise)๋ผ๋Š” ์ƒˆ๋กœ์šด ํ›…์ด ์‹คํ—˜์ ์œผ๋กœ ๋„์ž…๋˜๋ฉฐ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

โœ… ๊ตฌ์กฐ๋ฅผ ๋‹จ์ˆœํ•˜๊ฒŒ

// ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ import { fetchProducts } from '@/libs/fetchProducts'; import { Suspense } from 'react'; import { Products } from './products'; export default function Page() { const productsPromise = fetchProducts(); return ( <div> <h1>Use Example</h1> <Suspense fallback={<div>Loading...</div>}> <Products productsPromise={productsPromise} /> </Suspense> </div> ); }
// ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ 'use client'; import { Product } from '@/libs/types/types'; import { use } from 'react'; export function Products({ productsPromise }: { productsPromise: Promise<Product[]> }) { const products = use(productsPromise); return ( <ul> {products.map((product) => ( <li key={product.id}>{product.title}</li> ))} </ul> ); }
์ด์ œ๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ๋„ ์ง์ ‘ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ
useEffect๋„, ๋ณ„๋„์˜ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋„ ํ•„์š” ์—†๋‹ค.
ย 

๐Ÿง  ๋งˆ๋ฌด๋ฆฌ

React๋Š” ์›๋ž˜ state ์ค‘์‹ฌ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ์™€ UI์˜ ๊ด€๊ณ„๋ฅผ ์ž˜ ์ •๋ฆฌํ•ด๋‘๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•˜๋‹ค.
  • useEffect๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ์˜ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํŒจ์นญ์— ์ ํ•ฉ
  • ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํŒจ์นญํ•  ๋• ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ฑฐ๋‚˜
  • ์‹คํ—˜์ ์ธ use๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋”์šฑ ๊น”๋”ํ•œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค
react19์— ์ถ”๊ฐ€๋œ useํ›…์œผ๋กœ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐฉ์‹ ๋˜ํ•œ ํ›จ์”ฌ ์ž์—ฐ์Šค๋Ÿฝ๊ณ  ์ง๊ด€์ ์œผ๋กœ ์ง„ํ™”ํ•˜๊ณ  ์žˆ๋‹ค.
์ด๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜๊ณผ ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ ๋ชจ๋‘๋ฅผ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
ย 

์˜ˆ์ œ

์ด๊ณณ์—์„œ ์˜ˆ์ œ๋ฅผ ํ™•์ธํ•ด๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  1. client-component
  1. async-component
  1. use-component
์ˆœ์œผ๋กœ ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์˜ ๋ณ€ํ™”๋ฅผ ํ™•์ธํ•ด๋ณด์‹œ๋Š”๊ฒƒ์„ ์ถ”์ฒœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
ย 
react-use
entrolEC โ€ข Updated Jun 29, 2025
ย 
ย