AI ๊ธฐ๋ฐ ํ์ต ๋ฃจํด ๊ด๋ฆฌ ๋ฐ ํด์ฆ ์์ฑ ์์คํ ์ ๋ฐฑ์๋ ์๋ฒ
SSP-server๋ ์ฌ์ฉ์ ๋ง์ถคํ ์๋น์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ๋ฐ์ดํฐ์ ํจ์จ์ ์ธ ์ฒ๋ฆฌ์ ์์ ์ ์ธ API ํ๊ฒฝ์ ๊ตฌ์ถํ๋ ๊ฒ์ ๋ชฉํ๋ก ํฉ๋๋ค.
- GPT-4o API ์ฐ๋: ์ฌ์ฉ์๊ฐ ์ ๋ก๋ํ ํ์ต ์๋ฃ(ํ ์คํธ, PDF, ์ด๋ฏธ์ง)๋ฅผ ๋ถ์ํ์ฌ ๋ง์ถคํ ํด์ฆ ์๋ ์์ฑ
- ๋ค์ํ ๋ฌธ์ ์ ํ: ๊ฐ๊ด์, OX, ๋น์นธ ์ฑ์ฐ๊ธฐ ๋ฌธ์ ์ง์
- ํค์๋ ๊ธฐ๋ฐ ์ถ์ : ํน์ ํค์๋๋ฅผ ์ค์ฌ์ผ๋ก ํ ๋ฌธ์ ์์ฑ์ผ๋ก ํ์ต ํจ์จ์ฑ ๊ทน๋ํ
- Tesseract OCR + OpenCV: ์ด๋ฏธ์ง์์ ํ ์คํธ ์๋ ์ถ์ถ ๋ฐ ์ ์ฒ๋ฆฌ
- PDF ํ์ฑ: Apache PDFBox๋ฅผ ํ์ฉํ PDF ๋ฌธ์ ํ ์คํธ ์ถ์ถ
- ๋์ฉ๋ ์ฒ๋ฆฌ: ์ต๋ 30,000์๊น์ง ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌ
- Selenium WebDriver: ์๋ธ๋ฆฌํ์ ์๊ฐํ ์๋ ํฌ๋กค๋ง
- ๋์์ฑ ์ ์ด: Semaphore + ThreadLocal ํจํด์ผ๋ก ์์ ์ ์ธ ๋ฉํฐ์ค๋ ๋ ํฌ๋กค๋ง (์ต๋ 3๋ช ๋์ ์ฒ๋ฆฌ)
- ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ: ์ต๋ 900MB๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ์ ํ
- ๋ณต์ต ์๋ฆผ: ์ฃผ๊ฐ ํด์ฆ ์์ฝ ์ ๊ณต ๋ฐ ๋ณต์ต ํ์ ํญ๋ชฉ ์๋ ๊ฐฑ์
- ํ์ต ํต๊ณ: ์ฌ์ฉ์๋ณ ํด์ฆ ์์ ํ์, ์ ๋ต๋ฅ ์ถ์
- Kakao & Apple OAuth 2.0: ๊ฐํธํ ์์ ๋ก๊ทธ์ธ ์ง์
- JWT ๊ธฐ๋ฐ ์ธ์ฆ: ๋ฌด์ํ(Stateless) ์ธ์ฆ์ผ๋ก ํ์ฅ์ฑ ํ๋ณด
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| Spring Boot | 3.4.4 | ์์ฐ์ฑ ๋์ ์ํฐํ๋ผ์ด์ฆ ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ ํ๋ ์์ํฌ |
| Java | 21 | Virtual Threads ๋ฑ ์ต์ ์ฑ๋ฅ ๊ฐ์ ๊ธฐ๋ฅ ํ์ฉ |
| Gradle | 8.x | ๋น ๋ฅด๊ณ ์ ์ฐํ ๋น๋ ์๋ํ ๋๊ตฌ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| MySQL | 8.x | ์์ ์ ์ด๊ณ ๊ฒ์ฆ๋ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค |
| Spring Data JPA | 3.4.4 | ORM์ ํตํ ์์ฐ์ ์ธ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ๊ทผ ๋ฐ ๊ด๋ฆฌ |
| Hibernate | 6.x | JPA ๊ตฌํ์ฒด๋ก N+1 ์ฟผ๋ฆฌ ๋ฐฉ์ง ๋ฐ ์ต์ ํ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| Spring Security | 6.x | ํฌ๊ด์ ์ธ ๋ณด์ ํ๋ ์์ํฌ๋ก ์ธ์ฆ/์ธ๊ฐ ์ฒ๋ฆฌ |
| JWT (jjwt) | 0.11.5 | ๋ฌด์ํ ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ์ผ๋ก ํ์ฅ์ฑ ํ๋ณด |
| OAuth 2.0 | - | Kakao/Apple ์์ ๋ก๊ทธ์ธ ๊ตฌํ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| OpenAI API | GPT-4o | ํ์ต ์๋ฃ ๋ถ์ ๋ฐ ๋ง์ถคํ ํด์ฆ ์๋ ์์ฑ |
| RestTemplate | - | ์ธ๋ถ API ์ฐ๋ ๋ฐ Connection Pooling |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| Tesseract OCR | 5.13.0 | ์ด๋ฏธ์ง์์ ํ ์คํธ ์ถ์ถ |
| OpenCV | 4.5.4 | ์ด๋ฏธ์ง ์ ์ฒ๋ฆฌ ๋ฐ ํ์ง ๊ฐ์ |
| Apache PDFBox | 3.0.4 | PDF ๋ฌธ์ ํ ์คํธ ์ถ์ถ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| Selenium WebDriver | 4.20.0 | ๋์ ์น ํ์ด์ง ํฌ๋กค๋ง (์๋ธ๋ฆฌํ์ ์๊ฐํ) |
| WebDriverManager | 5.8.0 | ChromeDriver ์๋ ์ค์ ๋ฐ ๋ฒ์ ๊ด๋ฆฌ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| Docker | - | ์ปจํ ์ด๋ ๊ธฐ๋ฐ ๋ฐฐํฌ๋ก ํ๊ฒฝ ์ผ๊ด์ฑ ํ๋ณด |
| GitHub Actions | - | ์ง์์ ํตํฉ(CI)์ผ๋ก ์ฝ๋ ํ์ง ์๋ ๊ฒ์ฆ |
| ๊ธฐ์ | ๋ฒ์ | ์ฌ์ฉ ์ด์ |
|---|---|---|
| SpringDoc OpenAPI | 2.2.0 | Swagger UI๋ฅผ ํตํ API ๋ฌธ์ ์๋ ์์ฑ |
| Lombok | - | ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋ ์ ๊ฑฐ๋ก ์์ฐ์ฑ ํฅ์ |
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ ๋ฐ ํ ์ด๋ธ ๊ฐ ๊ด๊ณ๋ฅผ ๋ํ๋ ๋๋ค.
์ ์ฒด ์์คํ ์ ๊ตฌ์ฑ ์์ ๋ฐ ๋ฐ์ดํฐ ํ๋ฆ์ ๋ํ๋ ๋๋ค.
POST /quizzes- ํด์ฆ ์์ฑGET /quizzes- ์ฌ์ฉ์ ํด์ฆ ๋ชฉ๋ก ์กฐํPOST /quizzes/{quizId}/attempts- ํด์ฆ ์์DELETE /quizzes/{quizId}- ํด์ฆ ์ญ์
POST /calendar/timetable- ์๋ธ๋ฆฌํ์ ์๊ฐํ ํฌ๋กค๋ง ๋ฐ ์ ์ฅGET /calendar/timetable- ์ ์ฅ๋ ์๊ฐํ ์กฐํ
POST /auth/kakao- Kakao ๋ก๊ทธ์ธPOST /auth/apple- Apple ๋ก๊ทธ์ธ
- SRP ์ค์: QuizService๋ฅผ OpenAiClient, QuizPromptBuilder, QuizGrader๋ก ๋ถ๋ฆฌ
- ๋งค์ง ๋๋ฒ ์ ๊ฑฐ: QuizConstants, QuizStatus Enum ๋์
- N+1 ์ฟผ๋ฆฌ ๋ฐฉ์ง: @EntityGraph ๋ฐ Bulk ์ฐ์ฐ ์ ์ฉ
- ํ์ ์์ ์ฑ: Map โ DTO ๋ณํ
- Semaphore + ThreadLocal ํจํด: ์ต๋ 3๊ฐ WebDriver ๋์ ์คํ์ผ๋ก Race Condition ํด๊ฒฐ
- ๋ฉ๋ชจ๋ฆฌ ๋ณดํธ: ์ต๋ 900MB๋ก ์ฌ์ฉ๋ ์ ํ
- ์ฑ๋ฅ ํฅ์: 3๋ช ๋์ ์ฒ๋ฆฌ๋ก 3๋ฐฐ ์ฑ๋ฅ ๊ฐ์
- GitHub Actions: ์๋ ๋น๋๋ก ์ฝ๋ ํ์ง ๊ฒ์ฆ
- Docker ๋ฐฐํฌ: ์ปจํ ์ด๋ ๊ธฐ๋ฐ ์ผ๊ด๋ ๋ฐฐํฌ ํ๊ฒฝ
SSP-server/
โโโ src/main/java/group4/opensource_server/
โ โโโ auth/ # ์ธ์ฆ ๊ด๋ จ (JWT, OAuth)
โ โโโ calendar/ # ์๊ฐํ ํฌ๋กค๋ง
โ โ โโโ controller/
โ โ โโโ service/ # EverytimeCrawler, TimetableParser, WebDriverManager
โ โ โโโ domain/ # Entity, Repository, Constants
โ โ โโโ dto/
โ โ โโโ exception/
โ โโโ quiz/ # ํด์ฆ ์์ฑ ๋ฐ ๊ด๋ฆฌ
โ โ โโโ controller/
โ โ โโโ service/ # QuizService, OpenAiClient, QuizPromptBuilder, QuizGrader
โ โ โโโ domain/ # Entity, Repository, Constants, Enum
โ โ โโโ dto/
โ โ โโโ exception/
โ โโโ ocr/ # OCR ๋ฐ PDF ์ฒ๋ฆฌ
โ โโโ user/ # ์ฌ์ฉ์ ๊ด๋ฆฌ
โโโ src/main/resources/
โ โโโ application.yml # ์ค์ ํ์ผ
โโโ docs/
โ โโโ images/ # ERD, ๊ตฌ์กฐ๋ ์ด๋ฏธ์ง
โโโ Dockerfile
โโโ build.gradle
- Backend Developer: ์ด์ฌ์ค, ์ด์์ฌ, ์ ์ฑ์ง
- Frontend Developer: ํฉ์ํ