Skip to content

Conversation

@play-ancora-gyungmin
Copy link
Collaborator

스프린트 미션 8 요구사항 확인

기본 요구사항

공통

  • 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 메소드로 댓글을 삭제합니다.

Comment on lines +3 to +4
const API = process.env.API_URL + "/articles";
const PUBLIC_API = process.env.NEXT_PUBLIC_API_URL + "/articles";
Copy link
Collaborator

Choose a reason for hiding this comment

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

API와 PUBLIC_API는 어떤 차이가 있나요?
BFF와 메인 API를 구분하는 용도면 이름을 더 명확하게 구분하면 좋을 것 같습니다.

process.env.API_URL 처럼 여러 파일에서 같은 환경 변수에 접근하는 케이스가 있다면 환경 변수를 로드하는 파일을 하나 만들면 관리 포인트를 줄일 수 있습니다.

Comment on lines +16 to +22
export const getArticleById = cache(async ({ id }) => {
const res = await fetch(API + `/${id}`);
if (!res.ok) {
throw new Error("데이터를 가져오는데 실패했습니다");
}
return res.json();
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

실용성을 생각하면 api 서비스 함수에 cache를 씌울 수도 있지만, lib에 정의해둔 서비스 함수를 재사용을 고려한다면 api 서비스와 캐싱을 분리하면 좋을 것 같네요.


export function NavMenuWrap() {
const pathname = usePathname();
const baseMenuClasses =
Copy link
Collaborator

Choose a reason for hiding this comment

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

  1. 길어지는 스타일을 따로 분리한 선택은 좋아 보입니다.
  2. tailwind가 유연성은 좋지만, 유연함 때문에 임의값으로 때우고 넘어가기 쉬운 부분입니다. 프로젝트 내에서 반복적으로 사용될 스타일이라면 꼭 적절한 클래스로 정의해서 사용하는 게 좋습니다. max-[46.4rem] 같은 값은 breakpoint 값을 정의하면 좋을 것 같네요.

Comment on lines +45 to +58
<div className="flex flex-col mt-8 gap-6">
<div className="flex flex-col gap-3">
<h3 className="text-lg font-bold text-(--secondary-800)">*제목</h3>
<div className="flex grow items-center gap-1 rounded-xl bg-(--secondary-100) px-6 py-4 focus-within:border focus-within:border-solid focus-within:border-(--primary-100)">
<input
id="title"
className="h-6 w-full border-none bg-transparent text-base font-normal leading-6.5 placeholder:text-(--secondary-400) focus:outline-none"
type="text"
placeholder="제목을 입력해주세요"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
</div>
</div>
Copy link
Collaborator

Choose a reason for hiding this comment

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

전체적인 마크업 구조와 스타일이 유사하게 반복되는 부분이 보이는데, 이런 부분들은 리액트를 사용하는 장점을 살리기 위해 컴포넌트로 정의해서 사용하면 좋을 것 같네요. 제때 하지 않으면 부채가 계속 늘어나는 부분이니 여유가 있을 때 신경을 쓰는 게 좋습니다.

<span>닉네임 이건 정의되지 않은 더미</span>
</div>
<p className="text-(--secondary-400)">
{article.createdAt.split("T")[0]}
Copy link
Collaborator

Choose a reason for hiding this comment

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

만약 기획상 서비스에서 노출하는 날짜 형식을 전부 YYYY년 MM월 DD일 형태로 바꿔달라는 요구사항이 등장한다면 어떻게 해야 할까요?
날짜와 시간 포매팅은 자주 쓰이는 구문이라 포맷 함수를 정의해두면 깔끔하게 사용할 수 있습니다.

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