본문 바로가기
Project

[Prography] 영양제 알림 서비스 PILIT

by 리노 Linho 2023. 6. 2.

본 게시글은 Prography 7기 6팀 백엔드 팀원으로 참여하여 Pilit 서비스를 개발한 과정과 소개를 담고 있습니다.

Introduce

Pilit은 바쁜 현대 사회를 살고있는 사람들을 위해 영양제 조합을 추천하고, 영양제를 놓이지 않고 먹을 수 있도록 돕는 서비스 입니다.

Role

Backend Engineer & Devops Engineer

Architecture

AWS Service Amazon Elastic Container Service ( Fargate )
Amazon Elastic Container Registry
Amazon Elastic Load Balancer
Amazon ElastiCache ( Redis )
Amazon Relational Database Service ( Mysql )
Amazon Route 53
Deployment Pipeline Github Actions
Web Framework Nest.js
TypeORM
BullMQ ( https://docs.bullmq.io/ )
Messaging Solution Firebase Cloud Messaging

Feature

  • 복용하는 약을 조회/생성/갱신/제거 할 수 있는 API 구현
  • 일자별 복용여부를 확인하는 API 구현
  • 복용 시점이 다가왔을 때 Client에게 Notification을 제공

Experience for Nest.js

  • 기능별 모듈화 & MVC 패턴
    • 기능별로 모듈을 생성하여 각각의 모듈은 맡은 기능의 책임을 다하도록 구현
      • 다른 모듈의 변화가 일어나도 결합도를 낮춰서 최대한 의존성이 없도록 구현
      • 필요시 Dependency Injection을 통해 공유할 수 있도록 구현
    • 모듈 내부에 MVC 패턴을 사용하여 각각의 기능별로 컨트롤러가 존재하도록 구현
      • MVC 패턴을 모듈화와 함께 적용하여 가독성, 확장성, 재사용성을 증가
  • RESTful API & 직관적인 Naming
    • 모듈명, 함수명 그리고 변수명의 Naming을 직관적으로 작성
      • 모듈명과 함수명만 봐도 어떠한 기능을 하는지 최대한 이해할 수 있도록 작성
      • 모듈별로 기능을 분리해 놓았기에 직관적으로 작성 가능
    • RESTful API 규칙을 최대한 활용하여 작성
      • API만 보고 어떤 기능을 하는지 직관적으로 이해할 수 있도록 작성
      • 방법, 버전, 행위 그리고 명사형을 API가 길어지더라도 작성
        • 예를들어, GET api/v1/pill/taking-log API를 직관적으로 파악 가능
        • 버전1이며 약의 복용 기록을 가져오는 API
  • BullMQ & Firebase Cloud Messaging
    • BullMQ는 Message Queue를 Node.js 위에서 쉽게 사용할 수 있도록 하는 라이브러리
      • Redis를 기반이며 BullMQ에 Redis관련 Configuration 정보만 입력하면 쉽게 활용 가능
      • BullMQ를 통해 Job을 Managing하여 Nest.js 상에서 Job을 관리
      • Cron Job 형태를 제공하여 Message Queue가 특정 시점에 실행 될 수 있도록 구현 가능
      • 사용자가 복용시간 등록시 Cron 형태로 변환하여 Job을 등록 할 수 있도록 구현
    • Firebase Cloud Messaging은 구글에서 제공하는 Cross-platform messaging solution
      • Client의 Platform( Android & IOS )과 상관 없이 쉽게 연동할 수 있어서 선정
      • 모바일의 Online 상태와 Background 상태일때 모두 작동할 수 있도록 구현
      • BullMQ에 Job을 등록할때 Job 내부에 Message push 코드를 삽입하여 특정 시간에 Notification이 가도록 구현
  • JWT
    • JWT 토큰의 사용방식에 대한 이해
    • Access Token & Refresh Token 사용 방식에 대해 이해하고 Nest.js에서 특정 API에 대해 Authentication 과정을 진행할 수 있도록 구현
    • 본 프로젝트에서는 빠른 MVP 모델 개발을 위해 ID & PW 방식을 도입하지 않고 모바일 기기별로 갖고 있는 UUID를 고객 식별용으로 사용
    • JWT의 Expire 시간을 짧게 가져가서 MVP 모델 개발을 위해 사용하지 않은 Refresh Token 방식을 대체하기 위해 노력

Experience for AWS

  • Amazon Elastic Container Service
    • AWS ECS는 AWS에서 제공하는 Container Orchestration 서비스
    • AWS EC2 대신 Fargate 방식을 활용하여 AWS ECS를 생성
    • 총 3개의 Container를 띄워놓고 Load Balancer를 통해 부하 분산
    • 기본적으로 롤링 배포를 사용하도록 설정
    • AWS ECR의 Container Image를 불러와서 AWS ECS 상에 Container로 실행
  • Amazon Elastic Container Registry ( AWS ECR )
    • AWS ECR은 AWS에서 제공하는 Container Registry 서비스
    • Github Actions을 통해 Docker로 Build된 이미지를 전달 받으며 Private Repository에 저장되도록 설정
  • Amazon Elastic Load Balancer
    • AWS ELB는 AWS에서 제공하는 Load Balancer
    • 고가용성을 지원하는 AWS ECS를 사용하기 위해서는 AWS ELB가 최소 1개이상 꼭 필요
    • Health Check용 API를 미리 구현해 놓고 Load Balancer가 해당 API에 주기적으로 요청
    • 응답하는 Status Code를 기준으로 사전에 설정해놓은 Healthy Code가 응답하면 Container가 띄워져 있는 것으로 판단하며 그외 응답코드가 반환되면 Container가 죽은 것으로 판단
      • 해당 작업을 잘못 설정하여 오류가 발생했던 내용을 정리 ( https://linho.kr/3 )
  • Amazon Relational Database Service
    • AWS RDS는 AWS에서 Fully Managed로 제공하는 데이터베이스 서비스
    • MySQL Database로 생성하여 Nest.js의 TypeORM과 연결하여 사용
    • ERD를 그려서 TypeORM에 엔티티를 생성하고 관련해서 Data Transfer Object를 만들어서 Swagger에 연동하거나 Validation을 진행하고 모듈간의 결합도를 낮추기 위한 용도로 사용
  • Amazon ElastiCache
    • AWS ElastiCache는 AWS에서 Fully Managed로 Redis를 제공하는 서비스
    • Redis는 BullMQ에서 Message Queue를 사용하기 위해 
  • Amazon Route 53
    • AWS Route 53은 AWS에서 DNS 설정용 서비스
    • prograpy에서 제공한 DNS 서비스를 활용하기 위해 사용
    • AWS Route53에 등록되어있던 Prograpy 인증서를 함께 지원하여 본 API를 https 방식으로 서비스 제공
      • 결과적으로 https://api.prography.org/api/v1/pill/taking-log 형태의 API를 Client에게 제공

Experience for Github Actions

  • Github Actions Workflow 파일
    • .github/workflow 에서 yml 파일로 Deploy Pipeline을 구축
    • Docker를 활용하여 Github Actions 내부에서 Build 하는 과정을 수행
    • AWS IAM에서 제공하는 Access Token과 Secret Access Key를 발급 받아 Credentials 진행
    • AWS CLI를 사용하여 스크립트를 작성
  • Github Actions Secret Key
    • Github Actions 내부에서 사용되는 보안 정보를 암호화 하기 위한 방법
    • Deploy Pipeline 툴 특성상 배포에 사용되는 민감한 정보들이 담길 수 밖에 없는데 이를 Github Actions Secret Key를 사용하여 처리
  • .env 파일 생성
    • Nest.js의 보안 정보는 .env에서 관리하여 수동으로 .env파일을 생성
    • Github Actions에서 리눅스 명령어를 제공하여 Github Actions Secret Key와 조합하여 .env파일을 생성

Improvement

  • API Response시
    • API Response시 날 것의 JSON을 보내는 방식이 아닌 한번 감싸서 값을 보낸다고 한다.
    • 간략하게 예를 들면 {"name":"이재준","age":26} 이 아닌 {"data":["name":"이재준","age":26]} 처럼 data로 값을 감싼다.
  • IAM 방식
    • AccessToken 방식을 사용하는 것도 보안상 위험할 수 있지만, 해당 토큰에 많은 권한을 한번에 몰아주는 것 또한 위험하다.
    • 지식이 많이 부족한 상태에서 한개의 토큰에 많은 권한을 제공하였는데 필요에 맞게 권한을 분배해서 토큰이 유출되었을 경우에도 보안성을 크게 훼손하지 않도록 해야한다.
  • JWT 사용방식
    • Logout 방법 구현과 Refresh Token을 사용하지 못한 점이 아쉬웠다. 해당 부분 Redis를 사용하여 Token을 Black 하거나 Refresh Token을 사용하여 주기적으로 토큰을 갱신할 수 있도록 개선해 나간다.

Github

https://github.com/prography7-team6-pilit/team6-api