Style코드 관리 방법들

이수빈·2023년 2월 10일
2
post-thumbnail

Style코드들을 어떻게 효율적으로 관리 할 수 있을까?


SW 엘리스 2차 프로젝트에서 Style 코드에 관해 고민했던 지점들


ThemeProvider를 통한 공통 스타일 관리

  • 프로젝트에서는 빠른 개발을 위해 MUI와 Styled-Component를 함께 사용하여 컴포넌트 단위로 Style을 설계하였다.
  • 디자이너가 없는 프로젝트였기 때문에 기본적인 디자인은 Material UI를 사용하였다.
  • 유지보수가 쉽고 공통된 Style을 관리하기 위해 공용 theme을 정의해 Style을 관리하였다.
  • TS에서 공용 테마를 사용하려면 타입선언파일(styled.d.ts)을 통해 모듈을 내보낸 후 공용 theme을 정의해야한다.
  • 타입선언파일은 TS가 style코드 Type을 추론하는것을 도와준다. 타입선안파일이 없다면 any type으로 자동완성이 지원되지 않는다.

styled.d.ts

import 'styled-components';

declare module 'styled-components' {
 export interface DefaultTheme {
   fontSize: {
     title: string;
     subTitle: string;
     small: string;
   };
   
   colors: {
     main: string;
     emphasis: string;
     cancel: string;
     button: string;
     sub: string;
     background: string;
     innerContainer: string;
     container: string;
     gray: string;
     lightGray: string;
   };
   
   font: {
     color: {
       black: string;
       darkGray: string;
       white: string;
       description: string;
       subTitle: string;
     };
     
     size: {
       normal: string;
       containerTitle: string;
     };
   };
 }
}

모듈을 바탕으로 theme의 프로퍼티들을 정의한다.

import { DefaultTheme } from 'styled-components';

const theme: DefaultTheme = {
  fontSize: {
    title: '18px',
    subTitle: '14px',
    small: '10px',
  },
  colors: {
    main: '#E59A59',
    emphasis: '#712E1E',
    cancel: '#A82A1E',
    button: '#E59A59',
    sub: '#FFD5AF',
    background: '#FFFAF5',
    innerContainer: '#f7f7f7',
    container: '#FCF3EB',
    gray: '#888870',
    lightGray: '#C9CACC',
  },
  font: {
    color: {
      black: '#1E1F21',
      darkGray: '#303030',
      white: '#ffffff',
      description: '#5e5f61',
      subTitle: '#424140',
    },
    size: {
      normal: '14px',
      containerTitle: '18px',
    },
  },
};
export default theme;
  • App을 ThemeProvider로 감싸게되면 컴포넌트들은 theme속성에 Provider 안에서 접근 할 수있다.
  • 이런 방식으로 여러가지 theme을 정의해 style의 확장과 유지보수를 용이하게 할 수 있다.
  • prop의 theme객체에서 정의해놓은 프로퍼티에 접근 할 수 있다.
color: ${({ theme }) => theme.colors.main};

Styled-component와 MUI를 통한 컴포넌트 확장

  • 컴포넌트 형태로 스타일을 재사용하기 위해 Styled-component의 확장기능을 이용하였다.
  • 공용으로 사용하는 컴포넌트를 정의해놓고 필요한 곳에서 import하여 이를 확장하는 식으로 중복되는 스타일을 제거하였다.
  • prop으로 필요한 값들을 넘겨주어 재사용이 가능한 컴포넌트를 설계하였다.
export const FlexContainer = styled.div`
  display: flex;
  align-items: center;
  justify-content: space-around;
`; // 공용 FlexContainer

export const ContentContainer = styled(FlexContainer)`
  flex-direction: column;
  width: 60vw;
  justify-content: flex-start;
  margin-bottom: 70px;
`; // 컴포넌트 확장

type MenuCardProps = {
  width: string;
  padding?: string;
  margin?: string;
  flex?: string;
};

export const MenuCard = styled(Card)<MenuCardProps>`
  width: ${(props) => props.width};
  padding: ${(props) => props.padding};
  margin: ${(props) => props.margin};
  font-size: ${({ theme }) => theme.fontSize.subTitle};
  flex: ${(props) => props.flex};
  p {
    margin-bottom: 20px;
  }
`; //재사용가능한 컴포넌트 정의

S.dot Naming방식

  • 스타일코드가 많아지면 페이지 내에 스타일 관련 코드들이 많아져 가독성이 떨어지는 문제가 있었다.
  • style코드를 따로 분리한 후 S.dot Naming 방식을 통해 필요한 페이지에서 import하는 방식으로 스타일을 사용하였다.
  • content라는 page가 있으면 contentStyle.ts라는 파일에 필요한 style들을 분리한다.
  • 스타일 코드를 분리했기 때문에 재사용성이 높아지고, page에서 간결하게 로직을 볼 수 있다는 장점이 있다.
  • 사용하는 쪽에서는 S.Style이름을 통해 컴포넌트 형태로 사용한다.
//Content.tsx

import * as S from '../styles/contentStyle'; // style코드를 import

    return (
    <S.ContentContainer>
      <S.TitleContainer>
        <S.Title>
          {shop.name}({shop.category})
        </S.Title>
        {!gathering && !isJoined && (
          <S.LikeButton
            variant="contained"
            onClick={handleClick}
            sx={{
              fontSize: '20px',
              marginRight: '30px',
            }}>{`모임 생성`}</S.LikeButton>
        )}
        {gathering && !isJoined && (
          <S.LikeButton
            variant="contained"
            onClick={() => clickJoinButton(currentParty?.partyId as number)}
            sx={{
              fontSize: '20px',
              marginRight: '30px',
            }}>{`모임 참여`}</S.LikeButton>
        )}
        {isJoined && <p>참여중</p>}
      </S.TitleContainer>

      <S.MenuContainer>
        <S.MenuCard width={'20vw'} padding="20px" margin="20px" flex="2">
          <p className="description">{shop.description}</p>
          <p>{`거리 : 걸어서 ${shop.distance}분 거리`}</p>
          <S.ATag href={`${BASE_URL}${shop.address}`} target="_blank" rel="noreferrer">
            지도 보기
          </S.ATag>
        </S.MenuCard>
        <S.SelectContainer>
          <SelectTags type={'모집인원'} value={partyLimit} setValue={setpartyLimit} />
        </S.SelectContainer>
      </S.MenuContainer>
    </S.ContentContainer>
  );

ref)

profile
응애 나 애기 개발자

0개의 댓글