๊ฐ๋ฐ๊ธฐ๊ฐ: 2022-11. 01 ~ 2023-1.31
ํ๋ก ํธ ์๋ฒ : https://web-life-calender-front-6g2llffebnui.sel3.cloudtype.app/
๋ฐฑ์๋ ์๋ฒ :
ID- [email protected]
PW- Test123456!
๋๋ฐ์ด์ค์ ์ฌ์ด์ฆ๊ฐ ๋ค ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ , ๋ชจ๋ ๋๋ฐ์ด์ค์ ์ต์ ํ ๋์ด์์ง ์์ต๋๋ค.
ํน์ฌ, ๋ง์ง ์์ผ์๋ค๋ฉด ํ๋ฉด ํฌ๊ธฐ 90% ๋ก ์๋ํด ๋ณด์๊ธฐ ๋ฐ๋๋๋ค.
๊นํ์ (Front) | ๋ฐ๋คํ (BackEnd) |
---|---|
@haeunKim | @dahyeonPark |
๋น์ ์ ์ถ์ "๊ธฐ๋ก" ํด ๋ณด์ธ์ .
๋ฐ์ ์ผ์์ ์ฐ๋ฆฌ๊ฐ ๋ค์ ๊ธฐ์ต ํด๋ผ์ ์๋๊ฑด ๊ธฐ๋ก ๋๋ถ ์
๋๋ค. ๊ธฐ๋ก ์์ ์ถ์ต์ด ์๊ณ , ๊ธฐ๋ก๋ ์ถ์ต์ ์ด์๊ฐ๋๋ฐ ์๋๋ ฅ์ด ๋ฉ๋๋ค.
Life-calendar ๋ ํ๋ฃจ์ ํ ์ผ, ์ด๋ฃจ๊ณ ์ถ์ ๋ฒํท๋ฆฌ์คํธ , ๊ฐ์ ์ผ๊ธฐ๋ฅผ ํ ๊ณณ์ ์ ์์ ์๋๋ก ๊ตฌํ ํ์ ์ต๋๋ค.
๋ฐ์ ์ผ์์์๋ ๊ธฐ๋ก ํ ์ ์๋๋ก ์ต๋ํ ๊ฐํธํ๊ฒ ๊ตฌํ ํ์์ผ๋ฉฐ, ๊ท์ฌ์ฐ๋ฉด์๋ ์ฌํํ UI๋ฅผ ์๊ฐํ๋ฉฐ ๋ง๋ค์์ต๋๋ค.
์ด๋ ต์ง ์์ ๊ธฐ๋ฅ๊ณผ ํจ๊ป CRUD ๋ฅผ ๊ฒฝํํด ๋ณผ์ ์๋ ํ๋ก์ ํธ ๊ฐ ์ด๋ค๊ฒ ์์ ๊น ์๊ฐ ํ์์ต๋๋ค.
์์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด์ ์ผ์์์์ ์ ์ฐ์ด๋ ์๋น์ค๊ฐ ์ด๋ค๊ฒ ์์๊น ์๊ฐํ๋ค๊ฐ "Life- Calendar" ์ด๋ผ๋ ํ๋ก์ ํธ ์์ด๋์ด๊ฐ ๋์ค๊ฒ ๋์์ต๋๋ค.
๋ง์ ๊ธฐ๋ฅ์ ํ์๋ก ํ๋ ํ๋ก์ ํธ๋ฅผ ํ๋ค๊ฐ ์ด๋ ค์์ ์ค๋ ํฌ๊ธฐ ํ๋๊ฒ ๋ณด๋จ, ์๋๋ผ๋ ์๋ฒฝํ๊ฒ ๊ตฌํ ํ ์ ์๋ ํ๋ก์ ํธ๋ฅผ ํ๋๊ฒ ๋ง๋ค๊ณ ์๊ฐ ํ์ต๋๋ค.
๋ฐ๋ผ ์ด๋ณด์์ธ ๋ถ๋ค์ด ์ต๋ํ ๊ตฌํํ ์ ์๋ ํ๋ก์ ํธ๋ฅผ ์ ํ ํ์๊ณ , ๊ทธ์ ๋์์ ์๋ฏธ ์๋ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๊ณ ์ถ์์ต๋๋ค.
For building and running the application you need:
$ git clone https://github.com/hahahaday12/Life-Calender-front.git
$ cd client
$ cd server -> cd lifeserver
$ nvm use v.16.19.1
$ npm install
$ npm run start
$ cd client
$ nvm use v.8.19.3
$ npm install
$ npm run start
๋ฉ์ธ ํ์ด์ง | ํ์ ๊ฐ์ ํ์ด์ง |
---|---|
Calendar ํ์ด์ง | List ํ์ด์ง |
Diary ํ์ด์ง | |
๐ ์ ํจ์ฑ ๊ฒ์ฆ์ ํตํ์ฌ, ํ์๊ฐ์ ๊ฐ๋ฅ.
-> ์ ๊ท์์ ์ฌ์ฉํ์ฌ ์ด๋ฉ์ผ ํจ์ค์๋๋ฅผ ์ฒดํฌํ์ฌ ์ผ์นํ์ง ์์ผ๋ฉด ๊ฒฝ๊ณ ๋ฉ์์ง๋ก ๋ณด์ด๊ฒ ๋ฉ๋๋ค.
๐ Local storage ์ Token ์ ์ฅ.
-> ์ ๋ ฅํ ์์ด๋ ํจ์ค์๋๋ฅผ ์๋ฒ๋ก ๋ณด๋ธ ํ ์ฑ๊ณต์ ์ํ๊ฐ๊ณผ Token๊ฐ ์ ๋ฐ์์ local storage ์ ๋ณด๊ด ํฉ๋๋ค. ์คํจ์ โ์์ด๋ ๋๋ ๋น๋ฐ๋ฒํธ ์๋ชป ์ ๋ ฅ ํ์ จ์ต๋๋คโ ๋ผ๋ ์๋ฆผ์ด ๋น๋๋ค.
๐ ํ๋ฃจ ๋ ์ง ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ ์กฐํ/ Todo ๋ฑ๋ก/ Todo ์ํ๊ฐ ๋ณ๊ฒฝ ์์ / Todo ์ญ์
-> ๋ ์ง๋ ์์คํ ๋ ์ง๋ก ๊ธฐ๋ณธ์ผ๋ก ์ค์ ๋๋ฉฐ ํ๋ฃจ์ ์งํ๋ ์ผ์ ๋ฑ๋กํ Drag And Drop์ผ๋ก TODO ์ํ์์ Done ์ํ๋ก ์ฎ๊ฒจ ํ๋ฃจ ์๋ฃ ์ํ๋ฅผ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค. ์ง๋ ๋ ์ง์ TODO๋ ์ถ๊ฐ๋ฑ๋ก, ์ญ์ ๊ฐ ๊ฐ๋ฅํ๋ฉฐ ์์ผ๋ก ํ ์ผ๋ ๋ฏธ๋ฆฌ ๋ฑ๋กํด ํ๋ฃจ ์ผ์ ์ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
๐ ํ๋ฌ ๋ ์ง ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ ์กฐํ/ Diary ๋ฑ๋ก/ ์ด์ ์์ฑ๋ ๊ธ & ํ์ฌ๊ธ ์์ / Diary ์ญ์
-> ํ๋ฌ๊ฐ ์์ฑํ Diary ์ ๋ณด๋ฅผ ์นด๋ํํ๋ก ์กฐํํ๋ฉฐ Diary ์์ฑ์ ํ๋ฃจ ๊ธฐ๋ถ์ ์ํ๋ฅผ ์์ผ๋ก ์ ํํ ์ ์๊ฒ ๊ตฌํํ์ผ๋ฉฐ , ์นด๋ํํ๋ก ๋ฑ๋ก๋์ด ๋ ธ์ถ์ด ๋ฉ๋๋ค. ์นด๋ํํ๋ฅผ ํด๋ฆญํ๋ฉด ์์ฑํ๋ ์ ๋ชฉ, ๋ด์ฉ, ์ ํํ๋ ์์ด ๋ค์ ์์ ๊ฐ๋ฅํ๋ฉฐ, ์ญ์ ๋ฐ ์์ ์ ์๋ชป ๋๋ ์ ๊ฒฝ์ฐ๋ฅผ ๋๋นํ์ฌ ํ์ธ์ฐฝ์ด ๋ ธ์ถ๋๋๋ก ๊ตฌํ ํ์์ต๋๋ค.
๐ Diary Color ๋ ธ์ถ ๊ธฐ๋ฅ
-> Diary ์์ ์ ์ฅํ Color ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์์ฑํ ๋ ์ง์ ์์ ๋ณด์ฌ ์ค๋๋ค. ํ๋ฌ ๋์์ ๊ฐ์ ์ ๋ณผ์ ์์ต๋๋ค.
-> input ์ ํ ์ผ์ ์ ๋ ฅํ๊ณ , ๋ฑ๋ก ๋ฒํผ์ ๋๋ฅผ์ onClick์ ์ด๋ฒคํธ๊ฐ ํ์ฑ ๋๋ฉด์ content(๋ด์ฉ) , date(๋ ์ง), status(์ํ๊ฐ) ์ ๋ฐ์ดํฐ๊ฐ ์๋ฒ api ์ ์ ๋ฌ ๋ฉ๋๋ค. ์๋ฒ์๊ฒ ์ ๋ฌ ๋๋ ๋ฐฉ์์ผ๋ก๋ post ๋ฐฉ์์ผ๋ก ์ด์ฉ ํ์์ผ๋ฉฐ, ์๋ฒ์ ์ ์ฅ์ด ๋๋ฉด, "๋ฑ๋ก ๋์์ต๋๋ค." ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋น๋๋ค. ๊ทธํ setState ์ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ ์ฅํ๊ณ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ์กฐํํ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค. ์๋ฒ Api ์์ Get ๋ฐฉ์์ ์ฌ์ฉํด ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ์์ต๋๋ค.
-> x์ ์์ด์ฝ์ ๋๋ฅด๋ฉด onClick์ ์ด๋ฒคํธ ํจ์๊ฐ ํ์ฑ๋๋ฉด์ "์ญ์ ํ์๊ฒ ์ต๋๊น?" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ต๋๋ค. ์ด๋ ์ทจ์๋ฅผ ํด๋ฆญ์ "์ทจ์ ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ค๊ณ ํ์ธ์ ํด๋ฆญ์ ์๋ฒ Api์ delete ๋ฐฉ์์ผ๋ก ์ ํํ id์ ๊ฐ์ด ์ ๋ฌ๋๊ณ , ์ฑ๊ณต ์ด๋ผ๋ ์ํ๊ฐ์ ์ ๋ฌ ๋ฐ์ผ๋ฉด "์ญ์ ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ ๋๊ฒ๋ ๊ตฌํํ์์ต๋๋ค. ์ฑ๊ณต์ ์ํ๊ฐ์ ๋ฐ์์ค์ง ๋ชปํ๋ฉด ์๋ฌ์ ๋ํ ๋ฐ์ดํฐ ๋ฉ์์ง๊ฐ ์ฝ์์ฐฝ์ ๋น๋๋ค.
๐ Drag and Drop ๊ธฐ๋ฅ
-> onDragEnd ์ ํจ์๋ React์ useState Hook ์ ์ฌ์ฉํ์ฌ, ์ปดํฌ๋ํธ ๋ด์์ ๊ด๋ฆฌํ๋ ์ํ๊ฐ์ธ columns๊ณผ setColumns๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. columns๋ ๋๋๊ทธ ์ค ๋๋กญ์ด ์ ์ฉ๋ ์ฌ๋ฌ ์ด(column)๋ค์ ๋ด๊ณ ์์ต๋๋ค. result๋ react-beautiful-dnd ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ๋๋๊ทธ ์ค ๋๋กญ ์ด๋ฒคํธ ๊ฐ์ฒด์ ๋๋ค. ์ด ๊ฐ์ฒด์์๋ ๋๋๊ทธ๋ ์์ดํ , ์ถ๋ฐ์ง์ ๋ชฉ์ ์ง droppable ์์ญ์ ์ ๋ณด ๋ฑ์ด ํฌํจ๋ฉ๋๋ค. ์ด ํจ์์์๋ ๋จผ์ , result.destination์ด ์กด์ฌํ์ง ์๋ ๊ฒฝ์ฐ(์ฆ, ์์ดํ ์ด ๋๋กญ๋์ง ์์ ๊ฒฝ์ฐ) ํจ์๋ฅผ ์ข ๋ฃํฉ๋๋ค.
const onDragEnd = (result, columns, setColumns) => {
if (!result.destination) return;
const { source, destination } = result;
๊ทธ ๋ค์, ๋๋๊ทธ๋ ์์ดํ ์ด ์ถ๋ฐ์ง์ ๋ชฉ์ ์ง๊ฐ ๋ค๋ฅธ ๊ฒฝ์ฐ์ ๊ฐ์ ์ด(column) ๊ฐ ์ด๋์ผ ๊ฒฝ์ฐ์, ๊ฐ์ ์ด ๋ด์์์ ์์ดํ ์์ ๋ณ๊ฒฝ์ผ ๊ฒฝ์ฐ๋ฅผ ๊ตฌ๋ถํฉ๋๋ค. ๊ฐ์ ์ด(column) ๊ฐ ์ด๋์ด๋ผ๋ฉด, columns ์ํ๊ฐ์์ ์ถ๋ฐ์ง ์ด์ ์ฐพ์ ํด๋น ์ด์ items ๋ฐฐ์ด์์ ์์ดํ ์ ์ด๋์ํค๊ณ , ๋ณ๊ฒฝ๋ items ๋ฐฐ์ด์ ๋ค์ columns ์ํ๊ฐ์ ๋ฐ์ํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก, ChangeStatus() ํจ์๋ฅผ ํธ์ถํ์ฌ ๋๋๊ทธ๋ ์์ดํ ์ ์ํ๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค.
if (source.droppableId !== destination.droppableId) {
console.log(result);
const sourceColumn = columns[source.droppableId];
const destColumn = columns[destination.droppableId];
const sourceItems = [...sourceColumn.items];
const destItems = [...destColumn.items];
const [removed] =
sourceItems.splice(source.index, 1);
destItems.splice(destination.index, 0, removed);
setColumns({
...columns,
[source.droppableId]: {
...sourceColumn,
items: sourceItems
},
[destination.droppableId]: {
...destColumn,
items: destItems
},
});
ChangeStatus(result.draggableId, destination.droppableId.toLowerCase());
}
๊ทธ๋ฌ๋, ๋ค๋ฅธ ์ด ๊ฐ ์ด๋์ด๋ผ๋ฉด, ์ถ๋ฐ์ง ์ด๊ณผ ๋ชฉ์ ์ง ์ด์์ ์์ดํ ์ ์ด๋์ํค๊ณ , ์ด๋ฅผ columns ์ํ๊ฐ์ ๋ฐ์ํฉ๋๋ค.
else {
const column = columns[source.droppableId];
const copiedItems = [...column.items];
const [removed] = copiedItems.splice(source.index, 1);
copiedItems.splice(destination.index, 0, removed);
setColumns({
...columns,
[source.droppableId]: {
...column,
items: copiedItems
}
});
}
};
์ด๋ ๊ฒ onDragEnd ํจ์๋ ๋๋๊ทธ ์ค ๋๋กญ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋, ํด๋น ์ด๋ฒคํธ์ ๋ง๊ฒ columns ์ํ๊ฐ์ ์ ๋ฐ์ดํธํ์ฌ, ๋ณ๊ฒฝ๋ ์ํ๊ฐ์ ์ปดํฌ๋ํธ์์ ๋ ๋๋งํ๋๋ก ํฉ๋๋ค
๐ ๋ฐ์ดํฐ ์ํ ๋ณ๊ฒฝ ๊ธฐ๋ฅ
-> Todo์ ๋ฑ๋ก๋ item์ ์ํ๊ฐ ์๋ฃ๋ done์ ์ํ๋ก ๋ณ๊ฒฝ ๋์์๋ ๋ณ๊ฒฝ๋ ์ด๋ฒคํธ๋ฅผ ์ ์ฅํ๋ ํจ์๋ฅผ ๋ง๋ค์ด ์ฃผ์์ต๋๋ค. ์๋ฒ Api ์ Patch ๋ฐฉ์์ผ๋ก ์ ํํ item์ id ๊ฐ๊ณผ ํจ๊ป status ์ํ๊ฐ์ ์ ๋ฌํด ์ฃผ์๊ณ , ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ๋ณด์ฌ์ฃผ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค.
-> Datepicker ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉ ํ์ผ๋ฉฐ, Datepicker์์ ๊ฐ์ ธ์จ ๋ ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ์กฐํ ํ๊ณ ๋ฐ์ดํฐ ์ํ(todo,done) ๊ตฌ๋ถํ์ฌ ํ๋ฉด์ ๋ ธ์ถ๋๋ก ๋ถ๊ธฐ์ฒ๋ฆฌํ map์ผ๋ก ๋ ธ์ถํ์๋ค.
๐ ๋ฑ๋ก
-> input ์ ํ ์ผ์ ์ ๋ ฅํ๊ณ , ๋ฑ๋ก ๋ฒํผ์ ๋๋ฅผ์ onClick์ ์ด๋ฒคํธ๊ฐ ํ์ฑ ๋๋ฉด์ title(์ ๋ชฉ) , content(๋ด์ฉ) , date(๋ ์ง) ์ ๋ฐ์ดํฐ๊ฐ ์๋ฒ api ์ ์ ๋ฌ ๋ฉ๋๋ค. ์๋ฒ์๊ฒ ์ ๋ฌ ๋๋ ๋ฐฉ์์ผ๋ก๋ post ๋ฐฉ์์ผ๋ก ์ด์ฉ ํ์์ผ๋ฉฐ, ์๋ฒ์ ์ ์ฅ์ด ๋๋ฉด, "๋ฑ๋ก ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋น๋๋ค. ๊ทธํ setState ์ ๋ณ๊ฒฝ๋ ๊ฐ์ ์ ์ฅํ๊ณ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ ๋ณด์ฌ์ฃผ๋ ํจ์๋ฅผ ์คํํฉ๋๋ค. ์๋ฒ Api ์์ Get ๋ฐฉ์์ ์ฌ์ฉํด ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ํธ์ถํ์์ต๋๋ค.
๐ ์ญ์
-> x์ ์์ด์ฝ์ ๋๋ฅด๋ฉด onClick์ ์ด๋ฒคํธ ํจ์๊ฐ ํ์ฑ๋๋ฉด์ "์ญ์ ํ์๊ฒ ์ต๋๊น?" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ต๋๋ค. ์ด๋ ์ทจ์๋ฅผ ํด๋ฆญ์ "๋ค์ ์ ํํด ์ฃผ์ธ์" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ค๊ณ ํ์ธ์ ํด๋ฆญ์ ์๋ฒ Api์ delete ๋ฐฉ์์ผ๋ก ์ ํํ id์ ๊ฐ์ด ์ ๋ฌ๋๊ณ , ์๋ฒ์์ ์ฑ๊ณต ์ด๋ผ๋ ์ํ๊ฐ์ ์ ๋ฌ ๋ฐ์ผ๋ฉด "์ญ์ ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ ๋๊ฒ๋ ๊ตฌํํ์์ต๋๋ค. ์๋ฒ์์ ์ํ๊ฐ์ด ์ฑ๊ณต์ด ์๋๋ฉด ์๋ฌ์ ๋ํ ๋ฉ์์ง๊ฐ ์ฝ์์ฐฝ์ ๋น๋๋ค.
-> ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ์ ๋ ฅํ๊ณ , ๋ฑ๋ก ๋ฒํผ์ ๋๋ฅผ์ onClick์ ์ด๋ฒคํธ๊ฐ ํ์ฑ ๋๋ฉด์ title(์ ๋ชฉ) , content(๋ด์ฉ) , date(๋ ์ง) ์ ๋ฐ์ดํฐ๊ฐ ์๋ฒ api ์ ์ ๋ฌ ๋ฉ๋๋ค. ์๋ฒ์๊ฒ ์ ๋ฌ ๋๋ ๋ฐฉ์์ผ๋ก๋ post ๋ฐฉ์์ผ๋ก ์ด์ฉ ํ์์ผ๋ฉฐ, ์๋ฒ์ ์ ์ฅ์ด ๋๋ฉด, "๋ฑ๋ก ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋น๋๋ค. ๊ทธํ, ๋ฑ๋ก๋ ์ ๋ณด๊ฐ slider ์ปดํฌ๋ํธ์ ๋ฑ๋ก๋์ด ๋ณด์ด๊ธฐ ๋๋ฌธ์, ๊ธฐ์กด์ ์ ๋ ฅํ ๋ฐ์ดํฐ๋ฅผ ์ด๊ธฐํ ์์ผ์ฃผ๊ธฐ ์ํด, ๋ฐ์ดํฐ ์ด๊ธฐ๊ฐ์ ๋ํ ํจ์๋ฅผ ๋ง๋ค์ด ์ฃผ์์ต๋๋ค. ํจ์ ์์ setState ์ ์ฌ์ฉํ์ฌ ๋งจ์ฒ์ ์ํ์ธ ๋น ๋ฐ์ดํฐ ๊ฐ์ ์ ์๊ณ , date ๋ ํ์ฌ ์๊ฐ, color๋ ๋งจ์ฒ์ ๊ธฐ๋ณธ ์์์ ์ ์ด ๋์์ต๋๋ค.
-> x์ ์์ด์ฝ์ ๋๋ฅด๋ฉด onClick์ ์ด๋ฒคํธ ํจ์๊ฐ ํ์ฑ๋๋ฉด์ "์ญ์ ํ์๊ฒ ์ต๋๊น?" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ต๋๋ค. ์ด๋ ์ทจ์๋ฅผ ํด๋ฆญ์ "๋ค์ ์ ํํด ์ฃผ์ธ์" ๋ผ๋ ์๋ฆผ์ฐฝ์ด ๋์ค๊ณ ํ์ธ์ ํด๋ฆญ์ ์๋ฒ Api์ delete ๋ฐฉ์์ผ๋ก ์ ํํ ์ด๋ฒคํธ id์ ๊ฐ์ด ์ ๋ฌ๋๊ณ , ์๋ฒ์์ ์ฑ๊ณต ์ด๋ผ๋ ์ํ๊ฐ์ ์ ๋ฌ ๋ฐ์ผ๋ฉด "์ญ์ ๋์์ต๋๋ค" ๋ผ๋ ์๋ฆผ์ฐฝ์ ๋๊ฒ๋ ๊ตฌํํ์์ต๋๋ค. ์ฑ๊ณต์ ์ํ๊ฐ์ ๋ฐ์์ค์ง ๋ชปํ๋ฉด ์๋ฌ์ ๋ํ ๋ฐ์ดํฐ ๋ฉ์์ง๊ฐ ์ฝ์์ฐฝ์ ๋น๋๋ค.
-> recoile ์ ์ฌ์ฉํ์ฌ ์ํ๊ด๋ฆฌ๋ฅผ ํด์ฃผ์์ต๋๋ค. Color ๋ผ๋ ๋ณ์์ โ๊ฐ์ ์ ๋ํ๋ด๋ ๋จ์ด(key)โ : โ์๊น ์ฝ๋(value)โ, ํค์ ๋ฒจ๋ฅ ๊ฐ์ผ๋ก ๋ฃ์ด๋์์ต๋๋ค.
๊ทธํ, colorNameArray ๋ผ๋ ๋ณ์์ Color์ ์๋ key ๊ฐ์ ๋ฃ์ด๋์๊ณ , colorArray ๋ผ๋ ๋ณ์์๋ color ์ ์๋ value ๊ฐ์ ๋ฃ์ด์ฃผ์์ต๋๋ค. ์์ ์ ํํ๋ color์ type์ radio ํ์ ์ ๋๊ทธ๋ ๋ชจ์์ผ๋ก ๋ง๋ค์ด ์ฃผ์์ต๋๋ค. Map์ ์ฌ์ฉํ์ฌ colorArray ์ ์๋ color ๊ฐ๋ค์ ๋์ดํด ์ฃผ์๊ณ , ํด๋น color๋ฅผ ํด๋ฆญ์ onChange ์ ์ด๋ฒคํธ ํจ์๊ฐ ์คํ๋๊ฒ ๊ตฌํ ํ์์ต๋๋ค.
Onchange ํจ์๋ก ์ํ๊ฐ์ด ๋ฐ๋๊ฒ ๋๋ฉด
useEffect(() => {
const changedColor = {
color: colorState
};
setRecoilColor(changedColor);
}, [colorState, setRecoilColor]);
useEffect ํจ์๋ก ๋ณ๊ฒฝ๋ ์์์ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ์ผ์ต๋๋ค.
๋ค์ด์ด๋ฆฌํผ์์๋ ๋ฆฌ์ฝ์ผ ์ํ๊ฐ์ด ๋ฐ๋๋ฉด ๋์ผํ๊ฒ useEffect ๊ฐ ํธ์ถ๋๋ฉฐ,
const [recoilColor, setRecoilColor] = useRecoilState(recoilColorState);
const [colorPeeker, setColorPeeker ] = useState(recoilColor.color);
useEffect(() =>{
const tmpColor = { ...recoilColor };
setColorPeeker(tmpColor.color);
let defaultDate = new Date();
if(ViewData.date !== ""){
defaultDate = new Date(ViewData.date);
}
setViewData({
...ViewData,
color:tmpColor.color,
date:defaultDate
})
},[recoilColor] )
recoilColor ์ํ๊ฐ์ด ๋ฐ๋๋ฉด์ ์๋ก์ด ์ปฌ๋ฌ๊ฐ์ผ๋ก ๊ฐ์ ธ์ค๊ฒ ๋ฉ๋๋ค.
-> Sliderr ์ ์ปดํฌ๋ํธ์ props ๋ก ๋ฐ์ดํฐ์ ํจ์๋ฅผ ์ ๋ฌ ํ์์ต๋๋ค.
List = ์นด๋ ์ ๋ณด๋ค์ ๋ฟ๋ ค์ค ๋ฐ์ดํฐ ๋ฆฌ์คํธ Search = ์กฐํ ํจ์๋ ์ญ์ ํ ์นด๋ ๋ฆฌ์คํธ๋ฅผ ๋ค์ ์กฐํํ๊ธฐ ์ํด์ ์ฌ์ฉํ์ ์ต๋๋ค. refreshFunction = ์ ํํ ์นด๋๋ฆฌ์คํธ์ ์๋ ๊ฐ์ ์ ๋ ฅํ๋ฉด์ ๊ฐ์ ธ์ค๊ธฐ ์ํด์ ์ฌ์ฉ ํ์์ต๋๋ค.
<Sliderr
list={list}
search={search}
refreshFunction={updateList}
/>
{renderDiary()} ๋ผ๋ ํจ์๋ฅผ ๋ง๋ค์ด props๋ก ์ ๋ฌ๋ฐ์ list ๋ฐ์ดํฐ๋ฅผ map ์ ์ฌ์ฉํ์ฌ ํธ์ถํ์์ต๋๋ค.
const renderDiary = () => props.list && props.list.map((item) => (
๋ฑ๋ก๋ diary์ title์ ํด๋ฆญ์ ๋ค์ด์ด๋ฆฌ ๋ด์ฉ์ด ๋ณด์ฌ์ง๋ ์ด๋ฒคํธ ํจ์๋ฅผ ๋ง๋ค์์ต๋๋ค. Item์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ์ฌ ๋ฐ์ดํฐ๋ค์ ๋ฃ์๊ณ props ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ต๋๋ค.
const Viewdiary = (item) => {
const body = {
title : item.title
,content : item.content
,color : item.color
,id : item._id
,date : new Date(KSTchangeUTC(item.date))
}
props.refreshFunction(body);
};
-> Calendar ์๋ Diary ์์ ์ ์ฅํ Color ๊ฐ์ด ๋ํธ์ ํํ๋ก ๋ํ๋๊ฒ ๊ตฌํ ํ์์ต๋๋ค. Calendar ๋ fullCalendar ๋ผ๋ ๋ผ์ด๋ธ๋ฅผ ์ฌ์ฉ ํ์๊ณ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ ๋ด์ฌ๋์ด ์๋ ์ด๋ฒคํธ ๋ฅผ ์ด์ฉํ์ฌ ์ด๋ฒคํธ๋ฅผ ๋ํธ ํํ๋ก ๋ํ๋๊ฒ ๊ตฌํ ํ์์ต๋๋ค. Calendar ๋ผ๋ ํ์ด์ง์ ์ฒ์ ๋ค์ด์์ ๋ useEffect ์ด๋ผ๋ Hook ํจ์๋ฅผ ์ฌ์ฉํ์๊ณ , Get ๋ฐฉ์์ผ๋ก ์๋ฒ Api ๋ฅผ ์ด์ฉํ์ฌ diary์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํด์ค๋ ํจ์๋ฅผ ํธ์ถ ํ์ ์ต๋๋ค.
-> ํ์ด์ง๊ฐ ๋ณ๊ฒฝ๋๋๋ผ๋ ์ํ๊ด๋ฆฌ๋ฅผ ์ ์งํ๊ธฐ ์ํด recoil-persist ๋ฅผ ์ฌ์ฉํ์์ต๋๋ค. Recoil-persist๋ฅผ ์ฌ์ฉํ๋ฉด ์ด์ ์ฒ๋ผ ์๋ก๊ณ ์นจ์ ํด๋ recoil state๊ฐ ์์ด์ง์ง ์๊ณ sessionStorage ๋๋ localStorage์ ๋ณด๊ด๋ฉ๋๋ค.
import { atom } from 'recoil';
import { recoilPersist } from 'recoil-persist';
//1. ์๋ฌด๊ฒ๋ ์ค์ ์ ํ๊ณ ์ฐ๋ ๊ฒฝ์ฐ
//localStorage์ ์ ์ฅ๋๋ฉฐ, key ์ด๋ฆ์ 'recoil-persist'๋ก ์ ์ฅ๋๋ค.
const { persistAtom } = recoilPersist();
export const userState = atom({
key: "userState",
default: null,
effects_UNSTABLE: [persistAtom],
//Recoil-persist๋ฅผ ์ ์ฉ์ํค๋ ค๋ฉด ์๋์ effects_UNSTABLE์ ์ ์ด์ฃผ์ด์ผ ํ๋ค.
});
์ ์ธํด๋ atom์ ์ด์ฉํด์, ์๋์ ๊ฐ์ด state์ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํด์ค (userState) ๊ฐ์ ๋ฃ์ด ๋์์ต๋๋ค. ๊ทธํ server api๋ฅผ ์ด์ฉํด ๋ก๊ทธ์ธ์ ์ ์ฅ๋ user์ ์ ๋ณด๋ Get ๋ฐฉ์์ผ๋ก ๊ฐ์ ธ์๊ณ ๊ทธํ, setUser์ ๊ฐ์ ธ์จ data.user.name ์ ์ ์ฅ ํ์ ์ต๋๋ค.
const Usertitle = () => {
const [users, setUsers] = useRecoilState(userState);
Api.user()
.then(response => {
setUsers(response.data.data.user.name);
},(error) => {
console.log(error)
TokenRepository.removeToken();
});
-> ํ๋ก์ ํธ๋ฅผ ๊ธฐํํ๊ณ ์ค๊ณํ๋ ๊ณผ์ ์์๋ ์์ ํ๋ฉด ํ๋๋ ๊ตฌํํ๊ธฐ ์ํด์๋ ๋ค์ํ ๊ณ ๋ ค๊ฐ ํ์ํ ๊ฒ์ ๊นจ๋ฌ์์ต๋๋ค.
์ค์ ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์ ์ด๊ธฐ์ ์๊ฐํ ๋๋ก ์งํ๋์ง ์๋ ๋ถ๋ถ์ด ์์๊ณ , ๊ณ ๋ คํ์ง ๋ชปํ ๋ถ๋ถ๋ ์์์ต๋๋ค.
์ด๋ฅผ ํตํด ๊ธฐํ ๋ฐ ์ค๊ณ์ ์ค์์ฑ์ ๋์ฑ ๊นจ๋ซ๊ฒ ๋์์ต๋๋ค.
์ฝ๋ ์์ฑ ๊ณผ์ ์์๋ ์ฒ์์๋ ์๊ฐ๋๋ ๋๋ก ๊ตฌํํ๋ค๊ฐ, ๋์ค์ ์ฝ๋๋ฅผ ๋ณด๋ ์ค๋ณต๋ ์ฝ๋๊ฐ ๋ง์์ก์ต๋๋ค.
์ถํ , ์ค๋ณต ์ฝ๋๋ฅผ ์ค์ด๊ณ ๋ถํ์ํ ์ฝ๋๋ฅผ ๋ค๋ฌ๊ธฐ ์ํด ๋ฆฌํฉํ ๋ง์ ํ์์ฑ์ ๊นจ๋ซ๊ฒ ๋์์ต๋๋ค.
์ผ๊ด์ ์ธ ๋ฐ์ดํฐ ํํ ์ ์ง๋ฅผ ์ํด ์ํ๊ด๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๋ฅ์ ๊ตฌํํ๋๋ฐ, ์ด๋ฅผ ํตํด ์ํ๊ด๋ฆฌ์ ๋ํ ์ดํด๋๊ฐ ๋์์ง๊ณ ์์ฉํ ์ ์๋ ๊ธฐํ๊ฐ ๋์์ต๋๋ค.
๋ํ, ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ HTTP ๋น๋๊ธฐ ํต์ ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ดํด๋๊ฐ ์๊ธฐ๊ฒ ๋์์ต๋๋ค .
์ด๊ธฐ์๋ ์ค๋ฅ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ง์ฐํ๊ฒ ์ฐพ์๋ณด๊ธฐ๋ ํ์ง๋ง, ๋๋ฒ๊น
ํด์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ ํ๋ฆ์ ํ์
ํ๋ฉด์ ๋ ๋์ ์ฝ๋๋ฅผ ์ฐ๊ตฌํ๊ณ , ๊ณต๋ถํ๋ ๊ฒ์ ๋ํด ์ฆ๊ฑฐ์์ ๋๋ผ๊ฒ ๋์์ต๋๋ค.
ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ ์ด๋ ค์๋ ์์์ง๋ง, ๊ทธ๋งํผ ๋ป๊น์ ๊ฒฝํ์ด ๋์์ต๋๋ค. ์์ผ๋ก๋ ๊ฐ์ ํ ์ ๋ค์ ์ฐพ์๋ด์ด ๋ณด์ํ๊ณ , ๋์ฑ ์์ฑ๋ ๋์ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๊ณ ์ ๋
ธ๋ ฅํ๊ณ ์ถ์ต๋๋ค.
-> ์๋น์ค ๋ฐฐํฌํ ์ค์ฌ์ฉ์ ๋ํ ํผ๋๋ฐฑ์ ์ป๊ณ ์ถ์ด Okky ๋ผ๋ IT ์ปค๋ฎค๋ํฐ์ ์ฌ๋ ธ์ต๋๋ค.
-> https://okky.kr/articles/1421448
1์ฐจ ์์ 2023-04-05
-> Life-Clendar ์คํ ์์ ์๋ฃ
-> ์ด๋ฉ์ผ ์ ๊ท์ ์์ ์๋ฃ
-> ํ์๊ฐ์
์กฐ๊ฑด ์ค๋ฅ ์์ ์๋ฃ
-> input ์
๋ ฅ์ฐฝ ๊ฐ๊ฒฉ ์กฐ์ ์๋ฃ