1. 프로젝트 개요
Findex는 금융 지수 데이터를 한눈에 제공하는 대시보드 서비스입니다.
금융위원회 오픈 API와 연동하여 지수 정보를 자동으로 수집·관리하고, 사용자에게 성과 차트, 랭킹, 즐겨찾기 등의 기능을 제공합니다.
- 개발 기간: 2026년 3월 11일 ~ 3월 20일 (약 10일)
- 팀 구성: Spring Backend 10기 팀5 (Ant-Man) — 5인 (송시연, 김민형, 박성국, 성주현, 전창현)
- 핵심 기능: 지수 정보 CRUD, 지수 데이터 관리 및 CSV 다운로드, 금융위원회 오픈 API 연동, 자동 연동 스케줄러, 대시보드
2. 담당한 작업
저는 프로젝트 내에서 자동 연동(Auto Sync) 도메인을 설계·구현했으며, 프로젝트 초기 설정 및 인프라 작업도 담당했습니다.
초기 설정 및 인프라
| 작업 | 이슈/PR | 내용 |
|---|
| 협업 환경 구축 | Issue #3 | Git 브랜치 전략, 협업 도구(Discord, Notion 등) 환경 세팅 |
| 개발 규칙 정의 | Issue #4 | 코딩 컨벤션, 커밋 메시지 규칙 등 팀 개발 규칙 정의 |
| 프로젝트 초기 설정 | Issue #5 | 프로젝트 초기 구조 설정 및 Initial Commit |
| 요구사항 정의서 | Issue #6 | 요구사항 정의서 작성 |
| ERD 설계 | Issue #2 | 팀 전체와 함께 핵심 엔티티 도출, 속성 정의, 관계 설정 진행 |
| DB 환경 설정 | Issue #9 / PR #12 | H2(로컬) / PostgreSQL(운영) 프로필 분리 |
| 도메인 Entity 구현 | Issue #11 / PR #34 | Swagger 명세 기준 엔티티 필드명·JOIN 컬럼명·NOT NULL 매핑 정비 |
| PR 템플릿 | PR #7 | 팀 전체가 일관된 PR 작성을 할 수 있도록 템플릿 추가 |
| Projects 설정 | Issue #39 | GitHub Projects 보드 설정 |
| Railway 배포 | Issue #31 | Railway 플랫폼을 통한 서비스 배포 |
자동 연동(Auto Sync) 도메인 — 핵심 담당 영역
성능 최적화 및 운영
| 작업 | 이슈/PR | 내용 |
|---|
| 캐시 적용 | Issue #91 / PR #99 | 금융위원회 API 응답에 캐시 적용 (과거 데이터 7일, 당일 데이터 1시간) |
3. 기술적 성과
사용 기술 스택
- Backend: Spring Boot, Spring Data JPA, QueryDSL, MapStruct, Spring Scheduler
- API 문서화: Swagger (springdoc-openapi)
- Database: PostgreSQL (운영), H2 (로컬/테스트)
- 배포: Railway
- 협업: Git/GitHub, Discord, Notion
주요 구현 성과
1) 자동 연동 시스템 전체 설계 및 구현
AutoSyncConfig CRU API, 스케줄러까지 자동 연동 도메인 전체를 end-to-end로 구현했습니다.
- 지수 등록 시 비활성 상태의 자동 연동 설정이 함께 생성되는 연동 로직을 구현했습니다.
AutoSyncScheduler → IntegrationTaskService → IndexSyncService 로 이어지는 자동 동기화 파이프라인을 설계했습니다.
2) QueryDSL 기반 조회 기능
- 필터링(indexInfoId, enabled), 단일 필드 정렬, 커서 기반 페이지네이션을 지원하는 목록 조회 API를 구현했습니다.
AutoSyncConfigSortField Enum을 도입하여 정렬 대상 필드 반환, 커서 값 추출, 커서 조건 생성을 타입 안전하게 처리했습니다.
3) 캐시
- 금융위원회 오픈 API 응답에 대한 캐시 레이어(
MarketIndexApiCacheService)를 구현했습니다.
- 과거 데이터(변경 불가)는 7일 TTL, 당일 데이터(갱신 가능)는 1시간 TTL로 차등 적용했습니다.
- 지수 데이터 연동의 약 1,000건 기준(2020~2026 KRX 반도체 데이터) 응답 시간을 개선했습니다.(4183ms -> 495ms)
- 지수 정보 연동의 약 200건 기준 응답 시간을 개선했습니다.(892ms -> 210ms)
4) 개발 환경 및 인프라 기반 구축
- H2/PostgreSQL 프로필 분리로 로컬 개발 환경과 운영 환경을 독립적으로 관리할 수 있도록 했습니다.
- PR 템플릿, GitHub Projects 설정 등 팀 협업 기반 도구를 마련했습니다.
4. 문제점 및 해결 과정
문제 1: 동기화 이력이 없는 지수의 기준일 처리
- 문제: 자동 연동 스케줄러가 동기화 대상을 생성할 때, 성공 이력이 없는 지수에 대해
baseDateFrom이 null로 설정되어 API 호출 시 의도치 않은 대량 데이터 요청이 발생할 수 있었습니다.
- 해결: 성공 이력이 없는 경우
baseDateFrom = baseDateTo로 설정하여 1일치 데이터만 동기화하도록 정책을 변경했습니다. 또한 정책 결정 로직을 SyncService에서 대상 생성 단계(IntegrationTaskService)로 이동시켜, 동기화 서비스는 순수하게 동기화 실행에만 집중하도록 책임을 분리했습니다. (Issue #79 / PR #78)
문제 2: 문자열 기반 정렬 로직의 타입 안전성 부재
- 문제: QueryDSL 조회 시 정렬 필드를 문자열로 처리하고 있어, 잘못된 필드명이 런타임에서야 발견되고, 중첩 필드(예:
indexInfo.indexName) 바인딩 시 오류가 발생하는 등 유지보수성이 떨어지는 상황이었습니다.
- 해결:
AutoSyncConfigSortField Enum을 도입하여 정렬 대상 필드 반환, 커서 값 추출, 커서 조건 생성 로직을 Enum 내부에 캡슐화했습니다. 리뷰어가 지적해 준 중첩 필드 바인딩 이슈를 반영하여 후속 커밋으로 수정을 완료했습니다. (Issue #74 / PR #75)
문제 3: 외부 API 호출 병목
- 문제:
IndexSyncController.syncIndexData()가 약 1000건을 불러올 때 배포 서버 기준 10258ms로 응답 시간이 느렸습니다. 금융위원회 오픈 API를 매번 직접 호출하기 때문에 동일한 과거 데이터를 반복 요청하는 비효율이 있었습니다.
- 해결:
MarketIndexApiCacheService를 도입하여 API 요청 파라미터 조합 기반의 캐시 키를 생성하고, 과거 데이터(7일 TTL)와 당일 데이터(1시간 TTL)에 차등 TTL을 적용했습니다. 생성형 AI를 활용하여 캐시 hit/miss를 검증했고, 약 1,000건 기준으로 유의미한 성능 개선을 확인했습니다. (Issue #91 / PR #99)
5. 협업 및 피드백
코드 리뷰 문화
- 브랜치 보호 규칙을 설정하여 PR 리뷰 승인 없이는 병합할 수 없도록 팀 규칙을 만들었습니다.
- 모든 PR에서 팀원의 코드 리뷰를 받고 병합하는 프로세스를 준수했습니다.
- 리뷰를 통해 Lombok 활용, 중첩 필드 바인딩 이슈, 캐시 성능 개선 결과 추가 등 실질적인 피드백을 받고 반영했습니다.
- 머지 후 반드시 pull을 받는 프로세스를 팀 규칙으로 정립하여, 프로젝트 기간 동안 Git 충돌이나 브랜치가 꼬이는 사태를 예방하였습니다.
팀 기여
- 팀장을 맡아 매일 회의를 주관하고, 각 팀원의 진행 상황을 확인하며, 기술적 의사결정이 필요한 부분에서 방향을 정해주는 역할을 했습니다.
- 프로젝트 협업 환경 구축(Issue #3), 개발 규칙 정의(Issue #4), GitHub Projects 설정(Issue #39) 등 팀 전체 인프라 세팅을 주도했습니다.
- PR 템플릿을 도입하여 팀 전체가 일관된 형식으로 PR을 작성할 수 있게 했습니다.
느낀 점
- 짧은 개발 기간(10일) 내에 도메인 하나를 전담하면서, 설계부터 최적화까지 전체 생애주기를 경험할 수 있었습니다.
- 리뷰어의 피드백을 통해 Enum 기반 정렬, 중첩 필드 바인딩 등 실무에서 발생할 수 있는 이슈를 사전에 발견하고 해결할 수 있었습니다.
- 팀원 간 작업 의존 관계(예: 스케줄러 → SyncService)를 조율하며 비동기적 협업의 중요성을 배웠습니다.
- 팀장 역할을 맡으며 단순히 개발을 수행하는 것을 넘어, 팀 전체의 방향성과 진행 상황을 책임지는 경험을 할 수 있었습니다.
- 회의를 주도하며 의견을 정리하고 팀원들의 참여를 이끌어내는 과정에서 커뮤니케이션, 조율 능력과 같은 소프트 스킬이 크게 향상되었음을 느꼈습니다.
6. 코드 품질 및 최적화
코드 가독성 및 유지보수성
- Enum 기반 설계: 정렬 로직을
AutoSyncConfigSortField Enum으로 캡슐화하여 새로운 정렬 필드 추가 시 Enum 값만 추가하면 되도록 확장성을 확보했습니다.
- MapStruct 활용: 엔티티 ↔ DTO 변환을 MapStruct로 자동화하여 수동 매핑 코드를 제거하고, 필드 누락 가능성을 컴파일 타임에 검출할 수 있게 했습니다.
- Swagger 문서화: 모든 컨트롤러에 Swagger 설명을 추가하여 프론트엔드 협업 및 API 테스트가 용이하도록 했습니다.
- 코드 컨벤션 준수: Google Java Style XML을 적용하고, 코드 포맷팅 PR #49을 통해 일관된 코드 스타일을 유지했습니다.
- 책임 분리: 기준일 정책 결정 로직을 SyncService에서 IntegrationTaskService로 이동시켜, 각 서비스가 단일 책임을 갖도록 리팩토링했습니다.
성능 최적화
- 병목 지점 식별 (Issue #91): 실제 메서드 실행 시간을 측정하여
syncIndexData() (814~1,258ms)를 병목으로 정확히 파악한 후 캐시를 적용했습니다.
- 캐시: 금융위원회 API 응답에 대해 데이터 특성에 따른 차등 캐시 전략을 적용했습니다.
- 과거 데이터: 7일 TTL (변경 가능성 희박 → 호출 최소화)
- 당일 데이터: 1시간 TTL (변경 가능 → 최신성 확보)
- 커서 기반 페이지네이션: 오프셋 기반 대비 대규모 데이터셋에서 일관된 조회 성능을 보장하는 커서 기반 페이지네이션을 적용했습니다.
테스트
- 모든 PR에서 단위 테스트(Unit Test), 로컬 테스트, API 테스트를 수행했습니다.
- 기준일 정책 변경 시 이력 없음·실패 이력 시나리오에 대한 테스트 케이스를 추가했습니다 (PR #78).
7. 향후 개선 사항 및 제안
단기 개선 사항
- 캐시 무효화 전략 정교화: 현재 TTL 기반 만료만 적용되어 있으므로, 수동 연동이 발생했을 때 해당 캐시를 즉시 무효화하는 이벤트 기반 전략을 추가하면 데이터 정합성이 향상될 것으로 보입니다.
- 스케줄러 모니터링: 10분 간격 스케줄러의 실행 이력·성공/실패 건수를 로깅하고 대시보드에서 확인할 수 있도록 모니터링 체계를 구축하면 운영 안정성이 높아질 것입니다.
장기 개선 제안
- 분산 환경 대응: Railway 스케일 아웃 시 스케줄러 중복 실행을 방지하기 위해 ShedLock 등 분산 락 도입을 고려할 수 있습니다.
- QueryDSL 정렬 일반화:
AutoSyncConfigSortField Enum 패턴을 다른 도메인(IndexInfo, IndexData 등)에도 공통 인터페이스로 확장하여 정렬 로직의 재사용성을 높일 수 있다고 생각합니다.
- 비동기 동기화: 현재 스케줄러가 동기적으로 API를 호출하므로, 대량의 지수를 처리할 때 병렬 비동기 호출(@Async 또는 CompletableFuture)을 도입하면 전체 동기화 시간을 단축할 수 있습니다.
- 통합 테스트: 현재 단위 테스트 중심으로 검증하고 있으므로, 스케줄러 → 서비스 → 외부 API 연동까지 이어지는 통합 테스트를 추가하면 배포 안정성이 크게 향상될 것입니다.