Conversation
iamjaeholee
left a comment
There was a problem hiding this comment.
스프린트 미션6 작업하느라 수고하셨어요 🥇
전반적으로 태영님께서 얼마나 많이 고민하시고 작업을 진행해주셨는지 느껴지는 PR이었습니다.
여러 상황에 대응하기 위해 validation 처리해주시는 부분, 데이터 변환 해주시는 부분 등 너무 훌륭한 부분들이 많았어요 👍
| DATABASE_URL="postgresql://postgres:java7670@localhost:5432/comazon_dev?schema=public" | ||
| PORT=3000 No newline at end of file |
There was a problem hiding this comment.
.env파일에는 민감한 정보 (예를들면 DB_URL 같은 것)가 포함될 수 있어 왠만하면 .gitignore에 추가하는 것을 추천드려요 :-)
| import * as dotenv from 'dotenv'; | ||
| dotenv.config(); |
There was a problem hiding this comment.
dotenv패키지 활용해 환경변수 제어해주는 부분 좋습니다 !
| const corsOptions = { | ||
| origin: ['http://localhost:5173', 'http://localhost:3000', 'http://127.0.0.1:5173'], | ||
| credentials: true, | ||
| methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'], | ||
| allowedHeaders: ['Content-Type', 'Authorization'] | ||
| }; | ||
| app.use(cors(corsOptions)); // CORS 허용 | ||
| app.use(express.json({ limit: '50mb' })); // JSON 파싱 (이미지 업로드를 위해 크기 제한 증가) | ||
| app.use(express.urlencoded({ extended: true, limit: '50mb' })); // URL 인코딩된 데이터 파싱 | ||
|
|
||
| // OPTIONS 요청 처리 (preflight) | ||
| app.options('*', cors(corsOptions)); |
There was a problem hiding this comment.
corsOptions에서 OPTIONS가 포함되어 있어서 요것은 중복되는 부분이 아닌가 하는 의견입니다 !
| try { | ||
| return { | ||
| id: product.id, | ||
| name: product.name, | ||
| description: product.description || '', | ||
| category: product.category, | ||
| price: product.price, | ||
| stock: product.stock, | ||
| // 스키마의 image 필드를 사용 (productImage가 아니라 image) | ||
| productImage: product.image, | ||
| images: product.image || '/src/assets/products/default.png', | ||
| // 스키마에 favoriteCount 필드가 있음 | ||
| favoriteCount: product.favoriteCount || 0, | ||
| createdAt: product.createdAt, | ||
| updatedAt: product.updatedAt, | ||
| // 태그 정보 (선택사항) - 태그가 없을 수 있으므로 안전하게 처리 | ||
| tags: (product.tags && Array.isArray(product.tags)) | ||
| ? product.tags.map(pt => ({ | ||
| id: pt.tag?.id, | ||
| name: pt.tag?.name | ||
| })).filter(tag => tag.id && tag.name) // null 제거 | ||
| : [] | ||
| }; | ||
| } catch (error) { | ||
| console.error('[Backend] Error transforming product:', product.id, error); | ||
| // 에러가 발생해도 기본 정보는 반환 | ||
| return { |
There was a problem hiding this comment.
product를 react에서 원하는 형태로 변환하는 과정에서 에러가 발생하게 될 경우 기본값을 반환해주는 로직에 try catch문을 활용해주고 계세요 !
에러가 발생해 catch구문에 들어가게 될 경우 기본값을 반환하는 로직이기 때문에 try catch를 쓰지 않고 ?., ??, ? : 등의 다양한 오퍼레이터를 활용하면 에러가 나지 않고 기본값을 반환하도록 수정할 수도 있을 것 같아요. !
| : [] | ||
| }; | ||
|
|
||
| res.json(transformedProduct); |
There was a problem hiding this comment.
이 파일 내에서 어떤 부분에서는 return값을 사용하고 있고, 어떤 부분에서는 사용하지 않고 있어서 통일성을 맞춰주면 좋을 것 같다는 의견이에요 : -)
| -- CreateIndex | ||
| CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); | ||
|
|
||
| -- CreateIndex | ||
| CREATE UNIQUE INDEX "Tag_name_key" ON "Tag"("name"); | ||
|
|
There was a problem hiding this comment.
쿼리 최적화를 위해 인덱스 설정해주는 부분 너무 좋아요
| enum Category { | ||
| FASHION | ||
| BEAUTY | ||
| SPORTS | ||
| ELECTRONICS | ||
| HOME_INTERIOR | ||
| HOUSEHOLD_SUPPLIES | ||
| KITCHENWARE | ||
| } |
There was a problem hiding this comment.
enum활용해 스키마 작성해주는 부분 너무 좋습니다.
| @@ -0,0 +1,112 @@ | |||
| const ListProducts = "http://localhost:3000/products"; | |||
There was a problem hiding this comment.
url같은 부분은 환경변수를 통해서 주입받으면 더 유연하게 대처할 수 있을 것 같아요 : -)
| export async function getProducts({ page = 1, pageSize = 10, orderBy = "recent", keyword = "" } = {}) { | ||
| try { | ||
| const url = new URL(ListProducts); | ||
| url.searchParams.set("page", String(page)); | ||
| url.searchParams.set("pageSize", String(pageSize)); | ||
| if (keyword) { | ||
| url.searchParams.set("keyword", keyword); | ||
| } | ||
| if (orderBy) { | ||
| url.searchParams.set("orderBy", orderBy); | ||
| } | ||
|
|
||
| console.log('[getProducts] Fetching URL:', url.toString()); | ||
|
|
||
| let response; | ||
| try { | ||
| response = await fetch(url.toString(), { | ||
| method: 'GET', | ||
| headers: { |
There was a problem hiding this comment.
이 부분은 api를 호출하는 소스를 담고있는 파일인 것 같아요. 사실상 jsx의 확장자를 활용하지 않고 있어서 js확장자로 사용해도 될 것 같습니다.
| } finally { | ||
| setLoading(false); | ||
| } |
There was a problem hiding this comment.
finally활용해주는 부분 너무 좋습니다.
|
|
요구사항
기본
심화
주요 변경사항
스크린샷
멘토에게