Skip to content

사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 - #53

Merged
jhan0121 merged 12 commits into
be/devfrom
feat/cycle-option
Feb 2, 2026
Merged

사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현#53
jhan0121 merged 12 commits into
be/devfrom
feat/cycle-option

Conversation

@jhan0121

@jhan0121 jhan0121 commented Feb 2, 2026

Copy link
Copy Markdown
Collaborator

🚀 작업 내용

사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현

주기 선택 전략 패턴 도입 (CycleSelection & Resolver)

  • 리뷰 생성 시 선택된 주기가 '기본 주기'인지 '커스텀 주기'인지에 따라 처리하는 로직을 전략 패턴으로 구현
  • CycleSelection: 선택된 주기의 정보를 담는 추상 레이어를 도입
  • CycleSelectionResolver: 입력된 주기 정보(코드 또는 ID)를 바탕으로 실제 주기를 찾아오는 책임 분리
    • DefaultCycleSelectionResolver: 시스템 기본 주기를 매핑
    • CustomCycleSelectionResolver: 사용자가 정의한 커스텀 주기를 매핑
  • CycleSelectionResolverRegistry: 다양한 리졸버 중 적절한 전략을 선택하는 중앙 관리 객체를 도입

ReviewService 비즈니스 로직 고도화

  • 리뷰 저장 시 입력받은 주기 식별자를 바탕으로 CycleSelection을 추출하고, 이에 따라 복습 주기를 자동으로 계산하여 저장하는 로직 구현

커스텀 주기 옵션 관리 기능

  • 사용자가 커스텀 복습 주기를 구성할 수 있는 CRUD 기능 구현
  • CycleDurations 일급 컬렉션을 통해 주기 데이터의 유효성(최소 1개, 10분 단위, 1년 이내 등)을 도메인 레벨에서 강제

입력값 파싱 및 검증 리팩토링

  • CycleDurationParser를 도입하여 ISO-8601 포맷 파싱 로직을 유틸리티화
  • 파싱 책임을 Controller Request DTO로 이동시켜 Service 계층이 타입 안정성이 보장된 데이터만 다루도록 개선

📸 이슈 번호

✍ 궁금한 점

  • 리뷰 생성 시 주기를 확정 짓는 로직이 ReviewService에 위치해 있는데, 이를 도메인 서비스 등으로 더 분리할 필요가 있을까?

@jhan0121 jhan0121 added this to the v1.1.0 milestone Feb 2, 2026
@jhan0121
jhan0121 requested a review from Copilot February 2, 2026 22:32
@jhan0121 jhan0121 self-assigned this Feb 2, 2026
@jhan0121 jhan0121 added the ✨ feat 기능 추가 label Feb 2, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in recycle-study Feb 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a flexible cycle management system allowing users to define and use custom review schedules. It introduces a strategy pattern for cycle selection resolution, enabling the system to handle both default (Ebbinghaus) and user-defined custom cycles.

Changes:

  • Introduced CycleSelection interface with DefaultCycleSelection and CustomCycleSelection implementations to abstract cycle selection
  • Implemented resolver pattern (CycleSelectionResolver and CycleSelectionResolverRegistry) to dynamically resolve cycle durations based on selection type
  • Added CRUD operations for custom cycle options with validation constraints (max 5 custom cycles, 10-minute intervals, within 1 year)

Reviewed changes

Copilot reviewed 48 out of 49 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ReviewService.java Integrated cycle selection resolution into review creation workflow
ReviewSaveInput.java Extended to accept CycleSelection parameter
ReviewController.java Removed deprecated device identifier resolution method
CycleSelection.java Defined sealed interface for polymorphic cycle selection with JSON type discrimination
DefaultCycleSelection.java Implemented default cycle selection with code validation
CustomCycleSelection.java Implemented custom cycle selection with ID validation
CycleSelectionResolver.java Defined strategy interface for resolving cycle selections to durations
CycleSelectionResolverRegistry.java Implemented registry pattern for managing multiple resolver strategies
DefaultCycleSelectionResolver.java Resolver for default cycle codes
CustomCycleSelectionResolver.java Resolver for custom cycle IDs with database lookup
CycleOption.java Domain entity for user-defined custom cycles with ownership validation
CycleDurations.java Value object enforcing cycle duration constraints
CycleOptionService.java Business logic for custom cycle CRUD operations
CycleOptionController.java REST endpoints for custom cycle management
Database migration Tables for persisting custom cycle options and durations
Test files Comprehensive test coverage for new components

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/java/com/recyclestudy/cycle/domain/CycleOptionDurationId.java Outdated
@jhan0121
jhan0121 merged commit 1b4e5d2 into be/dev Feb 2, 2026
1 of 2 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in recycle-study Feb 2, 2026
@github-actions

github-actions Bot commented Feb 2, 2026

Copy link
Copy Markdown
Contributor

🧪 테스트 커버리지 리포트

Overall Project 97.08% -2.13% 🍏
Files changed 94.91% 🍏

File Coverage
Review.java 100% 🍏
CustomCycleSelectionResolver.java 100% 🍏
CycleSelectionResolverRegistry.java 100% 🍏
DefaultCycleSelectionResolver.java 100% 🍏
CycleOptionController.java 100% 🍏
ReviewService.java 100% 🍏
CycleOptionDuration.java 100% 🍏
CycleOptionDurationId.java 100% 🍏
CycleOption.java 100% 🍏
DefaultCycleOption.java 100% 🍏
DefaultCycleSelection.java 100% 🍏
CustomCycleSelection.java 100% 🍏
CycleDurationParser.java 100% 🍏
ReviewController.java 100% 🍏
CycleDurations.java 96.35% -3.65% 🍏
CycleOptionService.java 83.87% -16.13% 🍏
CycleOptionTitle.java 80.77% -19.23% 🍏

@jhan0121
jhan0121 deleted the feat/cycle-option branch February 3, 2026 06:44
jhan0121 added a commit that referenced this pull request Feb 3, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거
jhan0121 added a commit that referenced this pull request Mar 2, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)
jhan0121 added a commit that referenced this pull request Mar 7, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
jhan0121 added a commit that referenced this pull request Mar 9, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

* 이메일 재전송 포기 기준을 maxRetry 횟수 -> deadline 기반으로 전환 (#84)

* refactor: 전송 실패 이메일 재전송 기능 정리

* test: 테스트 회귀 문제 수정

* notification_history.review_cycle_id unique constraint 추가 (#86)

* chore: NotificationHistory review_cycle_id에 유니크 제약 조건 추가

* refactor: NotificationHistory 유니크 제약 조건명 명시

* style: NotificationHistory 테이블 설정 개행 정리

* deadline을 PENDING 생성 시점에 결정하도록 NotificationHistory 설계 개선 (#89)

* refactor: NotificationHistory deadline 계산 로직 변경
  - 새로운 복습 주기가 추가될 때, 계산하도록 수정

* README.md 설명 추가 (#90)

* docs: README.md 설명 추가

- 프로젝트 소개 추가
- 서비스 기능 설명 추가
- 기술 스택 추가
- 아키텍처 다이어그램 추가

* docs: README 문서 이미지 및 뱃지 수정

- 이미지 너비 100% 설정
- 기술 스택 뱃지 줄바꿈 추가

* docs: README 뱃지 색상 수정

- Loki, Tempo 뱃지 색상 변경

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
jhan0121 added a commit that referenced this pull request Mar 9, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

* 이메일 재전송 포기 기준을 maxRetry 횟수 -> deadline 기반으로 전환 (#84)

* refactor: 전송 실패 이메일 재전송 기능 정리

* test: 테스트 회귀 문제 수정

* notification_history.review_cycle_id unique constraint 추가 (#86)

* chore: NotificationHistory review_cycle_id에 유니크 제약 조건 추가

* refactor: NotificationHistory 유니크 제약 조건명 명시

* style: NotificationHistory 테이블 설정 개행 정리

* deadline을 PENDING 생성 시점에 결정하도록 NotificationHistory 설계 개선 (#89)

* refactor: NotificationHistory deadline 계산 로직 변경
  - 새로운 복습 주기가 추가될 때, 계산하도록 수정

* README.md 설명 추가 (#90)

* docs: README.md 설명 추가

- 프로젝트 소개 추가
- 서비스 기능 설명 추가
- 기술 스택 추가
- 아키텍처 다이어그램 추가

* docs: README 문서 이미지 및 뱃지 수정

- 이미지 너비 100% 설정
- 기술 스택 뱃지 줄바꿈 추가

* docs: README 뱃지 색상 수정

- Loki, Tempo 뱃지 색상 변경

* 서버 및 DB 시간 처리 정책 UTC로 통일 (#93)

* fix: 서버 타임존 처리 UTC로 통일

* fix: 서버 타임존 처리 UTC로 통일

* refactor: UTC 변환로직을 도메인 레이어로 이동

* refactor: Jackson 설정 application.yaml 설정으로 변경

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
jhan0121 added a commit that referenced this pull request May 19, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정



---------



* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

* 이메일 재전송 포기 기준을 maxRetry 횟수 -> deadline 기반으로 전환 (#84)

* refactor: 전송 실패 이메일 재전송 기능 정리

* test: 테스트 회귀 문제 수정

* notification_history.review_cycle_id unique constraint 추가 (#86)

* chore: NotificationHistory review_cycle_id에 유니크 제약 조건 추가

* refactor: NotificationHistory 유니크 제약 조건명 명시

* style: NotificationHistory 테이블 설정 개행 정리

* deadline을 PENDING 생성 시점에 결정하도록 NotificationHistory 설계 개선 (#89)

* refactor: NotificationHistory deadline 계산 로직 변경
  - 새로운 복습 주기가 추가될 때, 계산하도록 수정

* README.md 설명 추가 (#90)

* docs: README.md 설명 추가

- 프로젝트 소개 추가
- 서비스 기능 설명 추가
- 기술 스택 추가
- 아키텍처 다이어그램 추가

* docs: README 문서 이미지 및 뱃지 수정

- 이미지 너비 100% 설정
- 기술 스택 뱃지 줄바꿈 추가

* docs: README 뱃지 색상 수정

- Loki, Tempo 뱃지 색상 변경

* 서버 및 DB 시간 처리 정책 UTC로 통일 (#93)

* fix: 서버 타임존 처리 UTC로 통일

* fix: 서버 타임존 처리 UTC로 통일

* refactor: UTC 변환로직을 도메인 레이어로 이동

* refactor: Jackson 설정 application.yaml 설정으로 변경
jhan0121 added a commit that referenced this pull request May 19, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

* 이메일 재전송 포기 기준을 maxRetry 횟수 -> deadline 기반으로 전환 (#84)

* refactor: 전송 실패 이메일 재전송 기능 정리

* test: 테스트 회귀 문제 수정

* notification_history.review_cycle_id unique constraint 추가 (#86)

* chore: NotificationHistory review_cycle_id에 유니크 제약 조건 추가

* refactor: NotificationHistory 유니크 제약 조건명 명시

* style: NotificationHistory 테이블 설정 개행 정리

* deadline을 PENDING 생성 시점에 결정하도록 NotificationHistory 설계 개선 (#89)

* refactor: NotificationHistory deadline 계산 로직 변경
  - 새로운 복습 주기가 추가될 때, 계산하도록 수정

* README.md 설명 추가 (#90)

* docs: README.md 설명 추가

- 프로젝트 소개 추가
- 서비스 기능 설명 추가
- 기술 스택 추가
- 아키텍처 다이어그램 추가

* docs: README 문서 이미지 및 뱃지 수정

- 이미지 너비 100% 설정
- 기술 스택 뱃지 줄바꿈 추가

* docs: README 뱃지 색상 수정

- Loki, Tempo 뱃지 색상 변경

* 서버 및 DB 시간 처리 정책 UTC로 통일 (#93)

* fix: 서버 타임존 처리 UTC로 통일

* fix: 서버 타임존 처리 UTC로 통일

* refactor: UTC 변환로직을 도메인 레이어로 이동

* refactor: Jackson 설정 application.yaml 설정으로 변경

* notification_history 테이블에 status, deadline 복합 인덱스 추가 (#96)

* db 커넥션 풀 및 jvm 설정 추가 (#99)

- 컨테이너 별 메모리 제한
- jvm 힙 메모리 한도
- hikaricp 누수 감지 시간

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
jhan0121 added a commit that referenced this pull request May 24, 2026
* init: 프로젝트 초기 설정 추가

* 이메일 기반 멀티 디바이스 인증 및 관리 기능 구현 (#3)

* build: JPA 의존성 추가

* feat: BaseEntity 추가

* feat: NullValidator 추가

* feat: docker compose 파일 추가

* feat: Email 추가

* feat: DeviceIdentifier 추가

* test: BaseEntity equals 검증 테스트 추가

* feat: Member 추가

* feat: Device 추가

* style: 불필요한 개행 제거

* feat: DeviceIdentifier 추가

* feat: email에 toString 추가

* feat: Device 정적 팩터리 메서드 구조 수정

- isActive 추가

* feat: RecyclestudyApplication에 비동기 설정 추가

* feat: 이메일 전송 기능을 위한 의존성 추가

* feat: 전역 예외 처리용 ControllerAdvice 추가

* feat: EmailService  추가

* feat: IdentifierCreator 추가

* feat: 멤버 저장 기능 추가

- 멤버 저장
- 디바이스 id 발급

* feat: 멤버의 디바이스 전체 조회 기능 추가

* feat: 디바이스 이메일 인증 메일 발송 기능 추가

* feat: 이메일 인증 기능 추가

* test: MemberServiceTest 불필요한 검증 로직 제거

* feat: GlobalControllerAdvice 예외 처리 로직 추가

* test: MemberControllerTest 추가

* test: DeviceControllerTest 추가

* chore: DeviceControllerTest 패키지 위치 수정

* refactor: Member 이메일 유니크 제약 조건 설정

* refactor: Device 내 Member에 JoinColumn 추가

* refactor: Device identifier 유니크 제약 조건 설정

* refactor: DeviceController 패키지 위치 수정 및 파라미터명 변경

* feat: ActivationExpiredDateTime 추가

* refactor: EmailService 구조 개선

- 로그 추가
- 메서드 분리

* feat: Member 이메일 검증 기능 추가

* feat: Device 소유 검증 기능 추가

* feat: GlobalControllerAdvice  내 DeviceActivationExpiredException 처리 추가

* refactor: 이메일 인증 제한 시간 로직 추가

* jacoco 기반 테스트 커버리지 CI 구축 (#6)

* feat: jacoco 기반 테스트 커버리지 CI 스크립트 추자

* test: 테스트 환경 DB H2 사용하도록 변경

* 디바이스 삭제 기능 추가 (#7)

* feat: 디바이스 삭제 기능 추가

* chore: final 키워드 누락 수정

* fix: 대상 디바이스를 제거하도록 기능 수정

* 등록한 디바이스 조회 기능 응답 형식 수정 (#9)

* fix: 등록한 디바이스 조회 기능 응답 형식 수정

* chore: 실행 sql 로그 출력 기능 활성화

* 복습할 URL 저장 기능 추가 (#10)

* feat: 리뷰 대상 url 저장 기능 추가

* fix: ReviewService 트랜잭션 누락 수정

* swagger 기반 API 문서 작성 (#12)

* feat: swagger 기반 api 문서 기능 추가

* refactor: 불필요한 로그 출력 제거

* refactor: 누락된 타입 명시 로직 추가

* CI 대상 branch 설정 추가 (#13)

* 복습 대상 URL 이메일 전송 스케줄러 구현 (#19)

* feat: Review 엔티티에 Member 연관 관계 추가

* feat: 주기적 복습 이메일 전송 기능 추가

- 공통 이메일 전송 기능 별도 분리 리팩터링 진행

* test: ReviewCycleServiceTest 추가

* refactor: ReviewSendOutput collect 내 불변 리스트를 사용하도록 수정

* refactor: html 태그에 lang 추가

* feat: 이메일 전송 이력 관리 기능 추가

* style: 코드 구조 정리

* refactor: ReviewEmailSender 타임존 설정 추가

* test: 메일 발송 실패 처리 검증 추가

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* flyway 기반 db 마이그레이션 의존성 추가 (#24)

* feat: flyway 기반 db 마이그레이션 의존성 추가

- 환경별 jpa sql 출력 여부 분리

* fix: ReviewCycle#scheduledAt not null 누락 수정

* test: 테스트 환경에서 flyway 비활성화

* 로그 기능 추가 (#21)

* feat: 로그 기능 추가

* chore: 신규 유저 이메일 등록 시작 로그 태그명 수정

* feat: 이메일 마스킹 기능 적용

* refactor: 복습 주기 저장 로그 포맷 수정

* refactor: 이메일 전송 기능 도메인 객체 파라미터로 변경

* test: MemberServiceTest#authenticateDevice 테스트 커버리지 보완 (#22)

* 배포 스크립트 추가 (#31)

* feat: 배포 스크립트 추가

* refactor: docker-compose.yaml env 설정 수정

* chore: 태그 검증 로그 메시지 수정

* feat: 모니터링을 위한 alloy 설정 추가 (#34)

* 배포 최적화 적용 (#36)

* 배포 스크립트 오류 수정 (#38)

* fix: 배포 스크립트 오류 수정

* fix: trace 연결 문제 수정

* 모니터링 설정 불일치 수정 (#40)

* feat: 모니터링 설정 추가

* fix: 로그 경로 불일치 수정

* 모니터링 연결 오류 수정 (#43)

* fix: loki, tempo 연결 오류 수정

* refactor: 모니터링용 컨테이너 설정 코드 병합

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 1) (#46)

* feat: 디바이스 인증 기능 ArgumentResolver 추가

* refactor: 디바이스 id를 헤더를 활용하도록 마이그레이션 과정 추가

* 디바이스 인증 방식 헤더 마이그레이션 (Phase 3) (#49)

* hotfix: prod - dev 불일치 수정 (#51)

* 사용자 커스텀 복습 주기 관리 및 커스텀 주기 기반 리뷰 저장 기능 구현 (#53)

* chore: 불필요한 메서드 제거

* feat: 복습 주기 엔티티 추가

* feat: 커스텀 복습 주기 조회 기능 추가

* feat: 커스텀 복습 주기 저장 기능 추가

* feat: 커스텀 복습 주기 수정/삭제 기능 추가

* feat: 기본 복습 주기 처리 로직 수정

* style: 코드 컨벤션 정리

* style: 코드 컨벤션 정리

* feat: 주기별 리뷰 저장 기능 주기 옵션 설정 로직 추가

* refactor: 주기별 리뷰 저장 기능 주기 하위 호환성 분기 처리 추가

* refactor: ReviewService#calculateScheduledAts 초 단위 절삭 적용

* style: 불필요한 개행 제거

* LocalDateTime 초 단위 절삭 적용 (#54)

* 이메일 전송 실패 재시도 로직 구현 (#56)

* refactor: 리뷰 이메일 전송 기능 비동기 처리

* feat: 메일 전송 실패 재시도 로직 추가

* refactor: 리뷰 메일 재전송 로직 보완

- PENDING 데이터 고려
- 테스트 코드 추가 보완

* test: 불필요한 테스트 코드 제거

* 멤버 알림 시간 설정 변경 기능 추가 (#59)

* feat: 사용자 선호 알림 시간 설정 및 적용 기능 구현

- 리뷰 생성 시 1일 이상의 주기는 사용자 설정 시간에 맞춰 스케줄링되도록 로직 수정

* style: 테스트 코드 포맷팅 수정

* fix: 멤버 알림 시간 변경 로그의 이전 시간 표기 오류 수정

- 알림 시간 업데이트 후 로깅 시 변경 전 시간이 아닌 변경 후 시간이 기록되는 문제 수정

* 복습 주기 하위 호환성 로직 제거 (#61)

* style: 코드 컨벤션 정리

- 불필요한 import 제거
- 코드 포맷팅 수정

* refactor: 복습 주기 하위 호환성 로직 제거

- 프런트엔드 마이그레이션 완료에 따라 null 입력 시 기본 주기로 변환하는 로직 제거

* test: 불필요한 테스트 시나리오 제거

* test: 불필요한 테스트 시나리오 제거

* feat: 멤버 알림 시간 조회 API 추가 (#63)

- 멤버 조회 API에서 알림 시간 조회 기능 분리

* 로그 패턴에 스레드 정보 추가 (#65)

* chore: 콘솔 로그 패턴에 스레드 정보 추가

* chore: 파일 로그 패턴에 스레드 정보 추가

* 복습 주기 조회 쿼리 성능 개선 (#66)

* refactor: 복습 주기 조회 쿼리 성능 개선

- review_cycle 테이블 scheduled_at 컬럼 인덱스 추가
- findAllByScheduledAt 조회 시 fetch join 적용

* chore: 파일 개행 누락 수정

* 본인 소유 검증 누락으로 인한 멤버/디바이스 권한 문제 수정 (#69)

* refactor: 디바이스 인증 기능 마이그레이션

- 멤버 디바이스 조회 기능 수정
- RequestParam email 제거
- 인증된 디바이스 식별자로 멤버 조회하도록 변경

- 디바이스 삭제 기능 수정
- 인증된 디바이스 식별자로 요청자 식별
- 삭제 대상 디바이스 소유권 검증 로직 추가

- Service Input DTO 이메일 필드 제거
- MemberFindInput, DeviceDeleteInput

* refactor: 리뷰 저장 시 커스텀 주기 소유권 검증 로직 수정

- MemberServiceTest 예외 메시지 검증 구체화
- MemberControllerTest 불필요한 테스트 및 파라미터 제거

* test: 멤버 디바이스 조회 테스트 설명 수정

- 이메일 파라미터 누락 시 200 응답 반환에 맞춰 테스트 설명 수정

* feat: 리뷰 저장 시 커스텀 복습 주기 소유권 검증 로직 추가 (#71)

* 코드 리뷰 actions 스크립트 추가 (#72)

* Virtual Thread 적용을 통한 이메일 발송 처리량 개선 (#75)

* chore: virtual thread 설정 추가

- application.yaml VT 설정 추가
- Dockerfile 런타임 JDK 25버전으로 상향 조정

* chore: Docker 이미지 태그 버전 고정

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* 이메일 발송 로직 notification_history outbox 패턴 전환 (#77)

* refactor: 이메일 전송 로직 재구성

- notification_history를 outbox 패턴 전환: append-only INSERT → 단건 UPDATE 방식
- fail_count, last_attempted_at 컬럼 추가
- 스케줄러 조회를 정확 일치에서 범위 조회로 변경해 서버 다운 시 PENDING 누락 방지
- findAllRetryableCycles에 cutoffDateTime으로 단기 주기 재시도 제외

* refactor: 불필요한 트랜잭션 annotation 제거

* refactor: clearAutomatically 적용

* refactor: 벌크 update 결과 검증 로직 추가

* style: 단기 주기 판단 기준 주석화

* refactor: NotificationHistoryService#updateStatus 로직 최적화

* 다음 리뷰 전송 예정 정보 조회 API 구현 (#79)

* feat: 다음 리뷰 주기 조회 기능 추가

* refactor: NotificationHistoryRepository#findAllByMemberAndStatus로 메서드명 수정

* Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체 (#81)

* chore: Gmail SMTP에서 AWS SES SDK v2로 이메일 발송 인프라 교체

* refactor: 이메일 전송 예외 처리 및 테스트 보완

* 이메일 재전송 포기 기준을 maxRetry 횟수 -> deadline 기반으로 전환 (#84)

* refactor: 전송 실패 이메일 재전송 기능 정리

* test: 테스트 회귀 문제 수정

* notification_history.review_cycle_id unique constraint 추가 (#86)

* chore: NotificationHistory review_cycle_id에 유니크 제약 조건 추가

* refactor: NotificationHistory 유니크 제약 조건명 명시

* style: NotificationHistory 테이블 설정 개행 정리

* deadline을 PENDING 생성 시점에 결정하도록 NotificationHistory 설계 개선 (#89)

* refactor: NotificationHistory deadline 계산 로직 변경
  - 새로운 복습 주기가 추가될 때, 계산하도록 수정

* README.md 설명 추가 (#90)

* docs: README.md 설명 추가

- 프로젝트 소개 추가
- 서비스 기능 설명 추가
- 기술 스택 추가
- 아키텍처 다이어그램 추가

* docs: README 문서 이미지 및 뱃지 수정

- 이미지 너비 100% 설정
- 기술 스택 뱃지 줄바꿈 추가

* docs: README 뱃지 색상 수정

- Loki, Tempo 뱃지 색상 변경

* 서버 및 DB 시간 처리 정책 UTC로 통일 (#93)

* fix: 서버 타임존 처리 UTC로 통일

* fix: 서버 타임존 처리 UTC로 통일

* refactor: UTC 변환로직을 도메인 레이어로 이동

* refactor: Jackson 설정 application.yaml 설정으로 변경

* notification_history 테이블에 status, deadline 복합 인덱스 추가 (#96)

* db 커넥션 풀 및 jvm 설정 추가 (#99)

- 컨테이너 별 메모리 제한
- jvm 힙 메모리 한도
- hikaricp 누수 감지 시간

* Claude 코드 리뷰 동작 개선 및 코멘트 응답 기능 추가 (#102)

* feat: Claude 코드 리뷰 동작 개선 및 코멘트 응답 기능 추가

- `@claude` 멘션 시 응답하는 comment-response.yml 워크플로우 추가
- 중복 실행 방지를 위한 concurrency 설정 추가
- 리액션이 달린 인라인 코멘트는 삭제 대상에서 제외하도록 로직 수정

* fix: Claude 댓글 응답 워크플로우 접근 권한 및 동시성 제어 추가

* review_cycle에 notification_history 병합 및 복합 인덱스 적용 (#104)

* refactor: NotificationHistory 도메인을 ReviewCycle로 병합

- status, failCount, lastAttemptedAt, deadline 필드를 ReviewCycle 엔티티로 이동
- 불필요해진 NotificationHistory 도메인, 리포지토리, 서비스 클래스 제거
- 이메일 전송 상태 업데이트 및 조회 쿼리를 ReviewCycleRepository로 통합
- SingleReviewEmailSender에서 발송 결과 처리 시 ReviewCycleService를 사용하도록 변경
- ReviewService에서 ReviewCycle 엔티티를 생성할 때 발송 상태(PENDING)와 deadline을 함께 설정하도록 구조 변경
- 분리되어 있던 NotificationHistory 저장 로직 제거
- 기존 notification_history 테이블의 데이터를 review_cycle 테이블로 이전 및 제약조건 추가
- 발송 대상 및 재시도 조회를 위한 최적화 복합 인덱스(status, scheduled_at / status, deadline) 추가

* refactor: ReviewCycleRepository 조회 및 벌크 연산 쿼리 개선

- ReviewCycle 조회 쿼리에 Member 엔티티 fetch join 추가
- 상태 업데이트 벌크 연산(@Modifying) 실행 전 영속성 컨텍스트 동기화를 위해 flushAutomatically = true 옵션 추가

* test: ReviewCycleService updateStatus 테스트 추가

- ReviewCycleService updateStatus 관련 테스트 시나리오 추가
- ReviewCycleTest 내 불필요한 import 제거

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ feat 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants