- member.google_picture(구글 아바타 URL), profile_image(사용자 지정 data URL) 컬럼 추가(멱등)
- 구글 로그인 시 picture 클레임 추출 → 신규 저장, 기존은 변경 시 동기화
- PUT /api/auth/profile-image: 사용자 지정 사진 설정/해제(빈값=해제→구글 폴백), data URL·용량 검증
- MemberResponse 에 googlePicture/profileImage 노출(표시 우선순위 프론트 처리)
- 관리자 목록(findAll)은 무거운 profile_image 제외해 가볍게 조회
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- member.plan(FREE/PREMIUM) 컬럼 추가 + SessionUser/MemberResponse 노출
- auth_session 백업에 plan 저장(세션 복원 시 유료 상태 유지)
- 관리자 회원 plan 변경 API (PUT /api/admin/members/{id}/plan)
- PremiumInterceptor 로 유료 전용 경로 차단(통계/예산/고정지출/태그/OCR/투자/카드알림/백업)
· 관리자는 플랜과 무관하게 허용, 무료 회원은 403 PREMIUM_REQUIRED
- WebConfigTest: 유료 경로 등록 회귀 가드 추가
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- POST /api/account/restore: 기존 데이터 전부 삭제 후 이름 기준 재생성
(계좌→태그→분류(대/소)→내역→고정→예산→자주내역), 한 트랜잭션(실패 시 롤백)
- 빈 데이터 안전장치, 투자 종목/매매는 복구 대상 외(삭제됨)
- BackupMapper(deleteByMember), RestoreRequest DTO, BackupService/Controller
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- post.notice 컬럼 추가(멱등 ALTER)
- 목록 정렬 ORDER BY notice DESC, id DESC (공지 최상단)
- 작성 시 공지 설정(관리자만 반영) + /posts/{id}/notice·unnotice 토글
- Post/PostSummary/PostDetail/PostRequest 에 notice 반영
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- member.google_id 컬럼 추가(멱등 ALTER) + 기존 GOOGLE 계정 sub 백필
- googleLogin: google_id 조회 → 없으면 검증된 동일 이메일 계정(LOCAL 우선)에
연결 → 그래도 없으면 신규 생성. provider 는 유지(아이디 로그인/프로필 편집 보존)
- MemberMapper: findByGoogleId/findByEmailForLink/linkGoogle 추가, google_id 매핑
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AuthService.googleLogin: 구글 tokeninfo 로 ID 토큰 검증(aud==클라이언트 ID)
후 provider=GOOGLE 회원 조회/자동가입 → 세션 발급(login 과 동일 경로)
- GoogleLoginRequest DTO, /api/auth/google·/google-client-id 엔드포인트
- application.yml: app.google-client-id=${GOOGLE_CLIENT_ID:}
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- default_category 테이블(전체 공용) + 도메인/매퍼/서비스
- 관리자 API /api/admin/default-categories (CRUD·reorder, ADMIN 보호)
- 사용자 /account/categories/import: 기존 내역 기반 → 기본분류 복사로 변경
(대/소분류 계층 유지, 같은 이름은 건너뜀; CategoryMapper.findByMemberTypeName 추가)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- parent_id 추가(CREATE + ALTER IF NOT EXISTS 멱등 마이그레이션)
- 도메인/DTO/매퍼에 parentId 노출, 2단계 검증(대분류 아래만 소분류)
- 자식 있는 대분류는 소분류화·삭제 차단(countChildren)
- 통계/예산/내역은 소분류 이름 기준 그대로(무변경)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- RecurringService.buildEntry: pending=true로 생성 → 가계부 '확인 필요' 목록에 노출,
사용자가 실제 결제·이체 확인 후 확정(빈 body confirm은 분류/계좌 유지)
- 메모 없으면 제목으로 채워 확인 목록에서 식별 쉽게
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- RepaymentRequest.annualFee 추가, repay()에서 연회비>0이면 EXPENSE(분류=연회비) 생성
- 연회비는 카드 대상에만 허용(대출 입력 시 400)
- 원금/이자/연회비 중 하나는 필수로 완화
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 기존 광고 차단(if !strong && AD_HINT)은 강신호가 보장된 지점이라
항상 false → 한 번도 실행되지 않는 죽은 코드였음. 광고어가 섞여도
승인/입금 등 신호가 있으면 그대로 등록되던 원인.
- 광고어를 2단계로 분리:
- AD_BLOCK(이벤트·쿠폰·혜택·당첨 등): 거래신호가 있어도 무조건 제외
- AD_WEAK(적립·포인트·할인 등): '결제'만 있고 명확한 거래신호가 없을 때 제외
(실거래 영수증의 '포인트 적립'은 보존)
- '결제'는 광고 문구에도 흔해 약신호(weakApproval)로 강등
- 파서 단위테스트 +4 (광고+강신호 차단, 실거래 포인트 보존, 결제단독 광고/정상)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 파서: 입금→수입, 출금/이체→지출, 카드 승인→지출, 카드 취소/환불→수입(환불)
은행 거래는 은행(BANK) 지갑에, 카드는 카드(CARD) 지갑에 매칭(matchWalletId 일반화)
- createFromNotification: 파싱된 수입/지출 타입·지갑종류로 생성
- 파서 테스트 갱신(은행 입금/출금 케이스 포함)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 앱은 출처가 localhost 라 /api/images/{id} 상대경로가 백엔드로 안 감 → 안 보임
- app.public-url(기본 https://app.sblog.kr) 기준 절대 URL 반환 → 웹/PC/APK 모두 로드
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- board_image 테이블 + BoardImageController/Service/Mapper
· POST /api/board/images(로그인) → {url:/api/images/{id}}
· GET /api/images/{id}(공개, img src 로 로드) — 1년 캐시
- 본문엔 짧은 URL 만 들어가 글이 비대해지지 않음
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- CardIssuerMatcher: 공백·접미사(카드/은행/페이/뱅크) 제거 + 별칭 통합(KB↔국민, 농협↔NH, 비씨↔BC, 씨티↔시티)
· KB카드/국민카드/KB국민/국민 어떻게 등록해도 KB국민카드 알림에 자동 매칭
- AccountService.overlaps 가 CardIssuerMatcher 사용
- 단위테스트 4 추가
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- InvestController/Service/Mapper: updateTrade 추가
- 수정 결과를 시점별로 시뮬레이션해 보유수량이 음수가 되면 거부(매도 과다 방지)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 로그인/비밀번호 재인증에 실패 기반 레이트리밋(Redis 슬라이딩 윈도우)
· 로그인 IP당 10회/10분, 비밀번호 게이트 회원당 5회/10분, 초과 시 429
· 성공 시 실패 카운터 초기화, Redis 장애 시 통과(가용성 우선)
· 회원가입 레이트리밋도 공통 enforceRateLimit 으로 일원화
- GlobalExceptionHandler: 미처리 500 로그에 메서드+경로 기록(추적성), 잘못된 JSON은 400
- 테스트: 레이트리밋 429 케이스 2개 추가 (백엔드 총 34)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>