-
Notifications
You must be signed in to change notification settings - Fork 20
[선태영] Sprint6 #76
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
base: react-선태영
Are you sure you want to change the base?
[선태영] Sprint6 #76
Conversation
iamjaeholee
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
스프린트 미션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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.env파일에는 민감한 정보 (예를들면 DB_URL 같은 것)가 포함될 수 있어 왠만하면 .gitignore에 추가하는 것을 추천드려요 :-)
| import * as dotenv from 'dotenv'; | ||
| dotenv.config(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
product를 react에서 원하는 형태로 변환하는 과정에서 에러가 발생하게 될 경우 기본값을 반환해주는 로직에 try catch문을 활용해주고 계세요 !
에러가 발생해 catch구문에 들어가게 될 경우 기본값을 반환하는 로직이기 때문에 try catch를 쓰지 않고 ?., ??, ? : 등의 다양한 오퍼레이터를 활용하면 에러가 나지 않고 기본값을 반환하도록 수정할 수도 있을 것 같아요. !
| : [] | ||
| }; | ||
|
|
||
| res.json(transformedProduct); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 파일 내에서 어떤 부분에서는 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
쿼리 최적화를 위해 인덱스 설정해주는 부분 너무 좋아요
| enum Category { | ||
| FASHION | ||
| BEAUTY | ||
| SPORTS | ||
| ELECTRONICS | ||
| HOME_INTERIOR | ||
| HOUSEHOLD_SUPPLIES | ||
| KITCHENWARE | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum활용해 스키마 작성해주는 부분 너무 좋습니다.
| @@ -0,0 +1,112 @@ | |||
| const ListProducts = "http://localhost:3000/products"; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 api를 호출하는 소스를 담고있는 파일인 것 같아요. 사실상 jsx의 확장자를 활용하지 않고 있어서 js확장자로 사용해도 될 것 같습니다.
| } finally { | ||
| setLoading(false); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
finally활용해주는 부분 너무 좋습니다.
|
|
요구사항
기본
심화
주요 변경사항
스크린샷
멘토에게