Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5832a99
FEAT : 시설 정원·현원 관측 이력 적재 (#65)
RosieOh Aug 4, 2026
9921c89
FEAT : 관측 이력 기반 입소 가능 시점 예측 (#65)
RosieOh Aug 4, 2026
6e62fde
FEAT : 놓친 지원금 소급 판정 및 소득·자녀수 요건 도입 (#65)
RosieOh Aug 4, 2026
4fea5de
FEAT : 지원금 지급 방식 판별 및 누적 수령액 계산기 (#67)
RosieOh Aug 4, 2026
5667b71
FEAT : 거주지별 지원금 비교 및 차액 산출 (#67)
RosieOh Aug 4, 2026
5810ebc
FEAT : 충원율 추이 기반 시설 인기도 분석 (#67)
RosieOh Aug 4, 2026
20ea4be
FIX : 지역 비교에서 자녀수·소득 요건 미검증 수정 (#67)
RosieOh Aug 4, 2026
753dc17
FIX : 대상 연령과 지급 기간 혼동으로 인한 수령액 과대 계상 수정 (#67)
RosieOh Aug 4, 2026
ebda4e0
FEAT : 공공데이터 연동 전 확인용 개발 샘플 데이터 (#67)
RosieOh Aug 4, 2026
7ebeba2
FEAT : 리프레시 토큰 HttpOnly 쿠키 발급 (#39)
RosieOh Aug 4, 2026
b7807f8
FEAT : 건강 기록 측정값 저장 누락 보완 (#39)
RosieOh Aug 4, 2026
66bb783
STYLE : 주석과 Swagger description 한 줄로 정리 (#67)
RosieOh Aug 5, 2026
fedfefa
FEAT : 병원 찜 상태 조회 API 추가 (#39)
RosieOh Aug 5, 2026
cb276b2
FEAT : 사용자 행동 이벤트 수집 및 퍼널·리텐션 집계 (#68)
RosieOh Aug 5, 2026
35fefb1
FEAT : 건강정보 민감정보 동의 분리 및 접근 차단 (#68)
RosieOh Aug 5, 2026
dbbe571
FEAT : 지원금 금액 수기 검증 및 지역별 신뢰도 표기 (#68)
RosieOh Aug 5, 2026
af6786d
FEAT : 동기화 실패·미처리 예외 운영 알림 (#68)
RosieOh Aug 5, 2026
3e151bb
FEAT : 보육통합정보시스템 공급자 추가 및 어린이집 동기화 전환 (#68)
RosieOh Aug 5, 2026
43a793d
FEAT : 유치원알리미 연동 및 시군구 순회 동기화 (#68)
RosieOh Aug 5, 2026
7ddcd15
FEAT : 보조금24 정책 API 연동 및 지자체 지역 매핑 수정 (#68)
RosieOh Aug 5, 2026
eccb4eb
FIX : 컴파일 인코딩 미지정으로 한글 리터럴 깨짐 교정 (#68)
RosieOh Aug 6, 2026
1204b29
FIX : 캐시 타입이 none 이어도 Redis 캐시가 생성되던 문제 (#68)
RosieOh Aug 6, 2026
439bfe3
FEAT : 병원 진료과목과 요양기관 종별 분리 (#68)
RosieOh Aug 6, 2026
4034e5d
TEST : 공공데이터 실연동 점검 태스크 추가 (#68)
RosieOh Aug 6, 2026
3bdfa14
FEAT : 어린이집 실연동 - HTTPS 전환, 시군구 순회, 필드 매핑 교정 (#68)
RosieOh Aug 6, 2026
470db2a
FEAT : 보육통합정보 응답 코드 처리로 한도 초과·키 만료 감지 (#68)
RosieOh Aug 6, 2026
00cb0ba
FEAT : 주소 지오코딩으로 어린이집 좌표 보정 (#68)
RosieOh Aug 6, 2026
b62fddc
FIX : 동기화 정책의 지급유형 누락 및 금액 미상 정책 소실 (#68)
RosieOh Aug 6, 2026
983365b
FEAT : 정책 변경 감지 및 지역별 알림 (#69)
RosieOh Aug 6, 2026
2a0b159
FEAT : 지원금 실수령액 제보 및 합의 기반 금액 확정 (#69)
RosieOh Aug 6, 2026
0133858
FEAT : 어린이집 대기 기록 및 실제 대기기간 통계 (#69)
RosieOh Aug 6, 2026
95f7421
FEAT : 자녀 통합 현황 및 다자녀 혜택 안내 (#69)
RosieOh Aug 6, 2026
b9eab5b
FEAT : ETag 조건부 응답으로 재전송 절감 (#69)
RosieOh Aug 6, 2026
8418fc7
DOCS : 보육통합정보 API 명세서 보관 (#68)
RosieOh Aug 6, 2026
0751051
FEAT : 중복 수급 배타 그룹으로 총액 과대 집계 해소 (#69)
RosieOh Aug 6, 2026
8eb8a95
FEAT : 알림 클릭 집계 및 재방문 전환 퍼널 (#69)
RosieOh Aug 6, 2026
e7236aa
FEAT : 실수령액 제보 요청 발송 (#69)
RosieOh Aug 6, 2026
c0764eb
FIX : Logback 기본값 문법 오류로 기동 실패하던 로그 경로 (#70)
RosieOh Aug 6, 2026
8b43139
FIX : MariaDB 미지원 ngram 파서 제거 (#70)
RosieOh Aug 6, 2026
d1d0d90
FIX : 테이블명 대소문자 불일치로 전 엔티티 검증 실패 (#70)
RosieOh Aug 6, 2026
77b769b
FIX : DDL 에서 누락된 테이블·컬럼 보충 (#70)
RosieOh Aug 6, 2026
cabf747
REFACTOR : 참조 0건인 HealthRecordType 매핑 제거 (#70)
RosieOh Aug 6, 2026
b2c6517
FIX : 허구 데이터를 만들던 기동 러너 삭제 (#70)
RosieOh Aug 6, 2026
b90f042
FIX : 병원 공개 조회가 전부 로그인 필수였던 문제 (#70)
RosieOh Aug 6, 2026
6adc4ff
FIX : 404·403 이 500 으로 새며 운영 알림을 울리던 문제 (#70)
RosieOh Aug 6, 2026
14199c1
FEAT : 개인정보 처리방침·이용약관 v1.0 작성 및 공개 조회 API (#71)
RosieOh Aug 6, 2026
06db25d
TEST : Flyway 스키마와 엔티티 정합성 검증 추가 (#72)
RosieOh Aug 6, 2026
6ca92d9
TEST : 공개·보호 경로 접근제어 계약 테스트 추가 (#72)
RosieOh Aug 6, 2026
9385e04
FEAT : 대기 걸어둔 시설에 자리가 나면 알린다 (#73)
RosieOh Aug 6, 2026
4ee05ca
FEAT : 신청 마감 임박 지원금을 미리 알린다 (#74)
RosieOh Aug 6, 2026
a888b09
FEAT : 두 알림을 스케줄러·수동 실행에 연결 (#73, #74)
RosieOh Aug 6, 2026
41f176e
DOCS : 시스템 아키텍처 및 데이터 흐름 문서 (#75)
RosieOh Aug 6, 2026
12a8757
DOCS : 기능별 설계 문서 7종 (#75)
RosieOh Aug 6, 2026
665b0da
DOCS : 기동 안정화와 회귀 방지 기록 (#75)
RosieOh Aug 6, 2026
141146a
DOCS : 마이그레이션 이력과 접근제어 매트릭스 (#75)
RosieOh Aug 6, 2026
48d01d9
DOCS : 루트 README 에서 설계 문서 연결 (#75)
RosieOh Aug 6, 2026
aa1f73d
FIX : 요청한 적 없는 이메일 알림이 켜지던 기본값 (#76)
RosieOh Aug 9, 2026
e2b3be1
FEAT : 채널별 사용 가능 여부와 사유 노출 (#76)
RosieOh Aug 9, 2026
f8518d6
FEAT : 관리자 정책 부분 수정(PATCH) 지원 (#76)
RosieOh Aug 9, 2026
fc6f27e
DOCS : 알림 설정 기본값과 관계 표기 정정 (#76)
RosieOh Aug 9, 2026
9f05307
FIX : SYSTEM 이 아닌 알림에 푸시가 나가지 않던 문제 (#76)
RosieOh Aug 9, 2026
60e8ef5
FIX : 이메일 알림 DDL 기본값을 엔티티와 일치시킴 (#76)
RosieOh Aug 10, 2026
9c108c6
FEAT : 채널 사용 불가 사유에 구분 코드 추가 (#76)
RosieOh Aug 10, 2026
726eac9
DOCS : V18 반영 및 버전 고정 표기 제거 (#76)
RosieOh Aug 10, 2026
e9efcac
FIX : 근거 없이 85%로 고정돼 있던 영양 진행률 제거 (#22)
RosieOh Aug 10, 2026
691cc11
CHORE : 사용처 없는 asciidoctor 의존성 제거 (#29, #33)
RosieOh Aug 10, 2026
cc43048
FEAT : 요청별 추적 ID 전파 (#50)
RosieOh Aug 10, 2026
3c03e6e
DOCS : 요청 추적 방식 기록 (#50)
RosieOh Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
16 changes: 16 additions & 0 deletions .github/workflows/ci-cd.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,6 +68,22 @@ jobs:
- name: Run tests
run: ./gradlew clean test jacocoTestReport

# Testcontainers 테스트는 Docker 가 없으면 조용히 skip 되고 빌드는 초록불이 된다.
# 스키마 정합성 검증이 그렇게 빠지면 마이그레이션 누락을 아무도 못 잡는다.
- name: Assert schema validation actually ran
run: |
report=build/test-results/test/TEST-com.carecode.integration.FlywaySchemaValidationTest.xml
if [ ! -f "$report" ]; then
echo "::error::스키마 정합성 테스트 리포트가 없습니다."
exit 1
fi
if grep -q 'skipped="0"' "$report"; then
echo "스키마 정합성 테스트 실행 확인"
else
echo "::error::스키마 정합성 테스트가 skip 되었습니다. Docker 환경을 확인하세요."
exit 1
fi

- name: Publish test report
uses: mikepenz/action-junit-report@v5
if: always()
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line numberDiff line numberDiff line change
Expand Up@@ -62,3 +62,6 @@ logs/
### Temporary files ###
*.tmp
*.temp

# 별도 저장소로 관리되는 프론트엔드
CareCode_FE/
17 changes: 17 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -473,9 +473,26 @@ docker-compose up carecode-mariadb carecode-redis -d

## API 문서

### 설계 문서

기능별 상세 문서와 아키텍처는 [`docs/`](docs/README.md) 에 있습니다.
무엇을 만들었는지보다 **왜 그렇게 만들었는지**를 남기는 것을 목표로 합니다.

| 문서 | 내용 |
|------|------|
| [시스템 개요](docs/architecture/system-overview.md) | 계층 구조, 요청·배치 흐름 |
| [데이터 흐름](docs/architecture/data-flow.md) | 공공데이터 수집 → 알림까지의 파이프라인 |
| [공공데이터 연동](docs/features/public-data-integration.md) | 4개 정부 API, 공급자 추상화 |
| [지원금 지능화](docs/features/benefit-intelligence.md) | 추천·비교·놓친 지원금·금액 신뢰도 |
| [시설 지능화](docs/features/facility-intelligence.md) | 정원 시계열·입소 예측·빈자리 알림 |
| [알림과 리텐션](docs/features/notification-and-retention.md) | 알림 3종과 중복 방지 |
| [기동 안정화](docs/quality/runtime-hardening.md) | 실기동에서 드러난 차단 8건 |
| [회귀 방지](docs/quality/regression-safety.md) | 왜 CI 가 못 잡았는지 |

### Swagger UI

프로젝트는 **SpringDoc OpenAPI 3**를 사용하여 자동으로 API 문서를 생성합니다.
**운영(prod) 프로파일에서는 차단됩니다.**

**접속 URL**: http://localhost/swagger-ui.html

Expand Down
41 changes: 35 additions & 6 deletions build.gradle
Original file line numberDiff line numberDiff line change
Expand Up@@ -58,8 +58,8 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testImplementation 'org.testcontainers:junit-jupiter:1.20.4'
testImplementation 'org.testcontainers:mariadb:1.20.4'
testImplementation 'org.testcontainers:junit-jupiter:1.21.3'
testImplementation 'org.testcontainers:mariadb:1.21.3'

runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
// 소셜 로그인(OAuth2)
Expand All@@ -78,16 +78,45 @@ dependencies {
// Logging - JSON 형식 로깅 지원
implementation 'net.logstash.logback:logstash-logback-encoder:7.4'

// AsciiDoctor for documentation generation
implementation 'org.asciidoctor:asciidoctorj:2.5.7'
implementation 'org.asciidoctor:asciidoctorj-pdf:2.3.4'
// API 문서는 springdoc-openapi 가 런타임에 생성한다(운영 프로파일에서는 비공개).
// asciidoctor 로 정적 산출물을 만들던 시절의 의존성이 남아 있었는데, .adoc 도 사용처도 없이
// 실행 jar 에 7.5MB 를 차지하고 취약점 스캔 표면만 늘리고 있었다.
}

// 소스에 한글 문자열 리터럴이 있다. 인코딩을 지정하지 않으면 Windows(CP949)에서 깨져 컴파일된다.
// 공공데이터 응답의 한글 필드명("서비스ID" 등) 조회가 전부 실패하는 원인이었다.
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}

tasks.withType(Test).configureEach {
systemProperty 'file.encoding', 'UTF-8'
jvmArgs '-Dfile.encoding=UTF-8'
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform {
// 외부 API 를 호출하는 테스트는 기본 빌드에서 제외한다. 네트워크 상태로 빌드가 깨지면 안 된다.
// 실행: ./gradlew liveSyncCheck
excludeTags 'live'
}
finalizedBy(tasks.named('jacocoTestReport'))
}

/** 공공데이터 실연동 점검. 키를 환경변수로 넘겨 수동 실행한다. */
tasks.register('liveSyncCheck', Test) {
group = 'verification'
description = '실제 공공데이터 API 를 호출해 적재까지 확인한다'
testClassesDirs = sourceSets.test.output.classesDirs
classpath = sourceSets.test.runtimeClasspath
useJUnitPlatform {
includeTags 'live'
}
testLogging {
showStandardStreams = true
}
}

jacoco {
toolVersion = "0.8.12"
}
Expand Down
5 changes: 3 additions & 2 deletions docs/ERD.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -887,9 +887,10 @@ erDiagram
| ID | BIGINT | PK, AUTO_INCREMENT | 고유 식별자 |
| USER_ID | BIGINT | FK, NOT NULL | 사용자 ID |
| NOTIFICATION_TYPE | ENUM | NOT NULL | 알림 유형 |
| EMAIL_ENABLED | BOOLEAN | DEFAULT TRUE | 이메일 알림 활성화 |
| EMAIL_ENABLED | BOOLEAN | DEFAULT FALSE | 이메일 알림 활성화 |
| PUSH_ENABLED | BOOLEAN | DEFAULT TRUE | 푸시 알림 활성화 |
| SMS_ENABLED | BOOLEAN | DEFAULT FALSE | SMS 알림 활성화 |
| IN_APP_ENABLED | BOOLEAN | DEFAULT TRUE | 인앱 알림 활성화 |
| CREATED_AT | DATETIME | NOT NULL | 생성 시간 |
| UPDATED_AT | DATETIME | NULL | 수정 시간 |

Expand DownExpand Up@@ -1023,7 +1024,7 @@ TBL_USER (1) ----< (N) TBL_CHAT_SESSION
| Hospital - HospitalReview | 1:N | 한 병원은 여러 리뷰 받을 수 있음 |
| HealthRecord - Attachment | 1:N | 한 건강 기록은 여러 첨부파일 가능 |
| Policy - PolicyDocument | 1:N | 한 정책은 여러 문서를 가질 수 있음 |
| User - NotificationSettings | 1:1 | 한 사용자는 하나의 알림 설정을 가짐 |
| User - NotificationPreference | 1:N | 알림 유형별로 한 행씩 가짐 (UNIQUE: USER_ID + NOTIFICATION_TYPE) |
| ChatSession - ChatMessage | 1:N | 한 세션은 여러 메시지를 포함 |

---
Expand Down
Binary file not shown.
80 changes: 80 additions & 0 deletions docs/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
# CareCode(맘편한) 문서

육아 지원금·보육시설·건강관리를 한 곳에서 다루는 백엔드 서비스입니다.
이 디렉터리는 **무엇을 만들었는지**가 아니라 **왜 그렇게 만들었는지**를 남기는 것을 목표로 합니다.

## 이 문서들의 전제

이 서비스의 핵심 데이터는 전부 **정부 공공데이터**에서 옵니다. 그래서 대부분의 설계 판단은
"우리가 무엇을 하고 싶은가" 보다 **"공공데이터가 무엇을 주지 않는가"** 에서 출발합니다.

예를 들어 어린이집 정원 데이터는 시설 전체 수치만 주고 반별로는 주지 않습니다.
그래서 빈자리 알림은 "어느 반에 자리가 났는지는 알 수 없다" 는 한계를 문구에 그대로 밝힙니다.
정확한 척하는 것이 틀린 정보보다 위험하기 때문입니다.

이런 판단의 근거를 각 문서에 함께 적었습니다.

## 문서 지도

### 아키텍처

| 문서 | 내용 |
|------|------|
| [시스템 개요](architecture/system-overview.md) | 전체 구성, 계층 구조, 요청·배치 흐름 (Mermaid) |
| [데이터 흐름](architecture/data-flow.md) | 공공데이터 수집 → 정제 → 알림까지의 파이프라인 (Mermaid) |
| [carecode-architecture.drawio](architecture/carecode-architecture.drawio) | draw.io 편집용 아키텍처 원본 |

### 기능

| 문서 | 다루는 범위 | 관련 이슈 |
|------|-------------|-----------|
| [공공데이터 연동](features/public-data-integration.md) | 4개 정부 API 연동, 공급자 추상화, 전국 순회 동기화 | #61 #68 |
| [지원금 지능화](features/benefit-intelligence.md) | 추천·지역 비교·놓친 지원금·실수령액 제보·중복 수급 배타 | #65 #67 #69 |
| [시설 지능화](features/facility-intelligence.md) | 정원 시계열·입소 예측·인기도·대기 기록·빈자리 알림 | #65 #67 #69 #73 |
| [알림과 리텐션](features/notification-and-retention.md) | 정책 변경·빈자리·마감 임박 알림, 딥링크, 클릭 전환 | #69 #73 #74 |
| [지표 수집](features/analytics.md) | 행동 이벤트, 퍼널, 코호트 리텐션 | #68 |
| [개인정보와 법적 문서](features/privacy-and-legal.md) | 동의 분리, 민감정보 차단, 처리방침·약관 | #68 #71 |
| [운영](features/operations.md) | 운영 알림, 헬스체크, 스케줄러, 수동 실행 | #68 #70 |

### 품질

| 문서 | 내용 | 관련 이슈 |
|------|------|-----------|
| [기동 안정화](quality/runtime-hardening.md) | 실기동에서 드러난 차단 8건과 접근제어 결함 | #70 |
| [회귀 방지](quality/regression-safety.md) | 왜 CI 가 못 잡았는지, 어떻게 막았는지 | #72 |

### 레퍼런스

| 문서 | 내용 |
|------|------|
| [데이터베이스 마이그레이션](reference/database-migrations.md) | 각 마이그레이션이 왜 필요했는지 |
| [접근제어 매트릭스](reference/access-control-matrix.md) | 공개·인증·관리자 경로 전수 |

### 기존 문서

| 문서 | 내용 |
|------|------|
| [ERD.md](ERD.md) | 엔티티 관계도 |
| [ISSUE_MANAGEMENT.md](ISSUE_MANAGEMENT.md) | 이슈·커밋 연결 규칙 |
| [system-architecture.md](system-architecture.md) | 초기 아키텍처 문서 |
| [ARCHITECTURE_IMPROVEMENTS.md](ARCHITECTURE_IMPROVEMENTS.md) | 초기 개선 기록 |

## 기술 스택

| 구분 | 사용 기술 |
|------|-----------|
| 런타임 | Java 17, Spring Boot 3.3.3 |
| 데이터 | MariaDB 10.11, Redis 7, Flyway |
| 빌드 | Gradle 8.14, JaCoCo |
| 테스트 | JUnit 5, Mockito, AssertJ, Testcontainers, H2 |
| 문서 | springdoc-openapi (운영에서는 비공개) |
| 배포 | Docker, GitHub Actions, Blue/Green |

## 개발 규칙

- **커밋**: `TYPE : 한글 설명 (#이슈번호)` — 관심사별로 잘게 나눕니다.
- **스키마**: 운영은 `ddl-auto=validate` 입니다. 엔티티를 바꾸면 마이그레이션도 반드시 씁니다.
안 쓰면 [스키마 정합성 테스트](quality/regression-safety.md)가 기동 단계에서 깨뜨립니다.
- **접근제어**: 경로를 추가하면 [접근제어 계약 테스트](reference/access-control-matrix.md)에도 넣습니다.
SecurityConfig 는 앞선 규칙이 뒤를 덮어서, 규칙만 보고는 실제로 열렸는지 알 수 없습니다.
- **비밀값**: API 키·자격증명은 저장소에 넣지 않습니다. 환경변수로만 주입합니다.
Loading
Loading