feat: APNs 발송 모듈 구현 (#106) #107

Merged
seonkyu.kim merged 1 commits from feature/#106-apns-sender into develop 2026-02-10 07:00:06 +00:00
Owner

📋 작업 요약

  • APNs HTTP/2 기반 iOS 푸시 발송 모듈 구현
  • JWT(ES256) 토큰 생성 및 50분 주기 캐싱
  • 단건/배치(500건, 동시 50건) 발송 지원
  • APNs 에러 코드별 처리 로직 (토큰 삭제/재시도 판단)

Closes #106

🛠️ 작업 내용 (Changes)

  • SPMS.Application/Interfaces/IApnsSender.cs — APNs 발송 인터페이스 (SendAsync, SendBatchAsync)
  • SPMS.Infrastructure/Push/ApnsSender.cs — APNs HTTP/2 연동 구현
  • SPMS.Infrastructure/DependencyInjection.cs — IApnsSender DI 등록 + HttpClient 설정
  • SPMS.Infrastructure/SPMS.Infrastructure.csproj — Microsoft.Extensions.Http 패키지 추가

📢 리뷰어 참고 사항 (To Reviewers)

  • APNs는 FCM과 달리 멀티캐스트 API가 없어 개별 HTTP 요청으로 발송 (SemaphoreSlim으로 동시 50건 제한)
  • JWT 토큰은 (keyId, teamId) 조합으로 캐싱, 50분마다 자동 갱신 (APNs 토큰 유효기간 60분)
  • .p8 Private Key PEM 포맷 파싱 → ECDsa.ImportPkcs8PrivateKey → ES256 서명
  • 에러 매핑: 410 Gone → 디바이스 삭제, 400 BadDeviceToken → 디바이스 삭제, 503/429 → 재시도
  • mutable-content: 1 설정으로 iOS Notification Service Extension에서 이미지 다운로드 가능
  • HttpClient는 IHttpClientFactory로 관리, SocketsHttpHandler로 HTTP/2 멀티플렉싱 지원

체크리스트 (Self Checklist)

  • 빌드(Build)가 성공적으로 수행되었는가?
  • 모든 단위 테스트(Unit Test)를 통과하였는가?
  • 불필요한 로그나 주석을 제거하였는가?
  • 컨벤션(Clean Architecture, Naming)을 준수하였는가?
  • 기밀 정보(비밀번호, 키 등)가 하드코딩 되어있지 않은가?

📸 스크린샷 / 테스트 로그 (Screenshots/Logs)

빌드했습니다.
    경고 0개
    오류 0개
## 📋 작업 요약 - APNs HTTP/2 기반 iOS 푸시 발송 모듈 구현 - JWT(ES256) 토큰 생성 및 50분 주기 캐싱 - 단건/배치(500건, 동시 50건) 발송 지원 - APNs 에러 코드별 처리 로직 (토큰 삭제/재시도 판단) ## 🔗 관련 이슈 (Related Issues) Closes #106 ## 🛠️ 작업 내용 (Changes) - [x] `SPMS.Application/Interfaces/IApnsSender.cs` — APNs 발송 인터페이스 (SendAsync, SendBatchAsync) - [x] `SPMS.Infrastructure/Push/ApnsSender.cs` — APNs HTTP/2 연동 구현 - [x] `SPMS.Infrastructure/DependencyInjection.cs` — IApnsSender DI 등록 + HttpClient 설정 - [x] `SPMS.Infrastructure/SPMS.Infrastructure.csproj` — Microsoft.Extensions.Http 패키지 추가 ## 📢 리뷰어 참고 사항 (To Reviewers) - APNs는 FCM과 달리 멀티캐스트 API가 없어 개별 HTTP 요청으로 발송 (SemaphoreSlim으로 동시 50건 제한) - JWT 토큰은 `(keyId, teamId)` 조합으로 캐싱, 50분마다 자동 갱신 (APNs 토큰 유효기간 60분) - .p8 Private Key PEM 포맷 파싱 → ECDsa.ImportPkcs8PrivateKey → ES256 서명 - 에러 매핑: 410 Gone → 디바이스 삭제, 400 BadDeviceToken → 디바이스 삭제, 503/429 → 재시도 - `mutable-content: 1` 설정으로 iOS Notification Service Extension에서 이미지 다운로드 가능 - HttpClient는 IHttpClientFactory로 관리, SocketsHttpHandler로 HTTP/2 멀티플렉싱 지원 ## ✅ 체크리스트 (Self Checklist) - [x] 빌드(Build)가 성공적으로 수행되었는가? - [x] 모든 단위 테스트(Unit Test)를 통과하였는가? - [x] 불필요한 로그나 주석을 제거하였는가? - [x] 컨벤션(Clean Architecture, Naming)을 준수하였는가? - [x] 기밀 정보(비밀번호, 키 등)가 하드코딩 되어있지 않은가? ## 📸 스크린샷 / 테스트 로그 (Screenshots/Logs) ``` 빌드했습니다. 경고 0개 오류 0개 ```
seonkyu.kim added 1 commit 2026-02-10 06:53:01 +00:00
seonkyu.kim added the
Priority
Urgent
Status
In Progress
Type
Feature
labels 2026-02-10 06:53:18 +00:00
seonkyu.kim self-assigned this 2026-02-10 06:53:26 +00:00
seonkyu.kim added this to the Phase 3: 메시지 & Push Core milestone 2026-02-10 06:53:34 +00:00
seonkyu.kim requested review from Owners 2026-02-10 06:53:45 +00:00
seonkyu.kim merged commit 639069972b into develop 2026-02-10 07:00:07 +00:00
seonkyu.kim removed the
Status
In Progress
label 2026-02-10 07:00:24 +00:00
seonkyu.kim deleted branch feature/#106-apns-sender 2026-02-10 07:00:29 +00:00
seonkyu.kim added the
Status
Done
label 2026-02-10 07:00:44 +00:00
Sign in to join this conversation.
No description provided.