API를 통해 알림 시간을 관리하고, 스케쥴러가 매시간 알림을 발송하는 서비스
-
NestJS 프레임워크
- NestJS 애플리케이션 아키텍처를 활용하여 모듈과 공급자 간의 의존성 주입을 설정
- NestJS의 전송 계층 마이크로서비스 기능을 사용하여 마이크로서비스 간 TCP 통신을 구현
-
MSA (마이크로서비스아키텍처)
- Notification 서비스
- 알림 리소스를 관리하는 REST API 제공
- 알림 데이터는 Key-Value 데이터베이스인 DynamoDB에 저장
- DynamoDB의 TTL(Time to Live) 설정을 활용하여, 예약된 알림이 지나면 자동으로 삭제됨
- Worker 서비스
- Cron 스케줄러를 사용하여 매시간 주기적인 작업 수행
- Notification 서비스와 TCP 통신을 통해 알림 데이터를 조회
- OneSignal 서비스를 통해 알림 메시지를 전송
- Notification 서비스
프로젝트에서 사용되는 API 명세서입니다.
이 명세서는 매 릴리즈 업데이트 시 자동으로 최신 상태로 배포됩니다.
API 명세서 바로가기 |
프로젝트에서 사용되는 타입 정의를 문서화한 자료입니다.
이 타입 문서는 매 릴리즈 업데이트 시 자동으로 최신 상태로 배포됩니다.
타입 문서 바로가기 |
테스트 통과 여부와 커버리지 현황은 시각적으로 제공되며, 매 릴리즈 시 자동으로 최신 상태로 반영됩니다.
커버리지는 Codecov를 통해 분석됩니다.
테스트 리포트 바로가기 | 커버리지 대시보드 바로가기 |
- 사용자 (Actor)
- 웹사이트 사용자: 이벤트를 등록하고 알림을 받는 사용자
- 알림 워커: 정기적으로 메시지를 처리하고 전송하는 시스템
- 유즈케이스 (Use Case)
- 알림 등록: 사용자가 새로운 이벤트 알림을 등록하는 기능
- 알림 삭제: 사용자가 기존에 등록된 알림을 삭제하는 기능
- 알림 확인: 사용자가 등록된 알림 목록을 확인하는 기능
- 메시지 상태 확인:알림 워커가 이벤트를 읽는 기능
- 메시지 전송: 알림 워커가 메시지를 사용자에게 전송하는 기능
- 상호작용 (Interaction)
- 웹사이트 사용자 ↔ 알림 서비스: 웹사이트 사용자가 이벤트 정보를 입력하여 알림 등록을 요청
- 알림 워커 ↔ 알림 서비스: 알림 워커가 알림 서비스에 등록된 이벤트 정보를 확인
- 알림 워커 ↔ OneSignal: 알림 워커가 OneSignal을 통해 알림 메시지를 사용자에게 전송
flowchart LR
Web["웹사이트"]
click Web "https://github.com/Daily1Hour/PickMe-Calendar-Application"
event@{ shape: bow-rect, label: "이벤트 정보" }
Web --> event --> |REST/HTTP| Notification/server
subgraph Reminder
subgraph Worker
Worker/Cron@{ shape: circle, label: "스케줄러" }
end
subgraph Notification
Notification/server@{ shape: circle, label: "등록 서버" }
Notification/db@{ shape: lin-cyl, label: "DynamoDB" }
Notification/server <--> Notification/db
end
Worker/Cron <-.-> |TCP| Notification/server
end
Calendar
click Calendar "https://github.com/Daily1Hour/PickMe-Calendar-Service"
data@{ shape: bow-rect, label: "이벤트 상세 정보" }
Calendar --> data --> Worker/Cron
Worker/Cron --> |HTTP| message@{ shape: bow-rect, label: "메시지" } --> OneSignal
- 웹사이트에서 이벤트 정보를 Notification 서비스 등록 서버에 REST 방식으로 전송
- Notification 서비스는 데이터를 DynamoDB로 관리
- Worker 서비스의 스케줄러가 정기적으로 등록 서버에서 TCP 연결로 데이터 읽음
- 데이터가 존재하면 외부 Calendar 서비스에서 상세 정보를 가져옴
- 데이터를 통합하여 메시지로 만들어 OneSignal로 전송
- NestJS 프레임워크를 사용해 백엔드 서비스 구축
- NestJS의 MicroService 모듈을 사용해 두 개의 마이크로서비스로 구현
- Notification 서비스
- REST API 방식으로 외부 요청을 처리
- DynamoDB를 사용해 데이터베이스 관리
- Worker 서비스
- NestJS Schedule 라이브러리를 사용해 Cron Job 설정으로 주기 작업 처리
- 마이크로서비스 간 TCP 연결을 통해 Notification 서비스에서 데이터 읽기
- REST API로 외부 서비스 (Calendar 서비스)에서 데이터 요청
- 데이터 통합하고 OneSignal를 통해 알림을 전송
- 각 마이크로 서비스는 Docker Image 생성하여 컨테이너화
- Docker Compose로 마이크로서비스와 관련 서비스(DB)를 관리하고 배포
- ECR(Elastic Container Registery) 에 Docker 이미지 업로드
- ECS(Elastic Container Service) Cluster 생성
- 두 서비스 간의 연결을 위해 브릿지 모드 설정
- ECS의 용량 공급자로 EC2 인스턴스 생성 (Auto Scaling 적용)
- ECR 이미지를 기반으로 Task Definition 생성
- Task Definition을 바탕으로 ECS 서비스 생성
- ECS 서비스에서 태스크 실행 (Auto Scaling 적용)
- ALB(Application Load Balencer) 연결을 통해 외부 트래픽 라우팅
graph LR
Tag[태그 푸시] ---> test-report & openapi
subgraph test-report
direction LR
Test/Coverage[커버리지 측정] --> |🟢 통과|Test/Codecov[Codecov 퍼블리싱]
Test/Execution[테스트 수행] --> |🟢 통과|Test/Report[리포트 생성]
end
subgraph openapi
direction LR
Docs[타입 문서화]
OpenAPI/Define[명세서 생성] --> OpenAPI/Validate[검증] --> |🟢 통과|OpenAPI/Publish[API 문서 생성]
end
Test/Report & Docs & OpenAPI/Publish -.-> |📦 아티팩트|Artifact/Download
subgraph deploy-document
direction LR
Artifact/Download[다운로드] --> Release[릴리즈 배포]
Artifact/Download --> DeployGH[gh-pages 배포] --> |자동 워크플로 실행|pages-build-deployment[GitHub Pages 배포 완료]
end
click Test/Execution,Docs,OpenAPI/Define,DeployGH "https://github.com/Daily1Hour/PickMe-Reminder-Service/actions/workflows/document-hosting.yml"
click pages-build-deployment "https://github.com/Daily1Hour/PickMe-Reminder-Service/actions/workflows/pages/pages-build-deployment"
열기
Monorepo + Microservice
Clean Architecture
PickMe-Reminder-Service
├─ .github
│ ├─ workflows # 깃헙액션 워크플로어
│ │ └─ document-hosting.yml # 스웨거 및 테스터 리포트 작성
│ └─ document-index.html # 깃헙 페이지 진입점
├─ .gitignore
├─ notification # 알림 마이크로서비스
│ ├─ src
│ │ ├─ main.ts # 서버 실행 진입점
│ │ │ └─ main.test.ts
│ │ ├─ module.ts # 의존성 주입 모듈
│ │ ├─ application # 유즈케이스 계층
│ │ │ ├─ dto.ts
│ │ │ └─ service.ts # 유즈케이스
│ │ │ └─ service.spec.ts
│ │ ├─ domain # 도메인 계층
│ │ │ ├─ entity.ts # 엔티티 객체
│ │ │ └─ repository.ts # 레포지토리 인터페이스
│ │ ├─ infrastructure # 인프라스트럭쳐 계층
│ │ │ ├─ auth
│ │ │ │ ├─ jwtInterceptor.ts # JWT 토큰 인터셉터
│ │ │ │ │ └─ jwtInterceptor.test.ts
│ │ │ │ └─ verifier.ts # Cognito로 토큰 인증
│ │ │ └─ dynamo # DynamoDB
│ │ │ ├─ model.ts # 스키마
│ │ │ │ └─ model.test.ts
│ │ │ ├─ provider.ts # 프로바이더 의존성
│ │ │ │ └─ provider.test.ts
│ │ │ └─ repository.ts # 레포지토리 구현체
│ │ │ └─ repository.test.ts
│ │ ├─ presentation # 프레임워크 계층
│ │ │ ├─ controllers
│ │ │ │ ├─ healthCheckController.ts # 헬스체크
│ │ │ │ │ └─ healthCheckController.spec.ts
│ │ │ │ ├─ httpController.ts # Http API
│ │ │ │ │ └─ httpController.spec.ts
│ │ │ │ └─ messageController.ts # TCP API
│ │ │ │ └─ messageController.test.ts
│ │ │ └─ dtos # 데이터 전송 객체
│ │ │ ├─ index.ts
│ │ │ ├─ CreateRequestDTO.ts
│ │ │ ├─ ParametersDTO.ts
│ │ │ ├─ ReadRequestDTO.ts
│ │ │ └─ UpdateRequestDTO.ts
│ │ └─ utility
│ │ ├─ decorators # 커스텀 데코레이터
│ │ │ ├─ index.ts
│ │ │ ├─ AtLeastOneOption.ts # 옵션 하나 이상 유효성 검사
│ │ │ │ └─ AtLeastOneOption.test.ts
│ │ │ ├─ IsTimeRange.ts # 시간 범위 유효성 검사
│ │ │ │ └─ IsTimeRange.test.ts
│ │ │ ├─ PayloadEX.test.ts
│ │ │ │ └─ PayloadEX.ts # Payload를 dto 변환하고 데코레이터 기반 유효성 검사
│ │ │ └─ TrimSeconds.ts # 시간 데이터의 분초 삭제 변환
│ │ │ └─ TrimSeconds.test.ts
│ │ ├─ downloadOpenAPI.ts # yaml 파일로 스웨거 문서 다운로드
│ │ │ └─ downloadOpenAPI.test.ts
│ │ └─ generatorSwagger.ts # 스웨거 문서 생성
│ │ └─ generatorSwagger.test.ts
│ ├─ test
│ │ └─ app.e2e-spec.ts # end to end 테스트
│ ├─ .env # 환경변수
│ ├─ package.json # 워크스페이스 의존성 관리
│ │ └─ jest.config.js # jest 테스트 설정
│ └─ tsconfig.json # typescript 설정
│ ├─ tsconfig.build.json
│ └─ global.d.ts # 환경변수 타입
├─ worker # 알림 워커 서비스
│ ├─ src
│ │ ├─ main.ts # 서버 실행 진입점
│ │ ├─ module.ts # 의존성 주입 모듈
│ │ ├─ application
│ │ │ ├─ dto.ts # 페이로드 DTO
│ │ │ ├─ ports # 인터페이스
│ │ │ │ ├─ index.ts
│ │ │ │ ├─ client.ts # 알림 저장 서비스
│ │ │ │ ├─ receiver.ts # 메시지 수신
│ │ │ │ └─ sender.ts # 메시지 발송
│ │ │ └─ usecases
│ │ │ ├─ cron.ts # 잡 스케줄러
│ │ │ │ └─ cron.test.ts
│ │ │ └─ service.ts # 알림 TCP 요청, 발송 처리, 완료 처리
│ │ │ └─ service.test.ts
│ │ └─ infrastructure
│ │ ├─ api # axios API 인터셉터
│ │ │ ├─ index.ts
│ │ │ ├─ calendarClient.ts
│ │ │ │ └─ calendarClient.test.ts
│ │ │ └─ onesignalClient.ts
│ │ │ └─ onesignalClient.test.ts
│ │ ├─ receivers
│ │ │ └─ calendarReceiver.ts # 캘린더 서비스 구현체
│ │ │ └─ calendarReceiver.test.ts
│ │ ├─ senders
│ │ │ └─ webSender.ts # 웹 메시지 발송 구현체
│ │ │ └─ webSender.test.ts
│ │ └─ clientImpl.ts # 마이크로서비스 호출 구현체
│ │ └─ clientImpl.test.ts
│ ├─ test
│ │ └─ app.e2e-spec.ts # end to end 테스트
│ ├─ .env # 환경변수
│ ├─ package.json # 워크스페이스 의존성 관리
│ │ └─ jest.config.js # jest 테스트 설정
│ └─ tsconfig.json # typescript 설정
│ ├─ tsconfig.build.json
│ └─ global.d.ts # 환경변수 타입
├─ test # 통합 테스트
│ └─ jest.config.js
├─ .env # 공용 환경변수
├─ docker-compose.yml # 도커컴포즈
│ ├─ Dockerfile.notification # 알림 마이크로서비스 도커파일
│ └─ Dockerfile.worker # 워커 마이크로서비스 도커파일
├─ package.json # 의존성 관리
│ ├─ package-lock.json
│ ├─ .eslintrc.js # eslint 린터 설정
│ ├─ .eslintignore # eslint 무시 설정
│ ├─ .prettierrc # 포맷터 설정
│ ├─ jest.config.js # jest 테스트 설정
│ └─ nest-cli.json # nestjs 모듈 구조 설정
└─ tsconfig.json # typescript 설정
└─ typedoc.json # 문서 설정
# build
$ docker-compose build
# run
$ docker-compose up -d
$ npm install
# build
$ npm run build
# development
$ npm run start