์ ์ ์์ด 9์์ ๋ณด๋ด๋ค ๋ณด๋ 8์์ด ๋๋๊ณ ๋ ๋ฒ์จ 15์ผ์ด๋ ์ง๋๋ฒ๋ ธ๋ค. ์กฐ๊ธ ๋ฆ์์ง๋ง 8์์ ํ๊ณ ํ๊ณ 9์์ ๊ณํ์ ์ธ์๋ณด๋ ค ํ๋ค.
8์์ ์ก์ ์์ดํ
7์์ ๊ณํํ๋ 8์์ ์ก์ ์์ดํ ์ ์๋ 4๊ฐ์ง์ด๋ค. ์ด์ค ์์ 2๊ฐ์ง๋ ์๋ฃํ์ง๋ง, useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ํ ์คํ์์ค ๋ถ์ ๊ณผ์ ๊ณต์ ํ๊ธฐ์ ์ปดํฌ๋ํธ ์ค๊ณ ์ถ๊ฐ ์์ ์งํํ๊ธฐ๋ ํ์ง ๋ชปํ๋ค.
- MMKV ๋ฐ์ดํฐ ์คํ ๋ฆฌ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ ํ ์ฑ๋ฅ ๊ฐ์ ๊ฒฐ๊ณผ ์ ๋ฆฌํ๊ธฐ
- React Query๋ฅผ ์ด์ฉํ ๋น๋๊ธฐ ์ํ ๊ฐ์ ๋ฐฉํฅ ๊ณต์ ํ๊ธฐ
- useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ํ ์คํ์์ค ๋ถ์ ๊ณผ์ ๊ณต์ ํ๊ธฐ
- ์ปดํฌ๋ํธ ์ค๊ณ ์ถ๊ฐ ์์ ์งํํ๊ธฐ
MMKV ๋ฐ์ดํฐ ์คํ ๋ฆฌ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ ํ ์ฑ๋ฅ ๊ฐ์ ๊ฒฐ๊ณผ ์ ๋ฆฌํ๊ธฐ
์ง๋ ๋ฌ์ ๋ฒค์น๋งํฌ ์งํ๋ค์ ๊ณต์ ํ๋ฉด์ ๊ธฐ์กด ์ฌ์ฉํ๋ Async Storage์์ ๋ง์ด๊ทธ๋ ์ด์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ MMKV๋ก ์ ํ๊ณ , ์ด๋ฒ ๋ฌ์๋ ์ค์ ๋ง์ด๊ทธ๋ ์ด์ ์ ์งํํ๋ค.
์ด์ ๋ฐํ์์ ์ฑ์์๊ณผ์ ์์ API ํธ์ถ๊ณผ ํจ๊ป ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์๊ฐ์ ์ธก์ ํ๋ ๋ถ๋ถ์ด API ์์กด์ฑ์ ์ ๊ฑฐํ์ ๋ ์์น๋ฅผ ๋ณด๋ฉด ๋ ์ข์ ๊ฒ ๊ฐ๋ค๋ ์๊ฒฌ์ ์ฃผ์ จ๊ณ , ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ฑ์ ๋น๋ํ๊ณ ๋น๊ตํด ๋ณด์์ ๋ MMKV๋ 150ms์์ 65ms๋ก 50%์ด์ ๊ฐ์ ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์๋ค.
ํ์ง๋ง ๋ก์ปฌ DB์์ฒด๋ฅผ ์ ํ๋ด์์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ง ์์ ์์ฒญ๋๊ฒ ํฐ ๊ฐ์ ์ ๊ฐ์ ธ์ค์ง๋ ๋ชปํ ๊ฒ์ผ๋ก ๋ณด์ด์ง๋ง, Async Storage์์ ๊ฐํน 200ms๊น์ง ๊ฑธ๋ฆฌ๋ ์กฐํ ์๊ฐ์ด ์์๊ธฐ ๋๋ฌธ์, ์ด๋ฅผ ๊ฐ์ ํ๋ ๊ฑด ์๋ฏธ์๋ค๊ณ ์๊ฐ์ด ๋ค์๋ค.
์์ ๋ด์ฉ
๋ง์ด๊ทธ๋ ์ด์ ์์ ์ ์ด์ ๋ง์ด๊ทธ๋ ์ด์ ์์ ๋ค์ ๋นํด ์๋์ ์ผ๋ก ๊ฐ๋จํ์ง๋ง, ํ ์คํธ๋ ๊ธฐ์กด ์ฝ๋๋ค์ด Async Storage ์์ฒด์ ์์กดํ๊ณ ์์ด์ ์ด๋ฅผ ์์ ํ๋ ์์ ์ด ์กฐ๊ธ ๊น๋ค๋ก์ ๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๊ธฐ์กด ์ํคํ ์ฒ์์ AsyncStorage ์์ฒด์ ์์กดํ๊ธฐ ๋ณด๋ค ์ธํฐํ์ด์ค๋ฅผ ์์กดํ๊ฒ ํด ์ดํ ๋ค๋ฅธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ ํํ๋๋ผ๋ ์ต์ํ์ ์์ ์ผ๋ก ๊ฐ๋ฅํ๋๋ก ์ค๊ณ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ ์ด ํ์ํ๋ค.
// ๊ธฐ์กด ์์
class KeyValueStorage {
async setItem(key, value) {
await AsyncStorage.setItem(key, value)
}
async getItem(key) {
return AsyncStorage.getItem(key)
}
}
class Repository {
constructor() {
this.storage = new KeyValueStorage()
}
async getLocalData(key) {
return this.storage.getItem(key)
}
}
// ์ดํ
interface Storage {
getItem: (key: string) => Promise<string | null>
setItem: (key: string, value: string) => Promise<void>
}
const storage: Storage = new MMKVStorage()
class MMKVStorage implements Storage {
async setItem(key, value) {
await storage.set(key, value)
}
async getItem(key) {
// ๊ธฐ์กด๊ณผ ํธํ์ ์ํด JSON.parse๋ฅผ ์ฌ์ฉ
const value = storage.getString(key)
return value ? JSON.parse(value) : null
}
async setItem(key, value) {
storage.set(key, JSON.stringify(value))
}
}
class Repository {
constructor(storage: Storage) {
this.storage = storage
}
async getLocalData(key) {
return this.storage.getItem(key)
}
}
const repository = new Repository(storage)
์กฐ๊ธ ์์ฌ์ ๋ ๋ถ๋ถ์ MMKV ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ฒด๊ฐ AsyncStorage์๋ ๋ค๋ฅด๊ฒ ๊ธฐ๋ณธ ์๋ฃํ๋ค์ ๋ฐ๋ก ๊ฐ์ ธ์ฌ ์ ์๊ฒ ์ง์ํ์ง๋ง, ๊ธฐ์กด AsyncStorage์์ ํธํ์ฑ์ ์ํด JSON.Stringinfy๊ฐ ํ์ํ๊ณ , ๊ธฐ์กด ์ธํฐํ์ด์ค๋ฅผ ๋ง์ถ๊ธฐ ์ํด ๋ถํ์ํ promise๋ฅผ ๋ฐํํด์ผ ํ๋ค.
์ถ๊ฐ๋ก ์ ํธ๋ค์ ํ ์คํธ๊ฐ AsyncStorage์ ์์กดํ๊ณ ์๋ ๊ฒฝ์ฐ์ storage๋ฅผ ์ฃผ์ ํ๋ ๋ฐฉ์์ผ๋ก ์์ ํ๋ค๋ณด๋, ์คํ๋ ค ์ฌ์ฉ์ฒ ์ฝ๋๋ค์ด ๋ณต์กํด๋ณด์ด๊ธฐ๋ ํ๋ค. ํ ์คํธ๊ฐ ํ์ํ ๊ฒ ๋ง๋์ง ์กฐ๊ธ ๋ ๊ณ ๋ฏผํด๋ด์ผ ํ ๊ฒ ๊ฐ๋ค.
์ดํ ์์ ์์ฒด๋ ๋ชจ๋ ์๋ฃํ์ง๋ง ์์ง Native Module์์ ์ด๋ป๊ฒ ํ ํฐ์ ๊ฐ์ ธ์ค๊ณ ํ ์ง์ ๋ํด ๋ ผ์๊ฐ ์งํ๋๋ฉด์ ๋ฐฐํฌ๋ ๋ณด๋ฅ๋๊ฒ ๋์๋ค. ๋ฐฐํฌ ์ดํ ์ฑ๋ฅ์ ์ธก์ ํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ ๋ฆฌํด๋ณด๋ ์์ ์ 9์ ๋๋ 10์์ ์งํํด๋ณด๋ ค ํ๋ค.
React Query๋ฅผ ์ด์ฉํ ๋ก๋ฉ๊ฒฝํ ๊ฐ์ ์์ ๊ณต์ ํ๊ธฐ
React Query๋ฅผ ์ด์ฉํด Suspense๋ก ๋น๋๊ธฐ ์ํ๋ฅผ ๋ถ๋ฆฌํ๊ณ , ์ ์ญ ๋ก๋ฉ๊ฒฝํ์ ๊ฐ์ ํ๋ ์์ ์ ์๋ฃํ๋ค. ์์ ์์ฒด๋ ์๋ฃํ์ง๋ง, ๋ค์ํ ๋๋ฉ์ธ์์ ์์ ์ด ์งํ๋ ๋งํผ QA๊ฐ ๊ฐ๊ฐ ์งํ์ด ํ์ํ๋ค๋ณด๋ ์์ ํ ๋ฐฐํฌ๋ฅผ ํ์ง๋ ๋ชปํ๋ค.
์์ ๊ณผ์ ์์ ์ค๊ฐ์ค๊ฐ์ ๊ณต์ ํ๋ ค ํ์ง๋ง, ๋ฐํ๋ฅผ ํ๊ธฐ์ ๋ค๋ฅธ ๋ถ๋ค์ ๋ฐํ ์ผ์ ์ด ๊ฒน์ณค๊ณ , ์๋น๊ตฐ๋ ๋ค๋ ์ค๋ค ๋ณด๋ ์์ ๊ณผ์ ์ด ์๋๋ผ ๊ฒฐ๊ณผ๋ฅผ ๊ณต์ ํ๋ ๋ฐฉ์์ด ๋์ด๋ฒ๋ ธ๋ค. ์ฝ๋๋ฆฌ๋ทฐ์ ๋ฆฌ๋ทฐ์ด๋ก ๋ฐฐ์ ๋์ ๋ถ๋ค์ ์์ ๊ณผ์ ์ ๋ํด ์ดํดํ์ค ์ ์์์ง๋ง, ๋ค๋ฅธ ๋ถ๋ค์ ๊ฒฐ๊ณผ๋ง์ ๋ณด๊ฒ ๋ ๊ฒ ๊ฐ์ ์์ฌ์ ๊ณ , ๋ฌธ์ ์ ํฌ๊ธฐ์ ๋นํด ๋๋ฌด ์ด๋ ต๊ฒ ์์ ์ด ๋ ๊ฒ ๊ฐ๋ค๋ ํผ๋๋ฐฑ์ ๋ฐ๊ธฐ๋ ํ๋ค.
ํด๋น ํผ๋๋ฐฑ์ ๋ฐ์ผ๋ฉด์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์, ํ์ํ ๊ธฐ์ ์ ์ฌ์ฉํ๋๋ฐ ์ด๋ค ๋ถ๋ถ์ด ๋ฌธ์ ์๋์ง ์จ์ ํ ์ดํดํ๋๋ฐ์๋ ์๊ฐ์ด ํ์ํ๋ค. ์กฐ๊ธ ๋ ์ผ์ฐ ๊ณต์ ํ๋ค๋ฉด ๊ด์ฐฎ์์๊น ์์ฌ์์ด ๋จ์ ํ๋์ ๊ดด๋ก์ํ๊ธฐ๋ ํ๋ค.
๊ธฐ์ ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง, ๊ทธ ๊ณผ์ ์์ ๋ค๋ฅธ ๋ถ๋ค๊ณผ ์ํตํ๋ ๊ฒ๋ ์ค์ํ๋ค๋ ๊ฒ์ ๋ค์ ํ๋ฒ ๋๋ ์ ์์๋ค. ๋๋ฆ์ ์ฑ์ฅํต์ ๊ฒช์๋ ์์ ์ด์๊ณ , ํด๋น ๋ฐํ๋ด์ฉ์ ์ ๋ฆฌํด 9์์ค์ผ๋ก ํด๋น ์์ ์ ๋ํ ๊ธ์ ์์ฑํด๋ณด๋ ค ํ๋ค.
ํ์ง ๋ชปํ ์ก์ ์์ดํ
useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ํ ์คํ์์ค ๋ถ์ ๊ณผ์ ๊ณต์ ํ๊ธฐ
์ ์ปดํฌ๋ํธ ์ค๊ณ ์ถ๊ฐ ์์
์งํํ๊ธฐ
๋ ์งํํ์ง ๋ชปํ๋ค.
8์ ๋์ ์์ง ํ๋ก ํธ์๋์๋ accelarator ๋ฉํ ๋ง
๊ณผ์ ์ค์ด์๊ธฐ ๋๋ฌธ์ ๋์งธ์ฃผ๊น์ง ๋งค์ฃผ ๋ค๋ฅธ ์ฃผ์ ๋ก ๊ณผ์ ๋ฅผ ๊ฐ์ ์์ผ๋๊ฐ๋ฉด์ ์๊ฐ์ด ๋ถ์กฑํ๋ค.
9์์๋ ๊ผญ ์ด ๋๊ฐ์ง์ ๋ํด ์งํํด๋ณด๋ ค ํ๋ค.
์๋กญ๊ฒ ์งํํ๋ ํ๋๋ค
7์๊ณผ ๋์ผํ๊ฒ ํ๋ก ํธ์๋์๋ accelarator ๋ฉํ ๋ง ๊ณผ์ ์ 3์ฃผ์ฐจ, 4์ฃผ์ฐจ ๊ณผ์ ์ ์งํํด ๋ง๋ฌด๋ฆฌํ๊ฒ ๋์๋ค. 3์ฃผ์ฐจ ์ฃผ์ ๋ ์ฐ์ํ ๋น๋๊ธฐ ์ฒ๋ฆฌ, 4์ฃผ์ฐจ๋ UX ๊ฐ์ ์ ๋ํ ์ฃผ์ ๋ก ์งํ๋์๋ค. ๊ฐ ์ฃผ์ฐจ๋ณ ์ฃผ์ ์ ๋ํ ๋ด์ฉ์ ์ ๋ฆฌํด๋ณด์.
3์ฃผ์ฐจ - ์ฐ์ํ ๋น๋๊ธฐ ์ํ๊ด๋ฆฌ
3์ฃผ์ฐจ ์ฃผ์ ์ ์ฐ์ํ ๋น๋๊ธฐ์๋ Promise
, async/await
, Generator
, Observable
๋ฑ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ด๋ป๊ฒ ํ๋ฉด ๋ ์ฐ์ํ๊ฒ ํ ์ ์์์ง์ ๋ํด ์ด์ผ๊ธฐํ๋ค.
๋น๋๊ธฐ ์ํ๋ ์ฌ์ค React์์ ๊ฐ์ฅ ์ด๋ ค์ด ๋ถ๋ถ ์ค ํ๋๋ผ๊ณ ์๊ฐํ๋ค. ํ๋์ ์์ฒญ์ ๋ํด์๋ ๋ก๋ฉ/์ฑ๊ณต/์คํจ๊ฐ ๋ฐ์ํ๊ณ n๊ฐ์ ์์ฒญ์ ๋ํด์๋ 3^n๊ฐ์ ์ํ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฐธ๊ณ ์๋ฃ: ํ๋ก ํธ์๋ ์น ์๋น์ค์์ ์ฐ์ํ๊ฒ ๋น๋๊ธฐ ์ฒ๋ฆฌํ๊ธฐ
"์์ด, ์ ๋งํ๋ฉด ๋ค ์ฑ๊ณตํ์์" ๋ผ๊ณ ์๊ฐํ ์ ์์ง๋ง, ๊ฐ๋ฐ์์ ์ค์, ์๋ฒ์ ์ฅ์ , ๋คํธ์ํฌ์ ๋ฌธ์ ๋ฑ ๋ค์ํ ์ด์ ๋ก ์คํจํ ์ ์๊ธฐ ๋๋ฌธ์ ์ด๋ฌํ ์ํ๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ ๊ณ ๋ ค๋ฅผ ์ผ์ผ์ด manualํ๊ฒ ๊ด๋ฆฌํ๊ธฐ์๋ ์ฝ๋๊ฐ ๋๋ฌด ๋ณต์กํด์ง๊ฑฐ๋ ํน์ ๋ก์ง๊ฐ ๋น ์ง๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์, ์ ์ธ์ ์ธ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํ์ ๋ ๊ฐ ์ํ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋์น์ง ์์ ์ ์๋ค.
// ๋ช
๋ น์ ์ธ ๋ฐฉ์
function Profile(){
const foo=useAsyncValue(()=>{
return fetchFoo()
});
const bar=useAsyncValue(()=>{
if(foo.error||!foo.data){
return undefined
}
return fetchBar(foo.data);
});
if(foo.error||bar.error) return <div> ๋ก๋ฉ ์คํจ.. </div>
if(!foo.data||!bar.data) return <div> ๋ก๋ฉ์ค... </div>
return <div>{foo.data.name}๋ {bar} ํ์ํฉ๋๋ค. </div>
}
// ์ ์ธ์ ์ธ ๋ฐฉ์
function FooBar(){
const foo= useAsyncValue(()=> fetchFoo());
const bar=useAsyncValue(()=>fetchBar(foo));
return <div>{foo}{bar}</div>
}
function App(){
return (
<ErrorBoundary fallback={<MyErrorPage/>}>
<Suspenese fallback={<Loader/>}>
<FooBar/>
</Suspense>
</ErrorBoundary>
)
}
์ด๋ ๊ฒ ์ ์ธ์ ์ผ๋ก ์์ฑํ์ ๋ ๊ธฐ์กด๊ณผ ๋ฌ๋ฆฌ ๊ฐ ์ํ์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ๋์น์ง ์์ ์ ์๊ณ , ๋ก๋ฉ/์ฑ๊ณต/์คํจ๋ผ๋ ๊ฐ ๋น๋๊ธฐ ์ํ์ ๋ฐ๋ฅธ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ๊ฐ ๋์ด ์ฝ๋๊ฐ ๋์ฑ ๊น๋ํด์ง๋ค.
์ด๋ ๊ฒ ์ ์ธ์ ์ธ ๋น๋๊ธฐ ์ํ ๊ด๋ฆฌ์ ๋ํด ์๋ ผํ๊ณ ์์๊ฐ๋ฉด์, 3๋ถ๊ธฐ ์์ ์ค ์งํํ๊ณ ์๋ ๋ก๋ฉ ๊ฒฝํ๊ฐ์ ์์ ์ ์งํํ๋ฉด์ Suspense๋ฅผ ์ด์ฉํด ์ ์ธ์ ์ผ๋ก ๋น๋๊ธฐ ์ํ๋ฅผ ๋ถ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ ์ฉํ๊ฒ ๋์๋ค.
์ถ๊ฐ๋ก ๋๋ ๋์ณค๋ ๋ถ๋ถ์ด์ง๋ง ํจ๊ป ์งํํ๋ ๋ถ์ ์์ฑ๋ ํผ ์ ๋ณด๋ฅผ ์ฌ๋ฌ๋ฒ ์์ฒญํ ์ ์๋ ๊ฒฝ์ฐ๋ฅผ ๊ณ ๋ คํด Post ์์ฒญ์ ๋ํ ์ถ๊ฐ ๋ก๋ฉ ์ํ๋ฅผ ๊ตฌํํ๋ ๋ํ ์ผ์ ๋ณด์ฌ์ฃผ์๊ธฐ๋ ํด์, ๋ด๊ฐ ๋์ณค๋ ๋ํ ์ผ์ ๋ํ ๋ถ๋ถ๋ค์ ๋ฐฐ์ธ ์ ์์๋ค.
function Form() {
const [name, setName] = useState("")
const [email, setEmail] = useState("")
const { mutate, isPending } = useMutation({
mutationFn: submitForm,
onSuccess: () => {
navigate("/success")
},
})
return (
<form
onSubmit={e => {
e.preventDefault()
mutate({ name, email })
}}
>
<input value={name} onChange={e => setName(e.target.value)} />
<input value={email} onChange={e => setEmail(e.target.value)} />
<button type="submit" disabled={isPending}>
์ ์ถ
</button>
</form>
)
}
4์ฃผ์ฐจ - UX ๊ฐ์
UX๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก FCP/LCP ๊ฐ์ ๋ฐฉ๋ฒ๊ณผ ์ค์ผ๋ ํค UI๋ฅผ ์ด์ฉํ ์ฌ์ฉ์ ์ฒด๊ฐ ๋ก๋ฉ ์๋๋ฅผ ์ค์ด๋ ๋ด์ฉ์ ๋ํด ์ด์ผ๊ธฐํ๋ค.
FCP/LCP๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋๋ ๋ฒ๋ค์ ํฌ๊ธฐ๋ฅผ ์ค์ฌ์ ์ด๊ธฐ๋ก๋ฉ ์๊ฐ์ ๊ฐ์ ํ ์ ์์ง ์์๊น ์๊ฐํ๊ณ ์์ ํ๊ฒ ๋์๋ค. ์ด๋ฅผ ์ํ ๋ฐฉ๋ฒ์ผ๋ก ์ฝ๋์คํ๋ฆฟํ ๊ณผ CRA ๋์ vite๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๋ ๋ฐฉ์์ ์ ์ฉํด๋ณด์๋ค.
ํ์ง๋ง ์์ฝ๊ฒ๋ ๊ณผ์ ์์ฒด์ ํ์ด์ง ์๊ฐ ๋ง์ง ์๊ณ CRA์ webpack์์ vite์ esbuild์ rollup์ผ๋ก ๋ณ๊ฒฝํด ๋ณธ ๊ฒฐ๊ณผ ๋ฒ๋ค ํฌ๊ธฐ๋ ์ฐจ์ด๊ฐ ๋ฌ์ง๋ง, FCP์ ํฐ ์ํฅ์ ์ฃผ์ง ๋ชปํ๋ค.
์ด๋ฌํ ์ ๊ทผ์ ์ฌ์ค ๋ฐ์ดํฐ์ ์ผ๋ก ์ ๊ทผํ๋๋ฐ ๋๋ฌด ๋ง์ ์๊ฐ์ ํฌ์ํ๊ณ , ๊ฒฐ๊ณผ์ ์ผ๋ก๋ ํฐ ์ฑ๊ณผ๋ฅผ ๋ณด์ง ๋ชปํ๋ ๊ฒ ๊ฐ๋ค.
๋ค๋ฅธ ๋ถ๋ค์ ์ค์ผ๋ ํค UI์ ํ๋ฉด ์ ํ ์ ๋๋ฉ์ด์ ์ ๊ตฌํํ๊ณ , ํ๋ฉด ์ดํ์์ ์ดํ ๋ฐฉ์ง ๋ชจ๋ฌ์ ๋ ธ์ถํ๋ ๋ฑ ๋ณด๋ค ์ ์ ๊ฐ ๋๋ ์ ์๋ ์ค์ง์ ์ธ UX ๊ฐ์ ์ ์งํํ์ จ๋ค. ์ด๊ฑธ ๋ณด๋ฉด์ ์ ์ ์๊ฒ ์ ์๋ฏธํ ๊ฐ์ ์ ๋ฌด์์ผ์ง, ์ด๋ค ๋ฐฉ์์ผ๋ก ๊ฐ์ ํ ์ ์์์ง์ ๋ํด ๋ค์ ํ๋ฒ ์๊ฐํด๋ณด๊ณ ๋ฐฐ์ธ ์ ์๋ ์๊ฐ์ด์๋ค.
์ด๋ ๊ฒ ํ๋์ ๊ณผ์ ์ ๋ํด ๋ค์ํ ์ฃผ์ ๋ก ์งํํ๋ฉด์ ๋ด๊ฐ ๋์น๊ณ ์๋ ์ , ๋ค๋ฅธ ๋ถ๋ค๊ป์ ์ค์ํ๊ฒ ์๊ฐํ๋ ์ ๋ค์ ๋ฐฐ์ธ ์ ์์๋ ์ ๋ง ์์คํ ์๊ฐ์ด์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ ํ์ผ ์ ์ด์ ์ ๋งํ ๊ฑด ๋ค ๋ง๋ค ์ ์๊ณ , ์ํ๊ณ ์๋ค
๋ ์๊ฐ์ ๋น ์ ธ์๋ ๋ชจ์ต์ ๋๊ผ๊ณ , ๋ค์ ํ๋ฒ ๊ฒธ์ํด์ง๊ณ ๋์ฑ ๋ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
React Native๋ฅผ ์ด์ฉํ ์์ ๋ ์ข์ง๋ง ์น๊ฐ๋ฐ์ ๋ํ ์ง์์ ๋์ฑ ๋ ๊น๊ฒ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
9์์ ์ก์ ์์ดํ
๊ธ์ ์์ฑํ๋ ์์ ์ 9์ ์ค์์ด ์ง๋๊ฐ๊ณ ์์ง๋ง, 9์์ ์ก์ ์์ดํ ์ ์ ๋ฆฌํด๋ณด๋ คํ๋ค.
- MMKV ๋ฐ์ดํฐ ์คํ ๋ฆฌ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ์ฉ ์์ ์ ๋ฆฌํ๊ธฐ
- React Query๋ฅผ ์ด์ฉํ ๋ก๋ฉ ๊ฒฝํ ๊ฐ์ ์์ ์ ๋ฆฌํ๊ธฐ
- useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ํ ์คํ์์ค ๋ถ์ ๊ณผ์ ๊ณต์ ํ๊ธฐ
์ด๋ฒ ๋ฌ์๋ 8์์ ๋ชปํ๋ ์์ ๋ค๊ณผ ํจ๊ป ์๋ฃํ ์์ ๋ค์ ๋ํด์๋ ์ฑ๊ณผ์ ํธ๋ฌ๋ธ ์ํ ๋ค์ ๋ํ ๊ธ์ ์์ฑํด๋ณด๋ คํ๋ค. ์ถ๊ฐ๋ก useFunnel ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ถ์ ํ ์คํ์์ค ๋ถ์ ๊ณผ์ ์ ๊ณต์ ํด๋ณด๋ ค ํ๋ค.
8์ ํ๋ฌ ๋์ ๋ค์ํ ํ๋์ ํ๋ฉด์ ์๋ก์ด ๊ฒฝํ์ ๋ง์ด ํ๊ณ , ์ด๋ฅผ ํ ๋๋ก 9์์๋ ๋์ฑ ๋ ์ฑ์ฅํ๊ณ ์ถ๋ค๋ ์์์ด ์๊ธฐ๋ ํํธ, ๋ด๊ฐ ์ด๋๋ก ๊ฐ๊ณ ์ถ์์ง, ์ด๋ค ๊ฐ๋ฐ์๊ฐ ๋๊ณ ์ถ์์ง์ ๋ํด ๋ค์ ํ๋ฒ ๊ณ ๋ฏผ์ด ๊น์ด์ง๋ ์๊ธฐ๋ฅผ ๋ณด๋ด๊ณ ์๋ ๊ฒ ๊ฐ๋ค.
์์ผ๋ก๋ ๋์ฑ ๋ ์ฑ์ฅํ๊ณ ์ถ๋ค๋ ์์ง๋ฅผ ๊ฐ์ง๊ณ 9์์ ๋ณด๋ด๋ณด๋ ค ํ๋ค.