Track My Cash: Spring Boot, Vanilla JS, 그리고 Gemini를 활용한 안전하고 분리된 원장 구축
Source: Dev.to
위 링크에 있는 전체 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다. (코드 블록, URL 및 마크다운 형식은 그대로 유지됩니다.)
Google Gemini로 만든 것
저는 BookKeeping이라는 풀스택 금융 원장 애플리케이션을 만들었습니다. 이 앱은 매우 구체적인 문제, 즉 친구에게 빌려준 돈을 복잡한 회계 도구 없이 추적하는 문제를 해결합니다.
- 프론트엔드 – 프레임워크 없이 순수 JavaScript, HTML, CSS (프레임워크 의존성 없음) 를 Google Cloud Run에 안전하게 배포했습니다.
- 백엔드 – Java, Spring Boot 3, Spring Security 6, 그리고 Render에 호스팅된 PostgreSQL 데이터베이스.
Google Gemini는 전체 개발 주기 동안 저의 페어 프로그래밍 파트너 역할을 하며, 분리된 아키텍처의 복잡한 부분들을 연결하는 데 도움을 주었습니다.
Gemini가 도와준 방법
- 보안 흐름 설계 – HttpOnly 쿠키와 표준 Bearer 토큰을 사용한 무상태 JWT 인증을 구현했습니다.
- 브라우저 보안 장벽 처리 – 엄격한 CORS와 JSON 페이로드 전략을 설계하여 서드파티 쿠키 차단(예: Safari ITP)을 극복하고 CSRF 공격을 원천적으로 방지했습니다.
- 수학 엔진 구축 – 대출 금액을 동적으로 감소시키고 잔액이 0이 되면 데이터베이스 행을 자동으로 삭제하는 맞춤형 “Partial Repayment” 알고리즘을 공동 개발했습니다.
- Cloud Run Docker 환경 구성 – 프론트엔드를 위한 가벼운 Alpine‑Nginx 컨테이너를 만들었습니다. Gemini가 Cloud Run이 표준 포트 바인딩을 무시한다는 점을 알려주어, 배포 시 Cloud Run의
$PORT환경 변수를 주입하는 동적nginx.conf.template를 추가했습니다. - 네이티브 OS 로컬라이제이션 설계 – 다중 통화 로직에 하드코딩된
'en-US'로케일을 수정했습니다.Intl.NumberFormat에undefined를 전달함으로써 UI가 운영 체제의 로케일 설정을 상속받게 되었으며(예: 올바른 유로화 포맷).
인증에 대한 참고
로그인 시스템은 의도적으로 간단하게 설계되었습니다. 이 앱은 매우 집중된 개인 작업(우리 자신의 돈을 추적)만을 다루므로 복잡한 OAuth나 다중 역할 계층이 필요하지 않았습니다. 간단한 무상태 JWT 로그인은 앱을 가볍게 유지하고 완전히 우리 통제 하에 두게 합니다.
데모
- GitHub Pages: https://rohithv07.github.io/BookKeeping/
- Cloud Run URL: (여기에 Cloud Run URL을 삽입하세요)
Bookkeeping
Record the debts that we are lending to other people.
## 구현된 내용
### Spring Boot 애플리케이션
- **Java 21**와 **Gradle**로 구축된 견고한 REST API.
### 데이터베이스 모델
| 모델 | 필드 |
|------------|------------------------------------------------------------------------|
| **Borrower** | `name`, `email`, `phone` |
| **Loan** | `amount`, `dateLent`, `dueDate` (대출 후 정확히 1 개월), `status` (`ACTIVE` \| `REPAID`) |
### 핵심 API 엔드포인트
| Method | Endpoint | Description |
|--------|------------------------------|---------------------------|
| `POST` | `/api/borrowers` | 새 차용인 생성 |
| `GET` | `/api/borrowers` | 모든 차용인 목록 |
| `POST` | `/api/loans` | 새 대출 생성 |
| `GET` | `/api/loans` | 모든 대출 목록 |
| `PUT` | `/api/loans/{id}/repay` | 대출을 상환 처리 |
### 알림 작업
- **`NotificationService`**가 매일 **오전 08:00**에 실행됩니다.
- `dueDate`가 **오늘 또는 이전**인 활성 대출을 조회하고 지정된 개인 Gmail 계정으로 이메일을 전송합니다.
### 시스템 아키텍처 업그레이드
- **인터페이스 기반 설계** – 서비스 레이어는 느슨한 결합과 확장성을 위해 계약(`BorrowerService`, `LoanService`)을 사용합니다.
- **데이터 전송 객체 (DTO)** – 모든 API 페이로드는 `BorrowerDto`와 `LoanDto`로 표현됩니다.
## 배운 점
- **Security & Distributed Environments** – 프런트엔드(Google Cloud Run)와 백엔드(Render)를 분리하면서 교차 도메인 쿠키 처리, 사전 비행 `OPTIONS` 요청, 그리고 브라우저 개인정보 보호 기능을 강조하게 되었습니다.
- **Multi‑Tenancy & Data Migration** – 사용자 프로필 매핑을 추가하면서 기존 데이터가 “손실된” 것처럼 보였습니다. Gemini와 협업하여 `DataMigrationRunner`를 구축했으며, 이는 시작 시 PostgreSQL에서 고아 레코드를 스캔하고 새로운 외래 키를 통해 다시 연결합니다.
- **Interactive Debugging** – StackOverflow를 뒤져 보는 대신 로그를 Gemini에 붙여넣음으로써 Nginx Alpine 템플릿 처리 방식을 빠르게 파악하고, 단일 변수 치환 수정으로 `gcloud run deploy` 포트 바인딩 오류를 해결할 수 있었습니다.
## Google Gemini 피드백
### 잘 작동한 점
- **Context Retention** – Gemini는 복잡한 파일 구조를 추적하여 `JwtAuthenticationFilter`를 쿠키와 Bearer 토큰 모두를 지원하도록 정밀하게 리팩터링할 수 있었습니다.
- **Deep Architectural Awareness** – 이는 PostgreSQL 스키마 마이그레이션 및 Cloud Run Nginx 최적화 과정에서 필수적인 역할을 했습니다.
### 마주친 어려움
- **Premature Fix Suggestions** – 때때로 Gemini가 프런트엔드 JavaScript 문제(예: 간단한 문자열 보간 오류로 인한 `onclick` 오작동)를 설명하기 전에 백엔드 수정을 제안했습니다.
- **Superficial Script Loops** – 에이전트가 실제 답변을 제공하기 전에 시스템 작업 경계 검사를 만족시키기 위해 `echo "do something"`와 같은 사소한 내부 스크립트를 실행하는 경우가 있었습니다.