๋ชฉํ๋ฅผ ๊ธฐ๋กํ๊ณ , ํจ๊ป ๋์ ํ๋ฉฐ, ๋ค์ ๋ชฉํ๊น์ง ๋ฐ๊ฒฌํ๋ ๋ฒํท๋ฆฌ์คํธ ํ๋ซํผ
๋ฒํท๋ฆฌ์คํธ ๋ฑ๋ก๋ถํฐ ์งํ ๊ณผ์ ๊ณต์ , ๋ฌ์ฑ ์ธ์ฆ, AI ๊ธฐ๋ฐ ๋ค์ ๋ชฉํ ์ถ์ฒ๊น์ง
๋ชฉํ ๋ฌ์ฑ์ ์ ๊ณผ์ ์ ํ๋์ ์๋น์ค์์ ์ง์ํฉ๋๋ค.
- ํ๋ก์ ํธ ์๊ฐ
- ๊ธฐํ ๋ฐฐ๊ฒฝ
- ์๋น์ค ์ด์ฉ ํ๋ฆ
- ์ฃผ์ ๊ธฐ๋ฅ
- ํ๋ก์ ํธ ์ ๋ณด
- ๊ธฐ์ ์คํ
- ๊ธฐ์ ์ ํ ๋ฐ ํ์ฉ
- ์์คํ ์ํคํ ์ฒ
- ๋ด๋น ์ญํ
- ํต์ฌ ๊ตฌํ
- ํธ๋ฌ๋ธ์ํ ๋ฐ ์ค๊ณ ๊ฐ์
- API
- ๋ฐ์ดํฐ ๋ชจ๋ธ
- ํ๋ก์ ํธ ๊ตฌ์กฐ
- ์คํ ๋ฐฉ๋ฒ
- ์ฑ๊ณผ์ ํ๊ณ
WishBoard๋ ์ฌ์ฉ์๊ฐ ์์ ์ ๋ฒํท๋ฆฌ์คํธ๋ฅผ ๊ตฌ์ฒด์ ์ผ๋ก ๋ฑ๋กํ๊ณ , ์งํ ๊ณผ์ ๊ณผ ๋ฌ์ฑ ๊ฒฐ๊ณผ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๋๋ก ์ง์ํ๋ ๋ชฉํ ๊ด๋ฆฌ ํ๋ซํผ์ ๋๋ค.
์ฌ์ฉ์๋ ๋ชฉํ๋ฅผ ๋ค์ 5๊ฐ์ง ์นดํ ๊ณ ๋ฆฌ๋ก ๋ถ๋ฅํ๊ณ ์งํ๋ฅ , ๋ง๊ฐ ๊ธฐํ, ์ฐธ๊ณ ์๋ฃ์ ์ฌ์ง์ ํจ๊ป ๊ธฐ๋กํ ์ ์์ต๋๋ค.
- ํด๋ณด๊ณ ์ถ๋ค
- ๋๊ณ ์ถ๋ค
- ๊ฐ๊ณ ์ถ๋ค
- ๊ฐ๋ณด๊ณ ์ถ๋ค
- ๋ฐฐ์ฐ๊ณ ์ถ๋ค
๊ฐ์ ๋ชฉํ๋ฅผ ๊ฐ์ง ์ฌ์ฉ์๋ค์ ์ปค๋ฎค๋ํฐ์ ํ ํ๋์ ํตํด ๊ฒฝํ๊ณผ ์ ๋ณด๋ฅผ ๊ณต์ ํ๊ณ ์๋ก ์์ํ ์ ์์ต๋๋ค. ๋ชฉํ๋ฅผ ๋ฌ์ฑํ๋ฉด ํธ๋กํผ์ ์ธ์ฆ ๊ฒ์๊ธ๋ก ์ฑ๊ณผ๋ฅผ ๋จ๊ธธ ์ ์์ผ๋ฉฐ, ์๋ฃํ ๋ชฉํ ์ด๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก AI๊ฐ ์๋ก์ด ๋ชฉํ๋ฅผ ์ถ์ฒํฉ๋๋ค.
WishBoard๋ ๋จ์ํ ๋ชฉํ์ ์๋ฃ ์ฌ๋ถ๋ฅผ ํ์ธํ๋ ๋๊ตฌ๊ฐ ์๋๋ผ,
๋ชฉํ ์ค์ โ ๊ณผ์ ๊ธฐ๋ก โ ์ปค๋ฎค๋ํฐ ๊ณต์ โ ๋ฌ์ฑ ์ธ์ฆ โ ๋ค์ ๋ชฉํ ์ถ์ฒ
์ผ๋ก ์ด์ด์ง๋ ์ํํ ๋ชฉํ ๋ฌ์ฑ ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค.
๊ธฐ์กด ๋ชฉํ ๊ด๋ฆฌ ์๋น์ค๋ ๋ชฉํ๋ฅผ ๋ฑ๋กํ๊ณ ์๋ฃ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ๋ ๊ธฐ๋ฅ์ ์ง์ค๋์ด ์์ด, ์ฌ์ฉ์๊ฐ ๋ชฉํ๋ฅผ ์ง์ํ๋๋ก ๋๊ฑฐ๋ ๊ฐ์ ๋ชฉํ๋ฅผ ๊ฐ์ง ์ฌ๋๋ค๊ณผ ์ฐ๊ฒฐํ๋ ๊ธฐ๋ฅ์ด ๋ถ์กฑํ์ต๋๋ค.
WishBoard๋ ๋ค์ ์ธ ๊ฐ์ง ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ๊ธฐํํ์ต๋๋ค.
| ๋ฌธ์ | WishBoard์ ํด๊ฒฐ ๋ฐฉ์ |
|---|---|
| ๋ชฉํ๋ฅผ ์ธ์๋ ๊พธ์คํ ์ ์งํ๊ธฐ ์ด๋ ค์ | ์งํ๋ฅ , ํ๋ ๊ธฐ๋ก, D-Day๋ฅผ ํตํด ๊ณผ์ ์ ์๊ฐํ |
| ๋น์ทํ ๋ชฉํ๋ฅผ ๊ฐ์ง ์ฌ๋๊ณผ ์ ๋ณด๋ฅผ ๋๋๊ธฐ ์ด๋ ค์ | ๋ชฉํ ๊ธฐ๋ฐ ์ปค๋ฎค๋ํฐ, ๋๊ธยท๋๋๊ธ, ์ข์์, ํ ํ๋ ์ ๊ณต |
| ๋ชฉํ ๋ฌ์ฑ ํ ๋ค์ ๋ชฉํ๋ฅผ ์ฐพ๊ธฐ ์ด๋ ค์ | ์๋ฃ ์ด๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก AI๊ฐ ์๋ก์ด ๋ชฉํ ์ถ์ฒ |
flowchart LR
A["๋ฒํท๋ฆฌ์คํธ ๋ฑ๋ก"] --> B["์งํ๋ฅ ยทํ๋ ๊ธฐ๋ก"]
B --> C["์ปค๋ฎค๋ํฐยทํ ํ๋"]
C --> D["๋ชฉํ ๋ฌ์ฑ ๋ฐ ์ธ์ฆ"]
D --> E["ํธ๋กํผ ์์ฑ"]
E --> F["AI ๊ธฐ๋ฐ ๋ค์ ๋ชฉํ ์ถ์ฒ"]
F --> A
- ๋ชฉํ๋ฅผ 5๊ฐ์ง ์นดํ ๊ณ ๋ฆฌ๋ก ๋ถ๋ฅ
- ์งํ ์ํ์ ๋ชฉํ๋ณ ์งํ๋ฅ ๊ด๋ฆฌ
- ๋ง๊ฐ ๊ธฐํ๊ณผ D-Day ํ์
- ๋ชฉํ ์ค์ ์ด์ , ๋ค์ง, ์ฐธ๊ณ ์๋ฃ ๋ฐ ์ด๋ฏธ์ง ๋ฑ๋ก
- ์ต๋ 3๊ฐ์ ๋ชฉํ ์๋จ ๊ณ ์
- ๋ชฉํ ๋ฌ์ฑ ์ ์๋ฃ ์ผ์ ๊ธฐ๋ก
- ๊ฐ์ ๋ชฉํ๋ฅผ ๊ฐ์ง ์ฌ์ฉ์ ๊ฐ ์ ๋ณด ๊ณต์
- ๊ฒ์๊ธ ๊ฒ์ยท์กฐํยท์์ฑยท์์ ยท์ญ์
- ์ด๋ฏธ์ง๊ฐ ํฌํจ๋ ๊ฒ์๊ธ ์์ฑ
- ๋๊ธยท๋๋๊ธ ์์ฑ๊ณผ ์ข์์
- ๊ด์ฌ ๊ฒ์๊ธ ์ฆ๊ฒจ์ฐพ๊ธฐ
- ์ปค๋ฎค๋ํฐ ์ ํ๊ณผ ํค์๋ ๊ธฐ๋ฐ ๊ฒ์๊ธ ํํฐ๋ง
- ๋ชฉํ ๋ฌ์ฑ ์ ํธ๋กํผ ์์ฑ
- ์๋ฃํ ๋ชฉํ๋ฅผ ์ธ์ฆ ๊ฒ์๊ธ๋ก ๊ธฐ๋ก
- ๋ค๋ฅธ ์ฌ์ฉ์์ ์์๊ณผ ํผ๋๋ฐฑ ์ ๊ณต
- ๋ฌ์ฑ ๊ธฐ๋ก์ ํตํด ์ฑ์ทจ ๊ณผ์ ์๊ฐํ
- ์ฌ์ฉ์๊ฐ ์๋ฃํ ๋ฒํท๋ฆฌ์คํธ ๋ถ์
- OpenAI API๋ฅผ ํ์ฉํ ๋ค์ ๋ชฉํ ํค์๋ ์ถ์ฒ
- ์ถ์ฒ ํค์๋์ ๊ด๋ จ๋ ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ ์ฐ๊ฒฐ
- ๋งค์นญ ๊ฒ์๊ธ์ด ์์ ๊ฒฝ์ฐ ์ถ์ฒ ํค์๋ ์์ฒด ์ ๊ณต
- ํธ๋กํผ ๊ฒ์๊ธ ์ค ์ข์์๊ฐ ๋ง์ ์ด๋ฌ์ ๊ฒ์๊ธ ์ ๊ณต
- ์๊ฐ ์ธ๊ธฐ ๊ฒ์๊ธ Top 10 ์กฐํ
- ๋ค๋ฅธ ์ฌ์ฉ์์ ์ฑ๊ณต ๊ฒฝํ์ ํตํ ๋๊ธฐ๋ถ์ฌ
| ํญ๋ชฉ | ๋ด์ฉ |
|---|---|
| ์๋น์ค๋ช | WishBoard |
| ๊ฐ๋ฐ ๊ธฐ๊ฐ | 2025.03 ~ 2025.06 |
| ์ฐธ์ฌ ์ธ์ | 4๋ช |
| ํ๋ก์ ํธ ํํ | ํ์คํ ํ ํ๋ก์ ํธ |
| ์ฃผ์ ์ฌ์ฉ์ | ๋ชฉํ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๊ณ ๋ค๋ฅธ ์ฌ์ฉ์์ ๊ฒฝํ์ ๊ณต์ ํ๊ณ ์ถ์ ์ฌ๋ |
| ๋ด๋น ์์ญ | ์ปค๋ฎค๋ํฐ ๊ธฐ๋ฅ ํ๋ก ํธ์๋ยท๋ฐฑ์๋ ๊ฐ๋ฐ ๋ฐ API ์ฐ๋ |
| ์ฃผ์ ๋ด๋น ๊ธฐ๋ฅ | ์ฆ๊ฒจ์ฐพ๊ธฐ, ๊ฒ์๊ธ ๊ฒ์ยท์กฐํยท์์ฑ, ๋๊ธยท๋๋๊ธ, ํ๋ฉด ๊ธฐํ ๋ฐ ๊ตฌํ |
| ๊ธฐ์ | ๋ฒ์ ยท๊ตฌ๋ถ | ํ๋ก์ ํธ์์์ ํ์ฉ |
|---|---|---|
| React Native | Mobile App | ๋ฒํท๋ฆฌ์คํธยท์ปค๋ฎค๋ํฐยท๋๊ธ ๋ฑ ๋ชจ๋ฐ์ผ ํ๋ฉด ๊ตฌํ |
| JavaScript | Language | ํ๋ฉด ์ํ ๊ด๋ฆฌ, ์ด๋ฒคํธ ์ฒ๋ฆฌ ๋ฐ REST API ์ฐ๋ |
| React Navigation | Navigation | ํ๋ฉด ์ด๋, ์ปค๋ฎค๋ํฐ ํญ ์ ๋ณด์ ๋ผ์ฐํ ํ๋ผ๋ฏธํฐ ์ ๋ฌ |
| Figma | UI/UX | ์ปค๋ฎค๋ํฐ ํ๋ฉด ๊ธฐํ, ์์ด์ดํ๋ ์ ๋ฐ ํ๋กํ ํ์ ์ ์ |
| ๊ธฐ์ | ๋ฒ์ ยท๊ตฌ๋ถ | ํ๋ก์ ํธ์์์ ํ์ฉ |
|---|---|---|
| Java | 17 | ์๋ฒ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋๋ฉ์ธ ๋น์ฆ๋์ค ๋ก์ง ๊ตฌํ |
| Spring Boot | 3.4.5 | REST API, ์์กด์ฑ ์ฃผ์ , ์ค์ ๋ฐ ๊ณ์ธตํ ์๋ฒ ๊ตฌ์กฐ ๊ตฌ์ฑ |
| Spring Data JPA / Hibernate | ORM | ์ํฐํฐ ๋งคํ, ์๊ธฐ์ฐธ์กฐ ๋๊ธ ๊ตฌ์กฐ, ์ฐ๊ด๊ด๊ณ ๋ฐ ๊ฒ์ ์ฟผ๋ฆฌ ๊ตฌํ |
| Spring Security | Security | URL ์ ๊ทผ ์ ์ด ๋ฐ ์ธ์ฆ ํํฐ ์ฒด์ธ ๊ตฌ์ฑ |
| JJWT | 0.12.3 | Stateless JWT ์์ฑยท๊ฒ์ฆ๊ณผ ์ฌ์ฉ์ ์ธ์ฆ ์ฒ๋ฆฌ |
| JdbcTemplate | SQL | ์ข์์ ์ค๋ณต ๊ฒ์ฆ๊ณผ ์ง์ SQL ๊ธฐ๋ฐ ์นด์ดํธ ์ฒ๋ฆฌ |
| Spring WebClient | HTTP Client | OpenAI Chat Completion API ํธ์ถ |
| Spring Multipart | File Upload | ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ ์ด๋ฏธ์ง ์ ๋ก๋ ์ฒ๋ฆฌ |
| Spring Validation | Validation | ์์ฒญ DTO ์ ๋ ฅ๊ฐ ๊ฒ์ฆ |
| SpringDoc OpenAPI | 2.5.0 | Swagger UI ๊ธฐ๋ฐ API ๋ฌธ์ ์๋ ์์ฑ ๋ฐ ํ ์คํธ |
| Lombok | Productivity | ์์ฑ์ ์ฃผ์ , ๋ก๊น ๋ฐ ๋ฐ๋ณต ์ฝ๋ ์ถ์ |
| ๊ธฐ์ | ๋ฒ์ ยท๊ตฌ๋ถ | ํ๋ก์ ํธ์์์ ํ์ฉ |
|---|---|---|
| MySQL | 8.0 | ์ฌ์ฉ์, ๋ฒํท๋ฆฌ์คํธ, ์ปค๋ฎค๋ํฐ, ๋๊ธ ๋ฐ ์ถ์ฒ ๋ฐ์ดํฐ ์ ์ฅ |
| AWS RDS | Cloud DB | ํ ๊ฐ๋ฐ ํ๊ฒฝ์์ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด์ |
| Gradle Kotlin DSL | Build Tool | ์์กด์ฑ ๊ด๋ฆฌ, ๋น๋ ๋ฐ ํ ์คํธ ์คํ |
| Git / GitHub | Version Control | ๊ธฐ๋ฅ ๋ธ๋์น ๊ธฐ๋ฐ ํ์ , ์ฝ๋ ๋ฆฌ๋ทฐ ๋ฐ ๋ฒ์ ๊ด๋ฆฌ |
| Swagger UI | API Collaboration | ํ๋ก ํธ์๋์ ์์ฒญยท์๋ต ๊ท๊ฒฉ ๊ณต์ ๋ฐ API ํ ์คํธ |
| ๋ด๋น ๊ธฐ๋ฅ | ์ ์ฉ ๊ธฐ์ | ๊ตฌํ ๋ด์ฉ |
|---|---|---|
| ์ปค๋ฎค๋ํฐ ํญยทํ๋ฉด | React Native, React Navigation | ๋ผ์ฐํ ํ๋ผ๋ฏธํฐ๋ฅผ ์ด๊ธฐ ํญ ์ํ์ API ํํฐ์ ๋๊ธฐํ |
| ๊ฒ์๊ธ ๊ฒ์ | Spring Data JPA, MySQL | ํค์๋์ ์ปค๋ฎค๋ํฐ ์ ํ์ ์กฐํฉํ ๊ฒ์ยท๊ทธ๋ฃน ์ง๊ณ |
| ๋๊ธยท๋๋๊ธ | JPA, Lazy Loading, DTO | ์๊ธฐ์ฐธ์กฐ ๊ณ์ธต ๊ตฌ์กฐ์ ๋จ๊ณ๋ณ ๋ถ๋ถ ์กฐํ ์ค๊ณ |
| ๊ฒ์๊ธ ์์ฑ | Spring Boot, Multipart | ํ ์คํธยท์ด๋ฏธ์ง ๊ฒ์๊ธ ์์ฒญ ์ฒ๋ฆฌ |
| ์ข์์ยท์ฆ๊ฒจ์ฐพ๊ธฐ | JdbcTemplate, JPA | ์ฌ์ฉ์๋ณ ์ค๋ณต ์ฒ๋ฆฌ์ ๋งคํ ๋ฐ์ดํฐ ๊ด๋ฆฌ |
| API ์ฐ๋ | Swagger, REST API | ํ๋ก ํธ์๋ ์ํ์ ๋ฐฑ์๋ ์์ฒญ ํ๋ผ๋ฏธํฐ ๊ท๊ฒฉ ์กฐ์จ |
๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๋ฒํท๋ฆฌ์คํธ์ ์ปค๋ฎค๋ํฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ธฐ ์ํด React Native๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ์ปค๋ฎค๋ํฐ ํ๋ฉด์์๋ useRoute()๋ก ์ด์ ํ๋ฉด์์ ์ ๋ฌ๋ initialTab์ ๋ฐ๊ณ , ์ด๋ฅผ ํ๋ฉด์ ์ด๊ธฐ ์ํ์ ๋ฐฑ์๋ communityType ํํฐ์ ํจ๊ป ๋ฐ์ํ์ต๋๋ค.
์ด๋ฅผ ํตํด ์ฌ์ฉ์๊ฐ ์ ํํ ํญ, ํ๋ฉด์ ํ์๋๋ ์ํ, API ์์ฒญ ์กฐ๊ฑด์ด ํ๋์ ๊ฐ์ผ๋ก ์ ์ง๋๋๋ก ๊ตฌ์ฑํ์ต๋๋ค.
Controller, Service, Repository์ ์ฑ ์์ ๋ถ๋ฆฌํ์ต๋๋ค.
- Controller: HTTP ์์ฒญยท์๋ต, ์์ฒญ DTO์ ์ธ์ฆ ์ฌ์ฉ์ ์ ๋ณด ์ ๋ฌ
- Service: ๊ฒ์๊ธยท๊ฒ์ยท๋๊ธยท์ฆ๊ฒจ์ฐพ๊ธฐ ๊ด๋ จ ๋น์ฆ๋์ค ๋ก์ง ์ํ
- Repository: JPA ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ ์ฅยท์กฐํ์ ์ง๊ณ ์ฟผ๋ฆฌ ์คํ
ํ๋ฉด์ ํ์ํ ๊ฐ์ Entity๋ฅผ ์ง์ ๋ ธ์ถํ์ง ์๊ณ Response DTO๋ก ๋ณํํ์ฌ ๋ฐํํ์ต๋๋ค.
๋๊ธ ์ํฐํฐ๊ฐ ๋ถ๋ชจ ๋๊ธ์ ์ฐธ์กฐํ๋ ์๊ธฐ์ฐธ์กฐ ์ฐ๊ด๊ด๊ณ๋ฅผ ์ฌ์ฉํด ๋๊ธ๊ณผ ๋๋๊ธ์ ํ๋์ ํ
์ด๋ธ์์ ๊ด๋ฆฌํ์ต๋๋ค. parentCommentId๊ฐ ์๋ ๋ฐ์ดํฐ๋ ์ต์์ ๋๊ธ, ๊ฐ์ด ์๋ ๋ฐ์ดํฐ๋ ๋๋๊ธ๋ก ๊ตฌ๋ถํ์ต๋๋ค.
์ฐ๊ด ์ํฐํฐ์๋ ์ง์ฐ ๋ก๋ฉ์ ์ ์ฉํ๊ณ , ์ต์ด ์์ฒญ์์๋ ์ต์์ ๋๊ธ๋ง ์กฐํํ์ต๋๋ค. ๋๋๊ธ์ ์ฌ์ฉ์๊ฐ ๋๊ธ์ ํผ์น ๋ ๋ณ๋ API๋ก ์กฐํํด ์ด๊ธฐ ์๋ต์ ๋ถํ์ํ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ์ง ์๋๋ก ์ค๊ณํ์ต๋๋ค.
๋ก๊ทธ์ธ ์ฑ๊ณต ์ LoginFilter์์ JWT๋ฅผ ๋ฐ๊ธํ๊ณ , ์ดํ ์์ฒญ์ JwtFilter๊ฐ Authorization: Bearer {token} ํค๋๋ฅผ ๊ฒ์ฆํ๋๋ก ๊ตฌ์ฑํ์ต๋๋ค. ์๋ฒ ์ธ์
์ ์์ฑํ์ง ์๋ Stateless ์ ์ฑ
์ ์ ์ฉํ์ผ๋ฉฐ, ๊ฒ์๊ธยท๋๊ธ ์์ ๋ฐ ์ญ์ ์ ์ธ์ฆ ์ฌ์ฉ์์ ์์ฑ์๋ฅผ ๋น๊ตํด ๊ถํ์ ๊ฒ์ฆํ์ต๋๋ค.
์ผ๋ฐ์ ์ธ ์ํฐํฐ ์ ์ฅ๊ณผ ์ฐ๊ด๊ด๊ณ ์ฒ๋ฆฌ๋ JPA๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๋ฐ๋ฉด ์ข์์ ์ค๋ณต ์ฌ๋ถ ํ์ธ๊ณผ ์นด์ดํธ์ฒ๋ผ SQL์ ์ง์ ์ ์ดํ๋ ํธ์ด ๋จ์ํ ๋ก์ง์ JdbcTemplate๋ก ์ฒ๋ฆฌํ์ต๋๋ค.
๋๋ฉ์ธ ์ค์ฌ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ ORM์ผ๋ก ์ ์งํ๋ฉด์, ์ง์ ์ฟผ๋ฆฌ๊ฐ ์ ํฉํ ๊ธฐ๋ฅ์๋ JdbcTemplate๋ฅผ ์ ํํด ๊ตฌํ ๋ณต์ก๋๋ฅผ ์ค์์ต๋๋ค.
์ฌ์ฉ์๊ฐ ์๋ฃํ ๋ฒํท๋ฆฌ์คํธ ์ ๋ชฉ์ ๊ธฐ๋ฐ์ผ๋ก ๋ค์ ๋ชฉํ ํค์๋๋ฅผ ์ถ์ฒํ๊ธฐ ์ํด Spring WebClient๋ก OpenAI API๋ฅผ ํธ์ถํ์ต๋๋ค. ํ๋กฌํํธ์ ์ญํ , ์ถ๋ ฅ ํ์๊ณผ ๊ธ์ง ์กฐ๊ฑด์ ๋ช ์ํ๊ณ , ๋ฐํ๋ ํค์๋๋ฅผ ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ ๊ฒ์์ ๋ค์ ํ์ฉํ์ต๋๋ค.
SpringDoc OpenAPI๋ก Controller์ API ๋ฌธ์๋ฅผ ์๋ ์์ฑํ์ต๋๋ค. ํ๋ก ํธ์๋์์ ์์ฒญ ํ๋ผ๋ฏธํฐ์ ์๋ต DTO๋ฅผ ์ง์ ํ์ธํ๊ณ ํ ์คํธํ ์ ์๋๋ก Swagger UI๋ฅผ ์ ๊ณตํ์ฌ API ์ฐ๋ ๊ณผ์ ์ ์์ฌ์ํต ๋น์ฉ์ ์ค์์ต๋๋ค.
flowchart LR
Client["React Native Client"]
Security["Spring Security Filter Chain"]
Controller["Controller"]
Service["Service"]
Repository["Spring Data JPA"]
Jdbc["JdbcTemplate"]
DB[("MySQL / AWS RDS")]
OpenAI["OpenAI API"]
Client -->|"HTTP Request + Bearer Token"| Security
Security --> Controller
Controller --> Service
Service --> Repository
Service --> Jdbc
Service --> OpenAI
Repository --> DB
Jdbc --> DB
Controller -->|"DTO Response"| Client
React Native
โ API ์์ฒญ
Spring Security / JWT
โ ์ธ์ฆ ์ ๋ณด ์ ๋ฌ
Controller
โ ์์ฒญ DTO ์ ๋ฌ
Service
โ ๋น์ฆ๋์ค ๋ก์ง ์ํ
Repository / JdbcTemplate
โ ์กฐํยท์ ์ฅ
MySQL
โ
Response DTO
Controller, Service, Repository ๊ณ์ธต์ ๋ถ๋ฆฌํ์ฌ ์์ฒญ ์ฒ๋ฆฌ, ๋น์ฆ๋์ค ๋ก์ง, ๋ฐ์ดํฐ ์ ๊ทผ์ ์ฑ ์์ ๊ตฌ๋ถํ์ต๋๋ค. ์ธ์ฆ๋ ์ฌ์ฉ์ ์ ๋ณด๋ Spring Security Context๋ฅผ ํตํด ๊ฒ์ฆํ๊ณ , ํด๋ผ์ด์ธํธ์๋ Entity๊ฐ ์๋ DTO ํํ์ ์๋ต์ ๋ฐํํ์ต๋๋ค.
- ์ปค๋ฎค๋ํฐ ์ฆ๊ฒจ์ฐพ๊ธฐ ๊ธฐ๋ฅ ๊ฐ๋ฐ
- ๊ฒ์๊ธ ๊ฒ์ยท์กฐํยท์์ฑ ๊ธฐ๋ฅ ๊ฐ๋ฐ
- ๋๊ธยท๋๋๊ธ ์์ฑ ๋ฐ ์กฐํ ๊ธฐ๋ฅ ๊ฐ๋ฐ
- ํ๋ก ํธ์๋์ ๋ฐฑ์๋ ๊ฐ ๋ฐ์ดํฐ ํ๋ฆ ์ค๊ณ
- ์ปค๋ฎค๋ํฐ API ์์ฒญ ํ๋ผ๋ฏธํฐ ๋ฐ ์๋ต DTO ์ฐ๋
- Figma๋ฅผ ํ์ฉํ UI ๊ธฐํ๋ถํฐ React Native ํ๋ฉด ๊ตฌํ๊น์ง ์ํ
- ์ฌ์ฉ์ ์ ํ ํญ๊ณผ ๋ฐฑ์๋ ํํฐ ์กฐ๊ฑด ๋๊ธฐํ
- ํค์๋ ๋ฐ ์ปค๋ฎค๋ํฐ ์ ํ ๊ธฐ๋ฐ ๊ฒ์ ๊ธฐ๋ฅ ๊ตฌํ
flowchart LR
A["์ปค๋ฎค๋ํฐ ํญ ์ ํ"] --> B["๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ"]
B --> C["ํค์๋ ๊ฒ์"]
C --> D["๊ฒ์๊ธ ์์ธ ์กฐํ"]
D --> E["๋๊ธยท๋๋๊ธ ์์ฑ"]
D --> F["์ข์์ยท์ฆ๊ฒจ์ฐพ๊ธฐ"]
๋๊ธ๊ณผ ๋๋๊ธ์ ํ๋์ ๋๊ธ ์ํฐํฐ๋ก ๊ด๋ฆฌํ๊ณ , parentCommentId๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ํํํ์ต๋๋ค.
๊ฒ์๊ธ
โโ ๋๊ธ A
โ โโ ๋๋๊ธ A-1
โ โโ ๋๋๊ธ A-2
โโ ๋๊ธ B
โโ ๋๋๊ธ B-1
parentCommentId = null: ์ต์์ ๋๊ธparentCommentId != null: ํน์ ๋๊ธ์ ์ํ ๋๋๊ธ- ์ต์ด ๊ฒ์๊ธ ์กฐํ ์ ์ต์์ ๋๊ธ๋ง ์กฐํ
- ์ฌ์ฉ์๊ฐ ๋๊ธ์ ํผ์น ๋ ๋๋๊ธ์ ๋ณ๋ API๋ก ์กฐํ
- ์ปค๋ฎค๋ํฐ์ ๋ถ๋ชจ ๋๊ธ์ ์ฐ๊ด๊ด๊ณ์ ์ง์ฐ ๋ก๋ฉ ์ ์ฉ
- DTO ๋ณํ์ ํตํด ๋ถํ์ํ ์ฐ๊ด ๋ฐ์ดํฐ ๋ ธ์ถ ๋ฐฉ์ง
flowchart LR
A["๊ฒ์๊ธ ์กฐํ"] --> B["์ต์์ ๋๊ธ ์กฐํ"]
B --> C["์ฌ์ฉ์๊ฐ ๋๊ธ ํผ์น๊ธฐ"]
C --> D["๋ถ๋ชจ ๋๊ธ ID ์ ๋ฌ"]
D --> E["๋๋๊ธ ๊ฐ๋ณ ์กฐํ"]
์ด ๊ตฌ์กฐ๋ฅผ ํตํด ๋๊ธ ์๊ฐ ์ฆ๊ฐํ๋๋ผ๋ ์ฒซ ํ๋ฉด์์ ํ์ํ ๋ฐ์ดํฐ๋ง ์กฐํํ ์ ์๋๋ก ์ค๊ณํ์ต๋๋ค.
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฒ์์ด์ ์ปค๋ฎค๋ํฐ ์ ํ์ API ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ฒ์๊ณผ ์ง๊ณ๋ฅผ ์ํํ๋๋ก ๊ตฌํํ์ต๋๋ค.
ํค์๋ ์
๋ ฅ
โ
๊ฒ์ API ์์ฒญ
โ
JPA ๊ฒ์ยท์ง๊ณ ์ฟผ๋ฆฌ ์คํ
โ
CommunitySearchResponse DTO ๋ณํ
โ
๋ชฉ๋ก ๋๋ ๊ทธ๋ํ ์๊ฐํ
์ฃผ์ ์ฒ๋ฆฌ ๋ด์ฉ:
communityDiversity์ปฌ๋ผ์ ํค์๋๊ฐ ํฌํจ๋ ๊ฒ์๊ธ ๊ฒ์communityType์ ํจ๊ป ์ ๋ฌํ์ฌ ํ์ฌ ๊ฒ์ํ ๋ฒ์๋ก ๊ฒ์ ๋์ ์ ํ- ์ปค๋ฎค๋ํฐ ์ ํ๋ณ ๊ฒ์๊ธ ์ ๊ทธ๋ฃนํ
- ์ง๊ณ ๊ฒฐ๊ณผ๋ฅผ DTO๋ก ๋ณํํ์ฌ ํ๋ก ํธ์๋์ ๋ฐํ
- DB์์ ํํฐ๋ง๊ณผ ์ง๊ณ๋ฅผ ์ฒ๋ฆฌํ์ฌ ์๋ฒยทํด๋ผ์ด์ธํธ์ ์ถ๊ฐ ์ฐ์ฐ ์ต์ํ
์์ ์์ฒญ:
GET /search?keyword=์ฌํ&communityType=TRAVELFigma๋ก ์ปค๋ฎค๋ํฐ ํ๋ฉด์ ํญ, ๊ฒ์์ฐฝ, ๊ฒ์๊ธ ๋ชฉ๋ก๊ณผ ๋๊ธ UI๋ฅผ ์ค๊ณํ๊ณ React Native๋ก ๊ตฌํํ์ต๋๋ค.
sequenceDiagram
participant User as ์ฌ์ฉ์
participant RN as React Native
participant API as Spring Boot API
participant DB as MySQL
User->>RN: ์ปค๋ฎค๋ํฐ ํญ ์ ํ
RN->>RN: ๋ผ์ฐํ
ํ๋ผ๋ฏธํฐ๋ก initialTab ์ค์
RN->>API: communityType + ๊ฒ์ ์กฐ๊ฑด ์์ฒญ
API->>DB: ์กฐ๊ฑด์ ๋ง๋ ๊ฒ์๊ธ ์กฐํ
DB-->>API: ๊ฒ์๊ธ ๋ชฉ๋ก
API-->>RN: Response DTO
RN-->>User: ์ ํํ ํญ์ ๊ฒ์๊ธ ๋ ๋๋ง
ํ๋ก ํธ์๋์ ํ๋ฉด ์ํ์ ๋ฐฑ์๋์ ๊ฒ์ ์กฐ๊ฑด์ด ๋์ผํ ๊ฐ์ ์ฌ์ฉํ๋๋ก ์ค๊ณํด, ์ฌ์ฉ์๊ฐ ์ ํํ ์ปค๋ฎค๋ํฐ ๋ฒ์์ ๋ง๋ ๋ฐ์ดํฐ๊ฐ ์ผ๊ด๋๊ฒ ํ์๋๋๋ก ํ์ต๋๋ค.
์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ์ ์ด๋ฏธ์ง, ๋๊ธ, ์ข์์์ ์ฐ๊ด๊ด๊ณ๋ฅผ ๊ฐ์ง๋๋ค.
Community ์ํฐํฐ์ ์ฐ๊ด ์ปฌ๋ ์
์ cascade = CascadeType.ALL๊ณผ orphanRemoval = true๋ฅผ ์ ์ฉํ์ฌ ๊ฒ์๊ธ ์ญ์ ์ ์ฐ๊ด ๋ฐ์ดํฐ๋ ํจ๊ป ์ ๋ฆฌ๋๋๋ก ๊ตฌ์ฑํ์ต๋๋ค.
์ด๋ฅผ ํตํด ์๋น์ค ๋ก์ง์์ ์ฐ๊ด ๋ฐ์ดํฐ๋ง๋ค ๋ณ๋์ ์ญ์ ์ฝ๋๋ฅผ ๋ฐ๋ณตํ์ง ์๊ณ , ๊ฒ์๊ธ์ ์ค์ฌ์ผ๋ก ๋ฐ์ดํฐ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ์ต๋๋ค.
๋์ฉ๋ ๋ฐ์ดํฐ ํ๊ฒฝ์์๋ Cascade ์ญ์ ๋ฒ์์ ์ฟผ๋ฆฌ ์๋ฅผ ์ ๊ฒํ ํ์๊ฐ ์์ผ๋ฉฐ, ์ด๋ ํฅํ ์ฑ๋ฅ ๊ฐ์ ํญ๋ชฉ์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
์ปค๋ฎค๋ํฐ ํ๋ฉด์ ์ด๊ธฐ ํญ์ด All๋ก ๊ณ ์ ๋์ด ์์ด, ์ด์ ํ๋ฉด์์ ์ฌ์ฉ์๊ฐ ์ ํํ ์ปค๋ฎค๋ํฐ ์ ํ์ด ๋ฐ์๋์ง ์์์ต๋๋ค. ํ๋ฉด์ ํ์๋ ํญ๊ณผ API์ ์ ๋ฌ๋๋ ํํฐ๊ฐ์ด ๋ฌ๋ผ ๋ค๋ฅธ ๊ฒ์๊ธ์ด ์กฐํ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ผ์ฐํ ๊ณผ์ ์์ ์ ๋ฌ๋ ํญ ์ ๋ณด๊ฐ ํ๋ฉด์ ์ด๊ธฐ ์ํ์ ๋ฐ์๋์ง ์์๊ณ , ํ๋ก ํธ์๋๊ฐ ํญ์ ๋์ผํ ๊ฐ์ผ๋ก API๋ฅผ ํธ์ถํ๊ณ ์์์ต๋๋ค.
useRoute()๋ก ๋ผ์ฐํ ํ๋ผ๋ฏธํฐ์initialTab์์useState(initialTab)์ผ๋ก ์ด๊ธฐ ํญ ์ํ ๋์ ์ค์ - ํ์ฌ ํญ ๊ฐ์ ๋ฐฑ์๋์
communityTypeํํฐ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ - ํ๋ฉด ์ํ์ API ์์ฒญ ์กฐ๊ฑด์ ํ๋์ ๊ธฐ์ค์ผ๋ก ๋๊ธฐํ
์ฌ์ฉ์๊ฐ ์ ํํ ์ปค๋ฎค๋ํฐ ํญ๊ณผ ์ค์ ์กฐํ ๊ฒฐ๊ณผ๊ฐ ์ผ์นํ๋๋ก ๊ฐ์ ํ์ต๋๋ค. ํ๋ฉด ์ง์ ๊ฒฝ๋ก์ ๋ฐ๋ผ ์ฌ๋ฐ๋ฅธ ์ด๊ธฐ ํญ์ด ํ์๋๊ณ , ํด๋น ๋ฒ์์ ๊ฒ์๊ธ๋ง ์กฐํ๋ฉ๋๋ค.
Before
ํ๋ฉด ํญ: TRAVEL
API ํํฐ: ALL
After
ํ๋ฉด ํญ: TRAVEL
API ํํฐ: TRAVEL
ํน์ ๊ฒ์ํ์์ ํค์๋๋ฅผ ๊ฒ์ํด๋ ๊ฒ์ ์กฐ๊ฑด๊ณผ ๊ด๊ณ์์ด ์ ์ฒด ๊ฒ์๊ธ์ด ์ถ๋ ฅ๋๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
API ์์ฒญ์ ๊ฒ์ ํค์๋์ธ communityDiversity๋ง ํฌํจ๋๊ณ , ๊ฒ์ํ ๋ฒ์๋ฅผ ๊ตฌ๋ถํ๋ communityType์ด ๋๋ฝ๋์ด ์์์ต๋๋ค.
- ๊ฒ์ ์์ฒญ์
communityDiversity์communityType์ ํจ๊ป ์ ๋ฌ - ๋ฐฑ์๋ ์ฟผ๋ฆฌ์์ ๋ ์กฐ๊ฑด์ ๋์์ ์ ์ฉ
- ํ๋ก ํธ์๋์ ์ ํ ํญ๊ณผ ๊ฒ์ ํ๋ผ๋ฏธํฐ๋ฅผ ๋์ผํ ์ํ๊ฐ์์ ์์ฑ
์ฌ์ฉ์๊ฐ ์ ํํ ๊ฒ์ํ ๋ฒ์ ์์์ ํค์๋์ ์ผ์นํ๋ ๊ฒ์๊ธ๋ง ์ ํํ๊ฒ ์กฐํํ ์ ์๋๋ก ๊ฒ์ ๊ธฐ๋ฅ์ ์ ์ํํ์ต๋๋ค.
Before
keyword=์ฌํ
After
communityDiversity=์ฌํ
communityType=TRAVEL
๊ฒ์๊ธ์ ์กฐํํ ๋ ๋๊ธ๊ณผ ๋ชจ๋ ๋๋๊ธ์ ํ ๋ฒ์ ๋ถ๋ฌ์ค๋ฉด ์ด๊ธฐ ์๋ต ๋ฐ์ดํฐ๊ฐ ์ปค์ง๊ณ , ๋๊ธ ์๊ฐ ๋ง์์ง์๋ก DB ์กฐํ์ ๋คํธ์ํฌ ๋ถํ๊ฐ ์ฆ๊ฐํ ์ ์์ต๋๋ค.
parentCommentId๊ธฐ๋ฐ์ ์๊ธฐ์ฐธ์กฐํ ๋๊ธ ๊ตฌ์กฐ ์ ์ฉ- ์ต์ด ์กฐํ ์ ์ต์์ ๋๊ธ๋ง ๋ฐํ
- ๋๋๊ธ์ ์ฌ์ฉ์๊ฐ ํผ์น ๋ ๋ถ๋ชจ ๋๊ธ ID๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ณ๋ ์กฐํ
- ์ฐ๊ด ์ํฐํฐ์ Lazy Loading ์ ์ฉ
- DTO๋ฅผ ํตํด ํ์ํ ํ๋๋ง ์๋ต
ํ์ํ ๋๊ธ๋ง ๋จ๊ณ์ ์ผ๋ก ์กฐํํ ์ ์๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ด๊ธฐ ํ๋ฉด์์ ๋ถํ์ํ ๋๋๊ธ๊ณผ ์ฐ๊ด ๋ฐ์ดํฐ๋ฅผ ๋ก๋ฉํ์ง ์์ผ๋ฉฐ, ๊ณ์ธต ๊ตฌ์กฐ๋ฅผ ๋ช ํํ๊ฒ ์ ์งํด ๊ธฐ๋ฅ ํ์ฅ๊ณผ ์ ์ง๋ณด์๊ฐ ์ฉ์ดํด์ก์ต๋๋ค.
| ๊ธฐ๋ฅ | Method | Endpoint | ์ค๋ช | ์ธ์ฆ |
|---|---|---|---|---|
| ๊ฒ์๊ธ ๋ชฉ๋ก ์กฐํ | GET |
/api/posts |
์ ํ๋ณ ๊ฒ์๊ธ ๋ชฉ๋ก ๋ฐ ํ์ด์ง๋ค์ด์ | ์ ํ |
| ๊ฒ์๊ธ ์์ธ ์กฐํ | GET |
/api/posts/{communityId} |
๊ฒ์๊ธ๊ณผ ์ด๋ฏธ์ง ์ ๋ณด ์กฐํ | ์ ํ |
| ๊ฒ์๊ธ ํค์๋ ๊ฒ์ | GET |
/search |
ํค์๋์ ์ปค๋ฎค๋ํฐ ์ ํ ๊ธฐ๋ฐ ๊ฒ์ | ์ ํ |
| ๊ฒ์๊ธ ์์ฑ | POST |
/api/posts |
ํ ์คํธ ๋๋ ์ด๋ฏธ์ง ํฌํจ ๊ฒ์๊ธ ๋ฑ๋ก | ํ์ |
| ๊ฒ์๊ธ ์์ | PATCH |
/api/posts/{communityId} |
์์ฑ์ ๊ฒ์๊ธ ์์ | ํ์ |
| ๊ฒ์๊ธ ์ญ์ | DELETE |
/api/posts/{communityId} |
์์ฑ์ ๊ฒ์๊ธ ์ญ์ | ํ์ |
| ๊ฒ์๊ธ ์ข์์ | POST |
/api/posts/{communityId}/like |
์ข์์ ์ค๋ณต ๊ฒ์ฆ ๋ฐ ์นด์ดํธ ๋ฐํ | ํ์ |
| ์ฆ๊ฒจ์ฐพ๊ธฐ ์ถ๊ฐยทํด์ | POST |
/api/posts/{communityId}/scrap |
๊ด์ฌ ๊ฒ์๊ธ ์ ์ฅ ๋๋ ํด์ | ํ์ |
| ๊ธฐ๋ฅ | Method | Endpoint | ์ค๋ช | ์ธ์ฆ |
|---|---|---|---|---|
| ์ต์์ ๋๊ธ ์กฐํ | GET |
/api/posts/{communityId}/comments |
๊ฒ์๊ธ์ ์ต์์ ๋๊ธ๋ง ์กฐํ | ์ ํ |
| ๋๊ธ ์์ฑ | POST |
/api/posts/{communityId}/comments |
์ ๋๊ธ ๋ฑ๋ก | ํ์ |
| ๋๋๊ธ ์กฐํ | GET |
/api/comments/{commentId}/replies |
๋ถ๋ชจ ๋๊ธ์ ๋๋๊ธ ์กฐํ | ์ ํ |
| ๋๋๊ธ ์์ฑ | POST |
/api/comments/{commentId}/replies |
ํน์ ๋๊ธ์ ๋๋๊ธ ๋ฑ๋ก | ํ์ |
| ๋๊ธ ์์ | PATCH |
/api/comments/{commentId} |
์์ฑ์ ๋๊ธ ์์ | ํ์ |
| ๋๊ธ ์ญ์ | DELETE |
/api/comments/{commentId} |
์์ฑ์ ๋๊ธ ์ญ์ | ํ์ |
| ๋๊ธ ์ข์์ | POST |
/api/comments/{commentId}/like |
๋๊ธ ์ข์์ ์ฒ๋ฆฌ | ํ์ |
| ๊ธฐ๋ฅ | Method | Endpoint | ์ค๋ช |
|---|---|---|---|
| ๋ก๊ทธ์ธ | POST |
/login |
JWT ๋ฐ๊ธ |
| ๋ฒํท๋ฆฌ์คํธ ์์ฑ | POST |
/api/bucketlist |
์ ๋ชฉํ ๋ฑ๋ก |
| ๋ฒํท๋ฆฌ์คํธ ๋ชฉ๋ก | GET |
/api/bucketlist |
ํ ๊ณ ์ ยท๋ชฉํ์ผ ๊ธฐ์ค ์กฐํ |
| ๋ฒํท๋ฆฌ์คํธ ์๋ฃ | PUT |
/api/bucketlist/{id}/achieve |
๋ชฉํ ์๋ฃ ๋ฐ ๋ฌ์ฑ์ผ ๊ธฐ๋ก |
| AI ๋ชฉํ ์ถ์ฒ | POST |
/ai/recommend |
์๋ฃ ์ด๋ ฅ ๊ธฐ๋ฐ ๋ค์ ๋ชฉํ ์ถ์ฒ |
| ๋ช ์์ ์ ๋น | GET |
/api/hall-of-fame |
์ธ๊ธฐ ํธ๋กํผ ๊ฒ์๊ธ ์กฐํ |
์ค์ ์ ์ฅ์์ Controller ๋งคํ๊ณผ ๋ค๋ฅผ ๊ฒฝ์ฐ Endpoint๋ฅผ ์ต์ข ์ฝ๋ ๊ธฐ์ค์ผ๋ก ์์ ํด ์ฃผ์ธ์.
erDiagram
User ||--o{ BucketList : owns
User ||--o{ Community : writes
User ||--o{ Comment : writes
User ||--o{ CommunityScrap : scraps
BucketList ||--o{ BucketListLog : records
BucketList ||--o{ Community : shares
Community ||--o{ Image : contains
Community ||--o{ Comment : contains
Community ||--o{ CommunityLike : receives
Community ||--o{ CommunityScrap : receives
Comment ||--o{ Comment : replies
Comment ||--o{ CommentLike : receives
Community์BucketList๋ ์ ํ์ ์ฐ๊ด๊ด๊ณ๋ก ๊ตฌ์ฑ- ๋ฒํท๋ฆฌ์คํธ๊ฐ ์๋ ์ผ๋ฐ ์ปค๋ฎค๋ํฐ ๊ฒ์๊ธ๋ ์์ฑ ๊ฐ๋ฅ
Comment.parentCommentId๋ก ๋๊ธยท๋๋๊ธ ๊ณ์ธต ๊ตฌ์กฐ ํํ- ๊ฒ์๊ธยท๋๊ธ ์ข์์๋ฅผ ๋ณ๋ ํ ์ด๋ธ๋ก ๊ด๋ฆฌํ์ฌ ์ฌ์ฉ์๋ณ ์ค๋ณต ๋ฐฉ์ง
- ์ฆ๊ฒจ์ฐพ๊ธฐ๋ฅผ ์ฌ์ฉ์์ ๊ฒ์๊ธ ๊ฐ ๋งคํ ํ ์ด๋ธ๋ก ๊ด๋ฆฌ
- ๊ฒ์๊ธ ์ญ์ ์ ์ด๋ฏธ์ง, ๋๊ธ ๋ฑ ์ฐ๊ด ๋ฐ์ดํฐ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ
Spring Security์ JWT๋ฅผ ์ฌ์ฉํ Stateless ์ธ์ฆ ๋ฐฉ์์ ์ ์ฉํ์ต๋๋ค.
sequenceDiagram
participant Client as React Native
participant JwtFilter as JwtFilter
participant JwtUtil as JwtUtil
participant UserService as UserDetailsService
participant Context as SecurityContextHolder
Client->>JwtFilter: Authorization: Bearer {token}
JwtFilter->>JwtUtil: ํ ํฐ ๊ฒ์ฆ ๋ฐ ์ฌ์ฉ์๋ช
์ถ์ถ
JwtUtil-->>JwtFilter: username
JwtFilter->>UserService: ์ฌ์ฉ์ ์ ๋ณด ์กฐํ
UserService-->>JwtFilter: UserDetails
JwtFilter->>Context: Authentication ์ ์ฅ
JwtFilter->>Client: ๋ค์ ํํฐ ๋ฐ API ์ฒ๋ฆฌ
- BCrypt ๊ธฐ๋ฐ ๋น๋ฐ๋ฒํธ ์ํธํ
- JWT HS256 ์๋ช
- ์๋ฒ ์ธ์ ์ ์์ฑํ์ง ์๋ Stateless ์ ์ฑ
- URL ๋จ์ ๊ณต๊ฐยท์ธ์ฆ API ๋ถ๋ฆฌ
- ์ธ์ฆ ์ฌ์ฉ์๋ SecurityContext์์ ์กฐํ
- ๊ฒ์๊ธ ๋ฐ ๋๊ธ ์์ ยท์ญ์ ์ ์์ฑ์ ๊ฒ์ฆ
{
"status": "SUCCESS",
"message": null,
"data": {
"example": "response"
}
}ApiResponsTemplate<T>๋ฅผ ์ฌ์ฉํ์ฌ API ์ฑ๊ณต ์๋ต ํ์์ ํต์ผํ์ต๋๋ค. Controller๋ Entity๋ฅผ ์ง์ ๋
ธ์ถํ์ง ์๊ณ , ํ๋ฉด์ ํ์ํ ๋ฐ์ดํฐ๋ง ์๋ต DTO๋ก ๋ณํํด ๋ฐํํฉ๋๋ค.
src/
โโโ main/
โโโ java/
โ โโโ com/guesthouse/wishboard/
โ โโโ config/
โ โ โโโ SecurityConfig.java
โ โ โโโ SwaggerConfig.java
โ โ โโโ WebConfig.java
โ โโโ controller/
โ โ โโโ PostController.java
โ โ โโโ CommentController.java
โ โ โโโ CommunityController.java
โ โ โโโ CommunityScrapController.java
โ โ โโโ KeywordController.java
โ โ โโโ BucketListController.java
โ โ โโโ AIController.java
โ โ โโโ TrophyController.java
โ โโโ service/
โ โ โโโ PostService.java
โ โ โโโ CommentService.java
โ โ โโโ CommunityService.java
โ โ โโโ CommunityScrapService.java
โ โ โโโ BucketListService.java
โ โ โโโ AIService.java
โ โโโ repository/
โ โ โโโ CommunityRepository.java
โ โ โโโ CommentRepository.java
โ โ โโโ CommunityScrapRepository.java
โ โ โโโ BucketListRepository.java
โ โโโ entity/
โ โ โโโ User.java
โ โ โโโ Community.java
โ โ โโโ Comment.java
โ โ โโโ CommunityScrap.java
โ โ โโโ BucketList.java
โ โโโ dto/
โ โ โโโ PostRequest.java
โ โ โโโ PostResponse.java
โ โ โโโ CommunitySearchResponse.java
โ โ โโโ CommentResponse.java
โ โโโ global/
โ โ โโโ ApiResponsTemplate.java
โ โโโ jwt/
โ โโโ JwtUtil.java
โ โโโ JwtFilter.java
โ โโโ LoginFilter.java
โโโ resources/
โโโ application.yml
- Java 17
- MySQL 8.0
- Gradle
- Node.js ๋ฐ React Native ๊ฐ๋ฐ ํ๊ฒฝ
application.yml ๋๋ ์ด์ ํ๊ฒฝ ๋ณ์์ ๋ค์ ๊ฐ์ ์ค์ ํฉ๋๋ค.
spring:
datasource:
url: ${DB_URL:jdbc:mysql://localhost:3306/wishboard_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul}
username: ${DB_USERNAME:root}
password: ${DB_PASSWORD}
jwt:
secret: ${JWT_SECRET}
openai:
api-key: ${OPENAI_API_KEY}DB ๋น๋ฐ๋ฒํธ, JWT Secret, OpenAI API Key์ ๊ฐ์ ๋ฏผ๊ฐ ์ ๋ณด๋ ์ ์ฅ์์ ์ง์ ์ปค๋ฐํ์ง ์๊ณ ํ๊ฒฝ ๋ณ์๋ก ๊ด๋ฆฌํด์ผ ํฉ๋๋ค.
# ํ๋ก์ ํธ ๋น๋
./gradlew build
# ์ ํ๋ฆฌ์ผ์ด์
์คํ
./gradlew bootRun
# ํ
์คํธ ์คํ
./gradlew testhttp://localhost:8080/swagger-ui/index.html
npm install
npm startReact Native ์คํ ๋ช ๋ น์ Expo ์ฌ์ฉ ์ฌ๋ถ์ ์ค์
package.json์คํฌ๋ฆฝํธ์ ๋ง๊ฒ ์์ ํด ์ฃผ์ธ์.
WishBoard์ ์ฃผ์ ์ฌ์ฉ์ ํ๋ฆ๊ณผ ๊ธฐ๋ฅ์ ํ๋ฉด๋ณ๋ก ํ์ธํ ์ ์์ต๋๋ค.
- React Native์ Spring Boot ๊ฐ REST API ์ฐ๋
- Figma ๊ธฐํ๋ถํฐ ๋ชจ๋ฐ์ผ ํ๋ฉด ๊ตฌํ๊น์ง์ ์ ์ฒด ๊ณผ์
- ์ฌ์ฉ์ ํ๋ฉด ์ํ์ ๋ฐฑ์๋ ๊ฒ์ ์กฐ๊ฑด ๋๊ธฐํ
- Spring Data JPA๋ฅผ ํ์ฉํ ํค์๋ ๊ฒ์๊ณผ ๊ทธ๋ฃน ์ง๊ณ
- ์๊ธฐ์ฐธ์กฐ ์ฐ๊ด๊ด๊ณ๋ฅผ ํ์ฉํ ๋๊ธยท๋๋๊ธ ๋ชจ๋ธ๋ง
- ์ง์ฐ ๋ก๋ฉ๊ณผ ๋ถ๋ถ ์กฐํ๋ฅผ ๊ณ ๋ คํ ๋๊ธ ์กฐํ ๊ตฌ์กฐ ์ค๊ณ
- Spring Security์ JWT ๊ธฐ๋ฐ ์ธ์ฆ ํ๋ฆ ์ดํด
- ํ์๊ณผ API ์์ฒญยท์๋ต ๊ท๊ฒฉ์ ์กฐ์จํ ํ์ ๊ฒฝํ
- ๋๊ธ ๋ชฉ๋ก ์ฟผ๋ฆฌ์ N+1 ๋ฐ์ ์ฌ๋ถ ์ธก์ ๋ฐ Fetch JoinยทEntityGraph ์ ์ฉ ๊ฒํ
- ๋๊ธ ์์ ์๋ต ํฌ๊ธฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถ๋ถ ์กฐํ ํจ๊ณผ ์ ๋ํ
- ๊ฒ์ ์กฐ๊ฑด ์ฆ๊ฐ์ ๋๋นํ QueryDSL ๊ธฐ๋ฐ ๋์ ์ฟผ๋ฆฌ ์ ํ
- ์ปค๋ฎค๋ํฐ ์ธ๊ธฐ ๊ฒ์์ด์ ๊ฒ์๊ธ ๊ฒฐ๊ณผ ์บ์ฑ
- Refresh Token ๊ธฐ๋ฐ ์ธ์ฆ ๊ตฌ์กฐ ๋ณด์
- ์ด๋ฏธ์ง ์ ์ฅ์๋ฅผ ๋ก์ปฌ ํ๊ฒฝ์์ Object Storage๋ก ์ด์
@ControllerAdvice๊ธฐ๋ฐ ์ ์ญ ์์ธ ์๋ต ํ์คํ- Service ๋ ์ด์ด ๋จ์ ํ ์คํธ์ API ํตํฉ ํ ์คํธ ๊ฐํ
๋ชฉํ๋ฅผ ๊ธฐ๋กํ๊ณ , ํจ๊ป ๋ฌ์ฑํ๋ฉฐ, ๋ค์ ๋์ ์ผ๋ก ์ด์ด์ง๋ WishBoard