Skip to content

레이아웃으로 중복 코드 제거

이선근 edited this page Oct 9, 2023 · 2 revisions

레이아웃 구성

image-2

디자인에서 대부분의 페이지는 인증 후 모든 페이지에 헤더에 내비게이션 바가 있었습니다. 그리고 일부 페이지는 아래에도 고정적으로 바가 있었습니다. 기존에는 각 페이지마다 해당 스타일을 설정해주었지만 15개 정도 되는 페이지에서 각각 중복되는 스타일을 지정하는게 좋지 않다고 생각했습니다. 따라서 각각 레이아웃을 만들어 크기와 위치를 고정했습니다.

문제 1. 페이지마다 위치와 크기는 고정적이었으나 디테일이 달랐다.

  • 게시글, 상품 등록이나 프로필 수정 버튼
  • 검색 버튼
  • 검색 인풋
  • 기본 옵션 버튼

처음에는 pathname에 따라 분기처리를 시도했으나 검색 인풋이나 버튼의 경우 본문의 내용과 의존성이 있었습니다.

// src\components\Layout\MainLayout\MainLayout.jsx
export default function MainLayout() {
  return (
    <S.MainLayout>
      <S.HeaderRoot id="header-root" />
      <S.Main>
        <Outlet />
      </S.Main>
    </S.MainLayout>
  );
}

// src\components\Layout\MainLayout\HeaderBar.jsx
export default function HeaderBar({ children }) {
  const [isRendered, setIsRendered] = useState(false);

  useEffect(() => setIsRendered(true), []);

  return (
    isRendered &&
    createPortal(
      <S.HeaderBar>{children}</S.HeaderBar>,
      document.getElementById('header-root'),
    )
  );
}

위 코드와 같이 빈 div로 크기와 위치만 설정하고 portal을 사용해 만들어 어디에서 사용하든 해당 요소의 자식으로 들어가게 했고, 페이지에서 사용해 관리하기 쉽도록 만들었습니다.

문제 2. 헤더 바에 버튼이 있는 디자인

image-4

버튼은 form안에 있을 때 submit 이벤트를 발생시키는데 이 경우에는 밖에 있기 때문에 컨트롤할 수 없었습니다.

따라서 폼 내부에 빈 버튼을 ref로 만들고 페이지에서 해당 ref를 누르면 submit이벤트를 발생하도록 처리했습니다.

// src\features\posts\routes\PostUploadPage.jsx
export default function PostUploadPage() {
  const submitRef = useRef(null);
  const { mutate: createPostMutate } = useCreatePost();

  const handleSubmit = () => {
    submitRef.current?.click();
  };

  return (
    <>
      <HeaderBar>
        <HeaderBar.BackButton />
        <Button size="ms" onClick={handleSubmit}>
          업로드
        </Button>
      </HeaderBar>
      <PostEditor ref={submitRef} onSubmit={createPostMutate} />
    </>
  );
}
// src\features\posts\components\PostEditor.jsx
const PostEditor = forwardRef(function PostEditor(
  { onSubmit, initData = {} },
  submitRef,
) {

  ...

  return (
    <form onSubmit={handleSubmit}>
      <TagBar />
      <S.EditorWrapper>
       ...
      </S.EditorWrapper>
      <button ref={submitRef} />
    </form>
  );
});

라우터 구조

레이아웃을 적용하려다보니 라우터 구조도 변경해야했습니다.

기존에는 pathname기반으로 중복되는 pathname에 children으로 넣었습니다.

이 구조를 유지하며 레이아웃을 적용하면 레이아웃 컴포넌트가 많이 중복돼 한눈에 알아보기 어렵다고 생각했습니다.

그래서 레이아웃 기반으로 라우팅 구조를 변경했습니다.

이러면 각 레이아웃을 한 번만 사용하기 때문에 구조를 파악하기에 더 용이하다고 생각했습니다.

기존 pathname기반 라우팅

  • / (splash)
    • AuthLayout
      • signin
      • signup
        • profile
    • MainLayout
      • product
        • upload
        • edit/:id
      • post
        • upload
        • edit/:id
        • BottomLayout
          • :id
      • profile
        • edit
        • BottomLayout
          • :accountname
            • follower
            • following
      • BottomLayout
        • home
        • search
        • chat
          • :accountname
  • intro
  • - (not found)

변경 후 레이아웃 기반 라우팅

  • / (splash)
    • AuthLayout
      • signin
      • signup
    • MainLayout
      • profile/edit
      • post
        • upload
        • edit/:id
      • product
        • upload
        • edit/:id
      • BottomLayout
        • home
        • search
        • chat
          • :accountname
        • profile
          • :accountname
          • follower
          • following
        • post/:id
  • intro
  • * (not found)