- ์๋ฆฌ ๋ ์ํผ ๊ณต์ ๋ฐ ์๋ฆฌ ๊ด๋ จ ์ปค๋ฎค๋ํฐ ํ์ฑํ.
- ์ธ๊ณต์ง๋ฅ์ ํ์ฉํ ๋ง์ถคํ ๋ ์ํผ ์ถ์ฒ ๋ฐ ๋ณํ ๊ธฐ๋ฅ ์ ๊ณต.
- ์ฌ์ฉ์์ ์ฌ๋ฃ ๋ฐ ์ ํธ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ฐ์ธํ๋ ์๋ฆฌ ๊ฒฝํ ์ง์.
- ํ์๊ฐ์ , ๋ก๊ทธ์ธ, ํ๋กํ ๊ธฐ๋ฅ
- ์ปค๋ฎค๋ํฐ ๊ฒ์ํ ๊ธฐ๋ฅ(๋ ์ํผ ๊ฒ์ํ, Q&A ๊ฒ์ํ)
- AI ๋ง์ถค ๋ ์ํผ ๋ฐ ๋ณํ ๊ธฐ๋ฅ
- ์คํฌ๋ฉ ๊ธฐ๋ฅ
- ํฌํ ๊ธฐ๋ฅ (ex. ๊ฒ์๊ธ ์ข์์)
- ๋๊ธ ๊ธฐ๋ฅ
| ID | ์๊ตฌ์ฌํญ | ์ฐ์ ์์ | ์ค๋ช |
|---|---|---|---|
| UR-001 | ์ฌ์ฉ์๋ ํ์๊ฐ์ ๋ฐ ๋ก๊ทธ์ธ์ ํตํด ์๋น์ค๋ฅผ ์ด์ฉํ ์ ์์ด์ผ ํ๋ค. | ํ์ | ๋นํ์ ์ฌ์ฉ์๋ ์ผ๋ถ ๊ธฐ๋ฅ(์ด๋)์ ๊ฐ๋ฅํ์ง๋ง, AI ์ถ์ฒ ๋ฐ ๋ณํ, ๊ฒ์๊ธ ์์ฑ์ ํ์๋ง ๊ฐ๋ฅํ๋ค. |
| UR-002 | ์ฌ์ฉ์๋ ๋ ์ํผ ๊ฒ์ํ์์ ๋ ์ํผ๋ฅผ ๋ฑ๋ก, ์์ , ์ญ์ ํ ์ ์์ด์ผ ํ๋ค. | ํ์ | ๋ณธ์ธ์ด ์์ฑํ ๋ ์ํผ๋ง ์์ ๋ฐ ์ญ์ ๊ฐ๋ฅ. |
| UR-003 | ์ฌ์ฉ์๋ Q&A ๊ฒ์ํ์์ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ ์์ฑํ ์ ์์ด์ผ ํ๋ค. | ํ์ | ์๋ฆฌ ๊ด๋ จ ๊ถ๊ธ์ฆ ํด๊ฒฐ ๋ฐ ์ปค๋ฎค๋ํฐ ํ์ฑ์ ๋ชฉ์ ์ผ๋ก ํ๋ค. |
| UR-004 | ์ฌ์ฉ์๋ AI ๋ ์ํผ ๊ฒ์ํ์์ ์์ ์ ๋ง์ถคํ ๋ ์ํผ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ด๋ํ ์ ์์ด์ผ ํ๋ค. | ํ์ | AI๊ฐ ์ถ์ฒํ ๋ ์ํผ์ ๋ณํ๋ ๋ ์ํผ๋ฅผ ๊ฐ์ธ ๊ฒ์ํ์์ ํ์ธ. |
| UR-005 | ์ฌ์ฉ์๋ ๊ฒ์๊ธ์ ์ข์์๋ฅผ ๋๋ฅด๊ฑฐ๋ ๋๊ธ์ ์์ฑํ ์ ์์ด์ผ ํ๋ค. | ์ ํ | ๊ฒ์๊ธ์ ๋ํ ํผ๋๋ฐฑ ๋ฐ ์ํต ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-006 | ์ฌ์ฉ์๋ ๋ ์ํผ๋ฅผ ์คํฌ๋ฉํ์ฌ ๊ฐ์ธ ์ ์ฅ์์ ๋ณด๊ดํ ์ ์์ด์ผ ํ๋ค. | ์ ํ | ๊ด์ฌ ์๋ ๋ ์ํผ๋ฅผ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ ์ ์์. |
| UR-007 | ์์คํ ์ ๋ชจ๋ ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ(Q&A, ๋ ์ํผ ๊ฒ์ํ)์ ์ด๋์ ํ์/๋นํ์ ๋ชจ๋ ๊ฐ๋ฅํด์ผ ํ๋ค. | ํ์ | ์ ๊ทผ์ฑ์ ๋์ด๊ณ ์ปค๋ฎค๋ํฐ ํ์ฑํ๋ฅผ ์ง์. |
| UR-008 | ์์คํ ์ ์ฌ์ฉ์ ๋ฐ์ดํฐ์ ๊ฒ์๊ธ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ์ ์ฅ ๋ฐ ๊ด๋ฆฌํด์ผ ํ๋ค. | ํ์ | MySQL DB์ Spring Security๋ฅผ ํตํด ๋ฐ์ดํฐ ๋ณด์ ๊ฐํ. |
| ์ ์ค์ผ์ด์ค ์ด๋ฆ | ํ์๊ฐ์ |
|---|---|
| ํ์์ | ๋นํ์ |
| ๋ชฉํ | ์ฌ์ฉ์๊ฐ RecipeSpark ์๋น์ค์ ๊ฐ์ |
| ์ฌ์ ์กฐ๊ฑด | ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ ์ ์์ด์ผ ํจ. |
| ์ฌํ์กฐ๊ฑด | ๊ฐ์ ๋ ์ฌ์ฉ์ ์ ๋ณด๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋จ. |
| ์๋๋ฆฌ์ค | 1. ๋นํ์์ด ํ์๊ฐ์
ํ์ด์ง๋ฅผ ์ฐ๋ค. 2. ์ด๋ฉ์ผ, ๋น๋ฐ๋ฒํธ, ๋๋ค์์ ์ ๋ ฅํ๋ค. 3. ๊ฐ์ ๋ฒํผ์ ํด๋ฆญํ๋ค. 4. ์์คํ ์ด ์ ๋ ฅ ์ ๋ณด๋ฅผ ๊ฒ์ฆํ๊ณ ๊ฐ์ ์ฒ๋ฆฌํ๋ค. 5. ์ฑ๊ณต ์ ํ์ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๊ณ ๋ก๊ทธ์ธ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ๋๋ค. |
| ์์ธ | 1. ์ด๋ฉ์ผ์ด ์ค๋ณต๋ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. 2. ํ์ ์ ๋ ฅ ํญ๋ชฉ์ด ๋น์ด ์์ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. |
| ์ ์ค์ผ์ด์ค ์ด๋ฆ | ๋ ์ํผ ๊ฒ์ํ CRUD |
|---|---|
| ํ์์ | ๋ก๊ทธ์ธ ์ฌ์ฉ์ |
| ๋ชฉํ | ์ฌ์ฉ์๊ฐ ๋ ์ํผ๋ฅผ ๋ฑ๋ก, ์์ , ์ญ์ ํ ์ ์์. |
| ์ฌ์ ์กฐ๊ฑด | ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ํ์ฌ์ผ ํจ. |
| ์ฌํ์กฐ๊ฑด | ๊ฒ์ํ์ ๋ฑ๋ก๋ ๋ ์ํผ๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋จ. |
| ์๋๋ฆฌ์ค | 1. ์ฌ์ฉ์๊ฐ ๋ ์ํผ ๊ฒ์ํ ํ์ด์ง๋ฅผ ์ฐ๋ค. 2. ๋ ์ํผ๋ฅผ ๋ฑ๋กํ๊ฑฐ๋ ๊ธฐ์กด ๋ ์ํผ๋ฅผ ์์ ๋๋ ์ญ์ ํ๋ค. 3. ๋ณ๊ฒฝ๋ ๋ด์ฉ์ด ์์คํ ์ ์ ์ฅ๋๊ณ ํ๋ฉด์ ๋ฐ์๋๋ค. |
| ์์ธ | 1. ๋นํ์์ด ์ ๊ทผํ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. 2. ํ์ ์ ๋ ฅ ํญ๋ชฉ์ด ๋น์ด ์์ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. |
| ์ ์ค์ผ์ด์ค ์ด๋ฆ | Q&A ๊ฒ์ํ ๊ด๋ฆฌ |
|---|---|
| ํ์์ | ๋ก๊ทธ์ธ ์ฌ์ฉ์ ๋ฐ ๋นํ์ |
| ๋ชฉํ | ์ฌ์ฉ์๊ฐ ์ง๋ฌธ์ ๋ฑ๋กํ๊ณ ๋ต๋ณ์ ์์ฑํ ์ ์์. |
| ์ฌ์ ์กฐ๊ฑด | ์ง๋ฌธ/๋ต๋ณ ๋ฑ๋ก์ ๋ก๊ทธ์ธ ์ฌ์ฉ์๋ง ๊ฐ๋ฅ. |
| ์ฌํ์กฐ๊ฑด | ๊ฒ์ํ์ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ์ ์ฅ๋๊ณ ์ด๋ ๊ฐ๋ฅ. |
| ์๋๋ฆฌ์ค | 1. ์ฌ์ฉ์๊ฐ Q&A ๊ฒ์ํ ํ์ด์ง๋ฅผ ์ฐ๋ค. 2. ์ง๋ฌธ์ ์ด๋ํ๊ฑฐ๋ ์ ์ง๋ฌธ์ ์์ฑํ๋ค. 3. ๊ธฐ์กด ์ง๋ฌธ์ ๋ํด ๋ต๋ณ์ ์ถ๊ฐํ๋ค. 4. ์์คํ ์ ๋ณ๊ฒฝ ์ฌํญ์ด ๋ฐ์๋๋ค. |
| ์์ธ | 1. ์ง๋ฌธ ๋๋ ๋ต๋ณ ๋ด์ฉ์ด ๋น์ด ์๋ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. 2. ๋นํ์์ด ์ง๋ฌธ/๋ต๋ณ์ ๋ฑ๋กํ๋ ค๊ณ ํ ๊ฒฝ์ฐ ๋ก๊ทธ์ธ ์์ฒญ. |
| ์ ์ค์ผ์ด์ค ์ด๋ฆ | AI ๋ง์ถค ๋ ์ํผ ๊ด๋ฆฌ |
|---|---|
| ํ์์ | ๋ก๊ทธ์ธ ์ฌ์ฉ์ |
| ๋ชฉํ | AI๊ฐ ์ถ์ฒํ ๋ ์ํผ๋ฅผ ์ ์ฅ ๋ฐ ๋ณํํ์ฌ ๊ฐ์ธ ๊ฒ์ํ์ ๊ด๋ฆฌ |
| ์ฌ์ ์กฐ๊ฑด | ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ ์ํ์ฌ์ผ ํจ. |
| ์ฌํ์กฐ๊ฑด | AI๊ฐ ์์ฑํ ๋ ์ํผ๊ฐ ๊ฐ์ธ AI ๊ฒ์ํ์ ์ ์ฅ๋จ. |
| ์๋๋ฆฌ์ค | 1. ์ฌ์ฉ์๊ฐ AI ์ถ์ฒ ํ์ด์ง๋ฅผ ์ฐ๋ค. 2. ํ์ํ ์ฌ๋ฃ๋ฅผ ์ ๋ ฅํ๊ฑฐ๋ ๋ณํ ์์ฒญ์ ์งํํ๋ค. 3. ์์ฑ๋ ๋ง์ถคํ ๋ ์ํผ๊ฐ ๊ฐ์ธ ๊ฒ์ํ์ ์ ์ฅ๋๋ค. 4. ์ ์ฅ๋ ๋ ์ํผ๋ ์ดํ ์ด๋ ๋ฐ ์์ ๊ฐ๋ฅ. |
| ์์ธ | 1. ์
๋ ฅ๋ ๋ฐ์ดํฐ๊ฐ ์์ ๊ฒฝ์ฐ ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ. 2. AI API ํธ์ถ ์คํจ ์ '์ผ์์ ์ธ ๋ฌธ์ ๋ฐ์' ๋ฉ์์ง ์ถ๋ ฅ. |
| ์๊ตฌ์ฌํญ ID | ์ ์ค์ผ์ด์ค ID | ๊ธฐ๋ฅ ID | ์ค๋ช |
|---|---|---|---|
| UR-001 | UC-001 | F-001 | ํ์๊ฐ์ ๋ฐ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-002 | UC-002 | F-002 | ๋ ์ํผ ๊ฒ์ํ CRUD ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-003 | UC-003 | F-003 | Q&A ๊ฒ์ํ ์ง๋ฌธ ๋ฐ ๋ต๋ณ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-004 | UC-004 | F-004 | AI ๊ธฐ๋ฐ ๋ง์ถค ๋ ์ํผ ๊ด๋ฆฌ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-005 | UC-005 | F-005 | ์ข์์ ๋ฐ ๋๊ธ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-006 | UC-006 | F-006 | ๋ ์ํผ ์คํฌ๋ฉ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-007 | UC-007 | F-007 | ๋ชจ๋ ๊ฒ์ํ์ ์ด๋ ๊ธฐ๋ฅ ์ ๊ณต. |
| UR-008 | UC-008 | F-008 | ๋ฐ์ดํฐ ๋ณด์ ๋ฐ ์ ์ฅ ๊ด๋ฆฌ ๊ธฐ๋ฅ ์ ๊ณต. |
- ํด๋์ค ๊ฐ์ ์ฐ๊ด ๊ด๊ณ, ์์ ๊ตฌ์กฐ ๋ฑ์ ์ค๊ณ.
- ๋๋ฉ์ธ ๋ก์ง๊ณผ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฝ๋ ๊ตฌํ ์ค๋น.
- ๊ฐ ๋ ์ด์ด์ ์ญํ ๊ณผ ์ฑ ์ ์ ์.
- ๋ ์ด์ด ๊ฐ ํธ์ถ ๊ด๊ณ ์ค๊ณ.
- ๋ฐ์ดํฐ ํ๋ฆ๊ณผ ์ฃผ์ ์๋น์ค ๊ฐ ์ํธ์์ฉ ์ ์.
- ์ฃผ์ API ์๋ํฌ์ธํธ ์ค๊ณ (URL, HTTP ๋ฉ์๋)
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| POST | /submit-recipe |
AI ๋ฆฌ๋ทฐ ์์ฒญ ๋ฐ ์ ์ฅ | recipeInput(String), language(String) |
๋ฆฌ๋ทฐ ๊ฒฐ๊ณผ ๋ฐ์ดํฐ ๋ฐ ์ ์ฅ ์๋ฃ ๋ฉ์์ง |
| GET | /submit-recipe |
๋ ์ํผ ์ ๋ ฅ ํผ ํ์ด์ง | ์์ | ๋ ์ํผ ์ ๋ ฅ ํผ ๋ทฐ |
| GET | /my-reviews |
๋ด ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํ | page(int), keyword(String) |
๋ฆฌ๋ทฐ ๋ชฉ๋ก ๋ทฐ ๋ฐ ํ์ด์ง ์ฒ๋ฆฌ |
| POST | /delete-review/{id} |
ํน์ ๋ฆฌ๋ทฐ ์ญ์ | reviewId(Long) |
์ญ์ ์๋ฃ ํ ๋ฆฌ๋ทฐ ๋ชฉ๋ก ๋ฆฌ๋ค์ด๋ ํธ |
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| POST | /answer/create |
๋ต๋ณ ์์ฑ | questionId(Integer), content(String) |
๋ต๋ณ ์์ฑ ํ ์ง๋ฌธ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| GET | /answer/editForm/{answerId} |
๋ต๋ณ ์์ ํผ ์กฐํ | answerId(Integer) |
๋ต๋ณ ์์ ํผ ๋ทฐ |
| POST | /answer/modify/{answerId} |
๋ต๋ณ ์์ | answerId(Integer), content(String) |
์์ ์๋ฃ ํ ์ง๋ฌธ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| POST | /answer/delete/{answerId} |
๋ต๋ณ ์ญ์ | answerId(Integer) |
์ญ์ ์๋ฃ ํ ์ง๋ฌธ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| POST | /recipe/{recipeId}/comment |
๋๊ธ ์์ฑ | recipeId(Long), content(String) |
๋๊ธ ์์ฑ ํ ๋ ์ํผ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| GET | /recipe/{recipeId}/comment/{id}/edit |
๋๊ธ ์์ ํผ ์กฐํ | recipeId(Long), commentId(Long) |
๋๊ธ ์์ ํผ ๋ทฐ |
| POST | /recipe/{recipeId}/comment/{id}/edit |
๋๊ธ ์์ | recipeId(Long), commentId(Long), content(String) |
์์ ์๋ฃ ํ ๋ ์ํผ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| POST | /recipe/{recipeId}/comment/{id}/delete |
๋๊ธ ์ญ์ | recipeId(Long), commentId(Long) |
์ญ์ ์๋ฃ ํ ๋ ์ํผ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| GET | / |
๋ฉ์ธ ํ์ด์ง๋ก ๋ฆฌ๋ค์ด๋ ํธ | ์์ | ๋ฉ์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| GET | /main |
๋ฉ์ธ ํ์ด์ง ์กฐํ | ์์ | ๋ฉ์ธ ํ์ด์ง ๋ทฐ |
| GET | /about |
์๊ฐ ํ์ด์ง ์กฐํ | ์์ | ์๊ฐ ํ์ด์ง ๋ทฐ |
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| GET | /question/list |
์ง๋ฌธ ๋ชฉ๋ก ์กฐํ | page(int), kw(String) |
์ง๋ฌธ ๋ชฉ๋ก ๋ทฐ ๋ฐ ํ์ด์ง ์ฒ๋ฆฌ |
| GET | /question/detail/{id} |
์ง๋ฌธ ์์ธ ์กฐํ | id(Integer) |
์ง๋ฌธ ์์ธ ๋ทฐ |
| GET | /question/create |
์ง๋ฌธ ์์ฑ ํผ ์กฐํ | ์์ | ์ง๋ฌธ ์์ฑ ํผ ๋ทฐ |
| POST | /question/create |
์ง๋ฌธ ์์ฑ | title(String), content(String) |
์์ฑ ์๋ฃ ํ ์ง๋ฌธ ๋ชฉ๋ก ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| GET | /question/modify/{id} |
์ง๋ฌธ ์์ ํผ ์กฐํ | id(Integer) |
์ง๋ฌธ ์์ ํผ ๋ทฐ |
| POST | /question/modify/{id} |
์ง๋ฌธ ์์ | id(Integer), title(String), content(String) |
์์ ์๋ฃ ํ ์ง๋ฌธ ์์ธ ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| POST | /question/delete/{id} |
์ง๋ฌธ ์ญ์ | id(Integer) |
์ญ์ ์๋ฃ ํ ์ง๋ฌธ ๋ชฉ๋ก ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| HTTP Method | URL | ๊ธฐ๋ฅ | ์์ฒญ ํ๋ผ๋ฏธํฐ | ์๋ต ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| GET | /recipe/list |
๋ ์ํผ ๋ชฉ๋ก ์กฐํ | page(int), size(int), keyword(String) |
๋ ์ํผ ๋ชฉ๋ก ๋ทฐ ๋ฐ ํ์ด์ง ์ฒ๋ฆฌ |
| GET | /recipe/detail/{id} |
๋ ์ํผ ์์ธ ์กฐํ | id(Long) |
๋ ์ํผ ์์ธ ๋ทฐ |
| GET | /recipe/create |
๋ ์ํผ ์์ฑ ํผ ์กฐํ | ์์ | ๋ ์ํผ ์์ฑ ํผ ๋ทฐ |
| POST | /recipe/create |
๋ ์ํผ ์์ฑ | title(String), content(String), image(MultipartFile) |
์์ฑ ์๋ฃ ํ ๋ ์ํผ ๋ชฉ๋ก ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| GET | /recipe/edit/{id} |
๋ ์ํผ ์์ ํผ ์กฐํ | id(Long) |
๋ ์ํผ ์์ ํผ ๋ทฐ |
| POST | /recipe/edit/{id} |
๋ ์ํผ ์์ | id(Long), title(String), content(String), image(MultipartFile) |
์์ ์๋ฃ ํ ๋ ์ํผ ๋ชฉ๋ก ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
| POST | /recipe/delete/{id} |
๋ ์ํผ ์ญ์ | id(Long) |
์ญ์ ์๋ฃ ํ ๋ ์ํผ ๋ชฉ๋ก ํ์ด์ง ๋ฆฌ๋ค์ด๋ ํธ |
- ํ๋ฉด ๊ตฌ์ฑ ์์(๋ฒํผ, ์ ๋ ฅ ํผ, ๋ฐ์ดํฐ ๋ฐ์ธ๋ฉ ๋ฑ) ์ ์.
- ํ์ด์ง ๊ฐ์ ์ด๋ ํ๋ฆ ์ค๊ณ.
- ํ๋ฉด ์์์ ์์น ๋ฐ ๋์์ธ ๊ฐ์ด๋ ์์ฑ.
- Backend: Spring Boot, Java 17
- Database: MySQL
- Frontend: Thymeleaf
- API Integration: OpenAI API (ChatGPT)
- Deployment: AWS EC2, RDS (MySQL)
๋จ์ ํ
์คํธ๋ ๊ฐ ์๋น์ค ๊ณ์ธต(AIReviewService, QuestionService, UserService, RecipeService)์ ๋ฉ์๋๊ฐ ์์๋๋ก ์๋ํ๋์ง ํ์ธํ๋ ๊ณผ์ ์
๋๋ค. ๊ฐ ํ
์คํธ๋ ์ฃผ์ ๊ธฐ๋ฅ๋ณ๋ก ๊ฒ์ฆ๋์์ต๋๋ค.
| ํ ์คํธ ID | ํ ์คํธ ๋์ | ์ ๋ ฅ๊ฐ | ์์ ์ถ๋ ฅ | ๊ฒฐ๊ณผ |
|---|---|---|---|---|
| ATR001 | generateAIReview |
recipeInput = "Test recipe input", user = testUser | ์์ฑ๋ AIReview ๊ฐ์ฒด, ์ฌ์ฉ์ ๋ฐ ๋ ์ํผ ์
๋ ฅ ํฌํจ |
Pass |
| ATR002 | saveReview |
AIReview ๊ฐ์ฒด | ์ ์ฅ๋ AIReview ๊ฐ์ฒด |
Pass |
| ATR003 | getUserReviews |
user = testUser | ํด๋น ์ฌ์ฉ์์ ๋ํ ๋ชจ๋ ๋ฆฌ๋ทฐ ๋ฐํ | Pass |
| ATR004 | deleteReview |
reviewId = 1L | ํด๋น ๋ฆฌ๋ทฐ ์ญ์ | Pass |
| ATR005 | getUserByUsername |
username = "testUser" | ํด๋น ์ฌ์ฉ์ ๊ฐ์ฒด ๋ฐํ | Pass |
| QSR001 | getList |
keyword = "test", page = 0 | ๊ฒ์๋ ์ง๋ฌธ ๋ฆฌ์คํธ ๋ฐํ | Pass |
| QSR002 | getQuestion |
questionId = 1 | ํด๋น ID์ ์ง๋ฌธ ๋ฐํ | Pass |
| QSR003 | getQuestionNotFound |
questionId = 1 | DataNotFoundException ๋ฐ์ |
Pass |
| QSR004 | createQuestion |
title = "New Question", content = "This is a new question content." | ์๋ก์ด ์ง๋ฌธ ์์ฑ | Pass |
| QSR005 | modifyQuestion |
question ๊ฐ์ฒด, newTitle = "Updated Title", newContent = "Updated Content" | ์ง๋ฌธ ์์ | Pass |
| QSR006 | deleteQuestion |
question ๊ฐ์ฒด | ์ง๋ฌธ ์ญ์ | Pass |
| USR001 | createUser |
username = "testUser", email = "test@example.com", password = "password123" | ์ ์ฌ์ฉ์ ์์ฑ | Pass |
| USR002 | getUser (์ฑ๊ณต) |
username = "testUser" | ํด๋น ์ฌ์ฉ์ ๋ฐํ | Pass |
| USR003 | getUser (์คํจ) |
username = "nonExistingUser" | DataNotFoundException ๋ฐ์ |
Pass |
| USR004 | validatePassword (์ฑ๊ณต) |
password1 = "password123", password2 = "password123" | true ๋ฐํ | Pass |
| USR005 | validatePassword (์คํจ) |
password1 = "password123", password2 = "differentPassword" | false ๋ฐํ | Pass |
| RSR001 | createRecipe |
title = "Test Recipe", content = "Test content", user = testUser | ์ ๋ ์ํผ ๊ฐ์ฒด ์์ฑ | Pass |
| RSR002 | getRecipeById |
recipeId = 1L | ํด๋น ID์ ๋ ์ํผ ๋ฐํ | Pass |
| RSR003 | testSaveImage_InvalidFileType |
์๋ชป๋ MIME ํ์ | RuntimeException ๋ฐ์ |
Pass |
๋ชจ๋ ํ ์คํธ ์ผ์ด์ค๊ฐ ์์ํ ๋๋ก ์ฑ๊ณต์ ์ผ๋ก ์ํ๋์์ต๋๋ค. ์ฃผ์ด์ง ์ ๋ ฅ๊ฐ์ ๋ํ ์ ์ ํ ๋ฐํ ๊ฐ ๋ฐ ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ธ๋์์ต๋๋ค.
ํ ์คํธ ๊ฒฐ๊ณผ ์๋น์ค ๋ก์ง์ด ์์๋๋ก ์ ์๋ํ๋ฉฐ, ๊ฐ ๋ฉ์๋๋ ์ ๋ ฅ๊ฐ์ ๋ํด ์ฌ๋ฐ๋ฅธ ์ถ๋ ฅ์ ๋ฐํํ๊ฑฐ๋, ์์ธ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ณ ์์์ ํ์ธํ์ต๋๋ค.
| ํ ์คํธ ํญ๋ชฉ | ๊ฒฐ๊ณผ | ์์ธ ์ค๋ช |
|---|---|---|
์ฌ์ฉ์ ์์ฑ (createUser()) |
Pass | ์ฌ์ฉ์ ์์ฑ ์, username, email, ์ํธํ๋ password๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฅ๋จ. |
์ฌ์ฉ์ ์กฐํ (getUser()) |
Pass | ์์ฑ๋ ์ฌ์ฉ์๊ฐ ์ ์์ ์ผ๋ก ์กฐํ๋จ. |
๋น๋ฐ๋ฒํธ ๊ฒ์ฆ (validatePassword()) |
Pass | ๋ ๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ๋ฉด true, ๋ถ์ผ์นํ๋ฉด false ๋ฐํ๋จ. |
| ํ ์คํธ ํญ๋ชฉ | ๋ชฉํ | ๊ฒฐ๊ณผ | ๋น๊ณ |
|---|---|---|---|
| AIReviewService ํตํฉ ํ ์คํธ | AIReviewService์ ์ ์ฒด ํ๋ฆ ๊ฒ์ฆ |
generateAIReview์ saveReview๋ก ์์ฑ๋ AIReview๊ฐ DB์ ์ ์ฅ๋จ |
์ฑ๊ณต: AIReview ๊ฐ์ฒด๊ฐ DB์ ์ฑ๊ณต์ ์ผ๋ก ์ ์ฅ๋จ |
| QuestionService ํตํฉ ํ ์คํธ | QuestionService์ ์ง๋ฌธ ์์ฑ ๋ฐ ์ญ์ ํ์ธ |
createQuestion์ผ๋ก ์ง๋ฌธ ์์ฑ ํ, deleteQuestion์ผ๋ก ์ญ์ ํ์ธ๋จ |
์ฑ๊ณต: ์ง๋ฌธ์ด DB์ ์ ์ฅ๋๊ณ ์ญ์ ๋จ |
| RecipeService ํตํฉ ํ ์คํธ | RecipeService์ ๋ ์ํผ ์์ฑ ๋ฐ ์ ์ฅ ํ์ธ |
createRecipe๋ก ์์ฑ๋ ๋ ์ํผ๊ฐ DB์ ์ ์ฅ๋จ |
์ฑ๊ณต: ๋ ์ํผ๊ฐ DB์ ์ ์ฅ๋จ |
| UserService ํตํฉ ํ ์คํธ | UserService์ ์ฌ์ฉ์ ์์ฑ, ์กฐํ ๋ฐ ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ |
createUser๋ก ์์ฑ๋ ์ฌ์ฉ์์ validatePassword๊ฐ ์ ์ ์๋ํจ |
์ฑ๊ณต: ์ฌ์ฉ์ ์์ฑ ๋ฐ ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ ์ ์ ์๋ |
- ์ ์ฒด ๊ฒฐ๊ณผ: ๋ชจ๋ ํตํฉ ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ํต๊ณผํ์์ผ๋ฉฐ, ๊ฐ ์๋น์ค๊ฐ DB์ ์ฐ๋ํ์ฌ ์ ์์ ์ผ๋ก ์๋ํจ์ ํ์ธํ์์ต๋๋ค.
- ๋ค์ ๋จ๊ณ: ์ถ๊ฐ์ ์ธ ์๋น์ค์ ๊ธฐ๋ฅ์ ๋ํ ํตํฉ ํ ์คํธ๋ฅผ ์งํํ๊ณ , ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ๋ ํ์ฅํ ํ์๊ฐ ์์ต๋๋ค.
| ํ ์คํธ ํญ๋ชฉ | ๋ชฉํ | ๊ฒฐ๊ณผ | ๋น๊ณ |
|---|---|---|---|
| ๋ ์ํผ ์์ฑ ๋ฐ ์ ์ฅ | ์ฌ์ฉ์๊ฐ ๋ ์ํผ๋ฅผ ์์ฑํ๊ณ ์ ์ฅํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | createRecipe๋ก ๋ ์ํผ๊ฐ DB์ ์ฑ๊ณต์ ์ผ๋ก ์ ์ฅ๋จ |
์ฑ๊ณต |
| ์ฌ์ฉ์ ์์ฑ ๋ฐ ์กฐํ | ์ฌ์ฉ์๊ฐ ์ ์์ ์ผ๋ก ์์ฑ๋๊ณ ์กฐํ๋๋์ง ํ์ธ | createUser๋ก ์ฌ์ฉ์๊ฐ ์์ฑ๋๊ณ ์กฐํ๋จ |
์ฑ๊ณต |
| AI ๋ ์ํผ ์์ฑ ๋ฐ ์ ์ฅ | AI๊ฐ ์์ฑํ ๋ ์ํผ๋ฅผ ์ ์ฅํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | generateAIReview ๋ฐ saveReview๋ก AI ๋ ์ํผ ์์ฑ ํ ์ ์ฅ๋จ |
์ฑ๊ณต |
| ์ง๋ฌธ ์์ฑ ๋ฐ ์ญ์ | ์ฌ์ฉ์๊ฐ ์ง๋ฌธ์ ์์ฑํ๊ณ ์ญ์ ํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | createQuestion๋ก ์ง๋ฌธ ์์ฑ ํ, deleteQuestion์ผ๋ก ์ญ์ ๋จ |
์ฑ๊ณต |
- ์ ์ฒด ๊ฒฐ๊ณผ: ์์คํ ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ผ๋ฉฐ, ๋ชจ๋ ์ฃผ์ ๊ธฐ๋ฅ์ด ์ ์์ ์ผ๋ก ์๋ํจ์ ํ์ธํ์์ต๋๋ค.
- ๋ค์ ๋จ๊ณ: ์ถ๊ฐ์ ์ธ ๋น์ฆ๋์ค ๋ก์ง ๋ฐ ๋ ๋ณต์กํ ์๋๋ฆฌ์ค์ ๋ํด ์์คํ ํ ์คํธ๋ฅผ ํ์ฅํ ์์ ์ ๋๋ค.
| ํ ์คํธ ํญ๋ชฉ | ๋ชฉํ | ๊ฒฐ๊ณผ | ๋น๊ณ |
|---|---|---|---|
| ํ์๊ฐ์ ๋ฐ ๋ก๊ทธ์ธ | ์ฌ์ฉ์๊ฐ ํ์๊ฐ์ ํ ๋ก๊ทธ์ธ์ด ์ ์์ ์ผ๋ก ์ด๋ฃจ์ด์ง๋์ง ๊ฒ์ฆ | createUser๋ก ์ฌ์ฉ์๊ฐ ์์ฑ๋๊ณ login์ผ๋ก ๋ก๊ทธ์ธ ์ฒ๋ฆฌ๋จ |
์ฑ๊ณต |
| ๋ ์ํผ ์์ฑ | ์ฌ์ฉ์๊ฐ ๋ ์ํผ๋ฅผ ์์ฑํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | createRecipe๋ก ๋ ์ํผ ์์ฑ ํ, getRecipeById๋ก ์กฐํ ์ฑ๊ณต |
์ฑ๊ณต |
| AI ๋ ์ํผ ์์ฑ | AI๊ฐ ์์ฑํ ๋ ์ํผ๋ฅผ ์ ์ฅํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | generateAIReview ๋ฐ saveReview๋ก AI ๋ ์ํผ ์์ฑ ํ ์ ์ฅ๋จ |
์ฑ๊ณต |
| ์ง๋ฌธ ๊ฒ์ํ ์์ฑ ๋ฐ ์ญ์ | ์ฌ์ฉ์๊ฐ ์ง๋ฌธ์ ์์ฑํ๊ณ ์ญ์ ํ๋ ๊ธฐ๋ฅ ๊ฒ์ฆ | createQuestion๋ก ์ง๋ฌธ ์์ฑ ํ, deleteQuestion์ผ๋ก ์ญ์ ๋จ |
์ฑ๊ณต |
- ์ ์ฒด ๊ฒฐ๊ณผ: ์ธ์ ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋์์ผ๋ฉฐ, ์ฌ์ฉ์์ ์ฃผ์ ์๊ตฌ์ฌํญ์ด ์ ์์ ์ผ๋ก ์ฒ๋ฆฌ๋จ์ ํ์ธํ์์ต๋๋ค.
- ๋ค์ ๋จ๊ณ: ์ถ๊ฐ์ ์ธ ๊ธฐ๋ฅ์ ๋ํด ์ธ์ ํ ์คํธ๋ฅผ ์งํํ๊ณ , ์ฌ์ฉ์ ๊ฒฝํ์ ๊ธฐ๋ฐ์ผ๋ก ํ ๊ฒ์ฆ์ ๊ฐํํ ์์ ์ ๋๋ค.
- Auth & Scrap Page
Spring Security์์ PasswordEncoder๋ฅผ Bean์ผ๋ก ๋ฑ๋กํ์ง ์์์ ๋ ๋ฐ์ํ๋ ์ค๋ฅ์
๋๋ค.
์ฌ์ฉ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ํธํํ๋ PasswordEncoder๊ฐ ์์ผ๋ฉด ์ธ์ฆ ๋ฐ ์ ์ฅ ๊ณผ์ ์์ ์คํจํ ์ ์์ต๋๋ค.
Spring Security๊ฐ ๋ด๋ถ์ ์ผ๋ก PasswordEncoder Bean์ ์๊ตฌํ์ง๋ง, ํ๋ก์ ํธ ์ค์ ์์ ์ด๋ฅผ ์ ๊ณตํ์ง ์์ ๋ฐ์ํ ๋ฌธ์ ์
๋๋ค.
@Configuration ํด๋์ค์ PasswordEncoder๋ฅผ ์ ์ํ์ฌ Bean์ผ๋ก ๋ฑ๋กํฉ๋๋ค.
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Spring Data JPA์์ ์ง์ ๋ ์ฟผ๋ฆฌ ๋ฉ์๋๊ฐ ์ํฐํฐ ํ๋์ ์ผ์นํ์ง ์์ ๋ฐ์ํ๋ ์ค๋ฅ์ ๋๋ค.
์ํฐํฐ User ํด๋์ค์ ํ๋๋ช
์ด id๊ฐ ์๋๋ผ userId๋ก ์ ์๋์ด ์์ง๋ง, ์ฟผ๋ฆฌ ๋ฉ์๋์์ ์ด๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๋ฐ์ํ์ง ๋ชปํ ๊ฒฝ์ฐ์
๋๋ค.
์ํฐํฐ ํ๋๋ช ์ ๊ธฐ์ค์ผ๋ก ์ฟผ๋ฆฌ ๋ฉ์๋๋ฅผ ์์ ํฉ๋๋ค.
public interface AnswerVoterRepository extends JpaRepository<AnswerVoter, Long> {
// ์์ ์ : findByUserId(Long id)
// ์์ ํ:
List<AnswerVoter> findByUserUserId(Long userId);
}
OpenAI API ํธ์ถ ์ API ํค๊ฐ ๋๋ฝ๋๊ฑฐ๋ ์๋ชป ์ค์ ๋์ด ์ธ์ฆ ๋ฌธ์ ๊ฐ ๋ฐ์
ํ๊ฒฝ ๋ณ์๋ก ์ค์ ๋ API ํค๊ฐ ์ ๋๋ก ๋ก๋๋์ง ์๊ฑฐ๋, application.properties ๋๋ application.yml ํ์ผ์ ์ค์ ์ด ๋๋ฝ๋ ๊ฒฝ์ฐ์
๋๋ค.
application.propertiesํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด API ํค๋ฅผ ์ค์
spring.ai.openai.api-key=${OPENAI_API_KEY}
- dot env๋ก ํ๊ฒฝ๋ณ์ ์ค์
OPENAI_API_KEY=your_api_key
- Spring Boot ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ์์ํ์ฌ ํค๊ฐ ์ ๋๋ก ๋ก๋๋์๋์ง ํ์ธ
- Spring Security์ JPA ์ฌ์ฉ ์ ์ธ๋ถ ์ค์ ์ด ์ค์ํ๋ฉฐ, ๊ธฐ๋ณธ ์ค์ ์ ์์กดํ์ง ์๊ณ ๋ช ํํ ์ฝ๋ ์์ฑ์ด ํ์ํจ์ ๊นจ๋ฌ์
- OpenAI API์ ๊ฐ์ ์ธ๋ถ ์๋น์ค๋ฅผ ์ฐ๋ํ ๋, ํ๊ฒฝ ๋ณ์ ๋ฐ ์ค์ ํ์ผ ๊ด๋ฆฌ๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ ์ฑ๊ณผ ๋ณด์์ฑ์ ํฌ๊ฒ ์ข์ฐํ๋ค๋ ๊ฒ์ ๋ฐฐ์ ์
- ์คํ๋ง ๋ถํธ ํ๋ ์์ํฌ๋ฅผ ๋ค๋ฃจ๋ฉด์ ๋ค๋ฅธ ํ๋ ์์ํฌ์ ๋นํด ์ด๋ ต๋ค๊ณ ๋๊ผ๋๋ฐ ๋ง์ํด๋ณด๋ ์ํ์ฐฉ์ค๋ ๋ง์์ง๋ง ์ํ๋ ๊ธฐ๋ฅ๋ค์ ๊ตฌํํ ์ ์์์








.gif?raw=true)



