React์ ์ผ๊ด ์ ๋ฐ์ดํธ์ ๋ํ ์ฌ์ธต ๋ถ์๊ณผ ์์ธก ๊ฐ๋ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ํด ํจ๊ณผ์ ์ธ ๋ณํฉ ๋ก์ง์ ์ฌ์ฉํ์ฌ ์ํ ๋ณ๊ฒฝ ์ถฉ๋์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ.
React ์ผ๊ด ์ ๋ฐ์ดํธ ์ถฉ๋ ํด๊ฒฐ: ์ํ ๋ณ๊ฒฝ ๋ณํฉ ๋ก์ง
React์ ํจ์จ์ ์ธ ๋ ๋๋ง์ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์ผ๊ด ์ฒ๋ฆฌํ๋ ๋ฅ๋ ฅ์ ํฌ๊ฒ ์์กดํฉ๋๋ค. ์ด๋ ๋์ผํ ์ด๋ฒคํธ ๋ฃจํ ์ฃผ๊ธฐ ๋ด์์ ํธ๋ฆฌ๊ฑฐ๋ ์ฌ๋ฌ ์ํ ์ ๋ฐ์ดํธ๊ฐ ํจ๊ป ๊ทธ๋ฃนํ๋์ด ๋จ์ผ ์ฌ๋ ๋๋ง์ผ๋ก ์ ์ฉ๋จ์ ์๋ฏธํฉ๋๋ค. ์ด๋ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํค์ง๋ง, ํนํ ๋น๋๊ธฐ ์์ ์ด๋ ๋ณต์กํ ์ํ ์ข ์์ฑ์ ์ฒ๋ฆฌํ ๋ ์ฃผ์ํด์ ์ฒ๋ฆฌํ์ง ์์ผ๋ฉด ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด ๊ฒ์๋ฌผ์์๋ React์ ์ผ๊ด ์ ๋ฐ์ดํธ์ ๋ณต์ก์ฑ์ ์ดํด๋ณด๊ณ ํจ๊ณผ์ ์ธ ๋ณํฉ ๋ก์ง์ ์ฌ์ฉํ์ฌ ์ํ ๋ณ๊ฒฝ ์ถฉ๋์ ํด๊ฒฐํ๊ธฐ ์ํ ์ค์ฉ์ ์ธ ์ ๋ต์ ์ ๊ณตํ์ฌ ์์ธก ๊ฐ๋ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ณด์ฅํฉ๋๋ค.
React์ ์ผ๊ด ์ ๋ฐ์ดํธ ์ดํด
ํต์ฌ์ ์ผ๋ก ์ผ๊ด ์ฒ๋ฆฌ๋ ์ต์ ํ ๊ธฐ์ ์
๋๋ค. React๋ ํ์ฌ ์ด๋ฒคํธ ๋ฃจํ์ ๋ชจ๋ ๋๊ธฐ์ ์ฝ๋๊ฐ ์คํ๋ ๋๊น์ง ์ฌ๋ ๋๋ง์ ์ฐ๊ธฐํฉ๋๋ค. ์ด๋ ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ณ ๋ ๋ถ๋๋ฌ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ๊ธฐ์ฌํฉ๋๋ค. ์ปดํฌ๋ํธ ์ํ๋ฅผ ์
๋ฐ์ดํธํ๋ ๊ธฐ๋ณธ ๋ฉ์ปค๋์ฆ์ธ setState ํจ์๋ ์ํ๋ฅผ ์ฆ์ ์์ ํ์ง ์์ต๋๋ค. ๋์ ๋์ค์ ์ ์ฉ๋ ์
๋ฐ์ดํธ๋ฅผ ํ์ ๋ฃ์ต๋๋ค.
์ผ๊ด ์ฒ๋ฆฌ ์๋ ๋ฐฉ์:
setState๊ฐ ํธ์ถ๋๋ฉด React๋ ์ ๋ฐ์ดํธ๋ฅผ ํ์ ์ถ๊ฐํฉ๋๋ค.- ์ด๋ฒคํธ ๋ฃจํ๊ฐ ๋๋๋ฉด React๋ ํ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
- React๋ ํ์ ์๋ ๋ชจ๋ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๋จ์ผ ์ ๋ฐ์ดํธ๋ก ๋ณํฉํฉ๋๋ค.
- ์ปดํฌ๋ํธ๋ ๋ณํฉ๋ ์ํ๋ก ์ฌ๋ ๋๋ง๋ฉ๋๋ค.
์ผ๊ด ์ฒ๋ฆฌ์ ์ด์ :
- ์ฑ๋ฅ ์ต์ ํ: ์ฌ๋ ๋๋ง ํ์๋ฅผ ์ค์ฌ ๋ ๋น ๋ฅด๊ณ ๋ฐ์์ฑ์ด ๋ฐ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ญ๋๋ค.
- ์ผ๊ด์ฑ: ์ปดํฌ๋ํธ์ ์ํ๊ฐ ์ผ๊ด๋๊ฒ ์ ๋ฐ์ดํธ๋๋๋ก ํ์ฌ ์ค๊ฐ ์ํ๊ฐ ๋ ๋๋ง๋๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
๋ฌธ์ ์ : ์ํ ๋ณ๊ฒฝ ์ถฉ๋
์ผ๊ด ์
๋ฐ์ดํธ ํ๋ก์ธ์ค๋ ์ฌ๋ฌ ์ํ ์
๋ฐ์ดํธ๊ฐ ์ด์ ์ํ์ ์์กดํ ๋ ์ถฉ๋์ ์ผ์ผํฌ ์ ์์ต๋๋ค. ๋ ๊ฐ์ setState ํธ์ถ์ด ๋์ผํ ์ด๋ฒคํธ ๋ฃจํ ๋ด์์ ์ด๋ฃจ์ด์ง๊ณ ๋ ๋ค ์นด์ดํฐ๋ฅผ ์ฆ๊ฐ์ํค๋ ค๊ณ ์๋ํ๋ ์๋๋ฆฌ์ค๋ฅผ ์๊ฐํด ๋ณด์ญ์์ค. ๋ ์
๋ฐ์ดํธ ๋ชจ๋ ๋์ผํ ์ด๊ธฐ ์ํ์ ์์กดํ๋ ๊ฒฝ์ฐ ๋ ๋ฒ์งธ ์
๋ฐ์ดํธ๊ฐ ์ฒซ ๋ฒ์งธ ์
๋ฐ์ดํธ๋ฅผ ๋ฎ์ด์จ ์ต์ข
์ํ๊ฐ ์ฌ๋ฐ๋ฅด์ง ์์ ์ ์์ต๋๋ค.
์์:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1); // Update 1
setCount(count + 1); // Update 2
};
return (
Count: {count}
);
}
export default Counter;
์์ ์์์ "Increment" ๋ฒํผ์ ํด๋ฆญํ๋ฉด ์นด์ดํธ๊ฐ 2๊ฐ ์๋ 1์ฉ๋ง ์ฆ๊ฐํ ์ ์์ต๋๋ค. ์ด๋ ๋ setCount ํธ์ถ ๋ชจ๋ ๋์ผํ ์ด๊ธฐ count ๊ฐ(0)์ ๋ฐ๊ณ ์ด๋ฅผ 1๋ก ์ฆ๊ฐ์ํจ ๋ค์ React๊ฐ ๋ ๋ฒ์งธ ์
๋ฐ์ดํธ๋ฅผ ์ ์ฉํ์ฌ ์ฒซ ๋ฒ์งธ ์
๋ฐ์ดํธ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๋ฎ์ด์ฐ๊ธฐ ๋๋ฌธ์
๋๋ค.
๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๋ฅผ ํตํ ์ํ ๋ณ๊ฒฝ ์ถฉ๋ ํด๊ฒฐ
์ํ ๋ณ๊ฒฝ ์ถฉ๋์ ํผํ๋ ๊ฐ์ฅ ํ์คํ ๋ฐฉ๋ฒ์ setState์ ํจ๊ป ๊ธฐ๋ฅ์ ์
๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๊ธฐ๋ฅ์ ์
๋ฐ์ดํธ๋ ์
๋ฐ์ดํธ ํจ์ ๋ด์์ ์ด์ ์ํ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํ์ฌ ๊ฐ ์
๋ฐ์ดํธ๊ฐ ์ต์ ์ํ ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋๋ก ํฉ๋๋ค.
๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ ์๋ ๋ฐฉ์:
์ ์ํ ๊ฐ์ setState์ ์ง์ ์ ๋ฌํ๋ ๋์ ์ด์ ์ํ๋ฅผ ์ธ์๋ก ๋ฐ๋ ํจ์๋ฅผ ์ ๋ฌํ๊ณ ์ ์ํ๋ฅผ ๋ฐํํฉ๋๋ค.
๊ตฌ๋ฌธ:
setState((prevState) => newState);
๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํ ์์ ๋ ์:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount((prevCount) => prevCount + 1); // Functional Update 1
setCount((prevCount) => prevCount + 1); // Functional Update 2
};
return (
Count: {count}
);
}
export default Counter;
์ด ์์ ๋ ์์์ ๊ฐ setCount ํธ์ถ์ ์ฌ๋ฐ๋ฅธ ์ด์ ์นด์ดํธ ๊ฐ์ ๋ฐ์ต๋๋ค. ์ฒซ ๋ฒ์งธ ์
๋ฐ์ดํธ๋ ์นด์ดํธ๋ฅผ 0์์ 1๋ก ์ฆ๊ฐ์ํต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ ๋ฒ์งธ ์
๋ฐ์ดํธ๋ ์
๋ฐ์ดํธ๋ ์นด์ดํธ ๊ฐ 1์ ๋ฐ๊ณ ์ด๋ฅผ 2๋ก ์ฆ๊ฐ์ํต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฒํผ์ ํด๋ฆญํ ๋๋ง๋ค ์นด์ดํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ฆ๊ฐํฉ๋๋ค.
๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ์ ์ด์
- ์ ํํ ์ํ ์ ๋ฐ์ดํธ: ์ ๋ฐ์ดํธ๊ฐ ์ต์ ์ํ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ฌ ์ถฉ๋์ ๋ฐฉ์งํฉ๋๋ค.
- ์์ธก ๊ฐ๋ฅํ ๋์: ์ํ ์ ๋ฐ์ดํธ๋ฅผ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ์ถ๋ก ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค.
- ๋น๋๊ธฐ ์์ ์ฑ: ์ฌ๋ฌ ์ ๋ฐ์ดํธ๊ฐ ๋์์ ํธ๋ฆฌ๊ฑฐ๋๋๋ผ๋ ๋น๋๊ธฐ ์ ๋ฐ์ดํธ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํฉ๋๋ค.
๋ณต์กํ ์ํ ์ ๋ฐ์ดํธ ๋ฐ ๋ณํฉ ๋ก์ง
๋ณต์กํ ์ํ ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํ ๋๋ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๋ ๋ฐ ๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๊ฐ ์ค์ํฉ๋๋ค. ์ํ์ ์ผ๋ถ๋ฅผ ์ง์ ๋ฎ์ด์ฐ๋ ๋์ ์ ์ํ๋ฅผ ๊ธฐ์กด ์ํ์ ์ ์คํ๊ฒ ๋ณํฉํด์ผ ํฉ๋๋ค.
์์: ๊ฐ์ฒด ์์ฑ ์ ๋ฐ์ดํธ
import React, { useState } from 'react';
function UserProfile() {
const [user, setUser] = useState({
name: 'John Doe',
age: 30,
address: {
city: 'New York',
country: 'USA',
},
});
const handleUpdateCity = () => {
setUser((prevUser) => ({
...prevUser,
address: {
...prevUser.address,
city: 'London',
},
}));
};
return (
Name: {user.name}
Age: {user.age}
City: {user.address.city}
Country: {user.address.country}
);
}
export default UserProfile;
์ด ์์์ handleUpdateCity ํจ์๋ ์ฌ์ฉ์์ ๋์๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค. ์คํ๋ ๋ ์ฐ์ฐ์(...)๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ์ฌ์ฉ์ ๊ฐ์ฒด์ ์ด์ ์ฃผ์ ๊ฐ์ฒด์ ์์ ๋ณต์ฌ๋ณธ์ ๋ง๋ญ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด city ์์ฑ๋ง ์
๋ฐ์ดํธ๋๊ณ ๋ค๋ฅธ ์์ฑ์ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ์คํ๋ ๋ ์ฐ์ฐ์๊ฐ ์์ผ๋ฉด ์ํ ํธ๋ฆฌ์ ์ผ๋ถ๋ฅผ ์์ ํ ๋ฎ์ด์จ ๋ฐ์ดํฐ ์์ค์ด ๋ฐ์ํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ๋ณํฉ ๋ก์ง ํจํด
- ์์ ๋ณํฉ: ์คํ๋ ๋ ์ฐ์ฐ์(
...)๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ์กด ์ํ์ ์์ ๋ณต์ฌ๋ณธ์ ๋ง๋ ๋ค์ ํน์ ์์ฑ์ ๋ฎ์ด์๋๋ค. ์ด๋ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ฅผ ๊น์ด ์ ๋ฐ์ดํธํ ํ์๊ฐ ์๋ ๊ฐ๋จํ ์ํ ์ ๋ฐ์ดํธ์ ์ ํฉํฉ๋๋ค. - ๊น์ ๋ณํฉ: ๊น์ด ์ค์ฒฉ๋ ๊ฐ์ฒด์ ๊ฒฝ์ฐ Lodash์
_.merge๋๋immer์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊น์ ๋ณํฉ์ ์ํํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ๊น์ ๋ณํฉ์ ๊ฐ์ฒด๋ฅผ ์ฌ๊ท์ ์ผ๋ก ๋ณํฉํ์ฌ ์ค์ฒฉ๋ ์์ฑ๋ ์ฌ๋ฐ๋ฅด๊ฒ ์ ๋ฐ์ดํธ๋๋๋ก ํฉ๋๋ค. - ๋ถ๋ณ์ฑ ๋์ฐ๋ฏธ:
immer์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋ถ๋ณ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ํ์ํ ๋ณ๊ฒฝ ๊ฐ๋ฅํ API๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ํ์ ์ด์์ ์์ ํ ์ ์์ผ๋ฉฐimmer๋ ๋ณ๊ฒฝ ์ฌํญ์ด ์๋ ์ ๋ถ๋ณ ์ํ ๊ฐ์ฒด๋ฅผ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
๋น๋๊ธฐ ์ ๋ฐ์ดํธ ๋ฐ ๊ฒฝ์ ์กฐ๊ฑด
API ํธ์ถ ๋๋ ์๊ฐ ์ด๊ณผ์ ๊ฐ์ ๋น๋๊ธฐ ์์ ์ ์ํ ์ ๋ฐ์ดํธ๋ฅผ ์ฒ๋ฆฌํ ๋ ์ถ๊ฐ์ ์ธ ๋ณต์ก์ฑ์ ์ผ๊ธฐํฉ๋๋ค. ์ฌ๋ฌ ๋น๋๊ธฐ ์์ ์ด ๋์์ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๋ ค๊ณ ์๋ํ ๋ ๊ฒฝ์ ์กฐ๊ฑด์ด ๋ฐ์ํ์ฌ ๋ถ์ผ์นํ๊ฑฐ๋ ์๊ธฐ์น ์์ ๊ฒฐ๊ณผ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๋ ์ด๋ฌํ ์๋๋ฆฌ์ค์์ ํนํ ์ค์ํฉ๋๋ค.
์์: ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋ฐ ์ํ ์ ๋ฐ์ดํธ
import React, { useState, useEffect } from 'react';
function DataFetcher() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('https://api.example.com/data');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
const jsonData = await response.json();
setData(jsonData); // Initial data load
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
// Simulated background update
useEffect(() => {
if (data) {
const intervalId = setInterval(() => {
setData((prevData) => ({
...prevData,
updatedAt: new Date().toISOString(),
}));
}, 5000);
return () => clearInterval(intervalId);
}
}, [data]);
if (loading) {
return Loading...
;
}
if (error) {
return Error: {error.message}
;
}
return (
Data: {JSON.stringify(data)}
);
}
export default DataFetcher;
์ด ์์์ ์ปดํฌ๋ํธ๋ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์จ ๋ค์ ๊ฐ์ ธ์จ ๋ฐ์ดํฐ๋ก ์ํ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค. ๋ํ useEffect ํ
์ updatedAt ์์ฑ์ 5์ด๋ง๋ค ์์ ํ๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์
๋ฐ์ดํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํฉ๋๋ค. ๊ธฐ๋ฅ์ ์
๋ฐ์ดํธ๋ ๋ฐฑ๊ทธ๋ผ์ด๋ ์
๋ฐ์ดํธ๊ฐ API์์ ๊ฐ์ ธ์จ ์ต์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋๋ก ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๋น๋๊ธฐ ์ ๋ฐ์ดํธ ์ฒ๋ฆฌ ์ ๋ต
- ๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ: ์์์ ์ธ๊ธํ๋ฏ์ด ๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํ์ฌ ์ํ ์ ๋ฐ์ดํธ๊ฐ ์ต์ ์ํ ๊ฐ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋๋ก ํฉ๋๋ค.
- ์ทจ์: ์ปดํฌ๋ํธ๊ฐ ์ธ๋ง์ดํธ๋๊ฑฐ๋ ๋ฐ์ดํฐ๊ฐ ๋ ์ด์ ํ์ํ์ง ์์ ๋ ๋ณด๋ฅ ์ค์ธ ๋น๋๊ธฐ ์์
์ ์ทจ์ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ฒฝ์ ์กฐ๊ฑด๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
AbortControllerAPI๋ฅผ ์ฌ์ฉํ์ฌ ๋น๋๊ธฐ ์์ฒญ์ ๊ด๋ฆฌํ๊ณ ํ์ํ ๊ฒฝ์ฐ ์ทจ์ํฉ๋๋ค. - ๋๋ฐ์ด์ฑ ๋ฐ ์ค๋กํ๋ง: ๋๋ฐ์ด์ฑ ๋๋ ์ค๋กํ๋ง ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์ํ ์ ๋ฐ์ดํธ ๋น๋๋ฅผ ์ ํํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๊ณผ๋ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. Lodash์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๋๋ฐ์ด์ฑ ๋ฐ ์ค๋กํ๋ง์ ์ํ ํธ๋ฆฌํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ: ๋น๋๊ธฐ ์์ ์ด ๋ง์ ๋ณต์กํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ Redux, Zustand ๋๋ Recoil๊ณผ ๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ฌํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ์ํ๋ฅผ ๊ด๋ฆฌํ๊ณ ๋น๋๊ธฐ ์ ๋ฐ์ดํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ณด๋ค ๊ตฌ์กฐํ๋๊ณ ์์ธก ๊ฐ๋ฅํ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
์ํ ์ ๋ฐ์ดํธ ๋ก์ง ํ ์คํธ
์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํ๋ ค๋ฉด ์ํ ์ ๋ฐ์ดํธ ๋ก์ง์ ์ฒ ์ ํ ํ ์คํธํ๋ ๊ฒ์ด ํ์์ ์ ๋๋ค. ๋จ์ ํ ์คํธ๋ ๋ค์ํ ์กฐ๊ฑด์์ ์ํ ์ ๋ฐ์ดํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ํ๋๋์ง ํ์ธํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์์: ์นด์ดํฐ ์ปดํฌ๋ํธ ํ ์คํธ
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Counter from './Counter';
test('increments the count by 2 when the button is clicked', () => {
const { getByText } = render( );
const incrementButton = getByText('Increment');
fireEvent.click(incrementButton);
expect(getByText('Count: 2')).toBeInTheDocument();
});
์ด ํ
์คํธ๋ ๋ฒํผ์ ํด๋ฆญํ๋ฉด Counter ์ปดํฌ๋ํธ๊ฐ ์นด์ดํธ๋ฅผ 2์ฉ ์ฆ๊ฐ์ํค๋์ง ํ์ธํฉ๋๋ค. @testing-library/react ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๊ณ , ๋ฒํผ์ ์ฐพ๊ณ , ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ์๋ฎฌ๋ ์ด์
ํ๊ณ , ์นด์ดํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์
๋ฐ์ดํธ๋์๋์ง ๋จ์ธํฉ๋๋ค.
ํ ์คํธ ์ ๋ต
- ๋จ์ ํ ์คํธ: ๊ฐ๋ณ ์ปดํฌ๋ํธ์ ๋ํ ๋จ์ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์ํ ์ ๋ฐ์ดํธ ๋ก์ง์ด ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
- ํตํฉ ํ ์คํธ: ํตํฉ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์๋ก ๋ค๋ฅธ ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ํธ ์์ฉํ๊ณ ์ํ๊ฐ ์์๋๋ก ์๋ก ์ ๋ฌ๋๋์ง ํ์ธํฉ๋๋ค.
- ์๋ ํฌ ์๋ ํ ์คํธ: ์๋ ํฌ ์๋ ํ ์คํธ๋ฅผ ์์ฑํ์ฌ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ์ฉ์์ ๊ด์ ์์ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
- ๋ชจ์: ๋ชจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๊ฒฉ๋ฆฌํ๊ณ ๊ฒฉ๋ฆฌ๋ ์ํ์์ ๋์์ ํ ์คํธํฉ๋๋ค. API ํธ์ถ ๋ฐ ๊ธฐํ ์ธ๋ถ ์ข ์์ฑ์ ๋ชจ์ํ์ฌ ํ๊ฒฝ์ ์ ์ดํ๊ณ ํน์ ์๋๋ฆฌ์ค๋ฅผ ํ ์คํธํฉ๋๋ค.
์ฑ๋ฅ ๊ณ ๋ ค ์ฌํญ
์ผ๊ด ์ฒ๋ฆฌ๋ ์ฃผ๋ก ์ฑ๋ฅ ์ต์ ํ ๊ธฐ์ ์ด์ง๋ง, ์ ๋๋ก ๊ด๋ฆฌ๋์ง ์์ ์ํ ์ ๋ฐ์ดํธ๋ ์ฌ์ ํ ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค. ๊ณผ๋ํ ์ฌ๋ ๋๋ง ๋๋ ๋ถํ์ํ ๊ณ์ฐ์ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ถ์ ์ ์ธ ์ํฅ์ ๋ฏธ์น ์ ์์ต๋๋ค.
์ฑ๋ฅ ์ต์ ํ ์ ๋ต
- ๋ฉ๋ชจ์ด์ ์ด์
:
React.memo๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์ ํ๊ณ ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํฉ๋๋ค.React.memo๋ ์ปดํฌ๋ํธ์ props๋ฅผ ์๊ฒ ๋น๊ตํ๊ณ props๊ฐ ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ์๋ง ์ฌ๋ ๋๋งํฉ๋๋ค. - useMemo ๋ฐ useCallback:
useMemo๋ฐuseCallbackํ ์ ์ฌ์ฉํ์ฌ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ณ์ฐ ๋ฐ ํจ์๋ฅผ ๋ฉ๋ชจ์ด์ ์ด์ ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ถํ์ํ ์ฌ๋ ๋๋ง์ ๋ฐฉ์งํ๊ณ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค. - ์ฝ๋ ๋ถํ : ์ฝ๋๋ฅผ ๋ ์์ ์ฒญํฌ๋ก ๋ถํ ํ๊ณ ์์ฒญ ์ ๋ก๋ํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์ด๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ ์ธ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์์ต๋๋ค.
- ๊ฐ์ํ: ๊ฐ์ํ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ๋๊ท๋ชจ ๋ฐ์ดํฐ ๋ชฉ๋ก์ ํจ์จ์ ์ผ๋ก ๋ ๋๋งํฉ๋๋ค. ๊ฐ์ํ๋ ๋ชฉ๋ก์์ ๋ณด์ด๋ ํญ๋ชฉ๋ง ๋ ๋๋งํ์ฌ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์์ต๋๋ค.
์ ์ญ ๊ณ ๋ ค ์ฌํญ
๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ React ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋๋ ๊ตญ์ ํ(i18n) ๋ฐ ์ง์ญํ(l10n)๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ํ ์ธ์ด, ๋ฌธํ ๋ฐ ์ง์ญ์ ๋ง๊ฒ ์กฐ์ ํ๋ ๊ฒ์ด ํฌํจ๋ฉ๋๋ค.
๊ตญ์ ํ ๋ฐ ์ง์ญํ ์ ๋ต
- ๋ฌธ์์ด ์ธ๋ถํ: ๋ชจ๋ ํ ์คํธ ๋ฌธ์์ด์ ์ธ๋ถ ํ์ผ์ ์ ์ฅํ๊ณ ์ฌ์ฉ์์ ๋ก์ผ์ผ์ ๊ธฐ๋ฐ์ผ๋ก ๋์ ์ผ๋ก ๋ก๋ํฉ๋๋ค.
- i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ฌ์ฉ:
react-i18next๋๋FormatJS์ ๊ฐ์ i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ญํ ๋ฐ ํ์์ ์ฒ๋ฆฌํฉ๋๋ค. - ๋ค์ค ๋ก์ผ์ผ ์ง์: ๋ค์ค ๋ก์ผ์ผ์ ์ง์ํ๊ณ ์ฌ์ฉ์๊ฐ ์ ํธํ๋ ์ธ์ด ๋ฐ ์ง์ญ์ ์ ํํ ์ ์๋๋ก ํฉ๋๋ค.
- ๋ ์ง ๋ฐ ์๊ฐ ํ์ ์ฒ๋ฆฌ: ๋ค์ํ ์ง์ญ์ ์ ํฉํ ๋ ์ง ๋ฐ ์๊ฐ ํ์์ ์ฌ์ฉํฉ๋๋ค.
- ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ์ฐ๋ ์ธ์ด ๊ณ ๋ ค: ์๋์ด ๋ฐ ํ๋ธ๋ฆฌ์ด์ ๊ฐ์ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ์ฐ๋ ์ธ์ด๋ฅผ ์ง์ํฉ๋๋ค.
- ์ด๋ฏธ์ง ๋ฐ ๋ฏธ๋์ด ์ง์ญํ: ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค์ํ ์ง์ญ์ ๋ฌธํ์ ์ผ๋ก ์ ํฉํ๋๋ก ์ง์ญํ๋ ์ด๋ฏธ์ง ๋ฐ ๋ฏธ๋์ด ๋ฒ์ ์ ์ ๊ณตํฉ๋๋ค.
๊ฒฐ๋ก
React์ ์ผ๊ด ์ ๋ฐ์ดํธ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ ๊ฐ๋ ฅํ ์ต์ ํ ๊ธฐ์ ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ผ๊ด ์ฒ๋ฆฌ ์๋ ๋ฐฉ์๊ณผ ์ํ ๋ณ๊ฒฝ ์ถฉ๋์ ํจ๊ณผ์ ์ผ๋ก ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์ดํดํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๊ธฐ๋ฅ์ ์ ๋ฐ์ดํธ๋ฅผ ์ฌ์ฉํ๊ณ , ์ํ ๊ฐ์ฒด๋ฅผ ์ ์คํ๊ฒ ๋ณํฉํ๊ณ , ๋น๋๊ธฐ ์ ๋ฐ์ดํธ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํจ์ผ๋ก์จ React ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ธก ๊ฐ๋ฅํ๊ณ ์ ์ง ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ฉฐ ์ฑ๋ฅ์ด ๋ฐ์ด๋๋๋ก ํ ์ ์์ต๋๋ค. ์ํ ์ ๋ฐ์ดํธ ๋ก์ง์ ์ฒ ์ ํ ํ ์คํธํ๊ณ ๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํด ๊ฐ๋ฐํ ๋ ๊ตญ์ ํ ๋ฐ ์ง์ญํ๋ฅผ ๊ณ ๋ คํ์ญ์์ค. ์ด๋ฌํ ์ง์นจ์ ๋ฐ๋ฅด๋ฉด ์ ์ธ๊ณ ์ฌ์ฉ์์ ์๊ตฌ๋ฅผ ์ถฉ์กฑํ๋ ๊ฐ๋ ฅํ๊ณ ํ์ฅ ๊ฐ๋ฅํ React ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค.