diff --git a/.gitignore b/.gitignore index cd30345c..671e8e16 100644 --- a/.gitignore +++ b/.gitignore @@ -176,12 +176,11 @@ HELP.md .idea # application-local.yml +server/src/main/resources/application.yml server/src/main/resources/application-dev.yml -.github/workflows/server.yml - +server/src/main/resources/application-local.yml # .iml server/src/*/*.iml -# ========================================= Front ==================================================== - +# ========================================= Front ==================================================== \ No newline at end of file diff --git a/README.md b/README.md index a3157dc2..6b148e6b 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,45 @@ # ๐ŸŒณ Grow Story + ![main](https://github.com/nalsae/seb45_main_011/assets/101828759/1d9742ff-27eb-4ac2-8e59-d56bbade03d3) +

๐ŸŒฑ ์‹๋ฌผ์„ ๊ด€๋ฆฌํ•˜๊ณ  ๋‚˜๋งŒ์˜ ์ •์›์„ ๊พธ๋ฉฐ ๋ณด์„ธ์š” ๐ŸŒฑ


-> ๐Ÿค” ํ‚ค์šฐ๋Š” ์‹๋ฌผ์„ ์†์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์—†์„๊นŒ?
->
+> ๐Ÿค” ํ‚ค์šฐ๋Š” ์‹๋ฌผ์„ ์†์‰ฝ๊ณ  ์žฌ๋ฏธ์žˆ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ• ์—†์„๊นŒ?
>
> ์‹๋ฌผ์„ ์†์‰ฝ๊ฒŒ ๋“ฑ๋กํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” **์‹๋ฌผ ์นด๋“œ** ๊ธฐ๋Šฅ,
> ๋‚ด ์‹๋ฌผ์„ ์ž๋ž‘ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์‹์ง‘์‚ฌ๋“ค๊ณผ ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” **์ปค๋ฎค๋‹ˆํ‹ฐ** ๊ธฐ๋Šฅ,
-> ํ™œ๋™ํ•ด์„œ ํš๋“ํ•œ ํฌ์ธํŠธ๋กœ ๊พธ๋ฐ€ ์ˆ˜ ์žˆ๋Š” **๋‚˜๋งŒ์˜ ์ •์›** ๊ธฐ๋Šฅ๊นŒ์ง€!
->
+> ํ™œ๋™ํ•ด์„œ ํš๋“ํ•œ ํฌ์ธํŠธ๋กœ ๊พธ๋ฐ€ ์ˆ˜ ์žˆ๋Š” **๋‚˜๋งŒ์˜ ์ •์›** ๊ธฐ๋Šฅ๊นŒ์ง€!
>
> ๐ŸŒณ **Grow Story** ๐ŸŒณ์—์„œ๋Š” ์ด ๋ชจ๋“  ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜Š
------------- +---
## ๐Ÿšฉ ํ”„๋กœ์ ํŠธ ๊ฐœ์š” -* **ํ”„๋กœ์ ํŠธ ๋ช…** : Grow Story -* **์ง„ํ–‰ ๊ธฐ๊ฐ„** : 23.08.24 ~ 23.09.19 -* **์„œ๋น„์Šค URL** : [๐ŸŒณ Grow Story ๐ŸŒณ ๋ฐ”๋กœ ๊ฐ€๊ธฐ](https://growstory.vercel.app/) + +- **ํ”„๋กœ์ ํŠธ ๋ช…** : Grow Story +- **์ง„ํ–‰ ๊ธฐ๊ฐ„** : 23.08.24 ~ 23.09.19 +- **์„œ๋น„์Šค URL** : [๐ŸŒณ Grow Story ๐ŸŒณ ๋ฐ”๋กœ ๊ฐ€๊ธฐ](https://grow-story.vercel.app/)
## ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ ํŒ€์› ์†Œ๊ฐœ -| ๊น€๋ฏผ์„ | ์‹ฌ๋„์—ฐ | ์ตœํ•œ๋นˆ | ํ™ฉ๋„๊ฒฝ | ๊น€๋„ํ˜• | ์ด์Šนํƒœ | -| :---: | :---: | :---: | :---: | :---: | :---: | + +| ๊น€๋ฏผ์„ | ์‹ฌ๋„์—ฐ | ์ตœํ•œ๋นˆ | ํ™ฉ๋„๊ฒฝ | ๊น€๋„ํ˜• | ์ด์Šนํƒœ | +| :-----------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------: | | ๊น€๋ฏผ์„ | ์‹ฌ๋„์—ฐ | ์ตœํ•œ๋นˆ | ํ™ฉ๋„๊ฒฝ | ๊น€๋„ํ˜• | ์ด์Šนํƒœ | -| [@nalsae](https://github.com/nalsae) | [@shimdokite](https://github.com/shimdokite) | [@hanbinchoi](https://github.com/hanbinchoi) | [@Smile:DK](https://github.com/Dokyung-Hwang) | [@dohyoungK](https://github.com/dohyoungK) | [@NtoZero](https://github.com/NtoZero) -| **FE** (๋ถ€ํŒ€์žฅ) | **FE** | **FE** | **BE** (ํŒ€์žฅ) | **BE** | **BE** | +| [@nalsae](https://github.com/nalsae) | [@shimdokite](https://github.com/shimdokite) | [@hanbinchoi](https://github.com/hanbinchoi) | [@Smile:DK](https://github.com/Dokyung-Hwang) | [@dohyoungK](https://github.com/dohyoungK) | [@NtoZero](https://github.com/NtoZero) | +| **FE** (๋ถ€ํŒ€์žฅ) | **FE** | **FE** | **BE** (ํŒ€์žฅ) | **BE** | **BE** |
## ๐Ÿ”ง ๊ธฐ์ˆ  ์Šคํƒ + ![Web App Reference Architecture (1)](https://github.com/nalsae/seb45_main_011/assets/101828759/86f50a74-2e0c-4a5d-8865-45e95f595593)
@@ -50,46 +53,44 @@ #### [๐Ÿ“Œ API ๋ช…์„ธ์„œ](https://documenter.getpostman.com/view/27565928/2s9Y5YS34h) #### [๐Ÿ“Œ ERD](https://www.figma.com/file/yL1b8KClwZHoBXDcCp4wei/GrowStroy?type=design&node-id=1-8&mode=design) - ![ERD GrowStory_final](https://github.com/nalsae/seb45_main_011/assets/101828759/35b133c5-790e-48cf-be56-8eb2f4c54522) +![ERD GrowStory_final](https://github.com/nalsae/seb45_main_011/assets/101828759/35b133c5-790e-48cf-be56-8eb2f4c54522)
## ๐ŸŽค ๊ธฐ์ˆ  ๋ฐœํ‘œ -#### [๐ŸŽž ๋ฐœํ‘œ ์˜์ƒ ๋ฐ”๋กœ ๊ฐ€๊ธฐ](https://www.youtube.com/watch?v=GHia0UGUqTw) +#### [๐ŸŽž ๋ฐœํ‘œ ์˜์ƒ ๋ฐ”๋กœ ๊ฐ€๊ธฐ](https://www.youtube.com/watch?v=GHia0UGUqTw)
## ๐Ÿ“œ ์„œ๋น„์Šค ๋งค๋‰ด์–ผ -#### [๐Ÿ“ฅ ์„œ๋น„์Šค ๋งค๋‰ด์–ผ ๋‹ค์šด๋กœ๋“œ](https://github.com/codestates-seb/seb45_main_011/files/12667869/Grow.Story.pdf) - +#### [๐Ÿ“ฅ ์„œ๋น„์Šค ๋งค๋‰ด์–ผ ๋‹ค์šด๋กœ๋“œ](https://github.com/nalsae/seb45_main_011/files/12662276/Grow.Story.pdf)
## ๐Ÿ–ฅ ๊ตฌํ˜„ ์ด๋ฏธ์ง€ -| ํŽ˜์ด์ง€ (๊ธฐ๋Šฅ) | ์ด๋ฏธ์ง€ | -| ---------------------- | -------------------------------------------------------------------------------------- | -| ๋ฉ”์ธ | ![๋ฉ”์ธ ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/7e293d8a-9934-4aa8-b3af-e6ccd7aa112b)| -| ๋กœ๊ทธ์ธ | ![๋กœ๊ทธ์ธ ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/7b393893-9c3b-45a3-aa21-748f46b8b522)| -| ํšŒ์› ๊ฐ€์ž… | ![ํšŒ์› ๊ฐ€์ž… ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/9b6db6ec-0e98-4267-a172-c2adf29a9fb9) | -| ์ •์› (๊พธ๋ฏธ๊ธฐ) |![์ •์› ํŽ˜์ด์ง€ - ๊พธ๋ฏธ๊ธฐ](https://github.com/nalsae/seb45_main_011/assets/101828759/de3caba6-42f5-4708-ad9c-8bd2e50a4231)| -| ์ •์› (์žฅ์‹ํ’ˆ ๊ตฌ๋งค) | ![์ •์› ํŽ˜์ด์ง€ - ๊ตฌ๋งค](https://github.com/nalsae/seb45_main_011/assets/101828759/49c9acf3-b06d-44e9-9a16-208f8a022b63) | -| ์ •์› (์‹๋ฌผ ์นด๋“œ ์—ฐ๋™) | ![์ •์› ํŽ˜์ด์ง€ - ์‹๋ฌผ ์นด๋“œ ์—ฐ๋™](https://github.com/nalsae/seb45_main_011/assets/101828759/ef6da970-f632-45b8-b0f9-eb737d5b9903) | -| ์‹๋ฌผ ์นด๋“œ ๋ชฉ๋ก, ๋“ฑ๋ก | ![์‹๋ฌผ์นด๋“œ ๋ชฉ๋ก](https://github.com/nalsae/seb45_main_011/assets/101828759/a7f05c66-9a9b-4ff0-a32d-08599fb4dd9a) | -| ์‹๋ฌผ ์นด๋“œ ์ƒ์„ธ | ![์‹๋ฌผ ์นด๋“œ ์ƒ์„ธ](https://github.com/nalsae/seb45_main_011/assets/101828759/38ab89f9-ec9c-4410-aeb9-83e9cd09ca7e) | -| ์‹๋ฌผ ์นด๋“œ ์ˆ˜์ •, ์‚ญ์ œ | ![์‹๋ฌผ ์นด๋“œ ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/6fe42722-8676-4eee-bd00-27bc16c9c9f0)| -| ์ปค๋ฎค๋‹ˆํ‹ฐ | ![์ปค๋ฎค๋‹ˆํ‹ฐ](https://github.com/nalsae/seb45_main_011/assets/101828759/a27f3bfd-3346-4070-a6b8-082b5708f73a) | -| ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ | ![๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ](https://github.com/nalsae/seb45_main_011/assets/101828759/128584db-95cd-4edf-9161-74962f67d645) | -| ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก | ![๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก](https://github.com/nalsae/seb45_main_011/assets/101828759/211bd724-984e-45b8-989a-4c59246dbec2) | -| ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •, ์‚ญ์ œ | ![๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/1ea79b6f-2717-406b-89f4-adbdfcaa785e) | -| ๋Œ“๊ธ€ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ | ![๋Œ“๊ธ€ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/52ccd8f0-5e30-4198-bfc9-2dca9b28b870)| -| ์ •๋ณด ์ˆ˜์ • | ![์ •๋ณด ์ˆ˜์ •](https://github.com/nalsae/seb45_main_011/assets/101828759/a74749c1-d239-48cc-ac55-f6eda46ff228) | -| ๋‚ด ๊ฒŒ์‹œ๊ธ€ | ![๋‚ด ๊ฒŒ์‹œ๊ธ€](https://github.com/nalsae/seb45_main_011/assets/101828759/9d05dd7d-0cd3-4f86-b0b8-43b5438ba724) | -| ํšŒ์› ํƒˆํ‡ด | ![ํšŒ์› ํƒˆํ‡ด](https://github.com/nalsae/seb45_main_011/assets/101828759/120777f3-9c77-4681-bd3c-78cd5204c90e) | - +| ํŽ˜์ด์ง€ (๊ธฐ๋Šฅ) | ์ด๋ฏธ์ง€ | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| ๋ฉ”์ธ | ![๋ฉ”์ธ ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/7e293d8a-9934-4aa8-b3af-e6ccd7aa112b) | +| ๋กœ๊ทธ์ธ | ![๋กœ๊ทธ์ธ ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/7b393893-9c3b-45a3-aa21-748f46b8b522) | +| ํšŒ์› ๊ฐ€์ž… | ![ํšŒ์› ๊ฐ€์ž… ํŽ˜์ด์ง€](https://github.com/nalsae/seb45_main_011/assets/101828759/9b6db6ec-0e98-4267-a172-c2adf29a9fb9) | +| ์ •์› (๊พธ๋ฏธ๊ธฐ) | ![์ •์› ํŽ˜์ด์ง€ - ๊พธ๋ฏธ๊ธฐ](https://github.com/nalsae/seb45_main_011/assets/101828759/de3caba6-42f5-4708-ad9c-8bd2e50a4231) | +| ์ •์› (์žฅ์‹ํ’ˆ ๊ตฌ๋งค) | ![์ •์› ํŽ˜์ด์ง€ - ๊ตฌ๋งค](https://github.com/nalsae/seb45_main_011/assets/101828759/49c9acf3-b06d-44e9-9a16-208f8a022b63) | +| ์ •์› (์‹๋ฌผ ์นด๋“œ ์—ฐ๋™) | ![์ •์› ํŽ˜์ด์ง€ - ์‹๋ฌผ ์นด๋“œ ์—ฐ๋™](https://github.com/nalsae/seb45_main_011/assets/101828759/ef6da970-f632-45b8-b0f9-eb737d5b9903) | +| ์‹๋ฌผ ์นด๋“œ ๋ชฉ๋ก, ๋“ฑ๋ก | ![์‹๋ฌผ์นด๋“œ ๋ชฉ๋ก](https://github.com/nalsae/seb45_main_011/assets/101828759/a7f05c66-9a9b-4ff0-a32d-08599fb4dd9a) | +| ์‹๋ฌผ ์นด๋“œ ์ƒ์„ธ | ![์‹๋ฌผ ์นด๋“œ ์ƒ์„ธ](https://github.com/nalsae/seb45_main_011/assets/101828759/38ab89f9-ec9c-4410-aeb9-83e9cd09ca7e) | +| ์‹๋ฌผ ์นด๋“œ ์ˆ˜์ •, ์‚ญ์ œ | ![์‹๋ฌผ ์นด๋“œ ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/6fe42722-8676-4eee-bd00-27bc16c9c9f0) | +| ์ปค๋ฎค๋‹ˆํ‹ฐ | ![์ปค๋ฎค๋‹ˆํ‹ฐ](https://github.com/nalsae/seb45_main_011/assets/101828759/a27f3bfd-3346-4070-a6b8-082b5708f73a) | +| ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ | ![๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ](https://github.com/nalsae/seb45_main_011/assets/101828759/128584db-95cd-4edf-9161-74962f67d645) | +| ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก | ![๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก](https://github.com/nalsae/seb45_main_011/assets/101828759/211bd724-984e-45b8-989a-4c59246dbec2) | +| ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •, ์‚ญ์ œ | ![๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/1ea79b6f-2717-406b-89f4-adbdfcaa785e) | +| ๋Œ“๊ธ€ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ | ![๋Œ“๊ธ€ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ](https://github.com/nalsae/seb45_main_011/assets/101828759/52ccd8f0-5e30-4198-bfc9-2dca9b28b870) | +| ์ •๋ณด ์ˆ˜์ • | ![์ •๋ณด ์ˆ˜์ •](https://github.com/nalsae/seb45_main_011/assets/101828759/a74749c1-d239-48cc-ac55-f6eda46ff228) | +| ๋‚ด ๊ฒŒ์‹œ๊ธ€ | ![๋‚ด ๊ฒŒ์‹œ๊ธ€](https://github.com/nalsae/seb45_main_011/assets/101828759/9d05dd7d-0cd3-4f86-b0b8-43b5438ba724) | +| ํšŒ์› ํƒˆํ‡ด | ![ํšŒ์› ํƒˆํ‡ด](https://github.com/nalsae/seb45_main_011/assets/101828759/120777f3-9c77-4681-bd3c-78cd5204c90e) |
@@ -107,15 +108,16 @@ [FE/BE] โœจ OOO ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ ``` - 2. ๋‚ด์šฉ +2. ๋‚ด์šฉ + ## Abstracts * ๊ฐ„๋žตํ•˜๊ฒŒ ํ•  ์ผ์— ๋Œ€ํ•œ ์„ค๋ช…์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. - + ## To Do - [ ] ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ 1 - [ ] ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ 2 - + ## ETC * ์ถ”๊ฐ€์ ์ธ ์•ˆ๋‚ด ์‚ฌํ•ญ์ด ์žˆ๋‹ค๋ฉด ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. @@ -124,45 +126,48 @@

๐Ÿ“Œ Commit

- - ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ - - 1. ์ ์ ˆํ•œ ์ปค๋ฐ‹ ์ ‘๋‘์‚ฌ ์ž‘์„ฑ - 2. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๋‚ด์šฉ ์ž‘์„ฑ - 3. ๋‚ด์šฉ ๋’ค์— ์ด์Šˆ (#์ด์Šˆ ๋ฒˆํ˜ธ)์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜์—ฌ ์ด์Šˆ ์—ฐ๊ฒฐ +- ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ + +1. ์ ์ ˆํ•œ ์ปค๋ฐ‹ ์ ‘๋‘์‚ฌ ์ž‘์„ฑ +2. ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ๋‚ด์šฉ ์ž‘์„ฑ +3. ๋‚ด์šฉ ๋’ค์— ์ด์Šˆ (#์ด์Šˆ ๋ฒˆํ˜ธ)์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜์—ฌ ์ด์Šˆ ์—ฐ๊ฒฐ + [FE/BE] ๐Ÿ”ง Conf: ์ดˆ๊ธฐ ํ™˜๊ฒฝ ์„ค์ • (#1) - | ์ ‘๋‘์‚ฌ | ์„ค๋ช… | - | --- | --- | - | โœจ Feat : | ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๊ตฌํ˜„ | - | ๐Ÿฑ Add : | ์—์…‹ ํŒŒ์ผ ์ถ”๊ฐ€ | - | ๐Ÿ› Fix : | ๋ฒ„๊ทธ ์ˆ˜์ • | - | ๐Ÿ“ Docs : | ๋ฌธ์„œ ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ • | - | ๐Ÿ’„ Style : | ์Šคํƒ€์ผ๋ง ์ž‘์—… | - | โ™ป๏ธ Refactor : | ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง (๋™์ž‘ ๋ณ€๊ฒฝ ์—†์Œ) | - | ๐Ÿงช Test : | ํ…Œ์ŠคํŠธ | - | ๐Ÿš€ Deploy : | ๋ฐฐํฌ | - | ๐Ÿ”ง Conf : | ๋นŒ๋“œ, ํ™˜๊ฒฝ ์„ค์ • | - | โœ๏ธ Chore : | ๊ธฐํƒ€ ์ž‘์—… | +| ์ ‘๋‘์‚ฌ | ์„ค๋ช… | +| ------------- | ------------------------------ | +| โœจ Feat : | ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๊ตฌํ˜„ | +| ๐Ÿฑ Add : | ์—์…‹ ํŒŒ์ผ ์ถ”๊ฐ€ | +| ๐Ÿ› Fix : | ๋ฒ„๊ทธ ์ˆ˜์ • | +| ๐Ÿ“ Docs : | ๋ฌธ์„œ ์ถ”๊ฐ€ ๋ฐ ์ˆ˜์ • | +| ๐Ÿ’„ Style : | ์Šคํƒ€์ผ๋ง ์ž‘์—… | +| โ™ป๏ธ Refactor : | ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง (๋™์ž‘ ๋ณ€๊ฒฝ ์—†์Œ) | +| ๐Ÿงช Test : | ํ…Œ์ŠคํŠธ | +| ๐Ÿš€ Deploy : | ๋ฐฐํฌ | +| ๐Ÿ”ง Conf : | ๋นŒ๋“œ, ํ™˜๊ฒฝ ์„ค์ • | +| โœ๏ธ Chore : | ๊ธฐํƒ€ ์ž‘์—… |

๐Ÿ“Œ Pull Request

- 1. ์ œ๋ชฉ - - ์ž‘์—… ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์— ์‚ฌ์šฉํ•˜๋Š” Gitmoji๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑ - - ์ž์‹ ์ด ์ž‘์—…ํ•œ ๋‚ด์šฉ์„ ํ•œ ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ ์‰ฝ๋„๋ก ๋ช…์‚ฌํ˜•์œผ๋กœ ์ž‘์„ฑ - +1. ์ œ๋ชฉ + +- ์ž‘์—… ๋‚ด์šฉ์— ๋”ฐ๋ผ ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€์— ์‚ฌ์šฉํ•˜๋Š” Gitmoji๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑ +- ์ž์‹ ์ด ์ž‘์—…ํ•œ ๋‚ด์šฉ์„ ํ•œ ๋ˆˆ์— ํŒŒ์•…ํ•˜๊ธฐ ์‰ฝ๋„๋ก ๋ช…์‚ฌํ˜•์œผ๋กœ ์ž‘์„ฑ + ``` [FE/BE] โœจ OOO ์ปดํฌ๋„ŒํŠธ ๊ตฌํ˜„ ``` - 2. ๋‚ด์šฉ +2. ๋‚ด์šฉ + ## Title * ์ œ๋ชฉ์€ 'โœจ ํ™ˆ ํŽ˜์ด์ง€ ๊ตฌํ˜„'๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. - + ## PR Type - [ ] FEAT: ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ๊ตฌํ˜„ - [ ] ADD : ์—์…‹ ํŒŒ์ผ ์ถ”๊ฐ€ @@ -174,17 +179,17 @@ - [ ] DEPLOY: ๋ฐฐํฌ ๊ด€๋ จ - [ ] CONF: ๋นŒ๋“œ, ํ™˜๊ฒฝ ์„ค์ • - [ ] CHORE: ๊ธฐํƒ€ ์ž‘์—… - + ## Abstracts * ์ž‘์—… ๋‚ด์šฉ์— ๋Œ€ํ•ด ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. - + ## Description * ๊ตฌ์ฒด์ ์ธ ์ž‘์—… ๋‚ด์šฉ์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. * ์ด๋ฏธ์ง€๋ฅผ ๋ณ„๋„๋กœ ์ฒจ๋ถ€ํ•˜๋ฉด ๋” ์ข‹์Šต๋‹ˆ๋‹ค ๐Ÿ‘ - + ## Discussion * ์ถ”ํ›„ ๋…ผ์˜ํ•  ์ ์— ๋Œ€ํ•ด ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. - + --- Close #1 (์ž‘์„ฑํ•œ Issue๋ฅผ ์—ฐ๊ฒฐํ•ด์ฃผ์„ธ์š”.) diff --git a/client/package-lock.json b/client/package-lock.json index a036adeb..e14694e7 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@hookform/error-message": "^2.0.1", "@material-tailwind/react": "^2.1.1", + "@stomp/stompjs": "^7.0.0", "@tanstack/react-query": "^4.33.0", "@types/axios": "^0.14.0", "@types/node": "20.5.7", @@ -27,6 +28,7 @@ "react-hook-form": "^7.45.4", "react-infinite-scroller": "^1.2.6", "react-uuid": "^2.0.0", + "sockjs-client": "^1.6.1", "tailwind-merge": "^1.14.0", "tailwindcss": "3.3.3", "typescript": "5.2.2", @@ -34,6 +36,7 @@ }, "devDependencies": { "@types/lodash": "^4.14.197", + "@types/sockjs-client": "^1.5.4", "@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/parser": "^6.5.0", "eslint": "^8.48.0", @@ -580,6 +583,11 @@ "node": "^12.20.0 || ^14.18.0 || >=16.0.0" } }, + "node_modules/@stomp/stompjs": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/@stomp/stompjs/-/stompjs-7.0.0.tgz", + "integrity": "sha512-fGdq4wPDnSV/KyOsjq4P+zLc8MFWC3lMmP5FBgLWKPJTYcuCbAIrnRGjB7q2jHZdYCOD5vxLuFoKIYLy5/u8Pw==" + }, "node_modules/@swc/helpers": { "version": "0.5.1", "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.1.tgz", @@ -689,6 +697,12 @@ "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", "dev": true }, + "node_modules/@types/sockjs-client": { + "version": "1.5.4", + "resolved": "https://registry.npmmirror.com/@types/sockjs-client/-/sockjs-client-1.5.4.tgz", + "integrity": "sha512-zk+uFZeWyvJ5ZFkLIwoGA/DfJ+pYzcZ8eH4H/EILCm2OBZyHH6Hkdna1/UWL/CFruh5wj6ES7g75SvUB0VsH5w==", + "dev": true + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz", @@ -2125,6 +2139,14 @@ "node": ">=0.10.0" } }, + "node_modules/eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/execa/-/execa-7.2.0.tgz", @@ -2203,6 +2225,17 @@ "reusify": "^1.0.4" } }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2568,6 +2601,11 @@ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmmirror.com/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, "node_modules/human-signals": { "version": "4.3.1", "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz", @@ -3223,8 +3261,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/mz": { "version": "2.7.0", @@ -3803,6 +3840,11 @@ "node": ">=6" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -3920,6 +3962,11 @@ "node": ">= 0.4" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "node_modules/resolve": { "version": "1.22.4", "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.4.tgz", @@ -4078,6 +4125,11 @@ "node": ">=0.4" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -4159,6 +4211,29 @@ "node": ">=8" } }, + "node_modules/sockjs-client": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/sockjs-client/-/sockjs-client-1.6.1.tgz", + "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==", + "dependencies": { + "debug": "^3.2.7", + "eventsource": "^2.0.2", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4630,6 +4705,15 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -4655,6 +4739,27 @@ "node": ">=10.13.0" } }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", @@ -4820,7 +4925,8 @@ "version": "3.0.0", "resolved": "https://registry.npmmirror.com/@csstools/selector-specificity/-/selector-specificity-3.0.0.tgz", "integrity": "sha512-hBI9tfBtuPIi885ZsZ32IMEU/5nlZH/KOVYJCOh7gyMxaVLGmLedYqFN6Ui1LXkI8JlC8IsuC0rF0btcRZKd5g==", - "dev": true + "dev": true, + "requires": {} }, "@emotion/is-prop-valid": { "version": "0.8.8", @@ -4918,7 +5024,8 @@ "@hookform/error-message": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.1.tgz", - "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==" + "integrity": "sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg==", + "requires": {} }, "@humanwhocodes/config-array": { "version": "0.11.11", @@ -5168,6 +5275,11 @@ "tslib": "^2.6.0" } }, + "@stomp/stompjs": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/@stomp/stompjs/-/stompjs-7.0.0.tgz", + "integrity": "sha512-fGdq4wPDnSV/KyOsjq4P+zLc8MFWC3lMmP5FBgLWKPJTYcuCbAIrnRGjB7q2jHZdYCOD5vxLuFoKIYLy5/u8Pw==" + }, "@swc/helpers": { "version": "0.5.1", "resolved": "https://registry.npmmirror.com/@swc/helpers/-/helpers-0.5.1.tgz", @@ -5263,6 +5375,12 @@ "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", "dev": true }, + "@types/sockjs-client": { + "version": "1.5.4", + "resolved": "https://registry.npmmirror.com/@types/sockjs-client/-/sockjs-client-1.5.4.tgz", + "integrity": "sha512-zk+uFZeWyvJ5ZFkLIwoGA/DfJ+pYzcZ8eH4H/EILCm2OBZyHH6Hkdna1/UWL/CFruh5wj6ES7g75SvUB0VsH5w==", + "dev": true + }, "@typescript-eslint/eslint-plugin": { "version": "6.5.0", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz", @@ -5373,7 +5491,8 @@ "version": "5.3.2", "resolved": "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv": { "version": "6.12.6", @@ -6116,7 +6235,8 @@ "version": "9.0.0", "resolved": "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.9", @@ -6309,7 +6429,8 @@ "version": "4.6.0", "resolved": "https://registry.npmmirror.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", - "dev": true + "dev": true, + "requires": {} }, "eslint-scope": { "version": "7.2.2", @@ -6368,6 +6489,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "eventsource": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/eventsource/-/eventsource-2.0.2.tgz", + "integrity": "sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==" + }, "execa": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/execa/-/execa-7.2.0.tgz", @@ -6439,6 +6565,14 @@ "reusify": "^1.0.4" } }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "requires": { + "websocket-driver": ">=0.5.1" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -6719,6 +6853,11 @@ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmmirror.com/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==" + }, "human-signals": { "version": "4.3.1", "resolved": "https://registry.npmmirror.com/human-signals/-/human-signals-4.3.1.tgz", @@ -7244,8 +7383,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mz": { "version": "2.7.0", @@ -7665,6 +7803,11 @@ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7690,7 +7833,8 @@ "react-hook-form": { "version": "7.45.4", "resolved": "https://registry.npmmirror.com/react-hook-form/-/react-hook-form-7.45.4.tgz", - "integrity": "sha512-HGDV1JOOBPZj10LB3+OZgfDBTn+IeEsNOKiq/cxbQAIbKaiJUe/KV8DBUzsx0Gx/7IG/orWqRRm736JwOfUSWQ==" + "integrity": "sha512-HGDV1JOOBPZj10LB3+OZgfDBTn+IeEsNOKiq/cxbQAIbKaiJUe/KV8DBUzsx0Gx/7IG/orWqRRm736JwOfUSWQ==", + "requires": {} }, "react-infinite-scroller": { "version": "1.2.6", @@ -7757,6 +7901,11 @@ "functions-have-names": "^1.2.3" } }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, "resolve": { "version": "1.22.4", "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.4.tgz", @@ -7877,6 +8026,11 @@ "isarray": "^2.0.5" } }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, "safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -7943,6 +8097,28 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "sockjs-client": { + "version": "1.6.1", + "resolved": "https://registry.npmmirror.com/sockjs-client/-/sockjs-client-1.6.1.tgz", + "integrity": "sha512-2g0tjOR+fRs0amxENLi/q5TiJTqY+WXFOzb5UwXndlK6TO3U/mirZznpx6w34HVMoc3g7cY24yC/ZMIYnDlfkw==", + "requires": { + "debug": "^3.2.7", + "eventsource": "^2.0.2", + "faye-websocket": "^0.11.4", + "inherits": "^2.0.4", + "url-parse": "^1.5.10" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmmirror.com/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + } + } + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz", @@ -8178,7 +8354,8 @@ "version": "1.0.2", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-1.0.2.tgz", "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", - "dev": true + "dev": true, + "requires": {} }, "ts-interface-checker": { "version": "0.1.13", @@ -8305,10 +8482,20 @@ "punycode": "^2.1.0" } }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==" + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "requires": {} }, "util-deprecate": { "version": "1.0.2", @@ -8324,6 +8511,21 @@ "graceful-fs": "^4.1.2" } }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmmirror.com/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmmirror.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", diff --git a/client/package.json b/client/package.json index ab6c1deb..20749600 100644 --- a/client/package.json +++ b/client/package.json @@ -11,6 +11,7 @@ "dependencies": { "@hookform/error-message": "^2.0.1", "@material-tailwind/react": "^2.1.1", + "@stomp/stompjs": "^7.0.0", "@tanstack/react-query": "^4.33.0", "@types/axios": "^0.14.0", "@types/node": "20.5.7", @@ -28,6 +29,7 @@ "react-hook-form": "^7.45.4", "react-infinite-scroller": "^1.2.6", "react-uuid": "^2.0.0", + "sockjs-client": "^1.6.1", "tailwind-merge": "^1.14.0", "tailwindcss": "3.3.3", "typescript": "5.2.2", @@ -35,6 +37,7 @@ }, "devDependencies": { "@types/lodash": "^4.14.197", + "@types/sockjs-client": "^1.5.4", "@typescript-eslint/eslint-plugin": "^6.5.0", "@typescript-eslint/parser": "^6.5.0", "eslint": "^8.48.0", diff --git a/client/public/assets/icon/notification.svg b/client/public/assets/icon/notification.svg new file mode 100644 index 00000000..b97a466b --- /dev/null +++ b/client/public/assets/icon/notification.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/public/assets/icon/qna.svg b/client/public/assets/icon/qna.svg new file mode 100644 index 00000000..66d21946 --- /dev/null +++ b/client/public/assets/icon/qna.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/api/axios.ts b/client/src/api/axios.ts new file mode 100644 index 00000000..6f47a13f --- /dev/null +++ b/client/src/api/axios.ts @@ -0,0 +1,80 @@ +import axios, { AxiosResponse } from 'axios'; + +import LocalStorage from './localStorage'; + +import checkForToken from '@/utils/checkForToken'; + +const token = LocalStorage.getItem('user-key'); + +const { authVerify, storageData } = checkForToken(); + +const accessToken = + typeof window !== 'undefined' ? token.state.accessToken : null; +const refreshToken = + typeof window !== 'undefined' ? token.state.refreshToken : null; + +export const instance = axios.create({ + baseURL: process.env.NEXT_PUBLIC_API_URL, + headers: { + Authorization: accessToken, + Refresh: refreshToken, + }, + withCredentials: true, +}); + +export const chatInstance = axios.create({ + baseURL: process.env.NEXT_PUBLIC_API_URL, + headers: { + Authorization: accessToken, + Refresh: refreshToken, + }, + withCredentials: true, +}); + +const onFulfiled = async (response: AxiosResponse) => { + if (authVerify() === 'Refresh Token Expired') { + return ( + alert('ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด ์ฃผ์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.'), + localStorage.clear(), + (window.location.href = '/signin'), + Promise.reject('Refresh Token Expired') + ); + } + + if ( + authVerify() === 'Access Token Expired' && + authVerify() !== 'Refresh Token Expired' + ) { + const { authorization: newAccessToken } = response?.headers; + + storageData.state.accessToken = newAccessToken; + + LocalStorage.setItem('user-key', JSON.stringify(storageData)); + + response.config.headers = Object.assign({}, response.config.headers, { + authorization: `${newAccessToken}`, + refresh: refreshToken ?? '', + }); + + return await axios(response.config); + } + + return response; +}; + +instance.interceptors.request.use( + async (config) => { + config.headers = config.headers ?? {}; + + if (accessToken) { + config.headers.Authorization = `${accessToken}`; + } + + return config; + }, + (error) => Promise.reject(error), +); + +instance.interceptors.response.use(onFulfiled, (error) => { + return Promise.reject(error); +}); diff --git a/client/src/api/board.ts b/client/src/api/board.ts index b94667f0..26863975 100644 --- a/client/src/api/board.ts +++ b/client/src/api/board.ts @@ -19,7 +19,6 @@ export const commonAxios = axios.create({ withCredentials: true, }); -/** ํŽ˜์ด์ง€๋ฅผ query๋กœ ๋ณด๋‚ด ๊ฒŒ์‹œ๋ฌผ ์กฐํšŒ */ export async function getBoardsByPageNum({ pageParam = 1 }) { const res = await commonAxios .get(`/boards?page=${pageParam}`) @@ -32,7 +31,6 @@ export async function getBoardsByPageNum({ pageParam = 1 }) { }; } -/** ๊ฒ€์ƒ‰์–ด๋ฅผ query๋กœ ๋ณด๋‚ด ๊ฒ€์ƒ‰์–ด๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ */ export async function getBoardsBySearch({ pageParam, search, @@ -53,7 +51,6 @@ export async function getBoardsBySearch({ }; } -/** ๊ฒ€์ƒ‰์–ด๋ฅผ query๋กœ ๋ณด๋‚ด ๊ฒ€์ƒ‰์–ด๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ */ export async function getPostByBoardId(boardId: string) { const res = await commonAxios .get(`/boards/${boardId}`) @@ -61,26 +58,22 @@ export async function getPostByBoardId(boardId: string) { return res.data; } -/** boardId์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€์— ๋Œ“๊ธ€ ๋“ฑ๋ก */ export async function addComment(content: string, boardId: string) { return commonAxios.post(`comments/boards/${boardId}`, { content, }); } -/** commentId์— ํ•ด๋‹นํ•˜๋Š” ๋Œ“๊ธ€ ์‚ญ์ œ */ export async function deleteComment(commentId: string) { return commonAxios.delete(`comments/${commentId}`); } -/** commentId์— ํ•ด๋‹นํ•˜๋Š” ๋Œ“๊ธ€ ์‚ญ์ œ */ export async function editComment(commentId: string, content: string) { return commonAxios.patch(`comments/${commentId}`, { content, }); } -/** boardId์— ํ•ด๋‹นํ•˜๋Š” ๊ฒŒ์‹œ๊ธ€์— ๋Œ“๊ธ€ ๋“ฑ๋ก */ export async function likeBoard(boardId: string) { return commonAxios.post(`likes/boards/${boardId}`); } diff --git a/client/src/api/chat.ts b/client/src/api/chat.ts new file mode 100644 index 00000000..0b6da2c9 --- /dev/null +++ b/client/src/api/chat.ts @@ -0,0 +1,55 @@ +import { chatInstance } from './axios'; + +const reviewerId = 101; + +export const postCreateChatRoom = async ( + questionerId: number, + qnaTitle: string, +) => { + const response = await chatInstance.post(`/chat-rooms`, { + questionerId, + reviewerId, + qnaTitle, + }); + + return response; +}; + +export const getChatListById = async ({ pageParam = 0 }, id: string) => { + const response = await chatInstance + .get(`/chat-rooms/${id}?page=${pageParam}`) + .then((response) => response.data); + + return { chatList: response.data, pageInfo: response }; +}; + +export const getChatMessageById = async ({ pageParam = 0 }, id: string) => { + const response = await chatInstance + .get(`/chat-messages/${id}?page=${pageParam}`) + .then((response) => response.data); + + return { previousMessage: response.data, pageInfo: response }; +}; + +export const patchChatAnsweredById = async (chatRoomId: string) => { + const response = await chatInstance.patch(`/chat-rooms/qna-answer-renewal`, { + chatRoomId, + senderId: reviewerId, + }); + + return response; +}; + +export const sendAnsweredById = async ( + chatRoomId: string, + questionerId: string, + mailSubject: string, +) => { + const response = await chatInstance.post(`/emails/qna-answer`, { + chatRoomId, + questionerId, + mailSubject, + }); + + return response; +}; diff --git a/client/src/api/garden.ts b/client/src/api/garden.ts index 5308f673..5bb95cc7 100644 --- a/client/src/api/garden.ts +++ b/client/src/api/garden.ts @@ -69,3 +69,25 @@ export const connectLeaf = async ( return data; }; + +export const findGuestbookById = async (userId: string) => { + const { data } = await gardenAxios + .get(`/guestbooks/${userId}`) + .then((res) => res.data); + + return data; +}; + +export const addGuestbook = async (userId: string, content: string) => { + return await gardenAxios.post(`/guestbooks/${userId}`, { content }); +}; + +export const editGuestbook = async (guestbookId: string, content: string) => { + return await gardenAxios.patch(`/guestbooks/${guestbookId}`, { + content, + }); +}; + +export const deleteGuestbook = async (guestbookId: string) => { + return await gardenAxios.delete(`/guestbooks/${guestbookId}`); +}; diff --git a/client/src/api/guest.ts b/client/src/api/guest.ts new file mode 100644 index 00000000..5e125158 --- /dev/null +++ b/client/src/api/guest.ts @@ -0,0 +1,17 @@ +import axios from 'axios'; + +import { instance } from './axios'; + +const url = process.env.NEXT_PUBLIC_API_URL; + +export const postCreateGuest = async () => { + const response = await axios.post(`${url}/accounts/guest`); + + return response; +}; + +export const deleteGuestMode = async () => { + const response = await instance.delete(`${url}/accounts`); + + return response; +}; diff --git a/client/src/api/history.ts b/client/src/api/history.ts index 9232bfcf..a3f14fcc 100644 --- a/client/src/api/history.ts +++ b/client/src/api/history.ts @@ -1,32 +1,13 @@ -import axios from 'axios'; - -const accessToken = - typeof window !== 'undefined' - ? JSON.parse(localStorage.getItem('user-key') as string).state.accessToken - : null; - -const refreshToken = - typeof window !== 'undefined' - ? JSON.parse(localStorage.getItem('user-key') as string).state.refreshToken - : null; - -export const historyAxios = axios.create({ - baseURL: process.env.NEXT_PUBLIC_API_URL, - headers: { - Authorization: accessToken, - Refresh: refreshToken, - }, - withCredentials: true, -}); +import { instance } from './axios'; export const getUserInfo = async (id: string) => { - const { data } = await historyAxios.get(`/accounts/${id}`); + const { data } = await instance.get(`/accounts/${id}`); return data; }; export const postUserPassword = async (password: string) => { - const { data, headers } = await historyAxios.post( + const { data, headers } = await instance.post( `/accounts/password/verification`, { password, @@ -37,13 +18,13 @@ export const postUserPassword = async (password: string) => { }; export const deleteUser = async () => { - const { status } = await historyAxios.delete(`/accounts`); + const { status } = await instance.delete(`/accounts`); return status; }; export const getBoardWrittenByPage = async ({ pageParam = 1 }, id: string) => { - const response = await historyAxios + const response = await instance .get(`/accounts/boardWritten/${id}?page=${pageParam}`) .then((response) => response.data); @@ -51,7 +32,7 @@ export const getBoardWrittenByPage = async ({ pageParam = 1 }, id: string) => { }; export const getBoardLikedByPage = async ({ pageParam = 1 }, id: string) => { - const response = await historyAxios + const response = await instance .get(`/accounts/boardLiked/${id}?page=${pageParam}`) .then((response) => response.data); @@ -62,7 +43,7 @@ export const getCommentWrittenByPage = async ( { pageParam = 1 }, id: string, ) => { - const response = await historyAxios + const response = await instance .get(`/accounts/commentWritten/${id}?page=${pageParam}`) .then((response) => response.data); diff --git a/client/src/api/leaf.ts b/client/src/api/leaf.ts index a10b18bd..138a4665 100644 --- a/client/src/api/leaf.ts +++ b/client/src/api/leaf.ts @@ -23,7 +23,6 @@ export const commonAxios = axios.create({ withCredentials: true, }); -/** ํ† ํฐ์„ ํ†ตํ•ด ์œ ์ €์˜ ์‹๋ฌผ ์นด๋“œ ์ „์ฒด ์กฐํšŒ */ export async function getLeafsByUserId(userId: string) { const { data } = await commonAxios .get(`/leaves/account/${userId}`) @@ -32,7 +31,6 @@ export async function getLeafsByUserId(userId: string) { return data; } -/** leafId๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์‹๋ฌผ ์นด๋“œ ์ƒ์„ธ ์กฐํšŒ */ export async function getLeafByLeafId(leafId: string) { const { data } = await commonAxios .get(`/leaves/${leafId}`) @@ -40,7 +38,6 @@ export async function getLeafByLeafId(leafId: string) { return data; } -/** leaf ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ ์‹๋ฌผ ์นด๋“œ ๋“ฑ๋ก */ export async function addLeaf(inputs: InputValues) { const formData = convertToFormData({ usage: 'addLeaf', inputs }); @@ -53,12 +50,10 @@ export async function addLeaf(inputs: InputValues) { .then((res) => res.data); } -/** leafId๋ฅผ ํ†ตํ•ด ์‹๋ฌผ ์นด๋“œ ์‚ญ์ œ */ export async function deleteLeaf(leafId: string) { - return await commonAxios.delete(`/leaves/${leafId}`).then((res) => res.data); + await commonAxios.delete(`/leaves/${leafId}`); } -/** leaf data๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ leafId์— ํ•ด๋‹นํ•˜๋Š” ์‹๋ฌผ ์นด๋“œ ์ˆ˜์ • */ export async function editLeaf({ inputs, leafId, @@ -84,7 +79,6 @@ export async function editLeaf({ .then((res) => res.data); } -/** leafId์— ํ•ด๋‹นํ•˜๋Š” ๋‹ค์ด์–ด๋ฆฌ ์ „์ฒด ์กฐํšŒ */ export async function getDiariesByLeafAndUserId( leafId: string, userId: string, @@ -95,7 +89,6 @@ export async function getDiariesByLeafAndUserId( return data; } -/** leafId๋ฅผ ํ†ตํ•ด ํ•ด๋‹นํ•˜๋Š” ์‹๋ฌผ ์นด๋“œ์— ์ผ์ง€ ๋“ฑ๋ก */ export async function addDiary({ leafId, inputs, @@ -114,7 +107,6 @@ export async function addDiary({ leafId, userId, }); - return await commonAxios .post(`/leaves/${leafId}/journals`, formData, { headers: { @@ -124,7 +116,6 @@ export async function addDiary({ .then((res) => res.data); } -/** diary๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ journalId์— ํ•ด๋‹นํ•˜๋Š” journal(diary) ์ˆ˜์ • */ export async function editDiary({ diaryId, inputs, @@ -137,6 +128,7 @@ export async function editDiary({ isImageUpdated?: boolean; }) { if (!diaryId) return null; + const formData = convertToFormData({ usage: 'editDiary', inputs, @@ -153,7 +145,6 @@ export async function editDiary({ .then((res) => res.data); } -// diaryId์— ํ•ด๋‹นํ•˜๋Š” diary ์‚ญ์ œ export async function deleteDiary({ diaryId, userId, @@ -161,15 +152,12 @@ export async function deleteDiary({ diaryId: string; userId: string; }) { - const request = JSON.stringify({ - accountId: userId, - }); return await commonAxios .delete(`/leaves/journals/${diaryId}`, { - data: request, headers: { 'Content-Type': 'application/json', }, + params: { 'leaf-author-id': userId }, }) .then((res) => res.data); } diff --git a/client/src/api/localStorage.ts b/client/src/api/localStorage.ts new file mode 100644 index 00000000..fe392c5d --- /dev/null +++ b/client/src/api/localStorage.ts @@ -0,0 +1,19 @@ +class LocalStorage { + constructor() {} + + static setItem(key: string, value: string) { + if (typeof window !== 'undefined') { + localStorage.setItem(key, value); + } + } + + static getItem(key: string) { + if (typeof window !== 'undefined') { + return JSON.parse(localStorage.getItem(key) || ''); + } + + return null; + } +} + +export default LocalStorage; diff --git a/client/src/api/notification.ts b/client/src/api/notification.ts new file mode 100644 index 00000000..d84cdd51 --- /dev/null +++ b/client/src/api/notification.ts @@ -0,0 +1,44 @@ +import axios from 'axios'; + +const accessToken = + typeof window !== 'undefined' + ? JSON.parse(localStorage.getItem('user-key') as string).state.accessToken + : null; + +const refreshToken = + typeof window !== 'undefined' + ? JSON.parse(localStorage.getItem('user-key') as string).state.refreshToken + : null; + +export const commonAxios = axios.create({ + baseURL: process.env.NEXT_PUBLIC_API_URL, + headers: { + Authorization: accessToken, + Refresh: refreshToken, + }, + withCredentials: true, +}); + +export async function getNotificationsByUserId(userId: string) { + const res = await commonAxios + .get(`/alarms/${userId}`) + .then((res) => res.data); + + return res.data; +} + +export async function showNotification(userId: string) { + const res = await commonAxios + .post(`/alarms/${userId}`) + .then((res) => res.data); + + return res.data; +} + +export async function deleteNotification(notificationId: string) { + await commonAxios.delete(`/alarms/${notificationId}`); +} + +export async function deleteAllNotification(userId: string) { + await commonAxios.delete(`/alarms/all/${userId}`); +} diff --git a/client/src/api/profile.ts b/client/src/api/profile.ts index 7d1d379f..5cd02f0f 100644 --- a/client/src/api/profile.ts +++ b/client/src/api/profile.ts @@ -1,26 +1,7 @@ -import axios from 'axios'; - -const accessToken = - typeof window !== 'undefined' - ? JSON.parse(localStorage.getItem('user-key') as string).state.accessToken - : null; - -const refreshToken = - typeof window !== 'undefined' - ? JSON.parse(localStorage.getItem('user-key') as string).state.refreshToken - : null; - -export const historyAxios = axios.create({ - baseURL: process.env.NEXT_PUBLIC_API_URL, - headers: { - Authorization: accessToken, - Refresh: refreshToken, - }, - withCredentials: true, -}); +import { instance } from './axios'; export const updateUserNickname = async (displayName: string) => { - const { data, headers, status } = await historyAxios.patch( + const { data, headers, status } = await instance.patch( `/accounts/displayname`, { displayName, @@ -34,13 +15,10 @@ export const updateUserPassword = async ( presentPassword: string, changedPassword: string, ) => { - const { data, headers, status } = await historyAxios.patch( - `/accounts/password`, - { - presentPassword, - changedPassword, - }, - ); + const { data, headers, status } = await instance.patch(`/accounts/password`, { + presentPassword, + changedPassword, + }); return { data, headers, status }; }; @@ -53,15 +31,11 @@ export const updateUserProfileImage = async (file: File) => { const formData = new FormData(); formData.append('profileImage', file); - const response = await historyAxios.patch( - `/accounts/profileimage`, - formData, - { - headers: { - 'Content-Type': 'multipart/form-data', - }, + const response = await instance.patch(`/accounts/profileimage`, formData, { + headers: { + 'Content-Type': 'multipart/form-data', }, - ); + }); return response.data; }; diff --git a/client/src/app/admin/layout.tsx b/client/src/app/admin/layout.tsx new file mode 100644 index 00000000..90187b45 --- /dev/null +++ b/client/src/app/admin/layout.tsx @@ -0,0 +1,17 @@ +import { Header } from '@/components/common'; + +export default function AdminLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> +
+
+ {children} +
+ + ); +} diff --git a/client/src/app/admin/page.tsx b/client/src/app/admin/page.tsx new file mode 100644 index 00000000..ce4774d2 --- /dev/null +++ b/client/src/app/admin/page.tsx @@ -0,0 +1,9 @@ +import CheckInquiry from '@/components/admin/CheckInquiry'; + +export default function Admin() { + return ( +
+ +
+ ); +} diff --git a/client/src/app/board/page.tsx b/client/src/app/board/page.tsx index 3e5198d4..d22995e7 100644 --- a/client/src/app/board/page.tsx +++ b/client/src/app/board/page.tsx @@ -7,20 +7,26 @@ import { motion } from 'framer-motion'; import useUserStore from '@/stores/userStore'; import useBoardStore from '@/stores/boardStore'; -import CommonButton from '@/components/common/CommonButton'; -import Footer from '@/components/common/Footer'; -import BoardBanner from '@/components/board/BoardBanner'; -import BoardSearchForm from '@/components/board/BoardSearchForm'; -import RankBoard from '@/components/board/RankBoard'; -import PostList from '@/components/board/PostList'; -import SearchList from '@/components/board/SearchList'; +import useEffectOnce from '@/hooks/useEffectOnce'; + +import { + BoardBanner, + BoardSearchForm, + RankBoard, + PostList, + SearchList, +} from '@/components/board'; +import { InquiryButton } from '@/components/inquiry'; +import { CommonButton, Footer, NotificationButton } from '@/components/common'; export default function Board() { const router = useRouter(); const userId = useUserStore((state) => state.userId); - const { searchKey } = useBoardStore(); + const { searchKey, setSearchKey } = useBoardStore(); + + useEffectOnce(() => setSearchKey(null)); const navigateToAddPost = () => { if (userId !== null) return router.push('/post/add'); @@ -48,6 +54,9 @@ export default function Board() { + + +