Skip to content

greedy-team/doogoo-be

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

250 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

두ꡬ두ꡬ (DoogooDoogoo) Backend

μ„Έμ’…λŒ€ λ§žμΆ€ν˜• λ‘λ“œλ¦Ό Β· 학사일정 ICS ꡬ독 λ°±μ—”λ“œ

μ„Έμ’…λŒ€ν•™κ΅ λ‘λ“œλ¦Ό 비ꡐ과 곡지와 학사일정 데이터λ₯Ό μˆ˜μ§‘Β·κ°€κ³΅ν•˜κ³ ,
ν•™κ³ΌΒ·ν‚€μ›Œλ“œΒ·ν•™λ…„ 쑰건이 반영된 κ°œμΈν™” .ics ꡬ독 URL을 λ°œκΈ‰ν•˜λŠ” Spring Boot λ°±μ—”λ“œ μ„œλ²„


Java Spring Boot Spring Data JPA PostgreSQL OpenAPI Caffeine GitHub Actions Nginx


πŸ’‘ 기획 λ°°κ²½

λ‘λ“œλ¦Όκ³Ό 학사일정은 ν•„μš”ν•œ 정보가 흩어져 있고, μ‚¬μš©μžκ°€ 직접 찾아보지 μ•ŠμœΌλ©΄ μ‹ μ²­Β·μš΄μ˜ 일정을 λ†“μΉ˜κΈ° μ‰½μŠ΅λ‹ˆλ‹€.

문제 μ„€λͺ…
정보 λΆ„μ‚° 학사일정과 λ‘λ“œλ¦Ό 곡지가 μ„œλ‘œ λ‹€λ₯Έ μ„±κ²©μœΌλ‘œ 흩어져 있음
지속 확인 λΆ€λ‹΄ μ‚¬μš©μžκ°€ 주기적으둜 μ‚¬μ΄νŠΈλ₯Ό 직접 λ°©λ¬Έν•΄μ•Ό 함
κ°œμΈν™” λΆ€μ‘± ν•™κ΅μ—μ„œ μ œκ³΅ν•˜λŠ” κΈ°λ³Έ 일정은 개인 관심사 쀑심 필터링이 어렀움
μˆ˜λ™ 등둝 λ²ˆκ±°λ‘œμ›€ μΊ˜λ¦°λ” 앱에 직접 μž…λ ₯ν•˜κ±°λ‚˜ 볡사해야 ν•˜λŠ” 뢈편

λͺ©ν‘œ: 곡지 데이터λ₯Ό μžλ™ μˆ˜μ§‘ν•˜κ³ , μ‚¬μš©μž 쑰건이 반영된 κ°œμΈν™” ICS ꡬ독 URL을 λ°œκΈ‰ν•΄ μΊ˜λ¦°λ” μ•±μ—μ„œ μžλ™ λ™κΈ°ν™”λ˜λ„λ‘ 지원


πŸš€ μš”μ²­ 흐름

β‘  ν΄λΌμ΄μ–ΈνŠΈ μš”μ²­   학사/λ‘λ“œλ¦Ό 곡지 쑰회 λ˜λŠ” ICS λ°œκΈ‰ μš”μ²­
       ↓
β‘‘ λ°±μ—”λ“œ 처리      ν•„ν„° 검증 Β· 쑰회 Β· ꡬ독 토큰 생성
       ↓
β‘’ ICS URL λ°œκΈ‰     고유 token 기반 .ics μ£Όμ†Œ 생성
       ↓
β‘£ μΊ˜λ¦°λ” ꡬ독      μ‚¬μš©μžκ°€ ꡬ글 Β· μ• ν”Œ Β· 아웃룩에 등둝
       ↓
β‘€ ICS 쑰회         μΊ˜λ¦°λ” 앱이 /cal/{token}.ics 호좜
       ↓
β‘₯ μžλ™ 동기화      μΊμ‹œλœ 곡지/학사 데이터λ₯Ό 기반으둜 μ΅œμ‹  일정 반영

✨ μ£Όμš” κΈ°λŠ₯

κΈ°λŠ₯ μ„€λͺ…
πŸŽ“ 학사일정 API ν•™λ…„ 정보가 ν¬ν•¨λœ 학사일정 λͺ©λ‘ 쑰회
🌟 λ‘λ“œλ¦Ό 곡지 API λ‘λ“œλ¦Ό OPEN 곡지 λͺ©λ‘ 쑰회
πŸ”— ICS ꡬ독 URL λ°œκΈ‰ 학사/λ‘λ“œλ¦Ό ν•„ν„° 쑰건을 token 기반 ꡬ독 URL둜 λ³€ν™˜
πŸ“† ICS μΊ˜λ¦°λ” 생성 /cal/{token}.ics μš”μ²­ μ‹œ 동적 ICS λ³Έλ¬Έ λ Œλ”λ§
πŸ•· 크둀링 μžλ™ν™” λ‘λ“œλ¦Ό 곡지 및 학사일정 μžλ™ μˆ˜μ§‘/동기화
πŸ€– AI λΆ„λ₯˜/μš”μ•½ λ‘λ“œλ¦Ό 상세 곡지λ₯Ό ν•™κ³ΌΒ·ν‚€μ›Œλ“œ κΈ°μ€€μœΌλ‘œ λΆ„λ₯˜ν•˜κ³  μš”μ•½ 생성
⚑ μΊμ‹œ μ΅œμ ν™” ꡬ독 토큰/ICS/곡지 λͺ©λ‘μ„ Caffeine으둜 캐싱
πŸ“Š ꡬ쑰화 둜그 JSON 둜그 기반 운영 둜그 μˆ˜μ§‘ 및 λͺ¨λ‹ˆν„°λ§ λŒ€μ‘
λ°±μ—”λ“œ 운영 κΈ°λŠ₯ 펼치기
κΈ°λŠ₯ μ„€λͺ…
πŸ›  κ΄€λ¦¬μž 크둀링 API νŠΉμ • 연도 학사일정 λ˜λŠ” λ‘λ“œλ¦Ό 크둀링 μˆ˜λ™ μ‹€ν–‰
πŸ”„ μŠ€μΌ€μ€„ 배치 λ‘λ“œλ¦Ό μ •κΈ° 크둀링, 전체 동기화, 학사일정 크둀링, 만료 이벀트 정리
🧹 ꡬ독 정리 λΉ„ν™œμ„± ꡬ독 토큰 cleanup
πŸ§ͺ Swagger/OpenAPI 운영/둜컬 μ„œλ²„ λ¬Έμ„œν™” 및 ν…ŒμŠ€νŠΈ 지원

πŸ›  기술 μŠ€νƒ

Backend

Java Spring Boot Spring Web Spring Data JPA PostgreSQL H2 OpenAPI Caffeine jsoup

Infra / Ops

GitHub Actions Nginx EC2


πŸ“ ν”„λ‘œμ νŠΈ ꡬ쑰

νŒ¨ν‚€μ§€ ꡬ쑰 펼치기
src/main/java/com/doogoo/doogoo
β”œβ”€β”€ academic/                      # 학사일정 μ‘°νšŒΒ·λ™κΈ°ν™”
β”‚   β”œβ”€β”€ api/                       # 학사일정 API, μš”μ²­/응닡 DTO
β”‚   β”œβ”€β”€ application/               # 학사 쑰회/연도별 동기화 μ„œλΉ„μŠ€
β”‚   β”œβ”€β”€ domain/                    # AcademicSchedule μ—”ν‹°ν‹° 및 DTO
β”‚   └── infrastructure/            # AcademicScheduleRepository
β”‚
β”œβ”€β”€ calendar/                      # ICS μΊ˜λ¦°λ” 쑰회
β”‚   β”œβ”€β”€ api/                       # /cal/{token}.ics μ—”λ“œν¬μΈνŠΈ
β”‚   └── application/               # ICS λ Œλ”λ§, μΊμ‹œ, 토큰 처리
β”‚
β”œβ”€β”€ dodream/                       # λ‘λ“œλ¦Ό 곡지 μ‘°νšŒΒ·λ™κΈ°ν™”
β”‚   β”œβ”€β”€ api/                       # λ‘λ“œλ¦Ό API, μš”μ²­/응닡 DTO
β”‚   β”œβ”€β”€ application/               # 곡지 쑰회/μ €μž₯/μ—…λ°μ΄νŠΈ/마감 처리
β”‚   β”œβ”€β”€ domain/                    # Event μ—”ν‹°ν‹°, μƒνƒœ, DTO
β”‚   └── infrastructure/            # EventRepository
β”‚
β”œβ”€β”€ subscription/                  # ꡬ독 토큰 λ°œκΈ‰Β·μ‘°νšŒΒ·μ •λ¦¬
β”‚   β”œβ”€β”€ application/               # ꡬ독 λ°œκΈ‰/쑰회/cleanup μ„œλΉ„μŠ€
β”‚   β”œβ”€β”€ domain/                    # Subscription μ—”ν‹°ν‹° 및 κ΄€λ ¨ enum
β”‚   └── infrastructure/            # SubscriptionRepository
β”‚
β”œβ”€β”€ lookup/                        # ν•™λ…„Β·ν•™κ³ΌΒ·ν‚€μ›Œλ“œ 쑰회
β”‚   β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ application/
β”‚   └── domain/
β”‚
β”œβ”€β”€ crawl/                         # λ‘λ“œλ¦Ό/학사 크둀러, νŒŒμ„œ, μŠ€μΌ€μ€„λŸ¬
β”œβ”€β”€ classify/                      # AI λΆ„λ₯˜/μš”μ•½ 연동
β”œβ”€β”€ common/                        # μ—λŸ¬ 처리, 둜그, μœ ν‹Έλ¦¬ν‹°
β”œβ”€β”€ global/                        # κ΄€λ¦¬μž API, 곡톡 μ„€μ •, μΊμ‹œ, CORS, OpenAPI
└── DoogooApplication.java         # Spring Boot μ§„μž…μ 
src/main/resources
β”œβ”€β”€ application.yaml               # 곡톡 μ„€μ •
β”œβ”€β”€ application-prod.yaml          # 운영 DB / CORS μ„€μ •
β”œβ”€β”€ application-test.yaml          # ν…ŒμŠ€νŠΈ μ„€μ •
β”œβ”€β”€ application-dev.yml            # 개발 μ„€μ •
β”œβ”€β”€ logback-spring.xml             # ꡬ쑰화 둜그 μ„€μ •
└── prompts/                       # AI λΆ„λ₯˜/μš”μ•½ ν”„λ‘¬ν”„νŠΈ
src/test/java/com/doogoo/doogoo
β”œβ”€β”€ academic/api/                  # 학사 API ν…ŒμŠ€νŠΈ
β”œβ”€β”€ calendar/api/                  # ICS 쑰회 ν…ŒμŠ€νŠΈ
β”œβ”€β”€ calendar/application/          # ICS μΊμ‹œ ν…ŒμŠ€νŠΈ
β”œβ”€β”€ dodream/api/                   # λ‘λ“œλ¦Ό API ν…ŒμŠ€νŠΈ
β”œβ”€β”€ crawl/                         # 크둀링 νŒŒμ„œ ν…ŒμŠ€νŠΈ
└── subscription/domain/           # ꡬ독 도메인 ν…ŒμŠ€νŠΈ

πŸ”Œ API

λ°±μ—”λ“œ μ„œλ²„: https://www.sejongdoogoo-api.com

Swagger UI:

  • 운영: https://www.sejongdoogoo-api.com/swagger-ui/index.html
  • 둜컬: http://localhost:8080/swagger-ui/index.html

Public API

Method Endpoint μ„€λͺ…
GET /api/grades ν•™λ…„ λͺ©λ‘ 쑰회
GET /api/colleges λ‹¨κ³ΌλŒ€Β·ν•™κ³Ό λͺ©λ‘ 쑰회
GET /api/keywords λ‘λ“œλ¦Ό ν‚€μ›Œλ“œ λͺ©λ‘ 쑰회
GET /api/academic/notices 학사일정 λͺ©λ‘ 쑰회
GET /api/dodream/notices λ‘λ“œλ¦Ό 곡지 λͺ©λ‘ 쑰회
POST /api/academic/ics 학사일정 ICS ꡬ독 URL λ°œκΈ‰
POST /api/dodream/ics λ‘λ“œλ¦Ό ICS ꡬ독 URL λ°œκΈ‰
GET /cal/{token}.ics ꡬ독 토큰 기반 ICS μΊ˜λ¦°λ” 쑰회

Admin API

Method Endpoint μ„€λͺ…
POST /api/admin/crawl/academic/{year} νŠΉμ • 연도 학사일정 크둀링
POST /api/admin/crawl/academic/current ν˜„μž¬ 연도 학사일정 크둀링
POST /api/admin/crawl/academic/current-and-previous ν˜„μž¬Β·μ΄μ „ 연도 학사일정 크둀링
POST /api/admin/crawl/dodream λ‘λ“œλ¦Ό μ •κΈ° 크둀링 μˆ˜λ™ μ‹€ν–‰

Health Check

Method Endpoint μ„€λͺ…
GET /actuator/health μ„œλ²„ μƒνƒœ 확인

πŸ”„ 배치 및 동기화

μž‘μ—… 크둠 μ„€λͺ…
regularCrawl() 0 0 0 */2 * * λ‘λ“œλ¦Ό μ •κΈ° 크둀링
fullSync() 0 0 3 * * * open 이벀트 상세 동기화
crawlAcademicSchedule() 0 0 2 1 1 * μ—° 1회 학사일정 크둀링
cleanExpiredEvents() 0 0 4 * * * 만료 이벀트 정리
deleteSubscription() 0 0 1 * * MON λΉ„ν™œμ„± ꡬ독 정리

βš™οΈ μ‹€ν–‰ 방법

1. ν™˜κ²½ λ³€μˆ˜ μ€€λΉ„

ν”„λ‘œμ νŠΈ 루트의 .env.exampleλ₯Ό μ°Έκ³ ν•΄ λ‹€μŒ 값을 μ€€λΉ„ν•©λ‹ˆλ‹€.

SEJONG_PORTAL_ID=your_portal_id
SEJONG_PORTAL_PASSWORD=your_portal_password
OPENAI_API_KEY=sk-...
SPRING_PROFILES_ACTIVE=prod
DB_URL=jdbc:postgresql://localhost:5432/doogoo
DB_USERNAME=doogoo_user
DB_PASSWORD=your_db_password
CORS_ALLOWED_ORIGINS=https://yourdomain.com

2. 둜컬 μ‹€ν–‰

κΈ°λ³Έ ν”„λ‘œν•„μ€ devμž…λ‹ˆλ‹€.

./gradlew bootRun

ν…ŒμŠ€νŠΈ μ‹€ν–‰:

./gradlew test

JAR λΉŒλ“œ:

./gradlew bootJar

3. 운영 μ„€μ • μ°Έκ³ 

  • 운영 ν”„λ‘œν•„: prod
  • DB: PostgreSQL
  • JPA DDL: update
  • CORS: CORS_ALLOWED_ORIGINS 기반
  • 곡개 μ„œλ²„ 정보: OpenAPI 섀정에 production server 등둝

🧠 λ°±μ—”λ“œ 처리 포인트

ν•­λͺ© μ„€λͺ…
토큰 λ°œκΈ‰ Base62 12자리 토큰 생성 ν›„ subscriptions μ €μž₯
ICS λ Œλ”λ§ token -> Subscription -> ν•„ν„° 쑰건 -> ICS λ³Έλ¬Έ 생성
μΊμ‹œ icsCache, tokenCache, 곡지 λͺ©λ‘ μΊμ‹œ μ‚¬μš©
λ™μ‹œμ„± μ œμ–΄ ICS λ Œλ”λ§μš© Semaphore(10) μ‚¬μš©
둜그 logback-spring.xml 기반 JSON ꡬ쑰화 둜그
μ—λŸ¬ 처리 GlobalExceptionHandlerμ—μ„œ API/ICS μš”μ²­ 곡톡 처리

πŸ§ͺ ν…ŒμŠ€νŠΈ

ν˜„μž¬ ν¬ν•¨λœ ν…ŒμŠ€νŠΈ μ˜ˆμ‹œ:

  • AcademicControllerTest
  • DoDreamControllerTest
  • CalendarControllerTest
  • IcsCacheTest
  • AcademicParserTest
  • DodreamParserTest
  • SubscriptionTest

핡심 검증 λ²”μœ„:

  • 곡지 쑰회 API 응닡
  • ICS λ°œκΈ‰ 및 쑰회
  • ꡬ독 토큰 처리
  • μΊμ‹œ λ™μž‘
  • 크둀링 νŒŒμ‹± 둜직

πŸ—Ί ν–₯ν›„ κ³„νš

  • λ‘λ“œλ¦Ό ν•„ν„°λ₯Ό DB 쑰건으둜 더 직접 λ°˜μ˜ν•΄ 쑰회 λΉ„μš© μ΅œμ ν™”
  • cleanup 쿼리와 인덱슀 μ „λž΅ 고도화
  • 운영 둜그/Grafana 기반 λͺ¨λ‹ˆν„°λ§ κ°•ν™”
  • 배치 μƒνƒœ 및 크둀링 κ²°κ³Ό κ°€μ‹œμ„± κ°œμ„ 
  • 배포/운영 λ¬Έμ„œμ™€ λ°±μ—”λ“œ README 연동 κ°•ν™”

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages