
๐ฏ
@react-beautiful-dnd๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด drag and drop ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ,Firebase๋ก Login ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ๋ฐฐํฌํฉ๋๋ค.
@react-beautiful-dnd ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํด์ Drag and Drop ๊ธฐ๋ฅ์ ๊ตฌํํฉ๋๋ค.


<DragDropContext/> : ๋๋๊ทธ ์ค ๋๋กญ ๊ธฐ๋ฅ์ ํ์ฑํํ๊ณ ์ ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์์ญ์ ๊ฐ์ธ๋ ์ปดํฌ๋ํธ์
๋๋ค.
<Droppable/> : ๋๋กญ์ด ๊ฐ๋ฅํ ์์ญ์
๋๋ค.
<Draggable /> : ๋๋๊ทธํ ์ ์๋ ์์์
๋๋ค.



Firebase๋ Google์์ ์ ๊ณตํ๋ ๋ฐฑ์๋ ํ๋ซํผ์ผ๋ก, ์๋ฒ ์์ด๋ ๋น ๋ฅด๊ฒ ์ฑ์ ์ ์ํ๊ณ ๋ฐฐํฌํ ์ ์๊ฒ ๋์์ฃผ๋ ์๋น์ค์ ๋๋ค.
1๏ธโฃ Firebase์ ๋ก๊ทธ์ธํ์ฌ Go to console ๋ฒํผ์ ๋๋ฌ ์ฝ์์ ๋ค์ด๊ฐ๋๋ค.

2๏ธโฃ ํ๋ก์ ํธ๋ฅผ ์ ํํ๊ณ Firebase Hosting์ ์ค์ ํฉ๋๋ค.

3๏ธโฃ ํ๋ก์ ํธ ์ด๋ฆ์ ์ค์ ํ๊ณ , ๊ณ์ ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.

4๏ธโฃ AI ์ง์ ์ฌ๋ถ๋ฅผ ์ค์ ํ๊ณ , ๊ณ์ ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.

5๏ธโฃ ์ ๋๋ฆฌํฑ์ค ์ฌ๋ถ๋ฅผ ์ค์ ํ๊ณ , ํ๋ก์ ํธ ๋ง๋ค๊ธฐ ๋ฒํผ๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
(ํ์ฌ๋ ๊ฐ๋จํ ํ๋ก์ ํธ ๋ฐฐํฌ๊ธฐ ๋๋ฌธ์ ์ ๋๋ฆฌํฑ์ค๋ ์ฌ์ฉํ์ง ์์ต๋๋ค.)

6๏ธโฃ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๊ณ ๊ฐ์ด๋ฐ์ </>(์น) ๋ฒํผ์ ๋๋ฌ ์์ํด์ค๋๋ค.

7๏ธโฃ ์ฑ ๋๋ค์์ ์ ์ด์ฃผ๊ณ ๋ฑ๋กํด์ค๋๋ค.

8๏ธโฃ npm์ผ๋ก Firebase๋ฅผ ์ค์นํด์ฃผ๊ณ , firebase.ts ํ์ผ์ ๋ง๋ค์ด์ ์๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฃ๊ณ ์ฝ์๋ก ์ด๋ ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.

1๏ธโฃ Authentication์ ๋๋ฌ ์ธ์ฆ ๊ด๋ฆฌ ์ค์ ์ ํฉ๋๋ค.

2๏ธโฃ ์์ํ๊ธฐ ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.

3๏ธโฃ ์ ์ฉํ๊ณ ์ถ์ ๋ก๊ทธ์ธ ์
์ฒด๋ฅผ ๋๋ฌ์ค๋๋ค.

4๏ธโฃ ์ฌ์ฉ ์ค์ ๋ฒํผ์ ๋๋ฌ ๊ณต๊ฐ์ฉ ์ด๋ฆ๊ณผ ์ด๋ฉ์ผ์ ๋ฃ์ด ์ ์ฅ ๋ฒํผ์ ๋๋ฌ์ค๋๋ค.

5๏ธโฃ ์ค์ ์ด ๋ง๋ฌด๋ฆฌ๋์์ต๋๋ค.
(์ถ๊ฐํ๊ณ ์ถ๋ค๋ฉด ์ ์ ๊ณต์
์ฒด ์ถ๊ฐ ๋ฒํผ์ ๋๋ฌ ๋์ผํ ๊ณผ์ ์ ์ํํด์ฃผ๋ฉด ๋ฉ๋๋ค.)

import { createSlice } from '@reduxjs/toolkit';
const initialState = {
id: '',
email: '',
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
setUser: (state, action) => {
state.email = action.payload.email;
state.id = action.payload.id;
},
removeUser: (state) => {
state.email = '';
state.id = '';
},
},
});
export const { setUser, removeUser } = userSlice.actions;
export const userReducer = userSlice.reducer;
์์ฑํ reducer๋ฅผ dispatch(์ก์
)์ผ๋ก ๋ถ๋ฌ์ ์ฌ์ฉํฉ๋๋ค.
const handleLogin = () => {
signInWithPopup(auth, provider)
.then((userCredential) => {
console.log(userCredential);
dispatch(
setUser({
email: userCredential.user.email,
id: userCredential.user.uid,
})
);
})
.catch((error) => {
console.log(error);
});
};
const handleSignOut = () => {
signOut(auth)
.then(() => {
dispatch(removeUser());
})
.catch((error) => console.log(error));
};
[๊ฒฐ๊ณผ ํ๋ฉด] - ๊ตฌ๊ธ ๋ก๊ทธ์ธ ํ, user์ id, email์ด ์ ๋ค์ด๊ฐ ๋ชจ์ต


๐ก Github์ ํ์ผ์ด ์ ์ฅ๋์ด์์ด์ผ ํฉ๋๋ค.
1๏ธโฃfirebase๋ก ๋ฐฐํฌํ๊ธฐ ์ํด์๋ ์ ์ญ์ผ๋ก firebase-tools๋ฅผ ์ค์นํด์ฃผ์ด์ผ ํฉ๋๋ค.
$ npm install -g firebase-tools
2๏ธโฃfirebase์ ๋ก๊ทธ์ธ์ ํด์ค๋๋ค.
$ firebase login
3๏ธโฃ ์ฝ๋๋ฅผ ์๋น์ค์ ์ฌ๋ฆด ์ ์๋ ํํ๋ก ์์ถํ๊ณ ๋ณํํฉ๋๋ค.
$ npm run build
4๏ธโฃ firebase ์ด๊ธฐ ์ค์ ์ ํด์ค๋๋ค.
$ firebase init
? Are you ready to proceed? Yes
โ Hosting: Configure files for Firebase Hosting and (optionally) set up Github Action deploys
Use an existing project
ํ๋ก์ ํธ์ด๋ฆ
? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html) Yes
? Set up automatic builds and deploys with Github? Yes
? File dist/index.html already exists. Overwrite? No

? For which Github repository would you like to set up a Github workflow? ๋๋ค์/ํ๋ก์ ํธ์ด๋ฆ
? Set up the workflow to run a build script before every deploy? Yes
? What script should be run before every deploy? npm ci && npm run build
? Set up automatic deployment to your site's live channel when a PR is merged? Yes
? What is the name of the Github branch associated with your site's live channel? main
5๏ธโฃ ์ค์ ์ ํด์ค ๋ค์ Github์ pushํด ์ค๋๋ค.
git add .
git commit -m 'deploy'
git push
6๏ธโฃ Github ๋ ํ์งํ ๋ฆฌ์์ Actions ํญ์ ๋ค์ด๊ฐ ๋ฐฐํฌํ ์ปค๋ฐ์ผ๋ก ๋ค์ด๊ฐ์ค๋๋ค.

7๏ธโฃ build_and_deploy๋ก ๋ค์ด๊ฐ์ค๋๋ค.

8๏ธโฃ ํด๋น ๊ฒฝ๋ก๋ก ๋ค์ด๊ฐ๋ฉด ๋ฐฐํฌ๋ ์ฌ์ดํธ ์ฃผ์๊ฐ ํ์๋ฉ๋๋ค.

Firebase๋ฅผ ํ์ฉํ๋ฉด์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ๊ตฌํ๋ถํฐ ๋ฐฐํฌ๊น์ง ๋น๊ต์ ์์ํ๊ฒ ์งํํ ์ ์์๋ค. ํนํ Github Actions์ ์ฐ๋ํ์ฌ ์๋ํ๋ ๋ฐฐํฌ๊ฐ ๊ฐ๋ฅํ๋ค๋ ์ ์์ ๋ฐฐํฌ ๊ณผ์ ์ ๋ํ ๋ถ๋ด์ด ์ค์ด๋ ๋๋์ด๋ค.
