Next 페이지에서 같은 데이터를 여러 레이아웃 및 디자인으로 보여주기

우디·2024년 3월 4일
0
post-thumbnail

안녕하세요:) 개발자 우디입니다! 아래 내용 관련하여 작업 중이신 분들께 도움이되길 바라며 글을 공유하니 참고 부탁드립니다😊
(이번에 벨로그로 이사오면서 예전 글을 옮겨적었습니다. 이 점 양해 부탁드립니다!)

작업 시점: 2022년 1월

배경

  • 스트리머 정보를 보여주는 컴포넌트 구현이 필요했는데, 기획 및 디자인을 살펴보니 동일한 정보를 보여주면서 조금씩 디자인이 다르게 여러 곳에서 사용되고 있었음
  • 해당 정보는 이미지와 텍스트로 구성되어 있었는데, 디자인을 아래와 같이 정리할 수 있었음
    • 이미지가 사각형인 경우, 원형인 경우
    • 이미지와 텍스트의 구조가 수평인 경우, 수직인 경우
  • 디자인에 따라 각각 컴포넌트를 만드는 것이 비효율적으로 보여서 한 컴포넌트에서 여러 디자인을 구현할 수 있도록 함

구현 과정

  • 각 디자인 경우에 따른 속성값 설정

    const streamerInfo = {
      Horizontal: {
        Circle: {
          Mobile: { img: 32, name: 16 },
          Desktop: { img: 64, name: 20 },
        },
        Square: {
          Mobile: { img: 54, name: 16 },
          Desktop: { img: 56, name: 24 },
        },
      },
      Vertical: {
        Circle: {
          Mobile: { img: 80, name: 12 },
          Desktop: { img: 104, name: 16 },
        },
        Square: {
          Mobile: { img: 80, name: 12 },
          Desktop: { img: 104, name: 16 },
        },
      },
    };
  • 이미지와 텍스트 구조가 수직/수평인지, 이미지 모양이 사각/원형인지, 사용자 접속 기기가 모바일/데스크톱인지에 따라 속성값을 다르게 적용하여 컴포넌트 구성함

    const StreamerInfoContainer = styled.div`
      display: flex;
      flex-direction: ${props => (props.direction === 'Vertical' ? 'column' : 'row')};
      row-gap: 8px;
      column-gap: 8px;
      width: max-content;
      align-items: ${props => (props.direction === 'Vertical' ? 'center' : 'unset')};
      @media screen and (min-width: 769px) {
        row-gap: 14px;
        column-gap: 14px;
      }
    `;
    const StreamerImageWrapper = styled.div`
      position: relative;
      width: ${props => `${streamerInfo[props.direction][props.shape].Mobile.img}px`};
      height: ${props => `${streamerInfo[props.direction][props.shape].Mobile.img}px`};
      @media screen and (min-width: 769px) {
        width: ${props => `${streamerInfo[props.direction][props.shape].Desktop.img}px`};
        height: ${props => `${streamerInfo[props.direction][props.shape].Desktop.img}px`};
      }
    `;
    
    const StreamerImage = styled(Image)`
      border-radius: ${props => (props.shape === 'Circle' ? '50%' : '8px')};
      @media screen and (min-width: 769px) {
        border-radius: ${props => (props.shape === 'Circle' ? '50%' : '16px')};
      }
    `;
    const StreamerInfoTextWrapper = styled.div`
      display: flex;
      flex-direction: column;
      justify-content: space-evenly;
      align-items: ${props => (props.direction === 'Vertical' ? 'center' : 'unset')};
    `;
    const StreamerName = styled.div`
      width: max-content;
      font-weight: 500;
      font-size: ${props => `${streamerInfo[props.direction][props.shape].Mobile.name}px`};
      @media screen and (min-width: 769px) {
        font-size: ${props => `${streamerInfo[props.direction][props.shape].Desktop.name}px`};
      }
    `;
    const StreamerClipNum = styled.div`
      display: ${props => (props.isClipNum ? 'block' : 'none')};
      font-size: 14px;
      font-weight: 400;
      color: ${Colors.gray[400]};
      @media screen and (min-width: 769px) {
        font-size: 18px;
      }
    `;
    • media query 사용하여 모바일의 경우 고려
  • 컴포넌트 props로 direction과 shape을 받은 후, 적절한 디자인 출력

    export const StreamerInfo = props => {
    const streamerInfoData = props.data;
      return (
        <Link passHref href={`/streamer/${streamerInfoData.streamerName}`}>
          <StreamerInfoContainer direction={props.direction}>
            <StreamerImageWrapper direction={props.direction} shape={props.shape}>
              <StreamerImage
                src={streamerInfoData.profileUrl}
                alt="streamerProfileUrl"
                layout="fill"
                shape={props.shape}
              />
            </StreamerImageWrapper>
            <StreamerInfoTextWrapper direction={props.direction}>
              <StreamerName direction={props.direction} shape={props.shape}>
                {streamerInfoData.streamerName}
              </StreamerName>
              <StreamerClipNum isClipNum={streamerInfoData.clipNum}>
                {streamerInfoData.clipNum}
              </StreamerClipNum>
            </StreamerInfoTextWrapper>
          </StreamerInfoContainer>
        </Link>
      );
    };
    • 이미지와 텍스트의 방향이 수직인지 수평인지를 props.direction 속성으로 받음
    • 이미지의 모양이 원인지, 사각형인지를 props.shape 속성으로 받음.

배우고 느낀 점

  • styled-components에서 props로 값을 받아서 스타일 적용하니까 편했음.
  • 더 나은 코드가 있을 수 있지만, 비교적 효율적인 코드가 작성된 것 같아서 좋았음.
  • 완벽한 코드를 작성하는 날까지 효율적인 코드, 클린 코드에 대해 앞으로도 계속 고민해야겠다.
profile
넓고 깊은 지식을 보유한 개발자를 꿈꾸고 있습니다:) 기억 혹은 공유하고 싶은 내용들을 기록하는 공간입니다

0개의 댓글