Skip to content

Comments

Fix(#7): Dockerfile 경로 못 찾는 오류 수정#14

Merged
Yoonchulchung merged 4 commits intodevfrom
fix(#7)ci-cd-fix
Jan 17, 2026
Merged

Fix(#7): Dockerfile 경로 못 찾는 오류 수정#14
Yoonchulchung merged 4 commits intodevfrom
fix(#7)ci-cd-fix

Conversation

@ParkJiYeoung8297
Copy link
Contributor

related_to : #7

📝 작업 내용

Dockerfile을 못 찾는 cd 오류 수정

✅ 변경 사항

  • cd-prod.yml에 dockerfile 경로 추가

📷 스크린샷 (선택)

image image

💬 리뷰어에게

@ParkJiYeoung8297 ParkJiYeoung8297 self-assigned this Jan 17, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ParkJiYeoung8297, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 CI/CD 환경에서 Dockerfile 경로를 찾지 못하는 오류를 수정하는 것을 목표로 한다고 설명되어 있지만, 실제 변경 사항은 주로 애플리케이션의 테스트 데이터베이스를 PostgreSQL에서 MySQL로 마이그레이션하고, 애플리케이션 이름을 'Realmatch'로 변경하며, 일부 API 테스트 경로를 업데이트하고, PostgreSQL 런타임 의존성을 제거하는 데 중점을 둡니다. PR 설명에 언급된 cd-prod.yml 파일 변경은 포함되어 있지 않습니다. 전반적으로, 이 PR은 애플리케이션의 데이터베이스 인프라와 기본 설정을 업데이트하는 데 기여합니다.

Highlights

  • 테스트 환경 데이터베이스 마이그레이션: 테스트 환경의 데이터베이스 설정이 PostgreSQL에서 MySQL로 완전히 변경되었습니다. 이는 데이터소스 URL, 사용자 이름, 비밀번호, 드라이버 클래스 및 Hibernate dialect를 포함합니다.
  • 애플리케이션 이름 변경: 운영 및 테스트 환경의 애플리케이션 이름이 'Spot'에서 'Realmatch'로 일관되게 업데이트되었습니다.
  • API 경로 업데이트: 보안 설정(SecurityConfig.java)에서 테스트 관련 API 경로가 /api/v1/test에서 /api/test로, /api/v1/test-auth에서 /api/test-auth로 변경되었습니다.
  • PostgreSQL 의존성 제거: build.gradle 파일에서 PostgreSQL 런타임 의존성이 제거되었습니다.
Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/cd-prod.yml
    • .github/workflows/pr-check.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

이 PR은 데이터베이스를 PostgreSQL에서 MySQL로 마이그레이션하고, API 엔드포인트 경로를 수정하며, 애플리케이션 이름을 변경하는 등 여러 가지 개선 사항을 포함하고 있습니다. PR 설명에는 Dockerfile 경로 오류 수정에 대한 내용이 있지만, 실제 변경 사항에는 관련 파일(cd-prod.yml)이 포함되어 있지 않은 것 같습니다. 이 부분은 확인이 필요해 보입니다.

코드 변경 사항 자체는 대부분 좋아 보입니다. 다만, application-test.yml 파일에 데이터베이스 접속 정보를 하드코딩한 부분이 있어 보안상 취약할 수 있습니다. 이 부분을 환경 변수를 사용하도록 수정하는 것을 제안합니다. 자세한 내용은 개별 코멘트를 확인해주세요.

Comment on lines 15 to 18
url: jdbc:mysql://localhost:3306/test_db
username: test_user
password: test
driver-class-name: com.mysql.cj.jdbc.Driver
Copy link
Contributor

Choose a reason for hiding this comment

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

security-high high

테스트 환경 설정 파일(application-test.yml)에 데이터베이스 사용자 이름과 비밀번호가 하드코딩되어 있습니다. 이렇게 민감한 정보를 코드에 직접 포함하는 것은 보안상 위험할 수 있으며, 실수로 유출될 가능성이 있습니다. application-prod.yml에서처럼 환경 변수를 사용하여 이 정보를 외부에서 주입하는 것이 좋습니다. 로컬 테스트를 위해 기본값을 제공하더라도 환경 변수로 재정의할 수 있도록 구성하는 것을 권장합니다.

    url: ${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/test_db}
    username: ${SPRING_DATASOURCE_USERNAME:test_user}
    password: ${SPRING_DATASOURCE_PASSWORD:test}
    driver-class-name: com.mysql.cj.jdbc.Driver

Copy link
Member

@Yoonchulchung Yoonchulchung left a comment

Choose a reason for hiding this comment

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

좋습니다

@Yoonchulchung Yoonchulchung merged commit a964945 into dev Jan 17, 2026
1 check passed
@Yoonchulchung Yoonchulchung deleted the fix(#7)ci-cd-fix branch January 17, 2026 15:45
Yoonchulchung added a commit that referenced this pull request Jan 24, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
Template 추가

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
ISSUE 템플릿에 bug, chore, fix, refactor를 추가하고, PR 템플릿을 추가하였습니다.

PR 템플릿은 메인 브랜치에 추가가 되어야 자동으로 불러오기 때문에 main에 한 번 더 PR 요청을 하겠습니다.

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [X] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
DOCS #43 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang pushed a commit that referenced this pull request Jan 24, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅 기능의 미들웨어 사용을 위해 Docker compose에 RabbitMQ 추가

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
도커 컴포즈에 RabbitMQ 추가. Notion에 env 토글에 MIDDLEWARE 부분 추가.

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [X] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
FEAT #45 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
Yoonchulchung added a commit that referenced this pull request Jan 24, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
Docker Compose 설정을 개선하고, 환경변수 기반으로 설정을 통합하여 dev/prod 환경 전환을 용이하게 함

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- Docker Compose에 realmatch-network 브리지 네트워크 추가
- 모든 서비스 포트를 환경변수로 관리하도록 변경 (MYSQL_PORT, RABBITMQ_MQ_PORT 등)
- application-dev.yml, application-prod.yml에 Redis 설정 추가
(spring.data.redis)
- RabbitMQ 연결 설정 추가
- .env 파일을 통한 환경변수 주입 방식으로 통합 (env_file: .env)
- 컨테이너 이름 통일 (realmatch_mysql, realmatch_redis, realmatch_spring,
realmatch_mqtt)

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [X] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [X] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
FEAT #45 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Jan 26, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
채팅방 목록 조회 API를 QueryDSL 기반으로 구현했습니다. 탭/필터/커서 기반 페이지네이션, 미읽음 메시지 카운트, 상대방
정보 조회 기능을 포함했습니다.

<img width="500" height="300" alt="image"
src="https://github.com/user-attachments/assets/7a97c046-f27e-4d29-a22e-456947730571"
/>
<img width="500" height="300" alt="image"
src="https://github.com/user-attachments/assets/e8f92558-eb4d-4b58-aecb-88dc66b98316"
/>


## Changes
- QueryDSL 5.1.0 도입 및 설정
  - QueryDslConfig 추가 (JPAQueryFactory 빈 등록)
  - ChatRoomRepositoryCustom 인터페이스 및 구현체 추가
  - 동적 조건(탭/필터/커서)을 타입 안전하게 처리

- 채팅방 목록 조회 기능 구현
  - 탭 필터링 (SENT/RECEIVED/ALL) - lastProposalDirection 기준
  - 상태 필터링 (MATCHING/REVIEWING/REJECTED/ALL) - proposalStatus 기준
  - 커서 기반 페이지네이션 (lastMessageAt DESC, roomId DESC)
  - 메시지가 없는 방 제외 (lastMessageAt IS NOT NULL)

- 미읽음 메시지 카운트 기능
  - 탭별 미읽음 메시지 총합 (필터 무관, 전체 기준)
  - 채팅방별 미읽음 메시지 개수 (배치 조회로 N+1 해결)
  - senderId != userId 조건으로 정확한 미읽음 계산

- 상대방 정보 조회 최적화
  - Brand 정보 배치 조회 (findByCreatedByIn)
  - User 정보 배치 조회 (findAllById)
  - N+1 문제 해결

- Repository 메서드 추가
- ChatRoomMemberRepository: findByRoomIdIn, findByUserIdAndRoomIdIn,
findByRoomId
  - ChatMessageRepository: countByRoomIdAndIdGreaterThanAndSenderIdNot
  - BrandRepository: findByCreatedBy, findByCreatedByIn

- REST API 엔드포인트
  - GET /api/chat/rooms (탭/필터/커서/사이즈 파라미터 지원)
  - Swagger 문서화 추가


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [x] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #41

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
Yoonchulchung added a commit that referenced this pull request Jan 27, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
Redis와 Spring Swagger 버젼간의 버젼 충돌이 있어 Redis 버젼 수정을 진행함.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- Redis 버젼 변경
- UUID 사용방법 변경. 

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [X] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Jan 28, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
채팅 메시지 조회 API 서비스 구현을 완료했습니다. 이제 동시에 웹에 접속해있지 않아도 DB 조회를 통해 메시지를 확인할 수
있습니다. 채팅 기능의 코드 품질을 개선하고 실시간 채팅방 목록 업데이트 기능을 추가했습니다. 중복된 검증 로직을 통합하고 DB
중복 호출을 제거하여 성능을 최적화했으며, WebSocket을 통해 채팅방 목록이 실시간으로 업데이트되도록 구현했습니다.


https://github.com/user-attachments/assets/2f106a8f-4ec3-4191-98a7-c7b8b42eed12


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

### 채팅 메시지 조회 API 서비스 구현
- 웹에 접속하지 않은 상태에서도 DB 조회를 통해 메시지 확인 가능
- 채팅방 목록 및 메시지 조회 기능 구현

### 실시간 기능 추가
- **ChatRoomListUpdatedEvent**: 채팅방 목록 업데이트 이벤트 DTO 추가
- **ChatMessageEventPublisher**: `publishRoomListUpdated` 메서드 추가
- **WebSocketChatMessageEventPublisher**: 사용자별 채팅방 목록 업데이트 이벤트 발행 구현
  - `/topic/user/{userId}/rooms` 토픽으로 개별 사용자에게 알림 발행
- **ChatMessageSocketServiceImpl**: 메시지 전송 시 채팅방 목록 업데이트 이벤트 발행
- **ChatRoomCommandServiceImpl**: 채팅방 생성 시 양쪽 사용자에게 목록 업데이트 이벤트 발행


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #65 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
- 클라이언트 측에서 `/topic/user/{userId}/rooms` 토픽을 구독하여 채팅방 목록 업데이트 이벤트를 수신할 수
있습니다.
ParkJiYeoung8297 added a commit that referenced this pull request Jan 28, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
캠페인 제안하는 기능입니다.


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- [x] CampaignProposal, CampaignProposalContentTag 엔티티 변경
- [x] 캠페인 제안하기 기능 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [x] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
related to: #53 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
ParkJiYeoung8297 added a commit that referenced this pull request Jan 28, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
related_to : #11 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Jan 30, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
AWS S3를 활용한 파일 업로드 기능을 구현하고, Chat 도메인에 강하게 결합되어 있던 Attachment 기능을 독립적인
도메인으로 분리했습니다.


## Changes

### 1. 도메인 분리 및 아키텍처 개선
- **Attachment 도메인 독립화**
  - Chat 도메인에 있던 `ChatAttachment` 엔티티를 `Attachment` 엔티티로 분리
- `ChatAttachmentType`, `ChatAttachmentStatus` → `AttachmentType`,
`AttachmentStatus`로 변경
  - Attachment 전용 Repository, Service, Controller 생성
  - 도메인 간 통신을 위한 `AttachmentDto` (Application 레이어) 추가

- **레이어 아키텍처 준수**
  - Application 레이어에서 Presentation 레이어 DTO 직접 의존 제거
  - `AttachmentQueryService`가 `AttachmentDto` 반환하도록 변경
- `ChatMessageResponseMapper`에서 `AttachmentDto` →
`AttachmentInfoResponse` 변환 처리

### 2. S3 파일 업로드 기능 구현
- **AWS S3 통합**
  - AWS SDK for S3 의존성 추가 (`software.amazon.awssdk:s3`)
  - `S3FileUploadService` 인터페이스 및 구현체 추가
  - `S3Config`를 통한 S3Client, S3Presigner 빈 설정
  - `S3Properties`를 통한 설정값 관리 (application.yml)

- **파일 업로드 기능**
- `AttachmentController`에 파일 업로드 REST API 추가 (`POST
/api/v1/attachments`)
  - 파일 검증 로직 (`FileValidator`) 구현
  - 이미지/일반 파일 타입별 크기 제한 적용
  - Presigned URL 생성 기능 (Private Bucket 지원)

### 4. API 변경사항
- **Chat 도메인**
  - 첨부파일 업로드 API가 Chat 도메인에서 제거됨
- Chat 메시지 조회 시 `AttachmentInfoResponse` 사용 (기존
`ChatAttachmentInfoResponse` 대체)

- **Attachment 도메인**
  - 새로운 REST API 추가: `POST /api/v1/attachments`
  - Swagger 문서화 추가 (`AttachmentSwagger`)


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #83 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->

S3관련해서 .env와 application.yml 파일 변경 있습니다. 머지 후 노션에 업데이트할 예정입니다.
1000hyehyang added a commit that referenced this pull request Jan 30, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
채팅 기능의 보안성과 확장성을 개선하기 위해 WebSocket 인증을 강화하고, 시스템 메시지 이벤트 리스너를 구현했습니다. 또한
코드 품질 향상을 위한 리팩토링을 수행했습니다.


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

### 1. WebSocket 인증 강화
- **ChatWebSocketJwtInterceptor** 구현
  - WebSocket 연결 시 JWT 토큰 검증 로직 추가
  - 인증 실패 시 `MessageDeliveryException`을 던져 연결 거부 처리
  - Authorization 헤더에서 Bearer 토큰 추출 및 검증
  - 검증 성공 시 `UsernamePasswordAuthenticationToken`으로 인증 정보 설정

### 2. 시스템 메시지 이벤트 리스너 구현
- **ProposalSentEventListener** 구현
  - `ProposalSentEvent` 수신 시 `PROPOSAL_CARD` 시스템 메시지 자동 발행
  - 비동기 처리(`@Async`) 및 트랜잭션 관리
  - 예외 처리 및 로깅 추가

- **ProposalStatusChangedEventListener** 구현
  - `ProposalStatusChangedEvent` 수신 시 채팅방 제안 상태 업데이트
  - `PROPOSAL_STATUS_NOTICE` 시스템 메시지 발행
  - 매칭 완료 시 `MATCHED_CAMPAIGN_CARD` 시스템 메시지 발행
  - 비즈니스 도메인의 `ProposalStatus`를 채팅 도메인의 `ChatProposalStatus`로 변환

### 3. 코드 리팩토링
- **ChatRoomKeyGenerator** 유틸리티 클래스 생성
  - 채팅방 키 생성 로직 중복 제거
  - `ChatRoomCommandServiceImpl`, `ChatRoomQueryServiceImpl`에서 공통 사용
  - null 검증 및 `CustomException` 처리 추가

- **OpponentInfoServiceImpl** 리팩토링
  - `getOpponentInfoMapBatch` 메서드를 작은 단위로 분리
- `findOpponentMembersByRoom`, `buildOpponentUserIdMap`,
`loadOpponentUsers`, `toOpponentInfo` 메서드 추출
  - "알 수 없음" 상대방 정보 처리 로직을 `unknownOpponentInfo` 메서드로 중앙화

- **AttachmentQueryServiceImpl** 리팩토링
- `@Autowired(required = false)` 대신 `Optional<AttachmentUrlService>`
사용으로 의존성 명확화
  - presigned URL 생성 로직을 `enrichWithPresignedUrl` 메서드로 추출하여 중복 제거
  - `findById`, `findAllById`에서 공통 로직 재사용

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
Closes #107 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->

### WebSocket 인증
- `ChatWebSocketJwtInterceptor`는 `ChatWebSocketConfig`에서
`ObjectProvider`를 통해 선택적으로 주입됩니다
- 인증 실패 시 연결이 거부되며, 클라이언트는 적절한 에러 메시지를 받게 됩니다
- 기존에 연결된 사용자는 영향받지 않으며, 새로운 연결 시에만 인증이 적용됩니다

### 시스템 메시지 이벤트 리스너
- `ProposalSentEvent`와 `ProposalStatusChangedEvent`는 비즈니스 도메인에서 발행되어야
합니다.
- 이벤트 리스너는 `@Async`로 비동기 처리되며, 실패 시에도 메인 트랜잭션에 영향을 주지 않습니다
- 예외 발생 시 로깅만 수행하며, 재시도 메커니즘은 추후 구현 예정입니다
1000hyehyang added a commit that referenced this pull request Jan 30, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅방 목록 조회 API에 검색 기능을 추가했습니다. 사용자가 **상대방 이름(닉네임)** 또는 **메시지 내용**으로 채팅방을
검색할 수 있으며, 검색 시 목록에는 매칭된 메시지의 미리보기와 시간이 표시됩니다. 기존 필터(status),
페이지네이션(cursor, size)과 함께 동작합니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- **API**
  - `GET /api/v1/chat/rooms`에 optional 쿼리 파라미터 `search` 추가
  - 검색 시 상대방 이름 또는 메시지 내용 일치 방만 반환 (OR, 부분 일치, 대소문자 무시)
- **Repository**
- `ChatRoomRepositoryCustom.findRoomsByUser(..., String search)` 시그니처 추가
및 검색 조건 적용 (상대방 닉네임 서브쿼리 + 메시지 content 서브쿼리)
-
`ChatMessageRepositoryCustom.findLatestMatchingMessageByRoomIds(roomIds,
search)` 추가 — 검색 시 방별 매칭 메시지 1건 조회
- **Service / Assembler**
- `ChatRoomQueryService.getRoomList(..., String search)` 시그니처 추가 및 검색
파라미터 전달
- 검색 시 `ChatRoomCardAssembler`에서 매칭 메시지 기준으로 `lastMessagePreview` /
`lastMessageAt` / `lastMessageType` 설정
- **Controller / Swagger**
  - `ChatController.getRoomList`에 `search` 파라미터 추가
  - `ChatSwagger`에 `search` 설명 및 검색 규칙 반영
- **문서**
  - `PRD/chat-rest-api.md` 채팅방 목록 조회 섹션에 `search` 파라미터 및 규칙 추가
- **테스트**
- `chat-test.html`: 검색 입력/검색/초기화 버튼, 검색 시 API에 `search` 전달, 채팅방 목록
cursor 페이지네이션(더보기), 총 미읽음 뱃지 표시

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #125 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
- 검색어가 없거나 공백만 있으면 기존과 동일하게 전체 목록을 반환합니다.
- 메시지 검색 시 시스템 메시지(senderId가 null인 메시지)는 제외됩니다.
- 상대방 이름 검색은 `User` 테이블과 조인하여 `nickname` 기준으로 수행하며, 채팅 도메인 Repository에서만
User 엔티티를 참조합니다.
1000hyehyang added a commit that referenced this pull request Feb 1, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅과 첨부파일 도메인을 전반적으로 개선하고, S3를 private-only 구조로 전환했습니다. Redis 기반 채팅방 캐시,
메시지 읽음 이벤트 처리, Attachment 용도별 S3 경로 분리, 고아 파일 정리 스케줄러 등을 추가·개선했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

### 첨부파일(Attachment) 도메인
- **AttachmentUsage enum 추가** (CHAT, PUBLIC): S3 경로 prefix 분리 및 향후
TTL·캐싱 정책 분리용
- **AttachmentStatus에 DELETE_PENDING 추가**: 배치 정리용 내부 상태
- **AttachmentUploadRequest에 usage 필드 필수화**: 업로드 시 용도 지정 필수
- **accessUrl 제거 → presigned URL 전용**: private-only 전환,
AttachmentResponseMapper에서 accessUrl null 처리
- **AttachmentQueryService.findByIdOrThrow 추가**: 조회 시 예외 발생용 메서드
- **S3 key 생성 시 AttachmentUsage 기반 prefix 적용**: `chat/`, `public/` 경로 분리
- **S3FileUploadService에 deleteFile, isAvailable() 추가**
- **publicBucket 설정 제거**: 단일 private 버킷 사용
- **ProdS3BootGuard 추가**: prod 환경에서 S3 설정 필수 검증
- **S3FileNameSanitizer 추가**: 파일명 sanitize 유틸
- **AttachmentUploadPolicy, S3AttachmentUploadPolicy 추가**: 업로드 정책 인터페이스
분리
- **AttachmentCleanupService + AttachmentCleanupScheduler**: 고아 파일 정리 배치
- **NoOpS3FileUploadService**: isAvailable() false 반환

### 채팅(Chat) 도메인
- **ChatMessagesViewedEvent + ChatMessagesViewedEventListener**: 메시지 조회
시 읽음 처리 (lastReadMessage 업데이트)
- **ChatRoomUpdateService 분리**: ChatRoomCommandService에서
updateLastMessage, updateProposalStatusByUsers 분리
- **Redis 캐시 도입**: ChatCachePolicy, ChatRoomListCache,
ChatRoomDetailCache, ChatCacheEvictor, ChatCacheKeys, ChatCacheStore,
ChatCacheInvalidationService
  - 목록 TTL 30초, 상세 TTL 60초
  - 메시지 생성·읽음 처리·제안 상태 변경 시 캐시 무효화
- **ChatRoomMemberQueryService**: findActiveMembers →
findActiveMemberUserIds (반환 타입을 List&lt;Long&gt;로 변경)
- **계층 구조 정리**: ChatErrorCode, ChatRoomFilterStatus를 presentation →
domain/code로 이동
- **ChatSystemMessageKind에 payloadRequired 필드 추가**
- **SpringAfterCommitExecutor**: 비트랜잭션 시 IllegalStateException throw (즉시
실행 제거)
- **ChatUserIdResolver**: IllegalArgumentException →
CustomException(GeneralErrorCode.UNAUTHORIZED)
- **EnableScheduling 추가**: AttachmentCleanupScheduler 등 스케줄러 동작용

### 기타
- **TestController에 /test/token 엔드포인트 추가**: 테스트용 JWT 토큰 생성 (userId,
role, email 파라미터)
- **.githooks/commit-msg 삭제**
- **ChatRoomRepositoryCustomImpl**: roomIds null/empty 체크 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #127 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 1, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅 첨부파일 업로드 API의 이미지·파일 형식을 스펙(10.3.6, 10.3.7)에 맞게 제한했습니다.
- 이미지: png, jpeg만 허용 (기존 gif, webp 제거)
- 첨부파일: pdf, doc, docx만 허용 (기존 검증 없음 → 화이트리스트 검증 추가)


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

### 이미지 형식 제한
- `S3AttachmentUploadPolicy`: IMAGE 허용 확장자/Content-Type을 png,
jpeg(jpg)만으로 변경
  - 확장자: `jpg`, `jpeg`, `png` (gif, webp 제거)
  - Content-Type: `image/jpeg`, `image/jpg`, `image/png`

### 첨부파일 형식 검증 추가
- `AttachmentUploadPolicy`: `getAllowedFileExtensions()`,
`getAllowedFileContentTypes()` 추가
- `S3AttachmentUploadPolicy`: FILE용 허용 목록 추가 (pdf, doc, docx)
- `AttachmentErrorCode`: `INVALID_FILE_TYPE` (ATTACHMENT400_7) 추가
- `FileValidator`: `validateAttachmentFile()` 추가,
`validateFileFormat()`으로 공통 로직 추출
- `AttachmentValidationService`: FILE 타입 업로드 시 형식 검증 로직 추가

### 문서·Swagger
- `AttachmentSwagger`: 허용 형식 설명 및 ATTACHMENT400_7 응답 추가
- `chat-api-guide.md`: ATTACHMENT400_7 에러 코드 추가


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [x] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #162 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1000hyehyang added a commit that referenced this pull request Feb 1, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
Attachment URL 생성 로직을 storage key 기반으로 분리했습니다.


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- `AttachmentUrlService`에 `getAccessUrl(String storageKey)` 오버로드 추가
- 기존 `getAccessUrl(Attachment)`가 키 기반 메소드로 위임


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #164 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 2, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
기존 `GET /api/v1/matches/campaigns` API를 **쿼리 파라미터만 확장**하여, 매칭 캠페인 목록 조회와
캠페인명(keyword) 검색·카테고리 필터·정렬(매칭률/인기/금액/마감 순)·페이지네이션을 하나의 엔드포인트로 제공합니다. 별도
검색 API 없이 기존 코드를 기반으로 확장했으며, 응답 형식(`count` + `brands`)은 기존 API·카드와
호환됩니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- **Controller**: `GET /api/v1/matches/campaigns`에 optional 파라미터 추가  
`keyword`, `page`(기본 0), `size`(기본 20), 기존 `sortBy`, `category`, `tags`
유지
- **Service**: `MatchService.getMatchingCampaigns` 시그니처 확장  
  - 데이터 소스: 기존과 동일하게 DB `MatchCampaignHistory` (매칭 히스토리)  
  - `keyword` 없으면 전체 목록, 있으면 캠페인명(title) 기준 필터  
  - 정렬: MATCH_SCORE(동점 시 인기순), POPULARITY, REWARD_AMOUNT, D_DAY  
  - 페이지네이션: 요청 `page`/`size`로 구간 반환, 응답은 `count` + `brands`만 (기존 호환)
- **SortType**: `REWARD_AMOUNT`(금액 순), `D_DAY`(마감 순) 추가, 기존 값 유지
- **Repository**: `MatchCampaignHistoryRepository`에
`MatchCampaignHistoryRepositoryCustom` 확장
- `searchCampaigns`, `countSearchCampaigns` (QueryDSL 기반 검색·카운트) 추가, 기존
JpaRepository 메서드 변경 없음
- **DTO**: `MatchCampaignResponseDto` — 기존 `count`, `brands`,
`CampaignDto` 필드명 유지
- 카드 필드: `brandId`, `brandName`, `brandLogoUrl`, `brandMatchingRatio`,
`brandIsLiked`, `brandIsRecruiting`, `campaignManuscriptFee`,
`campaignDetail`(캠페인명 title), `campaignDDay`, `campaignTotalRecruit`,
`campaignTotalCurrentRecruit`
- **리팩터/정리**: 미사용 메서드 제거 (`toMatchCampaignDtoFromHistory`,
`getCampaignHistoryComparator`)
  - 실제 사용: `toCampaignCardDto`, `getCampaignSearchComparator`

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #182

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
- 검색 대상은 **캠페인명(Campaign.title)만** 적용됩니다. 브랜드명·설명·태그는 검색 대상이 아닙니다.
- `keyword` 없이 호출 시 기존과 동일하게 매칭 히스토리 기반 전체 목록이 반환됩니다.

---------

Co-authored-by: Yoonchulchung <yoonchul005@gmail.com>
1000hyehyang added a commit that referenced this pull request Feb 2, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
캠페인 목록 API 정렬 시 동률 발생하면 순서가 비결정적이던 문제를 수정했습니다. 정렬 타입별로 2차·3차·4차 정렬을 고정해
페이지네이션 결과가 일관되게 유지되도록 했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- `MatchCampaignHistoryRepositoryCustomImpl.buildOrderSpecifiers()` 수정
- 정렬 타입별 동률 처리 규칙 추가:
  - **매칭률 순**: 매칭률 → 인기 → id
  - **인기 순**: 인기 → 매칭률 → id
  - **금액 순**: 금액 → 매칭률 → 인기 → id
  - **마감 순**: 마감 → 매칭률 → 인기 → id

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [x] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #206 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 3, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅방 상단 협업 요약바에 캠페인 협찬 제품 정보를 추가하고, 매칭 완료 카드의 결제 안내 문구를 백엔드에서 처리하도록
수정했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- `CampaignSummaryResponse`에 협찬 제품 리스트(`sponsorProducts`) 필드 추가
- `CampaignSummaryServiceImpl`에서 캠페인 협찬 제품 조회 및 매핑 로직 추가
- `BrandAvailableSponsorRepository`에 `findByCampaignIdWithImages` 메서드 추가
(N+1 방지)
- `ChatRoomQueryServiceImpl`에서 협업중(`isCollaborating`)일 때만
`campaignSummary` 조회하도록 수정
- 캠페인 종료(`COMPLETED`) 시 협업 요약바 미노출 처리
- `MatchedCampaignPayloadProviderImpl`에서 결제 안내 문구로 메시지 변경

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [x] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #231

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 4, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
제안/재제안/수락 시 비즈니스 이벤트를 발행하고, 채팅 모듈이 이를 수신해 시스템 메시지(PROPOSAL_CARD,
RE_PROPOSAL_CARD, PROPOSAL_ACCEPTED 등)를 자동으로 채팅방에 전송하도록 연동했습니다. business
↔ chat 도메인 의존 분리(ProposalDirection, ChatProposalStatus) 및 이벤트 리스너 트랜잭션
경계 정리 포함.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- **비즈니스 이벤트**: `CampaignProposalSentEvent`,
`CampaignProposalStatusChangedEvent` 정의 및 `CampaignProposalService`에서 제안
생성/재제안/수락 시 발행
- **채팅 이벤트 리스너**: `CampaignProposalSentEventListener`,
`CampaignProposalStatusChangedEventListener` 추가 (비즈니스 이벤트 → 채팅 내부 이벤트
변환)
- **재제안 시스템 메시지**: `ChatSystemMessageKind.RE_PROPOSAL_CARD` 추가,
`ChatProposalEventAsyncHandler`에서 재제안 시 `RE_PROPOSAL_CARD` 전송
- **직렬화/캐시/조회**: `JacksonSystemMessagePayloadSerializer`,
`ChatCacheInvalidationService`, `ChatMessageRepositoryCustomImpl`에
`RE_PROPOSAL_CARD` 반영
- **도메인 분리**: `ProposalDirection` enum 추가 및
`CampaignProposalSentEvent`에서 Role 대신 사용, `ProposalStatusChangedEvent`는
`ChatProposalStatus`만 사용하도록 변경
- **리스너**: `@TransactionalEventListener` → `@EventListener`로 변경하여 트랜잭션
경계 이슈 방지

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #250

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 4, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅방 재제안 폼 이동을 위한 편의 코드 추가

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
채팅방 재제안 폼 이동을 위한 편의 코드 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #252 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 4, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
이벤트 기반 시스템 메시지 전송 파이프라인을 안정성 중심으로 재정비하고,
지원(Apply) 상태 변경에 대한 시스템 메시지를 신규 구현했습니다.

특히 재시도 로직 분리, 멱등성 확정 지점 명확화, 실패 fallback 보강을 통해
이벤트 중복·유실 가능성을 최소화하고, 운영 환경에서의 관측성과 복구 가능성을 강화했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### **시스템 메시지 전송 파이프라인 안정화**

* `SystemMessageSender` / `SystemMessageRetrySender` 책임 분리

  * `SystemMessageSender`

    * 실제 메시지 전송 + Spring Retry 기반 재시도 담당
    * `@Retryable / @Recover`를 통한 재시도 및 최종 실패 처리
  * `SystemMessageRetrySender`

    * 멱등성 선점/확정 오케스트레이션 전담
    * 성공 시 `markAsProcessed()`로 **성공 확정 지점 명시**
    * 실패/예외 시 선점 키 제거 fallback 처리

* Spring AOP self-invocation 문제 제거

  * `ApplicationContext.getBean()` 방식 제거
  * 재시도 로직을 별도 컴포넌트로 분리하여 프록시 안정성 확보

---

### **멱등성 처리 정책 명확화**

* Redis 기반 멱등성 처리 흐름 정리

  * 선점: `markIfNotProcessed()` (SETNX)
  * 성공 확정: `markAsProcessed()` (SET)
  * 실패: `removeProcessed()` + DLQ 기록
* fallback 경로에서도 **선점 키 제거 보장**

  * Spring Retry 프록시 미적용, @recover 예외 전파 등 엣지 케이스 대비
* 반환값 의미를 “전송 성공 여부”로 명확화

### **DLQ 중복 기록 방지**

* 재시도 소진 후 DLQ 기록이 **한 번만 발생하도록 예외 흐름을 명확히 분리**

  * `DlqEnqueuedException`

    * `@Recover` 단계에서 **DLQ 기록이 완료되었음**을 상위에 명시
    * `BaseSystemMessageHandler`는 해당 예외 감지 시 **중복 DLQ enqueue 차단**
  * cause / suppressed 체인까지 검사하여

    * 재래핑된 예외에서도 중복 기록이 발생하지 않도록 보호

### **DLQ 기록 실패 시 fallback 경로 명시화**

* DLQ enqueue 자체가 실패하는 경우를 명시적으로 구분

  * `DlqEnqueueFailedException`

    * 의미: **“DLQ를 넣으려 했으나 실패 → fallback 필요”**
    * 원래 전송 실패 원인(cause)과 DLQ 실패 원인(suppressed)을 분리 보존
* `BaseSystemMessageHandler`에서 해당 예외 감지 시

  * fallback DLQ enqueue 수행
  * 장애 상황에서도 **실패 이벤트 유실 방지**

### **멱등성 키 제거 책임 일원화**

* `removeProcessed()` 계약을 “**실패 시 swallow**”로 명확화

  * 호출부에서 불필요한 try-catch 제거
  * 전송 최종 실패(@recover) 시에만 키 제거 수행
* Redis 장애/판단 불가 상황은 **예외 전파 → DLQ 경로로 강제 유도**

### **공통 이벤트 핸들러 구조 개선**

* `BaseSystemMessageHandler` 도입

  * payload 생성 단계 / sendAction 단계 예외를 중앙에서 처리
  * 모든 실패 케이스를 DLQ로 일관되게 수집
* DLQ 컨텍스트 강화

  * `handler`, `stage`, `failureReason`, `messageKind`, `domainId` 포함
  * 장애 원인 추적 및 재처리 판단 용이

---

### **지원(Apply) 이벤트 시스템 메시지 구현**

* `ApplySystemMessageHandler` 리팩토링
* 신규 시스템 메시지 추가

  * 지원 전송: `APPLY_CARD`
  * 지원 상태 변경: `APPLY_STATUS_NOTICE`
* 상태 변경 이벤트에 대해 deterministic한 멱등성 키 적용

---

### **제안(Proposal) 이벤트 핸들러 개선**

* `ProposalSystemMessageHandler` 구조 정리
* 제안 전송 / 상태 변경 / 매칭 완료 메시지 처리 일관화

  * `PROPOSAL_CARD`, `RE_PROPOSAL_CARD`
  * `PROPOSAL_STATUS_NOTICE`
  * `MATCHED_CAMPAIGN_CARD`
* payload 생성 실패(`matchedCampaignPayloadProvider`) 시 DLQ 기록 보장

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #256

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
* `sendWithIdempotency()`는 **멱등성 선점 → 전송 → 성공 확정**의 전체 수명주기를 관리합니다.
* 전송 실패, 재시도 초과, payload 생성 실패 등 모든 실패 케이스는 DLQ로 수집됩니다.
* fallback 로직을 통해 **Redis 선점 키가 남아 이벤트가 영구 스킵되는 상황을 방지**했습니다.
* 이번 PR은 **기능 추가 + 이벤트 처리 안정성 강화**를 동시에 목표로 한 구조 개선입니다.
Yoonchulchung added a commit that referenced this pull request Feb 5, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

브랜드 상세 조회 로직 전체 수정 정리

대상 API
- GET /api/v1/brands/{brandId}

⸻

공통 처리
- brand 엔티티에서 brandId로 브랜드 조회
- 아래 필드는 industry_type과 관계없이 그대로 유지
- userId
- brandName
- logoUrl
- simpleIntro
- detailIntro
- homepageUrl
- randMatchingRatiobrandIs
- Liked
- brandTag
- 아직 테이블이 없으므로 빈 배열([])로 응답

⸻

industry_type = BEAUTY 인 경우

brandCategory
	•	tag_category = "관심 스타일" 인 모든 tag_name 조회

brandSkinCareTag
	•	skinType
	•	tag_category = "피부 타입" 인 모든 tag_name 조회
	•	mainFunction
	•	tag_category = "관심 기능" 인 모든 tag_name 조회

brandMakeUpTag
	•	skinType
	•	필드 제거
	•	brandMakeUpStyle
	•	tag_category = "메이크업" 인 모든 tag_name 조회

⸻

industry_type = FASHION 인 경우

brandClothingTag
	•	brandType
	•	tag_category = "관심 브랜드 종류" 인 모든 tag_name 조회
	•	brandStyle
	•	tag_category = "관심 스타일" 인 모든 tag_name 조회

⸻

요약
	•	브랜드 상세 조회 시 industry_type 기준으로 응답 구조 및 태그 조회 로직을 분기
	•	태그 관련 데이터는 모두 tag_category → tag_name 기준으로 전체 조회
	•	BEAUTY / FASHION 외의 industry_type은 추후 확장 고려
## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
#272

---------

Co-authored-by: Yoonchulchung <yoonchul005@gmail.com>
1000hyehyang added a commit that referenced this pull request Feb 6, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅방 `lastMessage` 업데이트와 읽음 처리에서 발생할 수 있는 Race Condition을 조건부 UPDATE로
해결하고, 불필요한 DB 조회를 제거하여 성능을 개선했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### 1. 동시성 문제 해결
- **채팅방 lastMessage 업데이트 Race Condition 해결**
  - `ChatRoomRepository.updateLastMessageIfNewer()` 추가 (조건부 UPDATE)
- `WHERE last_message_at IS NULL OR last_message_at < :newLastMessageAt`
조건으로 더 최신 메시지일 때만 업데이트
  - DB 레벨에서 원자적 연산 보장

- **읽음 처리 동시성 문제 해결**
- `ChatRoomMemberRepository.updateLastReadMessageIfNewer()` 추가 (조건부
UPDATE)
- `WHERE last_read_message_id IS NULL OR last_read_message_id < :newId`
조건으로 더 큰 메시지 ID일 때만 업데이트
  - 동시 읽음 처리 시에도 항상 최대값 유지

### 2. 성능 개선
- **불필요한 조회 제거**
- `ChatRoomUpdateServiceImpl.updateLastMessage()`: `existsById()`를
`updatedRows == 0`일 때만 실행
- `ChatRoomMemberCommandServiceImpl.updateLastReadMessage()`: 성공 시에만 필요한
데이터 조회

- **이벤트에 userId 포함하여 추가 조회 제거**
  - `ChatMessagesViewedEvent`에 `userId` 필드 추가
  - 호출부에서 이미 조회한 `member.getUserId()`를 이벤트에 포함
  - 성공 케이스에서 `findById()` 조회 제거 (SELECT 1회 제거)

### 3. 코드 개선
- 빈 분기 제거 및 guard clause 적용으로 가독성 향상
- `@Modifying(clearAutomatically = true, flushAutomatically = true)` 추가로
영속성 컨텍스트 정합성 보장
- `messageAt` null 방어 로직 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [x] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [x] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #285 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
Yoonchulchung pushed a commit that referenced this pull request Feb 6, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
브랜드 상세 페이지와 생성 프로세스에서 여러 개의 이미지를 관리할 수 있도록 Brand와 BrandImage 간의 연관 관계를
구축하고, 관련 API(조회/생성)를 고도화했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
1. Entity 연관 관계 설정
- Brand 엔티티 내에 BrandImage와의 @onetomany 양방향 연관 관계를 설정했습니다.
- 양방향 편의 메서드(addBrandImage)를 추가하여 데이터 정합성을 보장합니다.

2. DTO 필드 추가
- BrandDetailResponseDto: 조회 시 이미지 URL 리스트(brandImages)를 반환하도록 필드를
추가했습니다.
- BrandBeautyCreateRequestDto, BrandFashionCreateRequestDto: 생성 시 여러 이미지
URL을 받을 수 있도록 리스트 필드를 추가했습니다.

3. Service 로직 고도화
- getBrandDetail: brandImageRepository를 통해 해당 브랜드의 모든 상세 이미지를 조회하여 응답에
포함합니다.
- createBeautyBrand, createFashionBrand: 브랜드 저장 후 전달받은 이미지 URL 리스트를
BrandImage 엔티티로 변환하여 일괄 저장하는 로직을 구현했습니다.


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #281 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
WebSocket CONNECT 단계의 JWT 인증에 더해, **SUBSCRIBE / SEND 단계에서 리소스(방·유저 토픽)
접근 인가**를 적용했습니다.
구독/전송 경로를 “인증만 된 아무 유저”가 사용할 수 있던 문제를 막고, 타인 메시지·이벤트 접근을 차단합니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

### 1. 신규: `ChatWebSocketAuthorizationInterceptor`

- **역할**: SUBSCRIBE / SEND 단계의 리소스 접근 인가 전담 (인증은 기존 JWT 인터셉터 유지)
- **SUBSCRIBE 인가**
- `/topic/v1/rooms/{roomId}` → 해당 방 **활성 멤버**만 허용
(`ChatRoomMemberService.getActiveMemberOrThrow` 사용)
- `/topic/v1/user/{userId}/rooms` → path의 `userId`가 **인증된 사용자 ID와 일치**해야
함
  - `/user/**` → 인증된 사용자 허용 (ACK 등 개인 큐)
  - 그 외 destination → 거부 (STOMP ERROR)
- **SEND 인가**
  - 인증 여부만 확인 (Principal 존재)
- 방 멤버 검증은 기존처럼 **서비스
레이어**(`ChatMessageCommandServiceImpl.saveMessage`)에서 수행 (단일 책임·payload
결합 방지)

### 2. 수정: `ChatWebSocketConfig`

- `ChatWebSocketAuthorizationInterceptor`를 클라이언트 인바운드 채널에 등록
- 등록 순서: ① JWT(인증) → ② 인가 인터셉터

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [x] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #271 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
…317) (#320)

<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅 시스템에서 발견된 신뢰성·관측성 이슈 4가지를 수정했습니다.

1. **멱등성 선점 후 조용한 유실**: SETNX 선점 후 프로세스 다운 시 키가 6시간 동안 남아, 실제 미처리 메시지가
유실되던 문제를 2단계 상태머신(IN_PROGRESS 3분 → PROCESSED 6시간)으로 해결
2. **DLQ 무한 증가**: Redis List `chat:dlq`에 RPUSH 후 LTRIM을 적용해 최대 10,000건만
유지
3. **lastMessage 최신성 오판**: 동일 `lastMessageAt` 시 비교 불가 문제를
`(lastMessageAt, lastMessageId)` 튜플 비교로 해결
4. **논리 실패 관측성 부족**: Micrometer Counter
`chat.system_message.logical_failure`로 eventType, reason 태그 기반 관측 가능

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
- **ProcessedEventStore / RedisProcessedEventStore**
- `markIfNotProcessed(eventId, inProgressTtl)`: IN_PROGRESS 상태로 선점, 짧은
TTL(3분)
- `markAsProcessed(eventId, processedTtl)`: PROCESSED 상태로 승격, 긴 TTL(6시간)
  - 선점 후 프로세스 다운 시 IN_PROGRESS TTL 만료 후 재처리 가능

- **FailedEventDlq**
  - `RPUSH` 후 `LTRIM`으로 최근 10,000건만 유지
  - `MAX_DLQ_SIZE = 10_000` 상수 추가

- **ChatRoomRepository**
- `updateLastMessageIfNewer` WHERE 조건에 `(r.lastMessageAt = :messageAt
AND r.lastMessageId < :messageId)` 타이브레이크 추가

- **SystemMessageRetrySender**
  - `IN_PROGRESS_TTL`(3분), `PROCESSED_TTL`(6시간) 상수 분리
- 논리 실패 시 `chat.system_message.logical_failure` Counter 기록 (eventType,
reason 태그)
  - MeterRegistry 의존성 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [x] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #317 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
채팅 매칭 완료 카드(`MATCHED_CAMPAIGN_CARD`)에 **누가 제안했는지**를 나타내는
`proposalDirection` 필드를 추가했습니다.
프론트에서 "제안한 사람 / 받은 사람"에 따라 카드 문구·UI를 다르게 보여줄 수 있습니다.

- **비즈니스 이벤트** → **채팅 이벤트** → **시스템 메시지 payload**까지 방향 정보를 일관되게 전달
- `campaignId`가 null인 경우 매칭 카드 미전송 및 NPE 방지 처리
- PRD·API 가이드 등 채팅 문서 반영

## Changes
- **비즈니스**
- `CampaignProposalStatusChangedEvent`: `ProposalDirection
proposalDirection` 필드 추가
- `CampaignProposalService.publishProposalStatusChangedEvent`:
`ProposalDirection.fromWhoProposed(proposal.getWhoProposed())`로 설정 후 발행
- **채팅 이벤트**
- `ProposalStatusChangedEvent`: `ChatProposalDirection
proposalDirection` 필드 추가
- `CampaignProposalStatusChangedEventListener`: 비즈니스 `ProposalDirection`
→ `ChatProposalDirection` 변환 후 내부 이벤트에 포함
- **채팅 payload·서비스**
- `ChatMatchedCampaignPayloadResponse`: `ChatProposalDirection
proposalDirection` 필드 추가
- `MatchedCampaignPayloadProvider`: `getPayload(Long campaignId,
ChatProposalDirection proposalDirection)` 시그니처로 변경
- `MatchedCampaignPayloadProviderImpl`: 전달받은 `proposalDirection`을
payload에 포함
- `ProposalSystemMessageHandler`: 매칭 카드 생성 시 `event.proposalDirection()`
전달, **campaignId가 null이면 매칭 카드 전송 생략** (NPE 방지)
- **문서**
- `chat-api-guide.md`: MATCHED_CAMPAIGN_CARD payload에
`proposalDirection` 설명 및 프론트 분기 가이드
- `chat-system-architecture.md`: MATCHED_CAMPAIGN_CARD payload 예시에
`proposalDirection` 추가
  - `chat-rest-api.md`: 메시지 예시 payload에 `proposalDirection` 추가
  - `chat-dto.md`: 매칭 카드 payload 항목에 제안 방향 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)

## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #323

## 참고 사항
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
Notification 도메인과 알림 페이지 REST API를 구현했습니다. 푸시·이메일 발송은 다루지 않고,
저장·조회·필터·읽음 처리만 담당합니다.

**목표**: 알림 레코드를 저장·조회·필터·읽음 처리할 수 있는 도메인과 API를 갖추고, 이후 서브 이슈(이벤트
발행·푸시·이메일)에서 이 API를 그대로 사용할 수 있도록 합니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### 도메인 계층
- ✅ `Notification` 엔티티 (UUID PK, DeleteBaseEntity 상속)
- ✅ `NotificationKind` enum (8종: PROPOSAL_RECEIVED, CAMPAIGN_MATCHED 등)
- ✅ `NotificationCategory` enum (UI 필터용: PROPOSAL, MATCHING, SETTLEMENT,
CHAT)
- ✅ `ReferenceType` enum (CAMPAIGN_PROPOSAL, CAMPAIGN_APPLY, CAMPAIGN)
- ✅ `NotificationRepository` (JPQL 벌크 업데이트 포함)
- ✅ `NotificationErrorCode` (404, 403)

### 애플리케이션 계층
- ✅ `NotificationService` (생성, 단건 읽음, 전체 읽기, 소프트 삭제)
- ✅ `NotificationQueryService` (목록 조회, 미읽음 개수)
- ✅ `CreateNotificationCommand` (Phase 2 이벤트 리스너용 내부 DTO)

### 프레젠테이션 계층
- ✅ `NotificationController` (4개 REST 엔드포인트)
- ✅ `NotificationSwagger` 인터페이스
- ✅ Response DTO (record): `NotificationResponse`,
`NotificationListResponse`, `NotificationDateGroup`, `ReadAllResponse`,
`UnreadCountResponse`

### API 엔드포인트
1. **GET** `/api/v1/notifications` - 알림 목록 (filter, 페이징, 날짜 그룹)
2. **PATCH** `/api/v1/notifications/{id}/read` - 단건 읽음 처리
3. **PATCH** `/api/v1/notifications/read-all` - 전체 읽기 (벌크 UPDATE)
4. **GET** `/api/v1/notifications/unread-count` - 미읽음 개수

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #216 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
비즈니스 이벤트를 구독하여 알림을 생성하고, 발송 대기 상태의 Delivery 레코드를 자동 생성하는 기능을 구현했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### 핵심 기능 구현
- **NotificationEventListener** 추가
  - `@TransactionalEventListener(AFTER_COMMIT)`로 3종 이벤트 구독
  - `CampaignProposalSentEvent` → `PROPOSAL_RECEIVED` 알림 생성
- `CampaignProposalStatusChangedEvent` → `CAMPAIGN_MATCHED` /
`PROPOSAL_SENT` 알림 생성
  - `CampaignApplySentEvent` → `CAMPAIGN_APPLIED` 알림 생성
  - 각 알림 생성은 독립적으로 예외 처리 (하나 실패해도 다른 알림 생성에 영향 없음)

- **NotificationDelivery** 엔티티 및 Repository 추가
  - 알림 발송 상태 추적용 엔티티 (`PENDING`, `IN_PROGRESS`, `SENT`, `FAILED`)
  - 채널별 발송 상태 관리 (PUSH, EMAIL)
  - 재시도 정책을 위한 `attemptCount` 필드 추가
  - 멱등성 보장을 위한 `idempotency_key` UNIQUE 제약

- **NotificationService.create()** 개선
  - `REQUIRES_NEW` 트랜잭션으로 알림 생성 (비즈니스 트랜잭션과 분리)
  - 알림 저장 시 `NotificationDelivery` PENDING 레코드 자동 생성
  - 멱등성 보장: `eventId:kind:receiverId:channel` 조합으로 중복 방지

- **NotificationChannelResolver** 추가
  - 알림 종류별 발송 채널 자동 결정
  - PRD 기준으로 채널 매핑 (예: `CAMPAIGN_MATCHED` → PUSH + EMAIL)

- **NotificationMessageTemplateService** 추가
  - 이벤트 데이터를 기반으로 알림 제목/본문 생성
  - 브랜드명, 크리에이터명 등 동적 데이터 포함

### 데이터베이스 스키마
- `notification_delivery` 테이블 생성 스크립트 추가
- `attempt_count` 컬럼 추가를 위한 ALTER 스크립트 추가
- `idempotency_key` UNIQUE 제약 추가를 위한 ALTER 스크립트 추가

### 테스트
- **NotificationEventListenerIntegrationTest** 추가
  - 이벤트 발행 → 알림 생성 → Delivery 생성 전체 플로우 검증
  - 멱등성 테스트 포함
- `@TransactionalEventListener(AFTER_COMMIT)` 테스트를 위해 명시적 트랜잭션 커밋 방식 사용

- **NotificationChannelResolverTest** 추가
  - 알림 종류별 채널 매핑 검증

- **NotificationMessageTemplateServiceTest** 추가
  - 메시지 템플릿 생성 로직 검증

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #217 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 8, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
채팅방 상세 응답(`ChatRoomDetailResponse`)에 `myRole` 필드를 추가하여 더 깔끔한 설계로 개선했습니다.
프론트엔드는 채팅방 입장 시 1번만 `myRole`을 받아서 클라이언트 상태로 보관하고, 모든 시스템 메시지 카드 렌더링 시 이를
활용합니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
1. **`ChatRoomDetailResponse`에 `myRole` 필드 추가**
   - 채팅방 상세 조회 시 현재 사용자의 역할(`BRAND` 또는 `CREATOR`)을 함께 반환
   - 추가 쿼리 없이 기존 `getActiveMemberOrThrow` 결과에서 `getRole()`을 추출하여 전달

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #329 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 9, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
비즈니스 이벤트 기반 알림 시스템을 구현했습니다. 제안 수신, 캠페인 매칭 등 이벤트 발생 시 웹 푸시(FCM) 및 이메일 알림을
발송하고, 알림 페이지 API를 제공합니다. Outbox 패턴을 사용하여 비즈니스 트랜잭션과 완전히 분리되었으며, 재시도 정책과
장애 격리 메커니즘이 포함되어 있습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
### 도메인 레이어
- **Notification 엔티티**: 알림 원장 (읽음 처리, 소프트 삭제 지원)
- **NotificationDelivery 엔티티**: 채널별 발송 추적
(PENDING/IN_PROGRESS/SENT/FAILED 상태, 재시도 관리)
- **FcmToken 엔티티**: FCM 디바이스 토큰 저장소 (다중 기기 지원, 토큰 재할당)
- **NotificationKind enum**: 알림 종류 정의 (PROPOSAL_RECEIVED,
CAMPAIGN_MATCHED 등)
- **DeliveryStatus enum**: 발송 상태 정의 (PENDING, IN_PROGRESS, SENT, FAILED)

### 애플리케이션 레이어
- **NotificationService**: 알림 생성 및 읽음 처리
- **NotificationQueryService**: 알림 목록 조회 (필터링, 날짜별 그룹핑, 페이징)
- **NotificationDeliveryProcessor**: 개별 발송 처리 (장애 격리, REQUIRES_NEW 트랜잭션)
- **FcmTokenService**: FCM 토큰 등록/삭제 관리
- **NotificationChannelResolver**: 알림 종류별 채널 결정 (PUSH/EMAIL)
- **NotificationMessageTemplateService**: 알림 메시지 템플릿 생성

### 인프라스트럭처 레이어
- **NotificationEventListener**: 비즈니스 이벤트 구독 및 알림 생성
(`@TransactionalEventListener(AFTER_COMMIT)`)
- **NotificationDeliveryWorker**: 비동기 발송 워커 (`@Scheduled`, 30초마다 실행)
- **FcmNotificationSender**: FCM 웹 푸시 발송 (Firebase Admin SDK)
- **EmailNotificationSender**: 이메일 발송 (Spring Mail, HTML 템플릿)
- **FirebaseConfig**: Firebase Admin SDK 초기화 (선택적, 파일 없어도 동작)

### 프레젠테이션 레이어
- **NotificationController**: 알림 목록 조회, 읽음 처리 API
- **FcmTokenController**: FCM 토큰 등록/삭제 API
- **NotificationSwagger**: API 문서화 인터페이스
- **FcmTokenSwagger**: FCM 토큰 API 문서화 인터페이스

### 이벤트 정의 (데모데이 이후용)
- **CampaignCompletedEvent**: 캠페인 완료 이벤트 (리스너만 정의, 발행은 추후)
- **SettlementReadyEvent**: 정산 준비 이벤트 (리스너만 정의, 발행은 추후)
- **AutoConfirmedEvent**: 자동 확정 이벤트 (리스너만 정의, 발행은 추후)

### 설정 파일
- **application.yml**: 로컬 개발용 기본값 설정 (FCM, SMTP)
- **application-dev.yml**: dev 환경 설정 (환경변수 참조)
- **application-prod.yml**: prod 환경 설정 (환경변수 참조)
- **.gitignore**: Firebase 키 파일 제외 설정


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #218
Closes #219 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 9, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
제안을 받으면 즉시 발송으로 임시 변경

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
제안을 받으면 즉시 발송으로 임시 변경

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [x] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #343 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 10, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
public 버킷 설정 및 usage에 따라 분기

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
public 버킷 설정 및 usage에 따라 분기

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [x] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 11, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
swagger 추가

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->
swagger 추가

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [x] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #381

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 12, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 12, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 12, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->


## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->


## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [ ] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
1000hyehyang added a commit that referenced this pull request Feb 19, 2026
<!--
## PR 제목 컨벤션
[TYPE] 설명 (#이슈번호)

예시:
- [FEAT] 회원가입 API 구현 (#14)
- [FIX] 이미지 업로드 시 NPE 수정 (#23)
- [REFACTOR] 토큰 로직 분리 (#8)
- [DOCS] ERD 스키마 업데이트 (#6)
- [CHORE] CI/CD 파이프라인 추가 (#3)
- [RELEASE] v1.0.0 배포 (#30)

TYPE: FEAT, FIX, DOCS, REFACTOR, TEST, CHORE, RENAME, REMOVE, RELEASE
-->

## Summary
<!-- 변경 사항을 간단히 설명해주세요 -->
미읽음 알림 개수 조회 API(GET /api/v1/notifications/unread-count) 성능 개선을 위해 Redis
캐시를 적용했습니다.

## Changes
<!-- 변경된 내용을 목록으로 작성해주세요 -->

- NotificationUnreadCountCache 컴포넌트 추가 (캐시 키:
notification:unread:{userId}, TTL: 10분)
- NotificationQueryService.getUnreadCount(): 캐시 조회 → 미스 시 DB 조회 후 캐시 저장
- NotificationQueryService.getNotifications(): unread count를
getUnreadCount()로 조회해 캐시 재사용
- NotificationService: 알림 생성, 읽음 처리, 전체 읽기, 소프트 삭제 시 캐시 무효화
- Redis 장애 시 DB 조회로 폴백 (예외 처리 추가)

## Type of Change
<!-- 해당하는 항목에 x 표시해주세요 -->
- [ ] Bug fix (기존 기능에 영향을 주지 않는 버그 수정)
- [ ] New feature (기존 기능에 영향을 주지 않는 새로운 기능 추가)
- [ ] Breaking change (기존 기능에 영향을 주는 수정)
- [x] Refactoring (기능 변경 없는 코드 개선)
- [ ] Documentation (문서 수정)
- [ ] Chore (빌드, 설정 등 기타 변경)
- [ ] Release (develop → main 배포)


## Related Issues
<!-- 관련 이슈 번호를 작성해주세요 (예: Closes #123, Fixes #456) -->
Closes #403 

## 참고 사항
<!-- 리뷰어가 알아야 할 추가 정보가 있다면 작성해주세요 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants