Skip to content

메인화면 반응형 레이아웃 적용하기

HG.Seo edited this page Dec 15, 2022 · 2 revisions

왜 반응형 레이아웃 적용이 필요했나?

저희 서비스의 경우 프로필박스에서 코드를 보여주는 것이 중요하기에 사이즈가 무한정 늘어나거나 줄어들어 프로필박스의 코드를 알아보는데 지장을 주는 것은 저희 서비스에 올바를 방향이 아니었고 미관상으로도 좋지 않았습니다.

[기존 해결방식]

해결한 방법?

이에, 화면 사이즈에 맞게 width를 계산하도록 하였고 minWidth 값과 maxWidth값을 주어 해결하려고 했습니다.

여전히 남아있었던 문제점?

여전히 디자인 상 문제점이 남아있었습니다. 사이즈가 줄어들어서 프로필박스가 한 행에 2개씩 나오게 될 경우에 프로필박스의 개수가 홀수라면, 마지막 하나의 프로필 사이즈는 다른 프로필 사이즈와 다르게(넓어짐) 나타난다는 것이었습니다.

추가적인 해결방법?

가장 간단하게 해결할 수 있는 방법을 고민해보았습니다.
저희 메인화면에서 한 행에 표현될 수 있는 프로필박스 개수의 경우는 3개, 2개, 1개 이렇게 3가지가 있고 문제가 되는 경우는 2개인 경우입니다.
이에, 2개가 나오는 경우의 브라우저 사이즈를 측정하였고 window.addEventListener의 'resize'이벤트를 통해 한 행에 2개씩 표현이 되는 경우에는 빈 프로필 박스를 임의로 추가해줌으로써 간단히 추가적인 미관상 문제를 해결할 수 있었습니다.

/** @jsxImportSource @emotion/react */

import { useCallback, useEffect, useRef, useState } from 'react';

import Profile from './Profile';
import { singleProfileData } from './types';

import { emptyProfileBoxStyle, profileListStyle } from './styles';
import { COMMON_SIZE } from 'styles/sizes';

interface Props {
  profileData: Array<singleProfileData>;
}

const ProfileList = ({ profileData }: Props) => {
  const profileListRef = useRef<HTMLDivElement>(null);
  const [isOdd, setIsOdd] = useState<boolean>(false);
  const [isBlankNeeded, setIsBlankNeeded] = useState<boolean>(false);

  useEffect(() => {
    if (profileData.length % 2 !== 0) setIsOdd(true);
    else setIsOdd(false);
  }, []);

  const isWidthDouble = useCallback((targetWidth: number) => {
    return COMMON_SIZE.PROFILELIST_SINGLE_WIDTH < targetWidth && targetWidth < COMMON_SIZE.PROFILELIST_TRIPLE_WIDTH;
  }, []);

  const decideBlank = useCallback(() => {
    if (!profileListRef.current) return;
    if (isWidthDouble(profileListRef.current.clientWidth)) setIsBlankNeeded(true);
    else setIsBlankNeeded(false);
  }, [profileListRef.current]);

  useEffect(() => {
    window.addEventListener('resize', decideBlank);
    return () => {
      window.removeEventListener('resize', decideBlank);
    };
  }, []);

  return (
    <div css={profileListStyle} ref={profileListRef}>
      {profileData.map((data) => (
        <Profile key={`profile-${data.id}`} singleData={data} />
      ))}
      {isOdd && isBlankNeeded && <div css={emptyProfileBoxStyle} />}
    </div>
  );
};

export default ProfileList;

결과물

SCOPA-메인 반응형


[최종 해결방안]

변경 사유

프로필 개수 외에도 필터링 바 등 화면 사이즈에 따라, 디자인 변경이 필요했습니다.
또한, 프로필박스 개수가 4개, 5개 등인 경우에 기존 방식으로는 디자인에 예외사항이 발생했습니다.

변경 사항

미디어쿼리를 사용하여, 반응형 레이아웃 디자인(필터링 바 등)을 좀 더 다듬었습니다.
프로필박스를 사이즈에 맞게 보여주는 방법도 빈 박스를 추가하는 방식에서, 미디어 쿼리에 따라 width를 조정하는 방식으로 반영하였습니다.

성과

불필요한 resize이벤트를 제거할 수 있었습니다.
다양한 프로필 개수에 대해서도 동일한 레이아웃을 보장할 수 있었습니다.

결과물

Dec-15-2022 19-30-45

얼리버드

프로젝트

개발일지

스프린트 계획

멘토링

데일리 스크럼

데일리 개인 회고

위클리 그룹 회고

스터디

Clone this wiki locally