Skip to content

#389 [Merge] dev 변경사항을 main에 반영 (v2.0.32) - #390

Merged
jucheonsu merged 46 commits into
mainfrom
merge/#389
Aug 13, 2026
Merged

#389 [Merge] dev 변경사항을 main에 반영 (v2.0.32)#390
jucheonsu merged 46 commits into
mainfrom
merge/#389

Conversation

@jucheonsu

Copy link
Copy Markdown
Member

연관된 이슈

공유 사항

  1. 철학자 유형 및 철학자 태그 처리 범위를 지정된 10명으로 제한했습니다.
  2. 가치관 육각형은 기존 6축을 유지하며 반대 가치관을 대응 축의 음수 값으로 반영했습니다.
  3. 사후투표 변경 시 이전 점수를 제거한 후 새로운 선택 점수를 반영하도록 처리했습니다.
  4. 기존 API 및 DB 구조는 변경하지 않았습니다.

체크리스트

  • Reviewer에 팀원들을 선택했나요?
  • Assignees에 본인을 선택했나요?
  • 컨벤션에 맞는 Labels를 선택했나요?
  • Development에 이슈를 연동했나요?
  • Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • 컨벤션을 지키고 있나요?
  • 로컬에서 실행했을 때 에러가 발생하지 않나요?
  • 팀원들에게 PR 링크 공유를 했나요?

작업 내용

Fix

내용 파일
철학자 Enum을 지정된 10명으로 제한 PhilosopherType.java
지원하지 않는 철학자 태그의 생성 및 조회 제한 TagServiceImpl.java
지원하지 않는 철학자 태그의 옵션 연결 및 집계 제외 BattleServiceImpl.java, BattleQueryService.java
배틀 응답에서 지원하지 않는 철학자 태그 제외 BattleConverter.java

Feat

내용 파일
가치관 6축 및 양극 태그 매핑 ValueAxis.java
가치관 태그의 양수·음수 점수 계산 UserTendencyScore.java
사후투표 선택 및 변경 시 가치관 점수 반영 BattleVoteServiceImpl.java

Test

내용 파일
철학자 Enum 10명 제한 검증 PhilosopherTypeTest.java
철학자 태그 조회·생성 제한 검증 TagServiceImplTest.java
철학자 유형 집계 제외 검증 BattleQueryServiceTest.java
가치관 6축 양수·음수 계산 검증 UserTendencyScoreTest.java
실제 사후투표 및 선택 변경 점수 검증 BattleVoteServiceImplTest.java

테스트

  • 관련 신규·수정 테스트 통과
  • 기존 UserServiceTest, MypageServiceTest 통과

[ 추후 테스트 파일만 대대적인 수정이 필요할 듯합니다. ]

  • 전체 테스트 135개 중 119개 통과
  • APNs 인증 파일 부재로 컨텍스트 테스트 14개 실행 실패
  • 수정 범위 밖 기존 크레딧 테스트 2개 실패

HYH0804 and others added 30 commits May 27, 2026 21:58
## #️⃣ 연관된 이슈
<!-- Ex) - #이슈번호 -->
<!-- 연관된 이슈 번호를 링크 형태로 작성하세요 -->
- #250 

## 📝 작업 내용
<!-- 이번 PR/이슈에서 실제 수행한 작업 내용을 작성하세요 -->

### ♻️ Refactor
<!-- 기존 코드 리팩토링 내용 작성 -->
| 내용 | 파일 |
|------|------|
| 불필요한 import 제거 | `UserService.java` |
| 투표 비율 계산 기준을 preVoteOption → postVoteOption으로 수정 |
`BattleVoteServiceImpl.java` |
| totalCount도 사후 투표 완료된 건만 카운트하도록 수정 | `BattleVoteServiceImpl.java` |
| countByBattleAndPostVoteOption,
countByBattleAndPostVoteOptionIsNotNull 메서드 추가 |
`BattleVoteServiceImpl.java` |

## 📌 공유 사항
<!-- 팀원에게 공유할 내용이나 참고 사항 작성 -->
<!-- 노션 환경 설정 파일 확인 부탁드립니다! -->
> ▎ 1. 기존 코드에서 투표 비율(%)이 preVoteOption 기준으로 계산되어 사전 투표만 한 유저도 카운트에 포함되고
있었습니다.
  ▎ 2. 사후 투표(postVoteOption)가 완료된 건만 기준으로 비율을 계산하도록 수정했습니다.

## ✅ 체크리스트
<!-- PR 제출 전에 체크해야 할 사항들 -->
- [x] Reviewer에 팀원들을 선택했나요?
- [x] Assignees에 본인을 선택했나요?
- [x] 컨벤션에 맞는 Type을 선택했나요?
- [x] Development에 이슈를 연동했나요?
- [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
- [x] 컨벤션을 지키고 있나요?
- [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
- [x] 팀원들에게 PR 링크 공유를 했나요?

## 📸 스크린샷
<!-- Swagger, Postman, JUnit 테스트 화면 첨부 -->
<!-- 기능 동작 화면이나 테스트 결과 캡처를 첨부하면 좋습니다 -->

## 💬 리뷰 요구사항
<!-- 리뷰어에게 요청하는 구체적인 사항 작성 -->
<!-- 종료 의도 판단을 Java 키워드 → AI 2차 검증 구조로 설계했는데
해당 구조가 유지보수 및 확장 측면에서 적절한지 의견 부탁드립니다. -->
> 1.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## #️ 연관된 이슈
  - #254

  ## 📝 작업 내용

  ### ♻️ Refactor
  | 내용 | 파일 |
  |------|------|
  | 관점 등록/수정 시 GPT 검수 주석 코드 제거 | `PerspectiveService.java` |

  ## 📌 공유 사항
> 1. 기존에 `createPerspective()`, `updatePerspective()`에서 GPT 검수 호출이 주석
처리된 채 남아있던 dead code를 제거했습니다. 동작 방식은 동일하게 등록/수정 즉시 `PUBLISHED` 상태로
저장됩니다.

  ## ✅  체크리스트
  - [x] Reviewer에 팀원들을 선택했나요?
  - [x] Assignees에 본인을 선택했나요?
  - [x] 컨벤션에 맞는 Type을 선택했나요?
  - [x] Development에 이슈를 연동했나요?
  - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  - [x] 컨벤션을 지키고 있나요?
  - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
  - [x] 팀원들에게 PR 링크 공유를 했나요?

  ## 📸 스크린샷
  해당 없음 (코드 정리 작업)

  ## 💬 리뷰 요구사항
  > 1. 없습니다.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## #️ 연관된 이슈
  - #255

  ## 📝 작업 내용

  ### ♻️ Refactor
  | 내용 | 파일 |
  |------|------|
| VoteStatsResponse OptionStat에 title 필드 추가 | `VoteStatsResponse.java`,
`BattleVoteServiceImpl.java` |

  ## 📌 공유 사항
> 1. `GET /api/v1/battles/{battleId}/vote-stats` 응답의 `OptionStat`에
`title` 필드가 추가되었습니다. 옵션 이름(ex. "변기는 변기다")을 투표 % 바 및 관점 탭 구성에 활용해 주세요.
> 2. 관점 목록 조회 시 옵션 탭 필터는 `optionId` 파라미터로 전달하면 됩니다. (`GET
/api/v1/battles/{battleId}/perspectives?optionId={optionId}`)

  ## ✅  체크리스트
  - [x] Reviewer에 팀원들을 선택했나요?
  - [x] Assignees에 본인을 선택했나요?
  - [x] 컨벤션에 맞는 Type을 선택했나요?
  - [x] Development에 이슈를 연동했나요?
  - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  - [x] 컨벤션을 지키고 있나요?
  - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
  - [x] 팀원들에게 PR 링크 공유를 했나요?

  ## 📸 스크린샷
  해당 없음 (응답 필드 추가)

  ## 💬 리뷰 요구사항
  > 1. 없습니다.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## #️⃣연관된 이슈
  - #262
  
  ## 📝 작업 내용

  ### ✨ Feat                                                           
  | 내용 | 파일 |
  |------|------|
| 디바이스 푸시 토큰 등록/해제 API 추가 (Android: FCM 토큰, iOS: APNs 디바이스 토큰) |
`DeviceController.java`, `DeviceService.java`,
`RegisterDeviceRequest.java`,
`UserDevice.java`, `DevicePlatform.java`, `UserDeviceRepository.java` |
| FCM(Android) 푸시 발송 인프라 구축 (Firebase Admin SDK) |
`FirebaseConfig.java`, `FcmPushService.java`, `build.gradle` |
| iOS 푸시를 FCM 경유 방식에서 다이렉트 APNs 발송으로 전환 (Pushy) | `ApnsConfig.java`,
`ApnsPushService.java`, `FcmPushService.java`,
`NotificationDispatchService.java`,
  `build.gradle` |
| 새 배틀 발행 시 인앱 알림 + 푸시 발송 | `BattleServiceImpl.java`,
`NotificationDispatchService.java` |
| 답글 좋아요 / 새 댓글 발생 시 인앱 알림 + 푸시 발송 | `CommentLikeService.java`,
`PerspectiveCommentService.java`, `NotificationDispatchService.java` |
  | 포인트 적립 시 인앱 알림 발송 | `CreditService.java` |
  | 알림 API 명세 문서 작성 | `docs/api-specs/notification-api.md` |

  ### ♻️ Refactor
  | 내용 | 파일 |
  |------|------|
| 답글 좋아요/새 댓글 알림 문구에 배틀 제목 포함하도록 개선 |
`NotificationDispatchService.java`, `CommentLikeService.java`,
`PerspectiveCommentService.java` |

  ### 🐛 Fix
  | 내용 | 파일 |
  |------|------|
| 컨테이너 배포 환경(Railway)에서 FCM/APNs 자격증명 파일(JSON/.p8)을 읽지 못해 서버 기동 자체가 실패하던
문제 수정 — S3에서 자격증명을 다운로드해 사용하도록 변경 (로컬은 기존
파일 경로 방식 그대로 폴백) | `FirebaseConfig.java`, `ApnsConfig.java`,
`application.yml` |

  ## 📌 공유 사항
> 1. **(중요) Railway dev Variables 추가 완료** — 이 PR이 배포되려면 아래 값이 필요하며, dev
환경엔 이미 세팅해뒀습니다.
> - `FCM_CREDENTIALS_S3_KEY`, `APNS_CREDENTIALS_S3_KEY` (S3
`pique-bucket/credentials/`에 Firebase 서비스 계정 JSON, APNs `.p8` 키 업로드 완료)
> - `APNS_ENABLED=true`, `APNS_KEY_ID`, `APNS_BUNDLE_ID`,
`APNS_PRODUCTION`
  >    - `APNS_TEAM_ID`는 따로 안 넣어도 기존 `APPLE_TEAM_ID`로 폴백됩니다.
  > 2. **운영(main) 배포 시에도 동일하게 Railway 변수 추가 + S3 파일 업로드가 필요**합니다.
> 3. iOS는 더 이상 FCM을 거치지 않고 서버가 APNs로 직접 발송합니다. 디바이스 등록 시 `fcmToken` 필드에
iOS는 APNs 디바이스 토큰(hex 문자열)을 보내야 합니다. 자세한 내용은
  `docs/api-specs/notification-api.md` 참고.
  > 4. 새 의존성 추가: `firebase-admin:9.9.0`, `com.eatthepath:pushy:0.15.4`

  ## ✅ 체크리스트
  - [x] Reviewer에 팀원들을 선택했나요?
  - [x] Assignees에 본인을 선택했나요?
  - [x] 컨벤션에 맞는 Type을 선택했나요?
  - [x] Development에 이슈를 연동했나요?
  - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  - [x] 컨벤션을 지키고 있나요?
  - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
  - [x] 팀원들에게 PR 링크 공유를 했나요?

  ## 📸 스크린샷
  <!-- Swagger/Postman으로 디바이스 등록, 알림함 조회, 푸시 수신 테스트 캡처 첨부 -->

  ## 💬 리뷰 요구사항
> 1. APNs 환경(sandbox/production)이 `APNS_PRODUCTION` 전역 설정 1개로 고정되는 구조인데,
개발(TestFlight)/운영(App Store) 빌드를 동시에 지원하려면 별도 설계가 필요해 보입니다 —
  의견 부탁드립니다.
> 2. FCM/APNs 자격증명을 S3에서 받아오는 방식(이번 Fix)이 적절한지, 다른 방식을 선호하시면 의견 부탁드립니다.

---------

Co-authored-by: 현준혁 <guswnsgur2276@metabuild.co.kr>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
createTempFile로 생성된 빈 파일이 이미 존재해 S3 getObject의
toFile 다운로드가 FileAlreadyExistsException으로 실패하던 문제 수정
## #️ 연관된 이슈
  - #262

  ## 📝 작업 내용

  ### ✨  Feat
  | 내용 | 파일 |
  |------|------|
| 새 배틀/답글 좋아요/새 댓글/관리자 공지·이벤트 알림 발송 시 UserSettings의 ON/OFF 설정을 확인해 OFF인
사용자에게는 푸시를 보내지 않도록 분기 (인앱 알림은 항상 생성) |
`NotificationDispatchService.java`,
`UserSettingsRepository.java`, `UserDeviceRepository.java`,
`AdminNotificationService.java` |
| 오늘의 픽으로 자동 배정된 배틀에도 새 배틀 알림(인앱+푸시) 발송 추가 | `BattleServiceImpl.java` |

  ### 🐛 Fix
  | 내용 | 파일 |
  |------|------|
| 관점/댓글 삭제 시 좋아요·신고 잔여 데이터가 남아 FK 제약 조건 위반 오류가 발생하던 문제 수정 |
`PerspectiveService.java`, `PerspectiveCommentService.java`,
`CommentLikeRepository.java`,
`CommentReportRepository.java`, `PerspectiveCommentRepository.java`,
`PerspectiveLikeRepository.java`, `PerspectiveReportRepository.java` |

  ## 📌 공유 사항
  > 1. 알림 ON/OFF 설정 매핑은 다음과 같습니다.
  >    - `newBattleEnabled` → 새 배틀 알림
  >    - `contentLikeEnabled` → 좋아요 알림
  >    - `newCommentEnabled` → 새 댓글 알림
  >    - `marketingEventEnabled` → 이벤트 및 소식 알림 (공지/이벤트)
> - `commentReplyEnabled`, `battleResultEnabled` → 현재 매핑되는 알림 이벤트가 없어 보류
(정책 미정)
> 2. OFF 상태여도 인앱 Notification은 항상 생성되고, 푸시 발송만 차단됩니다. UserSettings가 없는
레거시 유저는 기본값 ON으로 처리됩니다.

  ## ✅  체크리스트
  - [x] Reviewer에 팀원들을 선택했나요?
  - [x] Assignees에 본인을 선택했나요?
  - [x] 컨벤션에 맞는 Type을 선택했나요?
  - [x] Development에 이슈를 연동했나요?
  - [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  - [x] 컨벤션을 지키고 있나요?
  - [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
  - [x] 팀원들에게 PR 링크 공유를 했나요?

  ## 📸 스크린샷


  ## 💬 리뷰 요구사항
> 1. 관리자 공지/이벤트 알림(POLICY_CHANGE/PROMOTION)을 `marketingEventEnabled` 하나로
묶어서 게이팅했는데, 이 매핑이 적절한지 의견 부탁드립니다.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
## #️⃣ 연관된 이슈
<!-- Ex) - #이슈번호 -->
<!-- 연관된 이슈 번호를 링크 형태로 작성하세요 -->
- closed #268  

## 📝 작업 내용
<!-- 이번 PR/이슈에서 실제 수행한 작업 내용을 작성하세요 -->

### 🔨 Chore
<!-- 새로운 기능 구현 내용 작성 -->
| 내용 | 파일 |
|------|------|
| 크롤링 파일 추가 | `app-ads.txt` |
|  |  |

## 📌 공유 사항
<!-- 팀원에게 공유할 내용이나 참고 사항 작성 -->
<!-- 노션 환경 설정 파일 확인 부탁드립니다! -->
> 없음

## ✅ 체크리스트
<!-- PR 제출 전에 체크해야 할 사항들 -->
- [x] Reviewer에 팀원들을 선택했나요?
- [x] Assignees에 본인을 선택했나요?
- [x] 컨벤션에 맞는 Type을 선택했나요?
- [x] Development에 이슈를 연동했나요?
- [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
- [x] 컨벤션을 지키고 있나요?
- [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
- [ ] 팀원들에게 PR 링크 공유를 했나요?

## 📸 스크린샷
<!-- Swagger, Postman, JUnit 테스트 화면 첨부 -->
<!-- 기능 동작 화면이나 테스트 결과 캡처를 첨부하면 좋습니다 -->
> 없음

## 💬 리뷰 요구사항
<!-- 리뷰어에게 요청하는 구체적인 사항 작성 -->
<!-- 종료 의도 판단을 Java 키워드 → AI 2차 검증 구조로 설계했는데
해당 구조가 유지보수 및 확장 측면에서 적절한지 의견 부탁드립니다. -->
> 없음
## #️⃣ 연관된 이슈
<!-- Ex) - #이슈번호 -->
<!-- 연관된 이슈 번호를 링크 형태로 작성하세요 -->
- #268

## 📝 작업 내용
<!-- 이번 PR/이슈에서 실제 수행한 작업 내용을 작성하세요 -->

### ✨ Feat
<!-- 새로운 기능 구현 내용 작성 -->
| 내용 | 파일 |
|------|------|
| 허용 설정 추가 | `SecurityConfig.java` |
|  |  |

## 📌 공유 사항
<!-- 팀원에게 공유할 내용이나 참고 사항 작성 -->
<!-- 노션 환경 설정 파일 확인 부탁드립니다! -->
> 없음

## ✅ 체크리스트
<!-- PR 제출 전에 체크해야 할 사항들 -->
- [x] Reviewer에 팀원들을 선택했나요?
- [x] Assignees에 본인을 선택했나요?
- [x] 컨벤션에 맞는 Type을 선택했나요?
- [x] Development에 이슈를 연동했나요?
- [x] Merge 하려는 브랜치가 올바르게 설정되어 있나요?
- [x] 컨벤션을 지키고 있나요?
- [x] 로컬에서 실행했을 때 에러가 발생하지 않나요?
- [ ] 팀원들에게 PR 링크 공유를 했나요?

## 📸 스크린샷
<!-- Swagger, Postman, JUnit 테스트 화면 첨부 -->
<!-- 기능 동작 화면이나 테스트 결과 캡처를 첨부하면 좋습니다 -->
> 없음

## 💬 리뷰 요구사항
<!-- 리뷰어에게 요청하는 구체적인 사항 작성 -->
<!-- 종료 의도 판단을 Java 키워드 → AI 2차 검증 구조로 설계했는데
해당 구조가 유지보수 및 확장 측면에서 적절한지 의견 부탁드립니다. -->
> 없음
si-zero and others added 16 commits July 13, 2026 13:13
## 변경
기존 관리자 페이지(`/api/v1/admin/**`, Thymeleaf)를 신규 Next.js 관리자 앱(admin-web)으로
리다이렉트합니다.

- `/api/v1/admin/login` → admin-web `/login` (OAuth `?code` 쿼리 보존)
- `/api/v1/admin/picke/list` → `/picke/list`
- `/api/v1/admin/picke` → `/picke/create`
- `/api/v1/admin/picke/notice` → `/notice`
- 대상 URL은 `admin.web.url` (기본: admin-web Railway URL)로 설정

## 참고
- 새 앱은 picke.store 관리자 API를 그대로 소비(BFF 프록시).
- OAuth redirect_uri는 기존 `picke.store/api/v1/admin/login` 등록값 유지 →
Server가 새 앱으로 포워딩.

https://claude.ai/code/session_01X32DuLFrYS7B7gR2vPkmJY
관리자 리다이렉트 대상 URL을 `ADMIN_WEB_URL` 환경변수로 주입 가능하게 하고 기본값을
`https://picke.up.railway.app` 로 변경.

- application.yml: `admin.web.url:
${ADMIN_WEB_URL:https://picke.up.railway.app}`
- AdminPickeController 기본값 갱신

https://claude.ai/code/session_01X32DuLFrYS7B7gR2vPkmJY
@jucheonsu
jucheonsu requested review from HYH0804 and si-zero August 13, 2026 01:20
@jucheonsu jucheonsu self-assigned this Aug 13, 2026
@jucheonsu jucheonsu added the 🔀 Merge (병합) 브랜치를 Merge할 때 사용합니다. label Aug 13, 2026
@jucheonsu jucheonsu linked an issue Aug 13, 2026 that may be closed by this pull request
3 tasks
@jucheonsu
jucheonsu merged commit 29806eb into main Aug 13, 2026
1 check failed
@jucheonsu
jucheonsu deleted the merge/#389 branch August 13, 2026 01:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔀 Merge (병합) 브랜치를 Merge할 때 사용합니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🔀 Merge: dev를 main에 병합 (v2.0.32)

3 participants