React Suspense ๋ฆฌ์์ค ์กฐ์ : ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ ๊ด๋ฆฌ ๋ง์คํฐํ๊ธฐ | MLOG | MLOGํ๊ตญ์ด
Suspense์ ์์กด์ฑ ์กฐ์ ์ ์ฌ์ฉํ์ฌ React ์ ํ๋ฆฌ์ผ์ด์
์์ ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ์ฌ ๋ ๋ถ๋๋ฌ์ด ์ฌ์ฉ์ ๊ฒฝํ์ ์ ๊ณตํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด์ธ์.
React Suspense ๋ฆฌ์์ค ์กฐ์ : ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ ๊ด๋ฆฌ ๋ง์คํฐํ๊ธฐ
React Suspense๋ ์ ํ๋ฆฌ์ผ์ด์
์์ ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌํ๊ณ ๋ก๋ฉ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฐ๋ ฅํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. ๋จ์ํ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์๋๋ฆฌ์ค๋ ๋น๊ต์ ๊ฐ๋จํ์ง๋ง, ์๋ก ์์กดํ๋ ์ฌ๋ฌ ๋ฆฌ์์ค๋ฅผ ๋ค๋ฃฐ ๋๋ ์ํฉ์ด ๋ ๋ณต์กํด์ง๋๋ค. ์ด ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์์๋ React Suspense๋ฅผ ์ฌ์ฉํ ๋ฆฌ์์ค ์กฐ์ ์ ๋ํด ๊น์ด ํ๊ณ ๋ค์ด, ๋ ๋ถ๋๋ฝ๊ณ ๋ฐ์์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ์ํด ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์์ฐํฉ๋๋ค.
๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ์ ๋ฌธ์ ์ ์ดํด
๋ง์ ์ค์ ์ ํ๋ฆฌ์ผ์ด์
์์ ์ปดํฌ๋ํธ๋ ์ข
์ข
์ฌ๋ฌ ์์ค์ ๋ฐ์ดํฐ์ ์์กดํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ํ๋กํ ํ์ด์ง๋ ์ฌ์ฉ์ ์ธ๋ถ ์ ๋ณด, ์ต๊ทผ ํ๋ ๋ฐ ๊ด๋ จ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์์ผ ํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฆฌ์์ค๋ฅผ ๋
๋ฆฝ์ ์ผ๋ก ๋ก๋ํ๋ฉด ์ฌ๋ฌ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค:
- ํญํฌ์ ์์ฒญ: ๊ฐ ๋ฆฌ์์ค๊ฐ ์์ฐจ์ ์ผ๋ก ๋ก๋๋์ด ๋ก๋ ์๊ฐ์ด ์ฆ๊ฐํฉ๋๋ค.
- ๋ถ์ผ์น UI ์ํ: UI์ ๋ค๋ฅธ ๋ถ๋ถ์ด ๋ค๋ฅธ ์๊ฐ์ ๋ก๋๋ ์ ์์ด jarringํ ๊ฒฝํ์ ๋ง๋ญ๋๋ค.
- ๋ณต์กํ ์ํ ๊ด๋ฆฌ: ์ฌ๋ฌ ๋ก๋ฉ ์ํ์ ์ค๋ฅ ์กฐ๊ฑด์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ๋ฒ๊ฑฐ๋กญ์ต๋๋ค.
- ๋ฏธํกํ ์ค๋ฅ ์ฒ๋ฆฌ: ์ฌ๋ฌ ๋ฆฌ์์ค์ ๊ฑธ์ณ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์กฐ์ ํ๋ ๊ฒ์ด ๊น๋ค๋ก์ธ ์ ์์ต๋๋ค.
Suspense๋ ๋ฆฌ์์ค ์กฐ์ ์ ๋ต๊ณผ ๊ฒฐํฉํ์ฌ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊น๋ํ๊ณ ํจ์จ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค.
ํต์ฌ ๊ฐ๋
: Suspense์ ๋ฆฌ์์ค
๋ฆฌ์์ค ์กฐ์ ์ ๋ต์ ๋ํด ์์๋ณด๊ธฐ ์ ์ ๊ธฐ๋ณธ ๊ฐ๋
์ ๋ณต์ตํด ๋ณด๊ฒ ์ต๋๋ค:
Suspense
Suspense๋ ๋น๋๊ธฐ ์์
(์: ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ)์ด ์๋ฃ๋ ๋๊น์ง ์ปดํฌ๋ํธ ํธ๋ฆฌ์ ์ผ๋ถ ๋ ๋๋ง์ '์ผ์ ์ค์ง'ํ ์ ์๋ React ์ปดํฌ๋ํธ์
๋๋ค. ์์
์ด ์งํ ์ค์ผ ๋ ๋์ฒด UI(์: ๋ก๋ฉ ์คํผ๋)๋ฅผ ํ์ํฉ๋๋ค. Suspense๋ ๋ก๋ฉ ์ํ ๊ด๋ฆฌ๋ฅผ ๋จ์ํํ๊ณ ์ ๋ฐ์ ์ธ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค.
์์:
import React, { Suspense } from 'react';
function MyComponent() {
return (
Loading... }>
);
}
๋ฆฌ์์ค
๋ฆฌ์์ค๋ ๋น๋๊ธฐ ์์
์ ์บก์ํํ๊ณ Suspense๊ฐ ์ก์ ์ ์๋ ๋ฐ์ดํฐ์ ์ก์ธ์คํ๊ฑฐ๋ promise๋ฅผ ๋์ง ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ๊ฐ์ฒด์
๋๋ค. ์ผ๋ฐ์ ์ธ ๋ฆฌ์์ค์๋ promise๋ฅผ ๋ฐํํ๋ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ํจ์๊ฐ ํฌํจ๋ฉ๋๋ค.
์์ (๊ฐ๋จํ fetch ๋ํผ ์ฌ์ฉ):
const fetchData = (url) => {
let status = 'pending';
let result;
let suspender = fetch(url)
.then(
(res) => res.json(),
(err) => {
status = 'error';
result = err;
}
)
.then(
(res) => {
status = 'success';
result = res;
}
);
return {
read() {
if (status === 'pending') {
throw suspender;
} else if (status === 'error') {
throw result;
}
return result;
},
};
};
export default fetchData;
๋ค์ค ๋ฆฌ์์ค ์กฐ์ ์ ๋ต
Suspense๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๋ฆฌ์์ค๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ช ๊ฐ์ง ์ ๋ต์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1. `Promise.all`์ ์ฌ์ฉํ ๋ณ๋ ฌ ๋ก๋ฉ
๊ฐ์ฅ ๊ฐ๋จํ ์ ๊ทผ ๋ฐฉ์์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ๋ณ๋ ฌ๋ก ๋ก๋ํ๊ณ `Promise.all`์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๊ธฐ ์ ์ ๋ชจ๋ promise๊ฐ resolve๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์
๋๋ค. ๋ฆฌ์์ค๊ฐ ๋
๋ฆฝ์ ์ด๊ณ ์๋ก ์์กดํ์ง ์๋ ๊ฒฝ์ฐ์ ์ ํฉํฉ๋๋ค.
์์:
import React, { Suspense } from 'react';
import fetchData from './fetchData';
const userResource = fetchData('/api/user');
const postsResource = fetchData('/api/posts');
const commentsResource = fetchData('/api/comments');
function UserProfile() {
const user = userResource.read();
const posts = postsResource.read();
const comments = commentsResource.read();
return (
{user.name}
{user.bio}
Posts
{posts.map((post) => (
- {post.title}
))}
Comments
{comments.map((comment) => (
- {comment.text}
))}
);
}
function App() {
return (
Loading user profile... }>
);
}
export default App;
์ฅ์ :
- ๊ตฌํ์ด ์ฝ์ต๋๋ค.
- ๋ณ๋ ฌ ๋ก๋ฉ์ ๊ทน๋ํํ์ฌ ์ ์ฒด ๋ก๋ ์๊ฐ์ ์ค์
๋๋ค.
๋จ์ :
- ๋ฆฌ์์ค์ ์ข
์์ฑ์ด ์๋ ๊ฒฝ์ฐ์๋ ์ ํฉํ์ง ์์ต๋๋ค.
- ์ผ๋ถ ๋ฆฌ์์ค๊ฐ ์ค์ ๋ก ํ์ํ์ง ์์ ๊ฒฝ์ฐ ๋ถํ์ํ ์์ฒญ์ผ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
2. ์ข
์์ฑ์ ์ฌ์ฉํ ์์ฐจ ๋ก๋ฉ
๋ฆฌ์์ค๊ฐ ์๋ก ์์กดํ๋ ๊ฒฝ์ฐ ์์ฐจ์ ์ผ๋ก ๋ก๋ํด์ผ ํฉ๋๋ค. Suspense๋ฅผ ์ฌ์ฉํ๋ฉด ์ข
์ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค๋ ์ปดํฌ๋ํธ๋ฅผ ์ค์ฒฉํ์ฌ ์ด๋ฌํ ํ๋ฆ์ ์กฐ์ ํ ์ ์์ต๋๋ค.
์์: ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋จผ์ ๋ก๋ํ ๋ค์ ์ฌ์ฉ์ ID๋ฅผ ์ฌ์ฉํ์ฌ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ต๋๋ค.
import React, { Suspense } from 'react';
import fetchData from './fetchData';
const userResource = fetchData('/api/user');
function UserPosts({ userId }) {
const postsResource = fetchData(`/api/posts?userId=${userId}`);
const posts = postsResource.read();
return (
{posts.map((post) => (
- {post.title}
))}
);
}
function UserProfile() {
const user = userResource.read();
return (
{user.name}
{user.bio}
Posts
Loading posts... }>
);
}
function App() {
return (
Loading user profile...}>
);
}
export default App;
์ฅ์ :
- ์ข
์์ฑ์ ์ํํ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค.
- ์ข
์ ๋ฆฌ์์ค์ ๋ํ ๋ถํ์ํ ์์ฒญ์ ํผํฉ๋๋ค.
๋จ์ :
- ์์ฐจ ๋ก๋ฉ์ผ๋ก ์ธํด ์ ์ฒด ๋ก๋ ์๊ฐ์ด ๊ธธ์ด์ง ์ ์์ต๋๋ค.
- ์ข
์์ฑ์ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ปดํฌ๋ํธ ๊ตฌ์กฐ๋ฅผ ์ ์คํ๊ฒ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค.
3. ๋ณ๋ ฌ ๋ฐ ์์ฐจ ๋ก๋ฉ ๊ฒฐํฉ
๋ง์ ์๋๋ฆฌ์ค์์ ์ฑ๋ฅ์ ์ต์ ํํ๊ธฐ ์ํด ๋ณ๋ ฌ ๋ฐ ์์ฐจ ๋ก๋ฉ์ ๋ชจ๋ ๊ฒฐํฉํ ์ ์์ต๋๋ค. ๋
๋ฆฝ์ ์ธ ๋ฆฌ์์ค๋ฅผ ๋ณ๋ ฌ๋ก ๋ก๋ํ ๋ค์ ๋
๋ฆฝ์ ์ธ ๋ฆฌ์์ค๊ฐ ๋ก๋๋ ํ ์ข
์ ๋ฆฌ์์ค๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ก๋ํฉ๋๋ค.
์์: ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ์ต๊ทผ ํ๋์ ๋ณ๋ ฌ๋ก ๋ก๋ํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๊ฐ ๋ก๋๋ ํ ์ฌ์ฉ์์ ๊ฒ์๋ฌผ์ ๊ฐ์ ธ์ต๋๋ค.
import React, { Suspense } from 'react';
import fetchData from './fetchData';
const userResource = fetchData('/api/user');
const activityResource = fetchData('/api/activity');
function UserPosts({ userId }) {
const postsResource = fetchData(`/api/posts?userId=${userId}`);
const posts = postsResource.read();
return (
{posts.map((post) => (
- {post.title}
))}
);
}
function UserProfile() {
const user = userResource.read();
const activity = activityResource.read();
return (
{user.name}
{user.bio}
Last activity: {activity.date}
Posts
Loading posts... }>
);
}
function App() {
return (
Loading user profile...}>
);
}
export default App;
์ด ์์์์๋ `userResource`์ `activityResource`๊ฐ ๋ณ๋ ฌ๋ก ๊ฐ์ ธ์์ง๋๋ค. ์ฌ์ฉ์ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํด์ง๋ฉด `UserPosts` ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋์ด ์ฌ์ฉ์ ๊ฒ์๋ฌผ์ ๋ํ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ํธ๋ฆฌ๊ฑฐํฉ๋๋ค.
์ฅ์ :
- ๋ณ๋ ฌ ๋ฐ ์์ฐจ ๋ก๋ฉ์ ๊ฒฐํฉํ์ฌ ๋ก๋ ์๊ฐ์ ์ต์ ํํฉ๋๋ค.
- ์ข
์์ฑ์ ๊ด๋ฆฌํ๋ ๋ฐ ์ ์ฐ์ฑ์ ์ ๊ณตํฉ๋๋ค.
๋จ์ :
- ๋
๋ฆฝ์ ์ธ ๋ฆฌ์์ค์ ์ข
์์ ์ธ ๋ฆฌ์์ค๋ฅผ ์๋ณํ๊ธฐ ์ํด ์ ์คํ ๊ณํ์ด ํ์ํฉ๋๋ค.
- ๋จ์ ๋ณ๋ ฌ ๋๋ ์์ฐจ ๋ก๋ฉ๋ณด๋ค ๊ตฌํ์ด ๋ ๋ณต์กํ ์ ์์ต๋๋ค.
4. ๋ฆฌ์์ค ๊ณต์ ๋ฅผ ์ํ React Context ์ฌ์ฉ
React Context๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ์ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํ๊ณ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ฒ ๋ค์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค. ์ฌ๋ฌ ์ปดํฌ๋ํธ๊ฐ ๋์ผํ ๋ฆฌ์์ค์ ์ก์ธ์คํด์ผ ํ๋ ๊ฒฝ์ฐ ํนํ ์ ์ฉํฉ๋๋ค.
์์:
import React, { createContext, useContext, Suspense } from 'react';
import fetchData from './fetchData';
const UserContext = createContext(null);
function UserProvider({ children }) {
const userResource = fetchData('/api/user');
return (
{children}
);
}
function UserProfile() {
const userResource = useContext(UserContext);
const user = userResource.read();
return (
);
}
function UserAvatar() {
const userResource = useContext(UserContext);
const user = userResource.read();
return (
);
}
function App() {
return (
Loading user profile... }>
);
}
export default App;
์ด ์์์์ `UserProvider`๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ `UserContext`๋ฅผ ํตํด ๋ชจ๋ ํ์ ์ปดํฌ๋ํธ์ ์ ๊ณตํฉ๋๋ค. `UserProfile` ๋ฐ `UserAvatar` ์ปดํฌ๋ํธ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ ๊ฐ์ ธ์ค์ง ์๊ณ ๋์ผํ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
์ฅ์ :
- ์ค๋ณต ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
- ์ปดํฌ๋ํธ ๊ฐ ๋ฐ์ดํฐ ๊ณต์ ๋ฅผ ๋จ์ํํฉ๋๋ค.
๋จ์ :
- ์ปจํ
์คํธ ์ ๊ณต์์ ๋ํ ์ ์คํ ๊ด๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
- ์ปจํ
์คํธ๊ฐ ์ผ๋ถ ์ปดํฌ๋ํธ์ ํ์ํ ๊ฒ๋ณด๋ค ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ๋ฉด ๊ณผ๋ํ ๊ฐ์ ธ์ค๊ธฐ๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
5. ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ํ ์ค๋ฅ ๊ฒฝ๊ณ
Suspense๋ ์ค๋ฅ ๊ฒฝ๊ณ์ ํจ๊ป ์๋ํ์ฌ ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ๋๋ ๋ ๋๋ง ์ค์ ๋ฐ์ํ๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ค๋ฅ ๊ฒฝ๊ณ๋ ํ์ ์ปดํฌ๋ํธ ํธ๋ฆฌ์์ JavaScript ์ค๋ฅ๋ฅผ ์ก๊ณ , ํด๋น ์ค๋ฅ๋ฅผ ๊ธฐ๋กํ๊ณ , ์ ์ฒด ์ปดํฌ๋ํธ ํธ๋ฆฌ๊ฐ ์ถฉ๋ํ๋ ๋์ ๋์ฒด UI๋ฅผ ํ์ํ๋ React ์ปดํฌ๋ํธ์
๋๋ค.
์์:
import React, { Suspense } from 'react';
import fetchData from './fetchData';
import ErrorBoundary from './ErrorBoundary';
const userResource = fetchData('/api/user');
function UserProfile() {
const user = userResource.read();
return (
);
}
function App() {
return (
Something went wrong! }>
Loading user profile...}>
);
}
export default App;
์ด ์์์์ `ErrorBoundary`๋ `UserProfile` ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๊ฑฐ๋ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋์ ๋ฐ์ํ๋ ๋ชจ๋ ์ค๋ฅ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ๋์ฒด UI๋ฅผ ํ์ํ์ฌ ์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์
์ด ์ถฉ๋ํ๋ ๊ฒ์ ๋ฐฉ์งํฉ๋๋ค.
์ฅ์ :
- ๊ฐ๋ ฅํ ์ค๋ฅ ์ฒ๋ฆฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์
์ถฉ๋์ ๋ฐฉ์งํฉ๋๋ค.
- ์ ๋ณด ์ ๊ณต์ ์ธ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํฅ์์ํต๋๋ค.
๋จ์ :
- ์ค๋ฅ ๊ฒฝ๊ณ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค.
- ์ปดํฌ๋ํธ ํธ๋ฆฌ์ ๋ณต์ก์ฑ์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๊ธ๋ก๋ฒ ์ ์ฌ ๊ณ ๊ฐ์ ์ํ ์ค์ง์ ์ธ ๊ณ ๋ ค ์ฌํญ
๊ธ๋ก๋ฒ ์ ์ฌ ๊ณ ๊ฐ์ ์ํ React ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ ๋๋ ๋ค์์ ๊ณ ๋ คํ์ญ์์ค:
- ๋ฐ์ดํฐ ํ์งํ: ์ฌ์ฉ์์ ์ธ์ด์ ์ง์ญ์ ๋ฐ๋ผ ๋ฐ์ดํฐ๊ฐ ํ์งํ๋๋์ง ํ์ธํฉ๋๋ค. ๊ตญ์ ํ(i18n) ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๋ ์ง, ์ซ์ ๋ฐ ํตํ๋ฅผ ์ ์ ํ๊ฒ ํ์ํํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๊ธ์ต ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์์ ์์น์ ๋ฐ๋ผ ํตํ ๊ธฐํธ(์: USD, EUR, JPY)๋ฅผ ํ์ํด์ผ ํฉ๋๋ค.
- API ์๋ํฌ์ธํธ: ์ง์ญ๋ณ API ์๋ํฌ์ธํธ ๋๋ ์ฝํ
์ธ ์ ์ก ๋คํธ์ํฌ(CDN)๋ฅผ ์ฌ์ฉํ์ฌ ์ง์ฐ ์๊ฐ์ ์ค์ด๊ณ ๋ค๋ฅธ ์ง์ญ์ ์ฌ์ฉ์์๊ฒ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. ์๋ฅผ ๋ค์ด, ์์
๋ฏธ๋์ด ํ๋ซํผ์ ๋ค๋ฅธ ์ง์ญ์์ ์ฝํ
์ธ ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ๋ค๋ฅธ API ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ค๋ฅ ๋ฉ์์ง: ์ฌ์ฉ์์ ์ธ์ด๋ก ๋ช
ํํ๊ณ ์ ์ตํ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ ๊ณตํฉ๋๋ค. i18n ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๋์ ์ผ๋ก ๋ฒ์ญํฉ๋๋ค.
- ์ ๊ทผ์ฑ: ์ ๊ทผ์ฑ ์ง์นจ(WCAG)์ ์ค์ํ์ฌ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ก์ธ์คํ ์ ์๋๋ก ํฉ๋๋ค. ์ด๋ฏธ์ง์ ๋ํ ๋์ฒด ํ
์คํธ๋ฅผ ์ ๊ณตํ๊ณ , ์๋ฏธ๋ก ์ HTML์ ์ฌ์ฉํ๊ณ , ์ ํ๋ฆฌ์ผ์ด์
์ด ํค๋ณด๋๋ก ํ์ ๊ฐ๋ฅํ์ง ํ์ธํฉ๋๋ค.
- ์๊ฐ๋: ๋ ์ง์ ์๊ฐ์ ํ์ํ ๋ ์๊ฐ๋๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํฉ๋๋ค. `moment-timezone`๊ณผ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ํ์ง ์๊ฐ๋๋ก ์๊ฐ์ ๋ณํํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ฒคํธ ์๊ฐ์ ํ์ํ๋ ๊ฒฝ์ฐ ์ฌ์ฉ์์ ํ์ง ์๊ฐ์ผ๋ก ๋ณํํ์ฌ ์ฌ๋ฐ๋ฅธ ์๊ฐ์ ๋ณผ ์ ์๋๋ก ํฉ๋๋ค.
์คํ ๊ฐ๋ฅํ ์ธ์ฌ์ดํธ ๋ฐ ๋ชจ๋ฒ ์ฌ๋ก
React Suspense๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ์ ๊ด๋ฆฌํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ์คํ ๊ฐ๋ฅํ ์ธ์ฌ์ดํธ์ ๋ชจ๋ฒ ์ฌ๋ก๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ข
์์ฑ ์๋ณ: ์ปดํฌ๋ํธ ํธ๋ฆฌ๋ฅผ ์ ์คํ๊ฒ ๋ถ์ํ๊ณ ๋ฆฌ์์ค ๊ฐ์ ์ข
์์ฑ์ ์๋ณํฉ๋๋ค.
- ์ฌ๋ฐ๋ฅธ ์ ๋ต ์ ํ: ์ข
์์ฑ ๋ฐ ์ฑ๋ฅ ์๊ตฌ ์ฌํญ์ ๋ฐ๋ผ ์ ์ ํ ๋ก๋ฉ ์ ๋ต(๋ณ๋ ฌ, ์์ฐจ ๋๋ ๊ฒฐํฉ)์ ์ ํํฉ๋๋ค.
- React Context ์ฌ์ฉ: ์ค๋ณต ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด React Context๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ๊ฐ์ ๋ฆฌ์์ค๋ฅผ ๊ณต์ ํฉ๋๋ค.
- ์ค๋ฅ ๊ฒฝ๊ณ ๊ตฌํ: ์ค๋ฅ๋ฅผ ์ํํ๊ฒ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ค๋ฅ ๊ฒฝ๊ณ๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ํํฉ๋๋ค.
- ์ฑ๋ฅ ์ต์ ํ: ์ฝ๋ ๋ถํ ๋ฐ ์ง์ฐ ๋ก๋ฉ์ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์
์ ์ด๊ธฐ ๋ก๋ ์๊ฐ์ ์ค์
๋๋ค.
- ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง: ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ ๋๊ตฌ ๋ฐ ์ฑ๋ฅ ๋ชจ๋ํฐ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ฑ๋ฅ ๋ณ๋ชฉ ํ์์ ์๋ณํ๊ณ ํด๊ฒฐํฉ๋๋ค.
- ์ฒ ์ ํ ํ
์คํธ: ๋ค์ํ ๋คํธ์ํฌ ์กฐ๊ฑด๊ณผ ์ค๋ฅ ์๋๋ฆฌ์ค๋ก ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒ ์ ํ๊ฒ ํ
์คํธํ์ฌ ์์๋๋ก ์๋ํ๋์ง ํ์ธํฉ๋๋ค.
- ๋ฐ์ดํฐ ์บ์ฑ: ํด๋ผ์ด์ธํธ ์ธก ์บ์ฑ์ ๊ตฌํํ์ฌ API ์์ฒญ ์๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค. `swr` ๋ฐ `react-query`์ ๊ฐ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ฐ์ดํฐ ์บ์ฑ์ ๋์์ด ๋ ์ ์์ต๋๋ค.
- ์๋ฒ ์ธก ๋ ๋๋ง(SSR) ๊ณ ๋ ค: SEO ๋ฐ ์ด๊ธฐ ๋ก๋ ์๊ฐ ๊ฐ์ ์ ์ํด ์๋ฒ ์ธก ๋ ๋๋ง ์ฌ์ฉ์ ๊ณ ๋ คํ์ญ์์ค.
๊ฒฐ๋ก
React Suspense๋ ๋น๋๊ธฐ ์์
์ ๊ด๋ฆฌํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ๋ ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํฉ๋๋ค. Suspense์ ๋ฆฌ์์ค์ ํต์ฌ ๊ฐ๋
์ ์ดํดํ๊ณ ์ด ๋ธ๋ก๊ทธ ๊ฒ์๋ฌผ์ ์ค๋ช
๋ ์ ๋ต์ ์ ์ฉํจ์ผ๋ก์จ ๋ค์ค ๋ฆฌ์์ค ๋ก๋ฉ์ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ๊ธ๋ก๋ฒ ์ ์ฌ ๊ณ ๊ฐ์ ์ํด ๋ ๋ฐ์์ ์ด๊ณ ๊ฒฌ๊ณ ํ React ์ ํ๋ฆฌ์ผ์ด์
์ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ์ ์ธ๊ณ ์ฌ์ฉ์๋ฅผ ์ํ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ ๋๋ ๊ตญ์ ํ, ์ ๊ทผ์ฑ ๋ฐ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ ์์ง ๋ง์ญ์์ค. ์ด๋ฌํ ๋ชจ๋ฒ ์ฌ๋ก๋ฅผ ๋ฐ๋ฅด๋ฉด ๊ธฐ๋ฅ์ ์ผ ๋ฟ๋ง ์๋๋ผ ๋ชจ๋ ์ฌ๋์๊ฒ ์ฌ์ฉ์ ์นํ์ ์ด๊ณ ์ก์ธ์ค ๊ฐ๋ฅํ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค ์ ์์ต๋๋ค.