Skip to content

[원태웅] 스프린트 미션 5, 6#77

Open
taewon-w wants to merge 53 commits into
codeit-sprint-fullstack:react-원태웅from
taewon-w:react-원태웅

Hidden character warning

The head ref may contain hidden characters: "react-\uc6d0\ud0dc\uc6c5"
Open

[원태웅] 스프린트 미션 5, 6#77
taewon-w wants to merge 53 commits into
codeit-sprint-fullstack:react-원태웅from
taewon-w:react-원태웅

Conversation

@taewon-w

@taewon-w taewon-w commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

스프린트 5 요구사항

기본 요구사항

공통

  • Github에 스프린트 미션 PR을 만들어 주세요.
  • React, Express를 사용해 진행합니다.

프론트엔드 구현 요구사항

랜딩 페이지

  • HTML과 CSS로 구현한 랜딩페이지를 React로 마이그레이션하세요.
  • 랜딩 페이지 url path는 "/"로 설정하세요.

중고마켓 페이지

  • 중고마켓 페이지 url path를 "/items"으로 설정하세요.
  • 페이지 주소가 "/items" 일 때 상단 내비게이션 바의 "중고마켓" 버튼의 색상은 "#3692FF"입니다.
  • 중고마켓 페이지 판매 중인 상품은 본인이 만든 GET 메서드를 사용해 주세요.
  • 다만 좋아요 순 정렬 기능은 제외해 주세요.
  • 사진은 디폴트 이미지로 프론트엔드에서 처리해주세요.
  • 베스트 상품 목록 조회는 구현하지 않습니다.
  • '상품 등록하기' 버튼을 누르면 "/registration" 로 이동합니다. (빈 페이지)

상품 등록 페이지

  • PC, Tablet, Mobile 디자인에 해당하는 상품 등록 페이지를 만들어 주세요.
  • 상품 등록 url path는 "/registration"입니다.
  • 상품 등록은 본인이 만든 POST 메서드를 사용해 주세요.
  • 등록 성공 시, 해당 상품 상세 페이지로 이동합니다. (빈 페이지)

백엔드 구현 요구사항

중고마켓 데이터 및 API

  • Product 스키마 작성
    • id, name, description, price, tags, createdAt, updatedAt 필드를 가집니다.
    • 필요한 필드가 있다면 자유롭게 추가해 주세요.
  • 상품 등록 API
    • name, description, price, tags를 입력하여 상품을 등록합니다.
  • 상품 상세 조회 API
    • id, name, description, price, tags, createdAt를 조회합니다.
  • 상품 수정 API
    • PATCH 메서드를 사용해 주세요.
  • 상품 삭제 API
  • 상품 목록 조회 API
    • id, name, price, createdAt를 조회합니다.
    • offset 방식의 페이지네이션 기능을 포함해 주세요.
    • 최신순(recent)으로 정렬할 수 있습니다.
    • name, description에 포함된 단어로 검색할 수 있습니다.

서버 설정 및 배포

  • 각 API에 적절한 에러 처리를 해 주세요.
  • 각 API 응답에 적절한 상태 코드를 리턴하도록 해 주세요.
  • .env 파일에 환경 변수를 설정해 주세요.
  • CORS를 설정해 주세요.
  • render.com로 배포해 주세요.
  • MongoDB를 활용해 주세요.

심화 요구사항

프론트엔드 구현 요구사항

상품 등록 페이지 기능 고도화

  • 모든 입력 input box에 빈 값이 있을 경우, 등록 버튼이 비활성화됩니다.
  • 태그를 입력한 후 엔터키를 누르면, 그 태그가 칩 형태로 쌓입니다.
  • 상품명, 상품 소개, 판매 가격, 태그에 대한 유효성 검사 Custom Hook을 만들어주세요.
  • 유효성 검사를 통과하지 않을 경우, 각 input에 빨간색 테두리와, 각각의 Input 아래에 빨간색 에러 메시지를 보여주세요.
  • 유효한 조건
    • 상품명: 1자 이상, 10자 이내
    • 상품 소개: 10자 이상, 100자 이내
    • 판매 가격: 1자 이상, 숫자
    • 태그: 5글자 이내

스프린트 6 요구사항

기본 요구사항

  • mongoDB에서 PostgreSQL을 사용하도록 코드를 마이그레이션 해주세요.

공통

  • PostgreSQL를 이용해 주세요.
  • 데이터 모델 간의 관계를 고려하여 onDelete를 설정해 주세요.
  • 데이터베이스 시딩 코드를 작성해 주세요.
  • 각 API에 적절한 에러 처리를 해 주세요.
  • 각 API 응답에 적절한 상태 코드를 리턴하도록 해 주세요.

자유게시판

  • Article 스키마를 작성해 주세요.
    • id, title, content, createdAt, updatedAt 필드를 가집니다.
  • 게시글 등록 API를 만들어 주세요.
    • title, content를 입력해 게시글을 등록합니다.
  • 게시글 조회 API를 만들어 주세요.
    • id, title, content, createdAt를 조회합니다.
  • 게시글 수정 API를 만들어 주세요.
  • 게시글 삭제 API를 만들어 주세요.
  • 게시글 목록 조회 API를 만들어 주세요.
    • id, title, content, createdAt를 조회합니다.
    • offset 방식의 페이지네이션 기능을 포함해 주세요.
    • 최신순(recent)으로 정렬할 수 있습니다.
    • title, content에 포함된 단어로 검색할 수 있습니다.

댓글

  • 댓글 등록 API를 만들어 주세요.
    • content를 입력하여 댓글을 등록합니다.
    • 중고마켓, 자유게시판 댓글 등록 API를 따로 만들어 주세요.
  • 댓글 수정 API를 만들어 주세요.
    • PATCH 메서드를 사용해 주세요.
  • 댓글 삭제 API를 만들어 주세요.
  • 댓글 목록 조회 API를 만들어 주세요.
    • id, content, createdAt 를 조회합니다.
    • cursor 방식의 페이지네이션 기능을 포함해 주세요.
    • 중고마켓, 자유게시판 댓글 목록 조회 API를 따로 만들어 주세요.

taewon-w added 29 commits June 29, 2026 11:01
@taewon-w
taewon-w requested a review from devbini July 5, 2026 08:01
@taewon-w taewon-w changed the title [원태웅] 스프린트 미션 5 [원태웅] 스프린트 미션 5, 6 Jul 7, 2026

@devbini devbini left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🎉 고생 많으셨습니다!

이번에 Express부터 Prisma/PostgreSQL 마이그레이션까지 작업량이 꽤 많았는데...
구조적으로나 코드 안정성 측면에서 잘 정리한 점이 놀랍기도 했습니다.

특히 백엔드 파일 분리부터 시작해서- request/constants 등으로 나눠 맞추려는 흐름도 유지보수 관점에서 좋았어요. (에러 역시 FE에게 전부 던지지 않음으로써 보안도 챙긴 것 같아요.)
프론트에서도 상품 등록 폼 필드를 컴포넌트화하고, finally에서 제출 상태를 정리하는 등 UX적으로도 큰 문제 없이 흘러가게 된 것 같습니다.

다만, 실제로 봤을 때 일부 입력값 검증이나 페이지 보정 시 데이터가 잠깐 맞지 않을 수 있는 부분 등 아주 자잘한? 공통 API 클라이언트 관련하여 더 세심하게 봐 주시면 좋을 것 같아요.

태웅님 코드의 경우에는 치명적인 문제나 꼭 수정해야 할 법한 부분이 없어서 리뷰 내용이 굉장히 적은데, 그만큼 좋은 코드를 잘 짜신 게 아닐까 싶습니다.

너무나 고생 많으셨어요! 🎉

Comment on lines +56 to +57
const isValid =
!errors.name && !errors.description && !errors.price && !errors.tags

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

☕ Thinking

error.TagInput 에러 처리가 빠진 것 같아요.
의도 된 것 같기도 보이긴 하는데 보통 error들은 모두 isValid에 반영될거다- 라고 생각하는 경우도 많아서
주석이든 뭐든 처리를 해 주면 좋을 것 같아요

Comment thread src/services/apiClient.js
const fetchOptions = { ...options }

if (body !== undefined) {
fetchOptions.headers = { 'Content-Type': 'application/json' }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

☕ Thinking

이렇게 매번 헤더를 덮어쓰게 만드는 것도 의도된 내용이면 괜찮긴 한데,,
나중에 인증 토큰이라던가- 커스텀 토큰을 쓰는 경우 문제가 생길 수 있어요.

...headers = {
  ...options.headers,
  'Content-Type': 'application/json',
}

이런 식으로 기존 헤더를 보존하면서 추가하는 것도 가능하니, 확장성을 조금 더 생각해보는 건 어떨까요!

Comment on lines +3 to +9
const ProductDetailPage = () => {
return (
<MainLayout>
<div />
</MainLayout>
)
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

☕ Thinking

상품 등록 성공 후 상세 페이지로 이동하는 건 좋은데,
그래도 겸사겸사 이동한 페이지에서도 등록이 성공적으로 된 건지, 등록한 상품이 뭔지 등
아주 작은 정보라도 표시 해 주는 게 좋지 않을까요!

Comment on lines +27 to +35
const handleSubmit = async (event) => {
event.preventDefault()
setHasSubmitted(true)
setSubmitError('')
setFormValues((prevValues) => ({ ...prevValues, tagInput: '' }))
setHasTriedAddingTag(false)

if (!isValid) return

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

☕ Thinking

음, tagInput을 먼저 비우고 유효성 검사를 하고 있네요.
state 업데이트가 비동기적으로 일어나기 때문에 isVaild값이 바로 바뀌진 않지만..
사용자가 "Enter"를 누르지 않은 상태에서 제출 버튼을 누르면 사라질 것 같아요.

  1. 사용자가 태그 입력창에 무언가를 입력함
  2. Enter를 누르지 않아서 tags에는 아직 안 들어감
  3. 바로 등록하기 클릭
  4. tagInput이 비워짐
  5. 노트북은 전송되지도 않고 화면에서도 사라짐

제출할 때 입력 중인 태그를 자동으로 추가할지 규칙을 정해두는 게 좋을 것 같아요

Comment on lines +193 to +195
return res.status(201).json(product)
} catch {
return res.status(500).json({ message: '상품 등록에 실패했습니다.' })

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

☕ Thinking

검증 단계를 서버에서 처리하게 설정 하셨네요,
다만, catch되는 에러가 모두 500으로만 처리되고 있어서... 차후에 원인 파악이 어려울 수도 있을 것 같아요.

생성/조회/수정 등 다양한 상황에서 나오는 Prisma 에러에 대한 공통 에러핸들러를 만들어보는 건 어떨까요?
isPrismaNotFoundError 같은 유틸도 만들어 두었으니 운영관리 관점에서 있으면 좋을 것 같아요.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants