Skip to content

[김희성] sprint 10 #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

HEES56
Copy link
Collaborator

@HEES56 HEES56 commented Mar 22, 2025

요구사항

기본

  • [o] (백엔드) 프론트엔드 코드에 맞게 백엔드 코드를 변경해 주세요.
  • [o] 백엔드 코드에 swagger를 추가해 API 명세 문서를 생성해 주세요.

상품 등록

  • [o] "상품 등록하기" 버튼 클릭 시, 상품 정보 등록 API 엔드포인트에 요청을 보내 상품을 등록합니다.
  • [o] 상품 등록 시 필요한 필드(이름, 설명, 가격 등)의 유효성을 검증하는 미들웨어를 구현합니다.
  • [o] multer 미들웨어를 사용하여 이미지 업로드 API를 구현해 주세요.
  • [o] 업로드된 이미지는 서버에 저장하고, 해당 이미지의 경로를 response 객체에 포함해 반환합니다.

상품 상세

  • [o] 상품을 조회할 때, 해당 상품에 대한 댓글 리스트, 사용자가 '좋아요'를 눌렀는지 여부를 확인할 수 있도록 응답 객체에 포함시켜 반환해 주세요.

좋아요 기능

  • [o] '좋아요' API를 만들어 주세요.
  • [o] 사용자는 상품 또는 게시글에 '좋아요'를 할 수 있습니다.
  • [o] $transaction을 사용해 주세요.
  • [o] '좋아요' 취소 API를 만들어 주세요.
  • [o] 사용자는 상품 또는 게시글에 '좋아요'를 취소할 수 있습니다.
  • [o] $transaction을 사용해 주세요.
  • [o] 상품 또는 게시글을 조회할 때, 사용자가 '좋아요'를 누른 항목인지 확인할 수 있도록 isLiked 필드를 응답 객체에 포함시켜 반환해 주세요.

에러 처리

  • [o] 모든 예외 상황을 처리할 수 있는 에러 핸들러 미들웨어를 구현합니다.
  • [o] 서버 오류(500), 사용자 입력 오류(400 시리즈), 리소스 찾을 수 없음(404) 등 상황에 맞는 상태값을 반환합니다.

라우트 중복 제거

  • [o] 중복되는 라우트 경로(예: /users에 대한 get 및 post 요청)를 app.route()로 통합해 중복을 제거합니다.
  • [o] express.Router()를 활용하여 중고마켓/자유게시판 관련 라우트를 별도의 모듈로 구분합니다.

인증

  • [o] User 스키마를 작성해 주세요.
  • [o] id, email, nickname, image, encryptedPassword, createdAt, updatedAt 필드를 가집니다.
  • [o] 회원가입 API를 만들어 주세요.
  • [o] email, nickname, password 를 입력하여 회원가입을 진행합니다.
  • [o] password는 해싱해 저장합니다.
  • [o] 로그인 API를 만들어 주세요.
  • [o] 사용자의 신원을 확인하고, 성공적인 인증 후에는 액세스 토큰을 발급해 response 객체에 포함해 반환합니다.

상품 기능 인가

  • [o] 로그인한 사용자만 상품을 등록할 수 있습니다.
  • [o] 상품을 등록한 사용자만 해당 상품의 정보를 수정 및 삭제를 할 수 있습니다.
  • [o] 로그인한 사용자만 상품에 '좋아요'를 추가하거나 삭제할 수 있습니다.

게시글 기능 인가

  • [o] 로그인한 사용자만 게시글을 등록할 수 있습니다.
  • [o] 게시글을 등록한 사용자만 해당 게시글 정보를 수정 및 삭제할 수 있습니다.
  • [o] 로그인한 사용자만 게시글에 '좋아요'를 추가하거나 삭제할 수 있습니다.

댓글 기능 인가

  • [o] 로그인한 사용자만 상품에 댓글을 등록할 수 있습니다.
  • [o] 로그인한 사용자만 게시글에 댓글을 등록할 수 있습니다.
  • [o] 댓글을 등록한 사용자만 댓글을 수정하거나 삭제할 수 있습니다.

심화

인증

  • [o] 토큰 기반 방식을 사용할 경우, 만료된 액세스 토큰을 새로 발급하는 리프레시 토큰 발급 기능을 구현합니다.(jwt sliding session 적용)
  • [o] 구글 OAuth를 사용하여 회원가입 및 로그인 기능을 구현합니다.

주요 변경사항

  • RESTfull API를 초점으로 만들었다.
  • 현재 필요한 API구현완료
  • cookie(유저 정보 보안), multer(이미지 최적화), swagger(api문서화) 추가

멘토에게

  • 최대한 구현해 봤습니다(구글은 OAuth구현만 나머지는 확인 완료)
  • 프론트영역은 고칠부분이 많아 미션11떄 타입스크립트로 리펙토링하면서 올리겠습니다!
  • 미흡한 부분은 멘토님의 리뷰를 통해 다음 미션11때 고치겠습니다!.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

article Article? @relation(fields: [articleId], references: [id], onDelete: Cascade)
product Product? @relation(fields: [productId], references: [id], onDelete: Cascade)

Copy link
Collaborator

Choose a reason for hiding this comment

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

userId 도 다른 외래키들과 마찬가지로 index 로 색인을 달아두는 것이 좋겠습니다. 댓글정보를 불러올때 조회성능을 높일 수 있겠습니다.

userId String?
productId String?
id String @id @default(uuid())
userId String?
Copy link
Collaborator

Choose a reason for hiding this comment

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

댓글은 로그인을 한 유저만 등록할 수 있기 때문에, userId 는 필수값으로 설정되어야 합니다. productId 와 articleId 는 댓글 모델을 공유하고 있기 때문에 옵셔널로 되어있는 것이 맞습니다.

import multer from "multer";
import { validateProduct } from "../middlewares/validateProduct.js";
import asyncHandler from "../middlewares/asyncHandler.js";

Copy link
Collaborator

Choose a reason for hiding this comment

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

multer 의 경우, 이미지를 저장하려는 경로에 해당하는 폴더가 존재하지 않는 경우, 자동으로 생성해주는 로직이 내장되어 있지 않습니다. 그래서 multer 로 이미지를 서버 내 특정 경로에 저장하는 경우 보통 아래 코드를 먼저 사용합니다.
// uploads 폴더가 없으면 생성
const uploadDir = "uploads/";
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}

@rjc1704
Copy link
Collaborator

rjc1704 commented Mar 24, 2025

희성님 스프린트 10 수행하시느라 고생하셨습니다! 프로젝트 준비중에도 성실하게 스프린트에 임해주셔서 감사합니다.
아래에 제너럴 코멘트를 드리겠습니다.

  • MVC 패턴을 따르며 구조화가 체계적으로 잘 되어 있습니다!
  • swaggerJsdoc 을 사용하셔서 스웨거 설정을 잘하셨습니다! 사실 swaggerJsdoc 주석을 처리하고 제대로 검토하는 것 뿐만 아니라 라우터 파일의 가독성을 보완하는 작업도 생각보다 번거로운 일이라 설정된 내용대로 자동으로 swagger docs 구조를 생성해주는 swagger autogen 을 사용해보시는 것을 권장 드리고 싶습니다. (물론 autogen 도 100% 자동화는 아닙니다..!)
  • auth.route.ts 를 보면 라우트 핸들링을 asyncHandler(signUp) 로 에러핸들링을 하고 있는데, signUp 함수도 내부를 보면 try/catch 로 에러핸들링을 또 하고 있어 중복입니다. asyncHandler 를 사용하는 경우 인자에 해당하는 signUp 같은 함수 내부에서는 try/catch 없이 심플하게 비즈니스 로직만 사용하시는 것이 깔끔하고 역할분담을 잘한 것이라 할 수 있겠습니다.
  • validateUser 함수에서 토큰 검증과 갱신 로직을 잘 구현해주셨습니다! 그런데 validateUser 보다 authenticateUser 이나 verifyAuth 정도가 더 적절하지 않을까 싶습니다.
  • 현재는 토큰 갱신 시 신규 엑세스토큰을 클라이언트에 응답하고 있어, 갱신의 경우 클라이언트에서 자동으로 재 요청하는 로직이 있어야 합니다. 보통 axios.interceptor 에서 처리해줍니다. 이런 방법이 난이도면에서 단순해서 구현이 쉽습니다. 하지만, 리프레시 토큰만 유효하다면 바로 next() 처리하고 엑세스토큰도 한번에 갱신해주는 방법도 있습니다. 이에 대해서는 내용이 길 수 있어 멘토링에서 다루도록 하겠습니다. 고생하셨습니다.

@rjc1704 rjc1704 merged commit a6c808a into codeit-sprint-fullstack:express-김희성 Mar 24, 2025
1 check passed
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