๐ข ์ด๋ฒ ํญํด๋?
3์ฃผ๊ฐ์ ์ฃผํน๊ธฐ ์ฃผ์ฐจ ๋ง์ง๋ง๊น์ง ์ ๋ฌ๋ ค์๋ค.๐ฅณ
๋งค์ฃผ ๊ณผ์ ์ ํ์ ๊ธฐ๋ฅ๋ค์ ๊ตฌํํด ๋ณด๋ฉฐ ํธ๋ฌ๋ธ ์ํ ์ ํ๋ ๊ณผ์ ์์ ์ฑ ๊ณผ ๊ฒ์์ ๋์์ ์ ๋ง ๋ง์ด ๋ฐ์๋ค. ๊ทธ๋ฌ๋ ๊ณผ์ ์์ ๋ฆฌ์กํธ์ ๊ธฐ์ด๋ฅผ ๋ง์ด ๋ค์ง ์ ์์๊ณ , ํ์ ๋ถ๋ค๊ณผ ๋ ๊ณต๋ถํด๋ณด๊ณ ์ถ์ ์ฃผ์ ๋ฅผ ์ ๋ฆฌํด์์ ์๋ก ๊ฐ๋ฅด์ณ ์ฃผ๊ธฐ๋ ํ๋ค. ํนํ ์ต์ ํ๋ ์์คํ์ค, ๋ฌดํ์คํฌ๋กค ๋ฑ ์ต์์ง ์์์ง๋ง ๊ด์ฌ ์์๋ ์ฃผ์ ๋ ๊ฐ์ด ์ด์ผ๊ธฐ ๋๋ ๋ณผ ์ ์์ด์ ์์ฐฌ ์๊ฐ์ด์๋ค. 3์ฃผ ๋์ ๊ฐ์ ํ์ด์๋ ํ์ ๋ถ๋ค๊ป ๊ฐ์ฌํ๋ค.
๋ฆฌ์กํธ ์ฃผ์ฐจ ํ ๊ณผ์ - ๋งก์ ๋ถ๋ ์ ๋ฆฌ ๋ ธ์
๐ ๋งค๊ฑฐ์ง ํ๋ก์ ํธ
์ด๋ฒ ๋ฆฌ์กํธ ์ฌํ์ฃผ์ฐจ์ ๊ณผ์ ๋ ๋ก๊ทธ์ธ ์ ์ ์ฉ ๋งค๊ฑฐ์ง ์ฌ์ดํธ๋ฅผ ๋ง๋ค์ด ๋ณด๋ ๊ฒ์ด์๋ค.
๊ฐ์ธ์ ์ผ๋ก ๋๋ ๋์์ธ์ด ์๋ป์ผ ๋ง๋๋ ์ฌ๋ฏธ๋ ์๋ ํธ์ด๋ผ, ์ง๊ธ๊น์ง ๋ฆฌ์กํธ ์ฃผ์ฐจ๋ฅผ ๊ฑฐ์น๋ฉด์ ์๊ฐ์ด ์ข ๊ฑธ๋ฆฌ๋๋ผ๋ ๋ชจ๋ ๊ณผ์ ๋ฅผ ํผ๊ทธ๋ง๋ก ์ฐ์ ๋์์ธ์ ํด๋ณด๊ณ ์์ ํ์๋ค. ํผ๊ทธ๋ง๋ฅผ ์ ์ฌ์ฉํ์ง ๋ชปํ์๋๋ฐ ๋ฆฌ์กํธ ์ฃผ์ฐจ ๋์ ์ต์ํด์ง๋ ๋ฐ๊น์ง๋ ์ฑ๊ณตํ ๊ฒ ๊ฐ๋ค. ์๋ ์ข์ ํด์ด๋ผ ๋ ๋ค์ํ ๊ธฐ๋ฅ์ ๋ฐฐ์๋ณด๊ณ ์ถ๊ธฐ๋ ํ๋ค.
๋ก๊ทธ์ธ ์ฌ๋ถ๋ ๊ฐ๋จํ๊ฒ recoil๋ก isLoggedInAtom์ ๋ง๋ค์ด์ ๊ด๋ฆฌํ๊ณ , ์ง๋ ์ฃผ์๋ ์ ์ฉํ์ง ๋ชปํ๋ redux-toolkit์ ์ด๋ฒ ๊ณผ์ ์ ๋๋์ด ๊ฐ๋จํ๊ฒ๋๋ง ์ ์ฉํด๋ณผ ์ ์์๋ค.
๋ฆฌ๋์ค ํดํท์ thunk๋ฅผ ๋ด์ฅํ๊ณ ์์ด์ createAsyncThunk
๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ ์์
๊ด๋ จ ํจ์๋ฅผ ์์ฑํ๊ณ , createSlice
๋ก ์ด๊ธฐ๊ฐ๊ณผ ์ก์
, ๋ฆฌ๋์(reducers, extraReducers)๋ค์ ํ๊บผ๋ฒ์ ๊ฐ์ฒด ํ๋์ ๋ด์ ์ ๋ฌํ ์ ์๋ค. ๋ํ ๋ฆฌ๋์ค ํดํท์ immer
๋ฅผ ๋์
ํ๊ธฐ ๋๋ฌธ์ ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ์ ์ ์งํ ์ ์์ด์ ์ํ๊ฐ์ ์ง์ ๋ณ๊ฒฝํ ์ ์๋ค๋ ์ ์์ ์ฐจ์ด๊ฐ ์์๋ค.
// postSlice.js
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { db } from 'shared/firebase';
import { getDocs, addDoc, collection, query, orderBy } from 'firebase/firestore';
export const getPosts = createAsyncThunk('post/getPosts', async () => {
// ...
});
export const createPost = createAsyncThunk('post/createPost', async (newPost) => {
// ...
});
const postSlice = createSlice({
name: 'post',
initialState: [],
reducers: {},
extraReducers: {
[getPosts.fulfilled]: (state, { payload }) => payload,
[createPost.fulfilled]: (state, { payload }) => [payload, ...state],
},
});
export default postSlice.reducer;
๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ์ธ/ํ์๊ฐ์ ์ ์ํด react-hook-form์ ์ฌ์ฉํ์๋ค. ์์ง ์ฌ์ฉํด๋ณธ ๊ฒฝํ์ด ์ ์ด์ ์ ์ฌ์ฉํ ๊ฒ์ธ์ง์ ๋ํ ํ์ ์ ์์ง๋ง, ํ์คํ validation ์ฒ๋ฆฌ ๋ฐ ์กฐ๊ฑด ๋ฏธ์ถฉ์กฑ ์ ๋ฒํผ ๋นํ์ฑํ ๋ฑ์ ๊ฐํธํ๊ฒ ํ ์ ์์ด์ ์ข์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
https://github.com/ddooyn/veryperi-magazine-2022
๐ค Together
๊ธ์์ผ๋ถํฐ ๋๋์ด ์คํ๋ง ์ฃผํน๊ธฐ๋ฅผ ์ ํํ ๋ฐฑ์๋ ๋ถ๋ค๊ณผ ํจ๊ป ๋ฏธ๋ ํ๋ก์ ํธ๋ฅผ ์์ํ๊ฒ ๋์๋ค. ํ๋ก ํธ์๋ 2๋ช , ๋ฐฑ์๋ 3๋ช ์ผ๋ก ํ์ด ๊ตฌ์ฑ๋์๋ค. API๋ฅผ ๊ธ,ํ ์์ผ์ ๊ฐ์ด ์ค๊ณํ๊ณ , ๋ฐ์ ํผ๋๋ฐฑ์ ํตํด ๋ณด์ํ๋ฉด์ ํ๋ก ํธ์ ๋ฐฑ์๋ ์ฌ์ด์ ์ถฉ๋ถํ ์ํต์ด ์ค์ํ๋ค๋ ๊ฒ์ ์ ์ ์์๋ค. ํ๋ก์ ํธ ์ฃผ์ ๋ ๊ณต๋๊ตฌ๋งค๋ ๋ฐฐ๋ฌ, ๊ณต์ฐ/์ ์ํ์ ํจ๊ป ํ ์ฌ๋์ ๋ชจ์งํ๋ ํ๋ซํผ์ผ๋ก ์ ํด์ก๋ค. ๊ทธ๋์ HeyYo ๋ผ๋ ์ด๋ฆ์ ์ง์ด๋ณด์๋๋ฐ ํจ๊ปํด์ ๊ฐ์ดํด์ ๋ผ๋ ๋ป์ ๋ด๊ณ ์๋ค.
ํ๋ก ํธ๋ฅผ ํจ๊ป ๋งก๊ฒ๋ ํ์๋ถ๊ณผ react-query์ Suspense์ ๋ํ ์ดํด๋ฅผ ํ์คํ ํ๊ณ ํ๋ก์ ํธ์ ์ํ๊ณ ์ถ์ด์ ์ด ์ฃผ์ ์ ๋ํ ์คํฐ๋๋ฅผ ์ ์ํด ๋ฐ๋์ ๋์ ํจ๊ป ํ๋ค. react-query ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ถ๊ณผ ์ผ์ฃผ์ผ๋ ์๋ ์ฌ์ด์ deprecated ๋์ด์ ๋นํฉํ์ง๋ง ๊ณต์๋ฌธ์๋ฅผ ์ฝ์ผ๋ฉฐ @tanstack/react-query
์ @tanstack/react-query-devtools
๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๊ณ ๋ฐ๋ 4๋ฒ์ ์ ๋ํด ๊ฐ์ด ์ ๋ฆฌํ๋ฉฐ ๊ณต๋ถํ๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ฐ์ด ๊ณต๋ถํ ๊ฒฐ๊ณผ๊ฐ ๋ง์กฑ์ค๋ฌ์์ ์ด๋ฒ ํ๋ก์ ํธ์ ์ ํ์ฉํด ๋ณผ ์ ์์ ๊ฒ ๊ฐ๋ค. ํ๋ก์ ํธ ๊ฒฐ๊ณผ๊ฐ ๋ฒ์จ ๊ธฐ๋๋๋ค.