Skip to content

Conversation

@fs6-kde
Copy link
Collaborator

@fs6-kde fs6-kde commented Apr 20, 2025

요구사항

기본

  • 게시글 목록에서 드롭다운을 사용하여 "최신 순"으로 정렬할 수 있도록 합니다.

  • 본인이 이전 미션에서 생성한 게시글 목록 조회 API를 활용해 GET 메서드로 데이터를 가져옵니다.

  • 게시글 제목에 검색어가 일부 포함되면 해당 게시글을 검색할 수 있도록 합니다.

  • 이미지는 디폴트 이미지로 프론트엔드에서 처리해 주세요.

  • 게시글 닉네임 및 좋아요 개수 역시 임의값으로 프론트엔드에서 처리해주세요.

  • 베스트 게시글은 최신순 3개 게시글을 요청으로 데이터를 가져와 구현해주세요.

  • 자유게시판 페이지에서 특정 게시글을 클릭하면 해당 게시물의 상세 페이지로 이동합니다.

  • 각 input 필드에 정확한 placeholder 값을 입력합니다.

  • 모든 input 필드에 값을 입력하면 '등록' 버튼이 활성화됩니다.

  • 본인이 이전 미션에서 생성한 게시글 생성 API를 활용해 POST 메서드로 게시글을 등록합니다.

  • '등록' 버튼을 누르면 해당 게시물 상세 페이지로 이동합니다.

  • 게시글 수정 페이지 UI는 게시글 등록 페이지와 동일합니다.

  • 본인이 이전 미션에서 생성한 게시글 상세 API의 PATCH 메소드를 사용하여 게시물을 수정합니다.

  • 본인이 이전 미션에서 생성한 게시글 상세 API의 GET 메소드를 사용하여 데이터를 가져옵니다.

  • 본인이 이전 미션에서 생성한 게시글 상세 API의 DELETE 메소드를 사용하여 게시물을 삭제합니다.

  • 댓글 input에 값을 입력하면 '등록' 버튼이 활성화됩니다.

  • 본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 POST 메소드로 댓글을 등록합니다.
    본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 PATCH 메소드로 댓글을 수정합니다.
    본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 DELETE 메소드로 댓글을 삭제합니다.

심화

  • 디자인 시안에 따라 반응형 디자인을 구현합니다. (피그마에 나온대로 다 똑같이 구사하진 못한 것 같습니다..)

주요 변경사항

  • util 함수를 만든 부분이 있으나 gpt를 참고해 만들었습니다.
  • 게시글을 수정할 때, writes 페이지에서 '등록' 버튼을 '수정' 버튼으로 보이게 설정하였습니다.
  • '좋아요 수'를 임의로 프론트에서 처리하기 위해 Math.random( )을 사용하여 만들었습니다.
  • 삭제할 때, confirm으로 삭제하시겠습니까?를 확인한 뒤, alert로 삭제되었습니다를 설정하였습니다.

스크린샷

image
image
image
image

멘토에게

  • 데이터는 제가 be 레포에 보낸 Sprint8 pr을 통해 확인하실 수 있습니다..! (배포는 못했습니다)
  • 컴포넌트로 따로 분리해서 만든 것이 너무 적어, 한 페이지 당 코드 양이 조금 많고 지저분한 것 같습니다..
  • next를 최대한 활용하려 했는데, 너무 활용한 부분이 적은 거 같습니다
  • '베스트 게시글' 부분에서 박스 크기 설정을 좀 잘못 주었는지 화면을 축소할 때 박스가 급격히 커지는 경향이 있습니다

Copy link

@dokdo2013 dokdo2013 left a comment

Choose a reason for hiding this comment

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

전반적으로 폴더 구조도 잘 작성되었고, 컴포넌트 분리만 적절히 이뤄지면 좋을 듯 합니다.

리뷰가 늦어져서 죄송합니다... 고생 많으셨습니다!

Choose a reason for hiding this comment

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

파일이 좀 큰데 헤더, 댓글, 유저 정보 등 더 작게 컴포넌트로 분리할 수 있는 부분이 많이 보입니다. 컴포넌트 분리에 대해 조금 더 고민해보면 좋을 것 같습니다!

Comment on lines +68 to +114
return (
<main className="flex flex-col items-center justify-start mt-20 min-h-screen px-4">
<div className="w-full max-w-3xl">
<div className="flex justify-between items-center mb-6">
<h1 className="text-lg font-semibold">게시글 쓰기</h1>
<button
className={`px-4 py-2 rounded-md text-sm font-semibold text-white ${
isButtonDisabled
? "bg-gray-300 cursor-not-allowed"
: "bg-blue-500 hover:bg-blue-600"
}`}
onClick={handleSubmit}
disabled={isButtonDisabled}
>
{id ? "수정" : "등록"}
</button>
</div>

<form className="space-y-6">
<div>
<label className="block text-sm font-semibold mb-2">*제목</label>
<input
type="text"
placeholder={titlePlaceholder}
onFocus={() => setTitlePlaceholder("")}
onBlur={() => setTitlePlaceholder("제목을 입력해주세요")}
value={title}
onChange={(e) => setTitle(e.target.value)}
className="w-full bg-gray-100 border border-gray-200 rounded-lg px-4 py-3 text-sm placeholder-gray-400 focus:outline-none hover:bg-gray-200 transition cursor-pointer focus:ring-2 focus:ring-blue-500"
/>
</div>

<div>
<label className="block text-sm font-semibold mb-2">*내용</label>
<textarea
rows="10"
placeholder={contentPlaceholder}
onFocus={() => setContentPlaceholder("")}
onBlur={() => setContentPlaceholder("내용을 입력해주세요")}
value={content}
onChange={(e) => setContent(e.target.value)}
className="w-full bg-gray-100 border border-gray-200 rounded-lg px-4 py-3 text-sm placeholder-gray-400 resize-none focus:outline-none hover:bg-gray-200 transition cursor-pointer focus:ring-2 focus:ring-blue-500"
></textarea>
</div>
</form>
</div>
</main>

Choose a reason for hiding this comment

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

전체를 form으로 감싸고, 수정/등록하는 버튼에 onClick을 거는게 아니라, button type을 submit으로 하여 form의 submit이벤트를 통해 게시물이 등록/수정될 수 있도록 하는게 더 좋아보입니다. html form 이벤트를 바로 사용하면, input이나 textarea에 required 옵션을 넣어서 따로 검증 로직을 작성할 필요도 없어져서 더 편하기도 합니다.

@@ -0,0 +1,11 @@
export async function deleteComment(commentId) {
const res = await fetch(`http://localhost:3000/comments/${commentId}`, {

Choose a reason for hiding this comment

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

이런 localhost:3000 같은 경로는 baseUrl로 빼서 환경변수로 관리하는게 더 좋아보이네요!

Choose a reason for hiding this comment

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

많이 사용되는 날짜 라이브러리인 dayjs에서도 relative-time을 제공하고 있습니다. 이걸 사용하면 따로 if 문 나열해서 힘들게 구현할 필요 없이 다 알잘딱하게 처리해줘서 좋습니다! (사이트에서는 영어로 표기되지만 실제 사용할 때는 한국어 버전으로도 쓸 수 있습니다)

https://day.js.org/docs/en/plugin/relative-time

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