Skip to content

Conversation

@fiivxyxxng
Copy link
Collaborator

@fiivxyxxng fiivxyxxng commented Jul 6, 2025

요구사항

백엔드 배포 주소

기본

공통

  • AWS 루트 유저 계정을 생성하세요. 이미 생성된 계정이 있다면 해당 계정을 활용해 주세요.
  • AWS Free Tier 제공 범위를 파악한 후, 해당 서비스를 적극 활용하세요.
    • 인스턴스의 중지 및 종료 과정을 꼭 숙지해야 합니다. EC2 과금 정책에 주의하여 프리 티어 한도 내에서 사용해 주세요.
  • 리전은 아시아 태평양(서울)'으로 설정하세요.

백엔드 배포

프로젝트 구조 및 환경 설정

  • 배포에 적합한 프로젝트 구조를 설정합니다.
  • 개발(development) 및 배포(production) 환경 설정을 구분하고, 환경 변수를 사용해 관리합니다.

AWS S3를 이용한 파일 업로드 시스템 구축

  • AWS S3 버킷을 생성하고, 파일 업로드를 위한 설정을 완료합니다.
  • multer-s3 라이브러리를 사용하여 이미지 업로드 미들웨어를 S3로 변경합니다.
  • S3에 이미지 업로드가 정상적으로 작동하는지 확인합니다.

AWS RDS를 사용한 데이터베이스 관리

  • AWS RDS 인스턴스를 설정하고, 프로젝트 데이터베이스와 연결합니다.
  • RDS에서 데이터베이스의 초기화 및 CRUD 작업을 테스트합니다.

AWS EC2에서의 애플리케이션 운영

  • AWS EC2 인스턴스를 생성합니다. 프리티어에 해당하는 인스턴스 타입과 운영 체제(OS)를 선택하세요.
  • EC2 인스턴스에 대한 보안 그룹을 설정합니다. HTTP(포트 80), HTTPS(포트 443), SSH(포트 22) 등 필요한 포트를 열어 네트워크 연결을 구성하세요.
  • 프로세스 매니저 pm2를 사용하여 애플리케이션을 백그라운드에서 실행시킵니다.
  • Nginx를 이용한 리버스 프록시 설정을 구축하고, 외부 접속을 관리합니다.

백엔드 테스트 구현

  • Jest 설정 파일(jest.config.js)을 만들고 기본 설정을 하세요.
  • 상품 CRUD 연산에 대한 유닛 테스트를 작성합니다. 각 CRUD 연산에 대해 적절한 입력과 예상 출력을 정의하여 테스트 코드를 구현하세요.
    • 사용자의 접근 권한 검증을 고려하여 상품 CRUD 연산에 대한 시나리오를 테스트해 주세요.
  • 회원가입, 로그인에 대한 유닛 테스트를 작성합니다.
  • API 요청이나 데이터베이스 작업 등 비동기 코드에 대한 테스트를 작성하세요. async/await와 done 콜백을 사용하여 비동기 코드의 완료를 테스트하세요.
  • Mock, Spy와 같은 테스트 더블을 사용하여 외부 서비스와의 상호 작용을 테스트하세요.
  • describe와 test 블록을 사용하여 테스트 케이스를 그룹화하고 정리하세요.

심화

테스트 구현

  • Jest의 테스트 커버리지 도구를 사용해 코드 커버리지를 분석하고 결과를 확인해 보세요.
  • 커버리지 결과를 바탕으로 누락된 테스트 케이스를 추가합니다. 커버리지 보고서를 검토하여 테스트되지 않은 코드 영역을 찾아내고 적절한 테스트를 추가해 보세요.

상품 이미지 업로드

  • AWS S3의 Presigned URL 기능을 활용하여 상품 이미지 업로드 기능을 구현합니다.

AWS Route 53을 활용한 도메인 관리

  • AWS Route 53을 사용하여 도메인을 구매하거나 기존 도메인을 연결합니다.
  • Route 53에서 DNS 설정을 관리하고, EC2 인스턴스와 연결합니다.
  • 도메인을 통한 애플리케이션 접속 및 운영을 테스트합니다.

SSL 인증서를 통한 HTTPS 연결 구현

  • SSL 인증서를 설정하여 EC2 인스턴스에서 HTTPS 연결을 구현합니다.
    • SSL 인증서는 AWS Certificate Mana ger(ACM)를 사용하여 무료로 생성하거나, 외부 인증 기관에서 구매할 수 있습니다.

주요 변경사항

  • 백엔드 배포 render -> aws ec2로 변경

스크린샷

테스트 커버리지 측정 결과

image

멘토에게

  • 시간 관계상 테스트 코드를 서비스 레이어(product/user), 유틸 함수밖에 작성하지 못하였습니다.
  • 유닛 테스트에서는 주로 어떤 레이어까지 테스트를 진행하나요? 컨트롤러나 라우터 레이어에서 테스트를 실행하는건 supertest를 사용하는 통합테스트 과정에 속하는게 맞나요?

Copy link

@reach0908 reach0908 left a comment

Choose a reason for hiding this comment

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

고생많으셨습니다. 코멘트들 확인해주세요!

점점 코드들의 체계가 잡혀가는게 눈에 보이는 것 같아서 좋네요. 항상 제 개인적인 관점에서 피드백을 주다보니 다른 관점의 코드들도 오픈소스들을 많이 참고해보시면 좋을 것 같습니다!!

import "dotenv/config";
import passport from "passport";
import "./config/passport";
import "./configs/passport.config";

Choose a reason for hiding this comment

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

[P2]
파일로 관리하는 것도 좋지만 개인적으로 저는 app.ts를 쭉 읽어가면서 어떠한 설정들이 해당 앱에 적용되어있는가를 읽는 것도 괜찮아서 config들을 모아두기만 하고 전략들만 한번에 import 해와서 하단에서 passport.use() 로 직접 app.ts 파일에서 명시하는 편이 더 좋다고 생각합니다!

그리고 나중에 선언의 순서가 중요한 것들이 몇몇 있어서 이렇게 통으로 import하면 디버깅이 힘들어질 수도 있습니다!

return await prisma.product.findMany(options);
const { where } = options;

const [totalCount, products] = await Promise.all([

Choose a reason for hiding this comment

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

[P)]
이 부분의 경우에는 같은 options로 검사하는데, 그냥 사용하는쪽에서 products.length를 계산하는게 더욱 효율적일 것 같습니다.

findAll과 count는 별도로 분리하고 사용이 필요한 경우에만 같이 부르면 좋을 것 같아요!

Comment on lines +8 to +31
const s3 = new S3Client({
region: "ap-northeast-2",
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID as string,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY as string,
},
});

const upload = multer({
storage: multerS3({
s3: s3,
bucket: process.env.AWS_BUCKET_NAME as string,
key: (
req: Request,
file: Express.Multer.File,
cb: (error: any, key?: string) => void
) => {
// ?access=private 인 경우 업로드 위치를 private/ 폴더로 지정
const isPrivate = req.query.access === "private";
const folder = isPrivate ? "private/" : "public/";
cb(null, `${folder}${Date.now()}_${file.originalname}`);
},
}),
});

Choose a reason for hiding this comment

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

[P1]
라우터에는 라우터와 관련된 파일들만 있으면 좋을 것 같습니다. 해당 코드는 별도의 s3를 위한 util로 분리해보면 어떨까요?

@reach0908
Copy link

추가 코멘트에 대해
저는 컨트롤러를 얇게 유지하는 편이라 (대부분 서비스 로직을 호출하는 정도) 서비스 및 레포지터리 레이어에있는 로직들에 대해서만 unit 테스트를 진행합니다.

통합테스트의 경우에는 도메인을 넘나드는 로직들이 유기적으로 구성되어 테스트가 필요할 때 구성하는 편입니다.

supertest를 통한 e2e테스트의 경우에는 사용자 플로우(시나리오)에 맞게 동작하는가를 중점적으로 테스트를 하고 있습니다.

첨언해서 개인적으로는 정말로 앱에 있어 중요한 로직(인증/인가, 주요서비스 로직)은 테스트 주도개발을 진행하고, 나머지 테스트의 경우 여유가 되면 진행합니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants