Skip to content

Next 최진영 - 스프린트미션8 제출#69

Merged
pers0n4 merged 3 commits intocodeit-sprint-fullstack:next-최진영from
Gephigirl:next-최진영
Nov 20, 2025

Hidden character warning

The head ref may contain hidden characters: "next-\ucd5c\uc9c4\uc601"
Merged

Next 최진영 - 스프린트미션8 제출#69
pers0n4 merged 3 commits intocodeit-sprint-fullstack:next-최진영from
Gephigirl:next-최진영

Conversation

@Gephigirl
Copy link
Collaborator

공통

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

자유 게시판 페이지

  • 게시글 목록에서 드롭다운을 사용하여 "최신 순"으로 정렬할 수 있도록 합니다.
  • 본인이 이전 미션에서 생성한 게시글 목록 조회 API를 활용해 GET 메서드로 데이터를 가져옵니다.
  • 게시글 제목에 검색어가 일부 포함되면 해당 게시글을 검색할 수 있도록 합니다.
  • 이미지는 디폴트 이미지로 프론트엔드에서 처리해 주세요.
  • 게시글 닉네임 및 좋아요 개수 역시 임의값으로 프론트엔드에서 처리해주세요. : 닉네임 없으면 익명으로 등록
  • 베스트 게시글은 최신순 3개 게시글을 요청으로 데이터를 가져와 구현해주세요.
  • 자유게시판 페이지에서 특정 게시글을 클릭하면 해당 게시물의 상세 페이지로 이동합니다.

게시글 등록 & 수정 페이지

  • 각 input 필드에 정확한 placeholder 값을 입력합니다.
  • 모든 input 필드에 값을 입력하면 '등록' 버튼이 활성화됩니다.
  • 본인이 이전 미션에서 생성한 게시글 생성 API를 활용해 POST 메서드로 게시글을 등록합니다.
  • '등록' 버튼을 누르면 해당 게시물 상세 페이지로 이동합니다.
  • 게시글 수정 페이지 UI는 게시글 등록 페이지와 동일합니다.
  • 본인이 이전 미션에서 생성한 게시글 상세 API의 PATCH 메소드를 사용하여 게시물을 수정합니다.

게시글 상세 페이지

  • 본인이 이전 미션에서 생성한 게시글 상세 API의 GET 메소드를 사용하여 데이터를 가져옵니다.
  • 본인이 이전 미션에서 생성한 게시글 상세 API의 DELETE 메소드를 사용하여 게시물을 삭제합니다.
  • 댓글 input에 값을 입력하면 '등록' 버튼이 활성화됩니다.
  • 본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 POST 메소드로 댓글을 등록합니다.
  • 본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 PATCH 메소드로 댓글을 수정합니다.
  • 본인이 이전 미션에서 생성한 댓글 생성 API를 활용해 DELETE 메소드로 댓글을 삭제합니다.

심화 요구사항

공통

  • 디자인 시안에 따라 반응형 디자인을 구현합니다.
  • (생략 가능) 원한다면 지금까지 진행한 모든 React 코드를 Next.js로 마이그레이션 해주세요.
  • 마이그레이션에 상당한 시간이 소요될 수 있으므로 진행을 권장하지 않습니다.

멘토님에게

초기에 테스트해보던 mock 데이터와 이전 미션1 파일들(미션1때 이것저것해보다 올라가있었나봐요)이 함께 올라가 버렸네요 ㅠㅠ
실제 연결되는 것은 BE 미션7과 연동된 현재 미션8 코드입니다. 커밋 일부를 정리하지 못했지만 양해부탁드립니다.

"prisma:migrate": "prisma migrate dev",
"start": "next start"
},
"dependencies": {
Copy link
Collaborator

Choose a reason for hiding this comment

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

잘 만들어진 라이브러리를 가져다 쓰는 건 좋다고 생각하지만, 현재 프로젝트에서는 사용하지 않는 라이브러리도 여럿 있어 보이네요. 불필요한 의존성 설치 과정과 사용 시 혼란을 없애기 위해 추가했던 라이브러리는 사용하지 않게 된 시점에 바로 제거해주면 좋습니다.

if (params.keyword) searchParams.append("keyword", params.keyword)
if (params.limit) searchParams.append("limit", params.limit.toString())

const response = await fetch(`${API_BASE_URL}/api/articles?${searchParams}`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

fetch에 API_BASE_URL을 항상 붙여서 사용하고 있는데, 이런 케이스는 fetch를 한 번 추상화해서 반복을 줄이면 편하게 사용할 수 있을 것 같아요.

Comment on lines +11 to +12
if (!response.ok) throw new Error("Failed to fetch posts")
return response.json()
Copy link
Collaborator

Choose a reason for hiding this comment

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

추상화하는 김에 이렇게 반복되는 구문도 같이 묶으면 좋겠네요.

useEffect(() => {
async function fetchPosts() {
try {
const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/articles?page=1&limit=5`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

lib/api.js에 정의해둔 함수를 사용해도 되지 않나요?

<span
className="flex items-center gap-1 px-3 py-1 text-xs font-medium text-white"
style={{
borderRadius: "0 0 16px 16px",
Copy link
Collaborator

Choose a reason for hiding this comment

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

사용 중인 tailwind에도 아마 borderRadius 속성을 대신할 수 있는 스타일 클래스가 있을 텐데, 만들어져 있는 클래스로 대체해보면 어떨까요?

Comment on lines +17 to +18
const [editingId, setEditingId] = useState(null);
const [editContent, setEditContent] = useState("");
Copy link
Collaborator

Choose a reason for hiding this comment

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

editingId와 editContent는 결합도가 높은 상태로 보이는데, 이 경우는 각각 state로 정의하기보다는 하나의 object로 정의하면 state의 목적(용도)을 더욱 확실하게 나타낼 수 있을 것 같네요.

e.g.

// 수정일 때
setState({
  id: 1,
  content: "",
})

// 생성일 때
setState({
  id: null,
  content: "",
})

<Button
onClick={handleAddComment}
className="mt-2 rounded-xl bg-[#9CA3AF] px-5 py-2 text-white text-sm font-medium hover:bg-[#6B7280] transition-colors"
style={{ fontFamily: "Pretendard" }}
Copy link
Collaborator

Choose a reason for hiding this comment

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

fontFamily는 루트 스타일 기본 스타일로 지정해도 되지 않을까요?

Comment on lines +5 to +13
export function PostForm({ mode = "create", postId }) {
const [title, setTitle] = useState("")
const [content, setContent] = useState("")
const [author, setAuthor] = useState("")

const isFilled = title.trim() !== "" && content.trim() !== ""

useEffect(() => {
if (mode === "edit" && postId) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

create와 edit 같은 리터럴 스트링을 직접 사용하면 실수하게 될 확률이 높아지므로 상수로 선언해서 사용하는 편이 좋습니다.

@pers0n4 pers0n4 merged commit 9652c3c into codeit-sprint-fullstack:next-최진영 Nov 20, 2025
1 check passed
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