개발자

styled-component을 사용할 때 많은 props는 어떻게 해결하시나요?

2023년 04월 19일조회 983

안녕하세요, 개인 프로젝트를 진행 중에 궁금한 점이 있어 현직의 선배님들께 여쭤보고 싶어 질문을 남깁니다! 현재 React 프로젝트에서 styled-components를 CSS-in-JS로 사용하고 있습니다. 하지만 styled-components를 사용하면서 많아지는 props로 인해 JSX의 복잡도가 높아지는 것 같아 고민이 생겼습니다. 개인 프로젝트에서 사용하고 있는 FlexContainer라는 Flex 스타일(정렬방향, 간격)을 적용하는 컴포넌트입니다. const FlexContainer = styled.div<FlexContainerProps>` display: flex; flex-direction: ${({ col }) => (col ? 'column' : 'row')}; gap: ${({ gap }) => gap && `${gap}rem`}; `; <FlexContainer> 컴포넌트를 '내부 컨텐츠 정렬'을 위해 확장한 <FlexContainerAlign>입니다. const FlexContainerAlign = styled( FlexContainer )<FlexContainerAlignProps>` justify-content: ${({ justifyContent }) => justifyContent}; align-items: ${({ alignItems }) => alignItems}; `; <FlexContainerAlign>을 확장하여 추가적인 style을 적용할 수 있는 <FlexContainerStyle>입니다. const FlexContainerStyle = styled( FlexContainerAlign )<FlexContainerStyleProps>` background-color: ${({ background }) => background && theme.colors.grey}; ${({ styles }) => styles && { ...styles }}; `; FlexContainerStyle 컴포넌트를 사용했을 때 아래처럼 많은 props로 인해 복잡해집니다. <FlexContainerStyle justifyContent="space-between" alignItems="center" background gap={1} styles={{ padding: '1rem 1.5rem', borderRadius: '0.5rem', }}></FlexContainerStyle> 혹시 styled-components를 실무에서 사용하실 때 많은 props를 깔끔하게 정리할 수 있는 팁이 있을까요?

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 3

인기 답변

조정민님의 프로필 사진

물론, 실제로 styled-component를 사용할 때 많은 소품을 깔끔하게 정리하기 위한 몇 가지 팁이 있습니다. 유틸리티 구성 요소를 사용하십시오. 유틸리티 구성요소는 공통 스타일 세트를 제공하는 구성요소입니다. 예를 들어 다음 스타일을 제공하는 플렉스 컨테이너용 유틸리티 구성 요소를 만들 수 있습니다. display: flex flex-direction: row gap: 1rem 테마를 사용하십시오. 테마는 구성 요소의 스타일을 지정하는 데 사용할 수 있는 미리 정의된 스타일 집합입니다. 예를 들어 다음 스타일을 포함하는 프로젝트의 테마를 만들 수 있습니다. primaryColor: blue secondaryColor: red textColor: black 디자인 시스템을 사용합니다. 디자인 시스템은 일관되고 사용자 친화적인 인터페이스를 구축하는 데 사용할 수 있는 재사용 가능한 구성 요소, 스타일 및 문서의 모음입니다. Material Design 및 Bootstrap과 같이 널리 사용되는 디자인 시스템이 많이 있습니다. 린터를 사용하십시오. Linter는 코드에서 오류를 찾아 수정하는 데 도움이 되는 도구입니다. 많은 linter에는 코드의 가독성과 유지 관리성을 개선하는 데 도움이 되는 규칙이 있습니다. 예를 들어 ESLint 린터에는 긴 코드 줄을 사용하지 않도록 도와주는 규칙이 있습니다. 일관된 명명 규칙을 사용하십시오. 일관된 명명 규칙을 사용하면 코드를 더 읽기 쉽고 유지 관리할 수 있습니다. 예를 들어 소품에 다음 명명 규칙을 사용할 수 있습니다. camelCase구성 요소에 전달되는 소품의 경우 kebab-case구성 요소의 스타일을 지정하는 데 사용되는 소품의 경우 주석을 사용하십시오. 주석은 코드가 수행하는 작업을 설명하는 데 도움이 될 수 있습니다. 예를 들어 특정 소품의 목적을 설명하는 주석을 추가할 수 있습니다. 코드를 더 작은 파일로 나눕니다. 큰 파일은 읽고 유지 관리하기 어려울 수 있습니다. 각 구성 요소 또는 관련 구성 요소 그룹에 대해 별도의 파일을 만들어 코드를 더 작은 파일로 나눌 수 있습니다. 코드 탐색 및 리팩터링 기능이 있는 코드 편집기를 사용합니다. 코드 탐색 및 리팩터링 기능이 있는 코드 편집기를 사용하면 코드를 보다 빠르고 쉽게 변경할 수 있습니다. 예를 들어 변수 또는 함수의 정의로 빠르게 이동할 수 있는 기능이 있는 코드 편집기를 사용할 수 있습니다. 디버거를 사용하십시오. 디버거는 코드를 한 줄씩 단계별로 실행하고 변수 값을 검사하는 데 도움이 될 수 있습니다. 이는 코드의 문제를 디버그하려고 할 때 유용할 수 있습니다. 라고 bard가 대답했습니다.

인기 답변

윤성연님의 프로필 사진

자주 사용되는 스타일 집합을 테마형태로 묶어서 사용하는 방법 정도가 유효하지 않을까 싶습니다. 예를 들면, display:flex, justify-content:center, align-items:center 같이 중앙정렬을 하기위해 자주 사용되는 스타일을 centerBox ( props ) 가 true 일때 사용되도록 테마형태로 축약표현을 할수 있을것 같습니다. 이렇게 되면 외부에서 주입하기 위한 스타일 값 (문자열형태로 내려주는 props) 를 좀더 줄일수 있겠네요. 스타일링을 외부에서 props 로 전달받아 커스텀 할수있는 범위가 넓을수록, 전달받는 props 도 많아 지고 손이 많이 가는것은 어찌보면 피할수 없는 일이 아닐까 싶습니다. 또한 필수적으로 받지 않아도 되는 값은 optional 하게 전달 받도록 설계해서 (ex: props 에 gap 값이 없어도 문제없도록 되도록 타입 지정) 필요하지 않은 css 는 굳이 props를 내려주지 않아도 되도록 해주면 될것 같아요. 단순히 스타일링용 props 만 좀 줄여서 표현하고 싶으시다면, 2번 코드처럼 spread 해서 쓸수도 있긴 합니다. 하지만 저는 별로 좋아하지 않는 표현 방식입니다.. 나중에 어떤 props 를 전달하고 있는지 추적하기가 어려워져서 수정이나 디버깅에 불편함이 많습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 1. 테마형태로 사용하는 예시

const Style = styled.div<{centerBox : boolean}>`
  ...
  ${(props) => {
    if (props.centerBox === true) {
      return "display:flex; justify-content:center; align-items:center;";
    }

      return "";
  }}
`

// 2. 스타일링 props 를 spread
// props 에 대한 타입은 임의로 지정했습니다.
// props 로 내려줄 스타일링 객체가 정적이라면 컴포넌트 내에 객체 리터럴을 만들 필요는 없습니다.
// styled 내부에 state 값을 props 로 넘겨 처리해도 상관없습니다.

const TempComponent = () => {
  const [isClick, setIsClick] = useState(false);

  const props : FlexContainerStyledPropsType = {
      display: "flex",
      justifyContent: "center",
      alignItems: "center",
      backgroundColor : isClick ? "#ccc" : "#fff"
  }

  return <FlexContainerStyle onClick={()=>{setIsClick((state) => !state)}} {...props} />
}
커리어리 AI 봇님의 프로필 사진

styled-components를 사용하다보면 props가 많아져서 코드의 가독성이 떨어질 수 있습니다. 이를 해결하기 위해 다음과 같은 팁들을 사용할 수 있습니다. 1. 재사용 가능한 스타일 함수 생성 재사용 가능한 스타일 함수를 생성하면 props를 중복해서 작성하지 않아도 되므로 가독성을 높일 수 있습니다. 예를 들어, 위에서 작성한 FlexContainerAlign와 FlexContainerStyle 컴포넌트는 동일한 속성을 가지고 있습니다. 이럴 때는 재사용 가능한 스타일 함수를 만들어 사용하는 것이 좋습니다. 아래 코드에서 flexContainerStyles 함수는 FlexContainer, FlexContainerAlign, FlexContainerStyle에서 공통으로 사용되는 속성을 모아놓은 것입니다. 2. Props를 객체로 전달하기 styled-components에서는 props를 객체 형태로 전달할 수 있습니다. 이를 활용하면 props의 개수를 줄일 수 있습니다. 예를 들어, FlexContainerStyle 컴포넌트에서 justifyContent, alignItems, background, gap, styles를 객체로 묶어 전달할 수 있습니다. 이렇게 작성하면 props의 개수를 줄이고, 가독성을 높일 수 있습니다. 3. 컴포넌트를 분리하기 속성이 많은 컴포넌트를 여러 개의 컴포넌트로 분리해서 사용할 수도 있습니다. 예를 들어, FlexContainer 컴포넌트에서 gap 속성을 제거하고, Gap 컴포넌트를 따로 만들어 사용하는 것입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#1
const flexContainerStyles = css`
  display: flex;
  flex-direction: ${({ col }) => (col ? 'column' : 'row')};
  gap: ${({ gap }) => gap && `${gap}rem`};
`;

const FlexContainer = styled.div<FlexContainerProps>`
  ${flexContainerStyles};
`;

const FlexContainerAlign = styled(FlexContainer)<FlexContainerAlignProps>`
  justify-content: ${({ justifyContent }) => justifyContent};
  align-items: ${({ alignItems }) => alignItems};
`;

const FlexContainerStyle = styled(FlexContainerAlign)<FlexContainerStyleProps>`
  background-color: ${({ background }) => background && theme.colors.grey};
  ${({ styles }) => styles && { ...styles }};
`;


#2
const FlexContainerStyle = styled(FlexContainerAlign)<FlexContainerStyleProps>`
  ${({ flexContainerStyle }) => ({
    backgroundColor: flexContainerStyle?.background && theme.colors.grey,
    gap: flexContainerStyle?.gap && `${flexContainerStyle.gap}rem`,
    justifyContent: flexContainerStyle?.justifyContent,
    alignItems: flexContainerStyle?.alignItems,
    ...flexContainerStyle?.styles,
  })}
`;

#3
const Gap = styled.div<GapProps>`
  ${({ gap }) => gap && `margin: ${gap}rem`};
`;

const FlexContainer = styled.div<FlexContainerProps>`
  display: flex;
  flex-direction: ${({ col }) => (col ? 'column' : 'row')};
`;

const FlexContainerAlign = styled(FlexContainer)<FlexContainerAlignProps>`
  justify

커리어리 AI 봇의 답변을 평가해 주세요!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

비슷한 질문 1

Q. React에서 props를 무조건 줄이는게 옳을까요?

안녕하세요 React를 기반으로 프로젝트 진행중인 개발자입니다. 리팩토링 작업중 컴포넌트 사이에 예를들어 const {type} = router.query 와 같이 선언으로 가져올수있는부분이나 react-query의 useQuery를 이용해서 가져올수있는 데이터같은경우 각 컴포넌트마다 선언해서 사용하는게 옳은것인지, 부모측에서 선언해서 props로 내려주는게 옳은것인지 궁금한데 직장에 사수가 없어 질문할 곳이 없어 이곳에 질문 남깁니다... 답변부탁드립니다 !

다른 개발자 분들의 의견이 궁금해지는 질문이네요 : ) 제가 이해한 바로는 "props로 자식 컴포넌트에게 react query 응답 데이터를 전달해야할까?" 의 질문으로 이해했습니다. 저의 경우에는 개발시에 데이터를 호출 및 가공처리를 담당하는 컴포넌트와 UI만을 담당하는 컴포넌트를 구분해서 개발하는편입니다. 그 이유는, 대부분의 버그나 이슈는 예측하기 어려운 곳에서 나타나는데요, 데이터를 Api를 이용해 호출해오거나 그 결과를 가공하는 과정이 대부분 해당이 된다고 생각해서에요. 그래서 react query를 쓰더라도 무조건적으로 데이터를 한곳에서 호출 후 자식에게 내려준다는 개념보다는 특정 기능을 하는 페이지를 개발할때 해당 페이지가 어떠한 비즈니스 기능들을 갖고 있는지 구분하고 각 비즈니스별로 Container 라는 컴포넌트를 만들어 해당 파일에서 필요한 데이터를 호출 및 관리하고 있습니다. 공통된 데이터 호출일지라도 react query가 캐싱된 데이터를 가져다가 사용해주기 때문에 중복호출 처리에 대해서는 react query를 믿고 그 역할을 위임하는 편입니다. 이후 각 비즈니스별로 필요한 UI들을 자식컴포넌트로 만들고 각 UI컴포넌트에서 필요로 하는 데이터를 Container에서 내려주고 UI 컴포넌트들은 데이터만 받아서 화면을 구성하도록 개발하고 있습니다. 질문에 대한 답변이 되셨을지 잘 모르겠네요 😅

외 2개 답변 보러 가기

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!