React ์๋ฒ ์ก์ ์๋ต ์คํธ๋ฆฌ๋ฐ์ ํตํ ์ ์ง์ ํผ ์๋ต์ ํ์ํด ๋ณด์ธ์. ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ์ ์ํด ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ ์ข์ ํผ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
React ์๋ฒ ์ก์ ์๋ต ์คํธ๋ฆฌ๋ฐ: ํฅ์๋ UX๋ฅผ ์ํ ์ ์ง์ ํผ ์๋ต
React ์๋ฒ ์ก์ ์ React ์ ํ๋ฆฌ์ผ์ด์ ๋ด์์ ์๋ฒ ์ธก ์์ ์ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ๊ฐ๋ ฅํ ํจ๋ฌ๋ค์ ์ ํ์ ๊ฐ์ ธ์ต๋๋ค. ๊ฐ์ฅ ํฅ๋ฏธ๋ก์ด ๊ธฐ๋ฅ ์ค ํ๋๋ ์๋ต์ ์ ์ง์ ์ผ๋ก ์คํธ๋ฆฌ๋ฐํ์ฌ ์ ์ฒด ์์ ์ด ์๋ฃ๋๊ธฐ ์ ์๋ ์ฌ์ฉ์์๊ฒ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํ ์ ์๋ค๋ ๊ฒ์ ๋๋ค. ์ด๋ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง์ ๋ฐ๋ผ UI๋ฅผ ์ ๋ฐ์ดํธํ์ฌ ๋ ๋ฐ์์ ์ด๊ณ ๋งค๋ ฅ์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ง๋ค ์ ์๋ ํผ์ ํนํ ์ ์ฉํฉ๋๋ค.
React ์๋ฒ ์ก์ ์ดํดํ๊ธฐ
์๋ฒ ์ก์ ์ React ์ปดํฌ๋ํธ์์ ์์๋์ด ์๋ฒ์์ ์คํ๋๋ ๋น๋๊ธฐ ํจ์์ ๋๋ค. ๊ธฐ์กด API ํธ์ถ์ ๋นํด ์ฌ๋ฌ ๊ฐ์ง ์ด์ ์ ์ ๊ณตํฉ๋๋ค:
- ํฅ์๋ ๋ณด์: ์๋ฒ ์ก์ ์ ์๋ฒ์์ ์ง์ ์คํ๋๋ฏ๋ก ๋ฏผ๊ฐํ ๋ฐ์ดํฐ๋ ๋ก์ง์ด ํด๋ผ์ด์ธํธ์ ๋ ธ์ถ๋ ์ํ์ ์ค์ ๋๋ค.
- ๋ณด์ผ๋ฌํ๋ ์ดํธ ๊ฐ์: ํด๋ผ์ด์ธํธ ์ธก์์ ๋ณ๋์ API ๋ผ์ฐํธ์ ๋ฐ์ดํฐ ํ์นญ ๋ก์ง์ด ํ์ ์์ด์ง๋๋ค.
- ์ฑ๋ฅ ํฅ์: ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR)๊ณผ ์บ์ฑ์ ํ์ฉํ์ฌ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ๋จ์ถํ๊ณ ์ฑ๋ฅ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
- ํ์ ์์ ์ฑ: TypeScript์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์๋ฒ ์ก์ ์ ์ข ๋จ ๊ฐ ํ์ ์์ ์ฑ์ ์ ๊ณตํ์ฌ ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ๋ฐ์ดํฐ ์ผ๊ด์ฑ์ ๋ณด์ฅํฉ๋๋ค.
์๋ต ์คํธ๋ฆฌ๋ฐ์ ํ
๊ธฐ์กด์ ํผ ์ ์ถ ๋ฐฉ์์ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์๋ฒ๋ก ๋ณด๋ด๊ณ , ์๋ต์ ๊ธฐ๋ค๋ฆฐ ๋ค์, ๊ทธ์ ๋ฐ๋ผ UI๋ฅผ ์ ๋ฐ์ดํธํ๋ ๊ณผ์ ์ ํฌํจํฉ๋๋ค. ์ด๋ ํนํ ๋ณต์กํ ํผ์ด๋ ๋๋ฆฐ ๋คํธ์ํฌ ์ฐ๊ฒฐ์์ ์ง์ฐ ์๊ฐ์ผ๋ก ๋๊ปด์ง ์ ์์ต๋๋ค. ์๋ต ์คํธ๋ฆฌ๋ฐ์ ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒญํฌ ๋จ์๋ก ๋ณด๋ผ ์ ์๊ฒ ํ์ฌ, ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง์ ๋ฐ๋ผ ์ ์ง์ ์ผ๋ก UI๋ฅผ ์ ๋ฐ์ดํธํ ์ ์๊ฒ ํด์ค๋๋ค.
์ฌ์ฉ์ ์ ๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก ๋ณต์กํ ๊ฐ๊ฒฉ์ ๊ณ์ฐํ๋ ํผ์ ์์ํด ๋ณด์ธ์. ์ ์ฒด ๊ณ์ฐ์ด ์๋ฃ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๋์ , ์๋ฒ๋ ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ํด๋ผ์ด์ธํธ๋ก ์คํธ๋ฆฌ๋ฐํ์ฌ ์ฌ์ฉ์์๊ฒ ์ค์๊ฐ ํผ๋๋ฐฑ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ํฌ๊ฒ ํฅ์์ํค๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ๋ฐ์์ ์ผ๋ก ๋๊ปด์ง๊ฒ ๋ง๋ญ๋๋ค.
์๋ฒ ์ก์ ์ผ๋ก ์ ์ง์ ํผ ์๋ต ๊ตฌํํ๊ธฐ
React ์๋ฒ ์ก์ ์ ์ฌ์ฉํ์ฌ ์ ์ง์ ํผ ์๋ต์ ๊ตฌํํ๋ ์์ ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์์ : ์ค์๊ฐ ํ์จ ๋ณํ๊ธฐ
์ฌ์ฉ์๊ฐ ๊ธ์ก์ ์ ๋ ฅํ ๋ ์ค์๊ฐ ํ์จ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ๋ ๊ฐ๋จํ ํ์จ ๋ณํ๊ธฐ ํผ์ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
1. ์๋ฒ ์ก์ ์ค์ ํ๊ธฐ
๋จผ์ , ํ์จ ๋ณํ์ ์ฒ๋ฆฌํ๋ ์๋ฒ ์ก์ ์ ์ ์ํฉ๋๋ค.
// server/actions.ts
'use server';
import { unstable_cache } from 'next/cache';
async function getExchangeRate(fromCurrency: string, toCurrency: string): Promise<number> {
// ์ธ๋ถ API์์ ํ์จ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค
console.log(`Fetching exchange rate for ${fromCurrency} to ${toCurrency}`);
await new Promise(resolve => setTimeout(resolve, 500)); // ๋คํธ์ํฌ ์ง์ฐ์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค
if (fromCurrency === 'USD' && toCurrency === 'EUR') return 0.92;
if (fromCurrency === 'EUR' && toCurrency === 'USD') return 1.09;
if (fromCurrency === 'USD' && toCurrency === 'JPY') return 145;
if (fromCurrency === 'JPY' && toCurrency === 'USD') return 0.0069;
throw new Error(`Exchange rate not found for ${fromCurrency} to ${toCurrency}`);
}
export const convertCurrency = async (prevState: any, formData: FormData) => {
const fromCurrency = formData.get('fromCurrency') as string;
const toCurrency = formData.get('toCurrency') as string;
const amount = Number(formData.get('amount'));
try {
if (!fromCurrency || !toCurrency || isNaN(amount)) {
return { message: '์ ํจํ ์
๋ ฅ๊ฐ์ ์ ๊ณตํด์ฃผ์ธ์.' };
}
// ์๋ต ์คํธ๋ฆฌ๋ฐ์ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค
await new Promise(resolve => setTimeout(resolve, 250));
const exchangeRate = await unstable_cache(
async () => getExchangeRate(fromCurrency, toCurrency),
[`exchange-rate-${fromCurrency}-${toCurrency}`],
{ tags: [`exchange-rate-${fromCurrency}-${toCurrency}`] }
)();
await new Promise(resolve => setTimeout(resolve, 250));
const convertedAmount = amount * exchangeRate;
return { message: `๋ณํ๋ ๊ธ์ก: ${convertedAmount.toFixed(2)} ${toCurrency}` };
} catch (e: any) {
console.error(e);
return { message: 'ํตํ ๋ณํ์ ์คํจํ์ต๋๋ค.' };
}
};
์ด ์์ ์์ `convertCurrency` ์๋ฒ ์ก์ ์ ํ์จ์ ๊ฐ์ ธ์(์ง์ฐ ์๊ฐ์ผ๋ก ์๋ฎฌ๋ ์ด์ ) ๋ณํ๋ ๊ธ์ก์ ๊ณ์ฐํฉ๋๋ค. `setTimeout`์ ์ฌ์ฉํ์ฌ ์ธ์์ ์ธ ์ง์ฐ์ ์ถ๊ฐํ์ฌ ๋คํธ์ํฌ ์ง์ฐ์ ์๋ฎฌ๋ ์ด์ ํ๊ณ ์คํธ๋ฆฌ๋ฐ ํจ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
2. React ์ปดํฌ๋ํธ ๊ตฌํํ๊ธฐ
๋ค์์ผ๋ก, ์๋ฒ ์ก์ ์ ์ฌ์ฉํ๋ React ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ญ๋๋ค.
// app/page.tsx
'use client';
import { useState, useTransition } from 'react';
import { convertCurrency } from './server/actions';
import { useFormState } from 'react-dom';
export default function CurrencyConverter() {
const [fromCurrency, setFromCurrency] = useState('USD');
const [toCurrency, setToCurrency] = useState('EUR');
const [amount, setAmount] = useState('');
const [isPending, startTransition] = useTransition();
const [state, formAction] = useFormState(convertCurrency, { message: '' });
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
startTransition(() => {
formAction(new FormData(event.target as HTMLFormElement));
});
};
return (
<div>
<h2>์ค์๊ฐ ํ์จ ๋ณํ๊ธฐ</h2>
<form action={handleSubmit}>
<label htmlFor="fromCurrency">๋ณด๋ด๋ ํตํ:</label>
<select id="fromCurrency" name="fromCurrency" value={fromCurrency} onChange={(e) => setFromCurrency(e.target.value)}>
<option value="USD">USD</option>
<option value="EUR">EUR</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="toCurrency">๋ฐ๋ ํตํ:</label>
<select id="toCurrency" name="toCurrency" value={toCurrency} onChange={(e) => setToCurrency(e.target.value)}>
<option value="EUR">EUR</option>
<option value="USD">USD</option>
<option value="JPY">JPY</option>
</select>
<label htmlFor="amount">๊ธ์ก:</label>
<input
type="number"
id="amount"
name="amount"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button type="submit" disabled={isPending}>
{isPending ? '๋ณํ ์ค...' : '๋ณํ'}
</button>
</form>
<p>{state.message}</p>
</div>
);
}
์ฃผ์ ์ฌํญ:
- ํผ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ ์๋ฒ ์ก์ ์ ํธ์ถํ๊ธฐ ์ํด `useFormState` ํ ์ ์ฌ์ฉํฉ๋๋ค.
- `useTransition`์์ ์ค๋ `isPending` ์ํ๋ ์ก์ ์ด ์คํ๋๋ ๋์ ์ ์ถ ๋ฒํผ์ ๋นํ์ฑํํ๊ณ "๋ณํ ์ค..." ๋ฉ์์ง๋ฅผ ํ์ํ์ฌ ์ฌ์ฉ์์๊ฒ ํผ๋๋ฐฑ์ ์ค๋๋ค.
- `useFormState`๊ฐ ๋ฐํํ๋ `formAction` ํจ์๋ ์๋์ผ๋ก ํผ ์ ์ถ์ ์ฒ๋ฆฌํ๊ณ ์๋ฒ ์ก์ ์ ์๋ต์ผ๋ก ์ํ๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค.
3. ์ ์ง์ ์ ๋ฐ์ดํธ ์ดํดํ๊ธฐ
์ฌ์ฉ์๊ฐ ํผ์ ์ ์ถํ๋ฉด `handleSubmit` ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค. ์ด ํจ์๋ ํผ์์ `FormData` ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ `formAction` ํจ์์ ์ ๋ฌํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์๋ฒ ์ก์ ์ด ์๋ฒ์์ ์คํ๋ฉ๋๋ค. ์๋ฒ ์ก์ ์ ๋์ ๋ ์ธ์์ ์ธ ์ง์ฐ ๋๋ฌธ์ ๋ค์๊ณผ ๊ฐ์ ํ์์ ๊ด์ฐฐํ ์ ์์ต๋๋ค:
- ์ ์ถ ๋ฒํผ์ด ๊ฑฐ์ ์ฆ์ "๋ณํ ์ค..."์ผ๋ก ๋ณ๊ฒฝ๋ฉ๋๋ค.
- ์งง์ ์ง์ฐ(250ms) ํ, ์ฝ๋๋ ํ์จ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์๋ฎฌ๋ ์ด์ ํฉ๋๋ค.
- ๋ณํ๋ ๊ธ์ก์ด ๊ณ์ฐ๋๊ณ ๊ฒฐ๊ณผ๊ฐ ํด๋ผ์ด์ธํธ๋ก ๋ค์ ์ ์ก๋ฉ๋๋ค.
- React ์ปดํฌ๋ํธ์ `state.message`๊ฐ ์ ๋ฐ์ดํธ๋์ด ๋ณํ๋ ๊ธ์ก์ ํ์ํฉ๋๋ค.
์ด๋ ์๋ต ์คํธ๋ฆฌ๋ฐ์ ํตํด ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง์ ๋ฐ๋ผ ์ฌ์ฉ์์๊ฒ ์ค๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ์ฌ ๋ ๋ฐ์์ ์ด๊ณ ๋งค๋ ฅ์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ผ๋ก ์ด์ด์ง๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
์ ์ง์ ํผ ์๋ต์ ์ด์
- ํฅ์๋ ์ฌ์ฉ์ ๊ฒฝํ: ์ฌ์ฉ์์๊ฒ ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ ๋ฐ์์ ์ด๊ณ ๋ ๋๋ฆฌ๊ฒ ๋๊ปด์ง๊ฒ ํฉ๋๋ค.
- ์ฒด๊ฐ ์ง์ฐ ์๊ฐ ๊ฐ์: ์ค๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค์ผ๋ก์จ ์ ์ฒด ์์ ์๊ฐ์ด ๊ฐ๋๋ผ๋ ์ฌ์ฉ์๋ ํ๋ก์ธ์ค๊ฐ ๋ ๋น ๋ฅด๋ค๊ณ ์ธ์ํฉ๋๋ค.
- ์ฐธ์ฌ๋ ํฅ์: ์ค์๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํ์ฌ ์ฌ์ฉ์์ ์ฐธ์ฌ๋ฅผ ์ ์งํ๊ณ ์ฒด๊ฐ ์ง์ฐ์ผ๋ก ์ธํ ํผ ์ดํ์ ๋ฐฉ์งํฉ๋๋ค.
- ์ ํ์จ ์ฆ๊ฐ: ๋ ๋ถ๋๋ฝ๊ณ ๋ฐ์์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ํนํ ๋ณต์กํ ํผ์์ ๋ ๋์ ์ ํ์จ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
๊ณ ๊ธ ๊ธฐ๋ฒ
1. ์ฆ๊ฐ์ ์ธ UI ์ ๋ฐ์ดํธ๋ฅผ ์ํ `useOptimistic` ์ฌ์ฉ
`useOptimistic` ํ ์ ์ฌ์ฉํ๋ฉด ์๋ฒ ์ก์ ์ด ์๋ฃ๋๊ธฐ ์ ์ UI๋ฅผ ๋๊ด์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค. ์ด๋ UI๊ฐ ์์ ๊ฒฐ๊ณผ๋ฅผ ์ฆ์ ๋ฐ์ํ๋ฏ๋ก ํจ์ฌ ๋ ๋น ๋ฅธ ์ฒด๊ฐ ์๋ต ์๊ฐ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
import { useOptimistic } from 'react';
function MyComponent() {
const [optimisticState, addOptimistic] = useOptimistic(
initialState,
(state, newUpdate) => {
// ์
๋ฐ์ดํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ์ํ๋ฅผ ๋ฐํํฉ๋๋ค
return { ...state, ...newUpdate };
}
);
const handleClick = async () => {
addOptimistic({ someValue: '๋๊ด์ ์
๋ฐ์ดํธ' });
await myServerAction();
};
return (
<div>
<p>{optimisticState.someValue}</p>
<button onClick={handleClick}>์
๋ฐ์ดํธ</button>
</div>
);
}
ํ์จ ๋ณํ๊ธฐ ์์ ์์๋ ํ์ฌ ํ์จ์ ๊ธฐ๋ฐ์ผ๋ก ๋ณํ๋ ๊ธ์ก์ ๋๊ด์ ์ผ๋ก ์ ๋ฐ์ดํธํ์ฌ ์๋ฒ์์ ์ค์ ๊ณ์ฐ์ด ์๋ฃ๋๊ธฐ ์ ์ ์ฌ์ฉ์์๊ฒ ์ฆ๊ฐ์ ์ธ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์๋ฒ๊ฐ ์ค๋ฅ๋ฅผ ๋ฐํํ๋ฉด ๋๊ด์ ์ ๋ฐ์ดํธ๋ฅผ ๋๋๋ฆด ์ ์์ต๋๋ค.
2. ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ํด๋ฐฑ ๋ฉ์ปค๋์ฆ ๊ตฌํ
์๋ฒ ์ก์ ์ด ์คํจํ๊ฑฐ๋ ๋คํธ์ํฌ ์ฐ๊ฒฐ์ด ์ค๋จ๋๋ ๊ฒฝ์ฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ ๋ฐ ํด๋ฐฑ ๋ฉ์ปค๋์ฆ์ ๊ตฌํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์๋ฒ ์ก์ ๋ด์์ `try...catch` ๋ธ๋ก์ ์ฌ์ฉํ์ฌ ์ค๋ฅ๋ฅผ ์ก๊ณ ํด๋ผ์ด์ธํธ์ ์ ์ ํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋ฐํํ ์ ์์ต๋๋ค.
// server/actions.ts
export const convertCurrency = async (prevState: any, formData: FormData) => {
// ...
try {
// ...
} catch (error: any) {
console.error(error);
return { message: 'ํตํ ๋ณํ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋์ค์ ๋ค์ ์๋ํด์ฃผ์ธ์.' };
}
};
ํด๋ผ์ด์ธํธ ์ธก์์๋ ์ฌ์ฉ์์๊ฒ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ๊ณ ์์ ์ ์ฌ์๋ํ๊ฑฐ๋ ๊ณ ๊ฐ ์ง์์ ๋ฌธ์ํ ์ ์๋ ์ต์ ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
3. ์ฑ๋ฅ์ ์ํ ํ์จ ์บ์ฑ
์ธ๋ถ API์์ ํ์จ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์ผ์ผํฌ ์ ์์ต๋๋ค. ์ฑ๋ฅ์ ํฅ์์ํค๊ธฐ ์ํด Redis๋ Memcached์ ๊ฐ์ ์บ์ฑ ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ์ฌ ํ์จ์ ์บ์ํ ์ ์์ต๋๋ค. ์์ ์์ ์ฌ์ฉ๋ Next.js์ `unstable_cache`๋ ๋ด์ฅ๋ ์บ์ฑ ์๋ฃจ์ ์ ์ ๊ณตํฉ๋๋ค. ํ์จ์ด ์ต์ ์ํ๋ก ์ ์ง๋๋๋ก ์ฃผ๊ธฐ์ ์ผ๋ก ์บ์๋ฅผ ๋ฌดํจํํ๋ ๊ฒ์ ์์ง ๋ง์ธ์.
4. ๊ตญ์ ํ ๊ณ ๋ ค์ฌํญ
์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ๋๋ ๊ตญ์ ํ(i18n)๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ ๋ค์์ด ํฌํจ๋ฉ๋๋ค:
- ์ซ์ ์์: ๋ค๋ฅธ ๋ก์ผ์ผ์ ๋ง๋ ์ซ์ ์์์ ์ฌ์ฉํฉ๋๋ค (์: ์ผํ๋ ๋ง์นจํ๋ฅผ ์์์ ๊ตฌ๋ถ ๊ธฐํธ๋ก ์ฌ์ฉ).
- ํตํ ์์: ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๋ฐ๋ผ ํตํ ๊ธฐํธ์ ์์์ ํ์ํฉ๋๋ค.
- ๋ ์ง ๋ฐ ์๊ฐ ์์: ๋ค๋ฅธ ๋ก์ผ์ผ์ ๋ง๋ ๋ ์ง ๋ฐ ์๊ฐ ์์์ ์ฌ์ฉํฉ๋๋ค.
- ํ์งํ: UI๋ฅผ ๋ค๋ฅธ ์ธ์ด๋ก ๋ฒ์ญํฉ๋๋ค.
`Intl` ๋ฐ `react-intl`๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ React ์ ํ๋ฆฌ์ผ์ด์ ์์ i18n์ ๊ตฌํํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ค์ ์ฌ๋ก ๋ฐ ์ฌ์ฉ ์
- ์ ์์๊ฑฐ๋: ์ฌ์ฉ์๊ฐ ์ฅ๋ฐ๊ตฌ๋์ ์ํ์ ์ถ๊ฐํ ๋ ์ค์๊ฐ ๋ฐฐ์ก๋น ๋ฐ ๋ฐฐ์ก ์์ ์๊ฐ์ ํ์ํฉ๋๋ค.
- ๊ธ์ต ์ ํ๋ฆฌ์ผ์ด์ : ์ค์๊ฐ ์ฃผ์ ์์ธ ๋ฐ ํฌํธํด๋ฆฌ์ค ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ฌํ ์์ฝ: ์ค์๊ฐ ํญ๊ณต๊ถ ๊ฐ๊ฒฉ ๋ฐ ์์ฝ ๊ฐ๋ฅ ์ฌ๋ถ๋ฅผ ํ์ํฉ๋๋ค.
- ๋ฐ์ดํฐ ์๊ฐํ: ์ฐจํธ ๋ฐ ๊ทธ๋ํ์ ๋ฐ์ดํฐ ์ ๋ฐ์ดํธ๋ฅผ ์คํธ๋ฆฌ๋ฐํฉ๋๋ค.
- ํ์ ๋๊ตฌ: ๋ฌธ์ ๋ฐ ํ๋ก์ ํธ์ ๋ํ ์ค์๊ฐ ์ ๋ฐ์ดํธ๋ฅผ ํ์ํฉ๋๋ค.
๊ฒฐ๋ก
React ์๋ฒ ์ก์ ์๋ต ์คํธ๋ฆฌ๋ฐ์ React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํค๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ์ ์ง์ ์ธ ํผ ์๋ต์ ์ ๊ณตํจ์ผ๋ก์จ ์ฌ์ฉ์์ ์ฐธ์ฌ๋ฅผ ์ ์งํ๊ณ ์ ํ์จ์ ๋์ด๋ ๋ ๋น ๋ฅด๊ณ , ๋ ๋ฐ์์ ์ด๋ฉฐ, ๋ ๋งค๋ ฅ์ ์ธ ํผ์ ๋ง๋ค ์ ์์ต๋๋ค. ์๋ต ์คํธ๋ฆฌ๋ฐ์ ๋๊ด์ ์ ๋ฐ์ดํธ ๋ฐ ์บ์ฑ๊ณผ ๊ฐ์ ๊ธฐ์ ๊ณผ ๊ฒฐํฉํ๋ฉด ์ง์ ์ผ๋ก ๋ฐ์ด๋ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.
React ์๋ฒ ์ก์ ์ด ๊ณ์ ๋ฐ์ ํจ์ ๋ฐ๋ผ, ๋ณต์กํ๊ณ ๋์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ๋์ฑ ๋จ์ํํ๋ ๋ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ด ๋ฑ์ฅํ ๊ฒ์ผ๋ก ๊ธฐ๋ํ ์ ์์ต๋๋ค.
๋ ์์๋ณด๊ธฐ
์ด ๊ฐ์ด๋๋ React ์๋ฒ ์ก์ ์๋ต ์คํธ๋ฆฌ๋ฐ๊ณผ ์ ์ง์ ํผ ์๋ต์ ๋ํ ์ ์ฉ์ ํฌ๊ด์ ์ผ๋ก ๊ฐ๊ดํฉ๋๋ค. ์ฌ๊ธฐ์ ๋ ผ์๋ ๊ฐ๋ ๊ณผ ๊ธฐ์ ์ ์ดํดํจ์ผ๋ก์จ, ์ด ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๋ ๋น ๋ฅด๊ณ , ๋ ๋ฐ์์ ์ด๋ฉฐ, ๋ ๋งค๋ ฅ์ ์ธ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.