Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
528e20b
chore(gradle): Gradle 9.0.0 업그레이드 및 바이브코딩 가이드 프롬프트 추가
pureliture Dec 10, 2025
097f929
feat: implement weather lookup service
google-labs-jules[bot] Dec 10, 2025
24d2f56
feat(api): 날씨 조회 서비스 구현
pureliture Dec 10, 2025
77a15d0
refactor: 패키지 구조 변경 및 롬복 의존성 추가
pureliture Dec 11, 2025
4b3562e
Merge pull request #2 from pureliture/feature/weather-service-by-jules
pureliture Dec 11, 2025
0e3b993
Merge pull request #3 from pureliture/refactor/modify-package-structure
pureliture Dec 11, 2025
563cf3c
Revert "Implement weather lookup service API"
pureliture Dec 11, 2025
6df1c50
Merge pull request #4 from pureliture/revert-2-feature/weather-servic…
pureliture Dec 11, 2025
0fdd88a
Merge pull request #1 from pureliture/feature/weather-service-7550212…
pureliture Dec 11, 2025
3447d69
refactor: externalize configuration and add JavaDoc
google-labs-jules[bot] Dec 11, 2025
b496ff7
refactor: 설정 외부화 및 JavaDoc 추가
google-labs-jules[bot] Dec 11, 2025
cb253c0
Merge pull request #5 from pureliture/refactor/externalize-config-and…
pureliture Dec 11, 2025
974091f
refactor: Java 코드를 Kotlin으로 변환 및 DB 마이그레이션
google-labs-jules[bot] Dec 11, 2025
6027e88
Merge pull request #6 from pureliture/refactor/java-to-kotlin-migrati…
pureliture Dec 11, 2025
3f06488
refactor(infrastructure): outbound 요청을 위해 Netty 기반 RestClient로 전환
google-labs-jules[bot] Dec 11, 2025
1e513b0
refactor(infrastructure): outbound 요청을 위해 Netty 기반 RestClient로 전환
google-labs-jules[bot] Dec 14, 2025
24a9f9f
Merge pull request #8 from pureliture/refactor-rest-client-netty-1775…
pureliture Dec 14, 2025
c3198a8
refactor: 불필요한 .gitkeep 제거
pureliture Dec 14, 2025
7b58454
refactor: 불필요한 주석 코드 제거 및 예외 처리 로직 개선
pureliture Dec 14, 2025
da5ecee
docs(README, guidelines): 아키텍처 및 구현 전략 업데이트
pureliture Dec 14, 2025
fd11dd7
Merge pull request #9 from pureliture/refactor/modify-document-clean-…
pureliture Dec 14, 2025
c21c996
feat(weather): implement simple UI using Thymeleaf
google-labs-jules[bot] Dec 14, 2025
977a9bb
Merge pull request #10 from pureliture/feat/weather-ui-14702300259910…
pureliture Dec 14, 2025
aef5bc5
feat(infrastructure): RestClient 타임아웃 및 재시도 기능 추가
google-labs-jules[bot] Dec 15, 2025
5ee94af
chore(config): 불필요한 설정값 제거 및 application.yml 정리
pureliture Dec 15, 2025
f9dc297
Merge pull request #11 from pureliture/feature/rest-client-resilience…
pureliture Dec 15, 2025
6852a13
refactor: Kotlin 코드베이스를 Java 21로 전체 변환
google-labs-jules[bot] Dec 15, 2025
076691b
refactor: main 브랜치 변경사항(RestClient Resilience) 반영 및 Java 변환
google-labs-jules[bot] Dec 15, 2025
2e8aa97
Merge remote-tracking branch 'origin/main' into refactor/kotlin-to-ja…
pureliture Dec 15, 2025
97e975e
Merge pull request #12 from pureliture/refactor/kotlin-to-java-139555…
pureliture Dec 15, 2025
1888545
refactor(infrastructure): reorganize packages and apply DIP to weathe…
google-labs-jules[bot] Dec 15, 2025
3513981
refactor: 예외 처리 계층 및 의존성 구조 개편
pureliture Dec 15, 2025
8d8bf24
feat(exception): SystemException 클래스 추가 및 InfrastructureException 계층 …
pureliture Dec 15, 2025
9b9463d
Merge pull request #13 from pureliture/refactor-infrastructure-archit…
pureliture Dec 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,39 @@
# spring-sunshine-precourse
# 날씨 조회 서비스 (Weather Service)

## 기능 목록
1. **도시 좌표 조회**: 입력된 도시 이름(Seoul, Tokyo, NewYork, Paris, London)에 해당하는 위도/경도를 조회한다.
2. **날씨 정보 조회**: Open-Meteo API를 사용하여 해당 좌표의 현재 날씨(온도, 체감 온도, 날씨 코드, 습도, 풍속)를 조회한다.
3. **날씨 요약 생성**: 조회된 날씨 정보를 바탕으로 사용자에게 친화적인 한 줄 요약 문장을 생성한다.
4. **API 응답**: 조회된 날씨 정보와 요약 문장을 JSON 형태로 반환한다.
5. **예외 처리**: 지원하지 않는 도시나 외부 API 오류 발생 시 정해진 포맷의 에러 응답을 반환한다.
6. **설정 외부화**: 도시 좌표 및 날씨 코드를 프로퍼티 파일로 분리하여 관리한다.
7. **회복 탄력성(Resilience)**: 외부 API 호출 시 타임아웃 및 재시도 기능을 통해 네트워크 불안정에 대비한다.

## 구현 전략
1. Jules, Codex 2개의 Sandboxed AI Coding Agent를 활용하여 초기 코드 개발
2. guideline 파일을 통해 Backend Architecture, 개발 규칙 등을 사전에 정의하고 Agent가 이를 참조하여 개발
3. 가능한 사전에 `build.gradle.kts`에 정의되어있던 의존성울 모두 사용하여 기능을 구현
4. Agent가 개발한 코드를 검토하고 필요 시 리팩토링 수행

## 구현 상세
* **아키텍처**: Domain Layer는 컴포넌트 기반, Service Layer가 Facade 역할로 조합하는 구조를 적용한다.
* `api`: 컨트롤러 및 요청/응답 DTO (검증 및 위임).
* `service`: Service Layer, Facade 역할로 여러 컴포넌트를 오케스트레이션.
* `component`: 단일 책임을 가진 작은 컴포넌트들 (좌표 매핑, 요약 생성 등).
* `domain`: 도메인 모델, 도메인 서비스.
* `repository`: 도메인 리포지토리 포트 정의.
* `infrastructure`: 외부 API 통신 (Open-Meteo Client) 등 기술 어댑터.
* **제약 사항 준수**:
* `else`, `switch`, `ternary operator` 사용 금지.
* 들여쓰기 2단계 제한.
* 메서드 길이 15줄 제한.
* Google Java Style Guide (4 spaces indent).
* **No-Else/Switch 전략**:
* 도시 매핑: `Map<String, Coordinate>` 자료구조를 활용하여 조건문 없이 O(1) 조회.
* 날씨 코드 매핑: `Map<Integer, String>` 활용.
* 방어적 코딩(Guard Clauses)을 통해 `else` 제거.
* **설정 관리**:
* `CityProperties`, `WeatherProperties` 클래스를 통해 외부 설정(YAML)을 객체로 바인딩하여 사용.
* **회복 탄력성**:
* `RestClient` 설정 시 `HttpClient` 타임아웃(Connect, Response) 적용.
* `ClientHttpRequestInterceptor`를 구현하여 실패 시 재시도 로직 적용 (Custom Retry Interceptor).
21 changes: 6 additions & 15 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
plugins {
id("org.springframework.boot") version "3.3.1"
id("io.spring.dependency-management") version "1.1.5"
kotlin("plugin.jpa") version "1.9.24"
kotlin("jvm") version "1.9.24"
kotlin("plugin.spring") version "1.9.24"
id("java")
}

group = "camp.nextstep.edu"
Expand All @@ -24,21 +22,14 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-reactor-netty")
implementation("org.flywaydb:flyway-core")
implementation("org.flywaydb:flyway-mysql")
implementation("org.jetbrains.kotlin:kotlin-reflect")
runtimeOnly("com.h2database:h2")
runtimeOnly("com.mysql:mysql-connector-j")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit5")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

kotlin {
compilerOptions {
freeCompilerArgs.addAll("-Xjsr305=strict")
}
implementation("com.h2database:h2")
implementation("com.mysql:mysql-connector-j")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
14 changes: 8 additions & 6 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 14 additions & 12 deletions gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading