Styled-components 사용해보기

박요진·2023년 10월 11일
0

Styled-components

1. Styled-components 사용 이유

장점

  • 화면에 컴포넌트가 렌더링 되었는지 추적하여 컴포넌트에 대한 스타일을 자동으로 삽입하여 줍니다. 코드를 적절히 분배해 놓으면 최소한의 코드만으로 화면이 띄워질 수 있습니다.

  • 스타일에 대한 고유한 클래스 이름을 생성합니다. 중복 또는 철자 오류에 대해 걱정할 필요가 없습니다.

  • 코드베이스 어딘가에서 클래스 이름이 사용되는지에 대한 여부를 알기 어려울 수 있습니다. 하지만 styled-components를 사용하면 모든 스타일링이 특정 구성 요소에 연결되어 있으므로 이를 명확하게 알 수 있고, 구성 요소가 사용되지 않아 삭제를 하면 모든 스타일도 함께 삭제 됩니다.

  • 수십 개의 클래스를 수동으로 관리할 필요 없이 전역 테마를 기반으로 구성 요소의 스타일을 조정할 수 있습니다.

  • 구성 요소에 영향을 미치는 스타일을 찾기 위해서 여러 파일을 검색할 필요가 없고 코드 베이스가 아무리 크더라도 유지관리가 쉽습니다.

  • 개별 컴포넌트마다 기존의 CSS를 이용하여 스타일 속성을 정의하면 됩니다. 이외의 것들은 Styled-Components가 알아서 처리해줍니다.

단점

  • CSS-IN-JS 방식으로 컴포넌트가 렌더링 될 때만 해당 스타일 정보를 읽습니다.

  • 동적인 이벤트가 많은 사이트라면 컴포넌트가 자주 렌더링 될 때 그만큼 스타일 정보도 다시 읽어와야 합니다. CSS-IN-CSS는 이미 HTML 문서에 읽혀져 있는 상태이기 때문에 처음에는 스타일 정보를 가져오는 양이 많더라도 그 후 추가적인 렌더링은 상대적으로 styled-component보다 적습니다.

2. Styled-Components 설치하기

npm i styled-component

3. Styled-Components 적용

3-1. import

import styled from 'styled-components';

먼저 styled-components 를 사용하기 위해서 사용할 페이지 상단에 import 해줍니다.

3-2. 컴포넌트 만들기

const Title = styled.h1`
 font-size: 1.5em;
 text-align: conter;
 color: red;
`;

const Wrapper - styled.section`
	padding : 4em;
    background : white;
`;


render(
<Wrapper>
	<Title>
    Hello World!
    </Title>
</Wrapper>
);

3-3. 응용하기

3-3-1. 조건부 스타일링하기 (with props)

const Button = styled.button`
	background : ${props => props.primary ? "black" : "white"};
    color : ${props => props.primary ? "white" : "black"}
`;

render(
	<div>
    	<Button>Normal</Button>
        <Button primary>Primary</Button>
    </div>
);
  • 같은 button 태그를 가진 element 중 background를 변경해야할 때 어떻게 할 수 있을까요? 같은 태그를 가진 styled-component를 하나 더 추가로 만들어서 사용하는 방법도 있지만 그렇게 하게되면 새로운 색이 필요할 때마다 새로운 컴포넌트를 생성해야하는 불필요한 행위를 계속 해야합니다. 이런 불필요한 작업을 피하기 위해 우리는 styled-component의 props를 잘 사용해야 합니다.

잘못된 사용의 예시

const button = styled.button`
	background : red;
`;

const button2 = styled.button`
	background : blue;
`;

function App() => {
	return (
    	<section>
        	<button>버튼1</button>
            <button2>버튼2</button2>
        </section>
    )
}
  • 위의 사례는 잘못된 사용의 예시를 보여드렸습니다. background의 속성값만 변경되었을 뿐인데 이름만 다른 styled-component를 하나 더 생성했기 떄문입니다. 이 것은 좋지 않은 접근입니다. 위의 상황을 좋은 방향으로 사용하기 위해서는 props를 사용하는 방법이 있습니다.

좋은 방식의 사용 예시

const button = styled.button`
	background : ${props => props.background};
`;

function App() => {
	return (
    	<section>
        	<button background="red">버튼1</button>
            <button background="blue">버튼2</button>
        </section>
    )
}
  • 위와 같이 사용하면 불필요한 styled-component의 생성을 제한할 수 있습니다. 하지만 여기서 또 의문이 들 수 있습니다. 만약 위와 같이 사용하면 같은 background가 여러번 사용되는 경우 그 값을 디폴트 값으로 정하고 사용할 수는 없을까? 그건 아래와 같이 코드를 작성하면 됩니다.
const button = styled.button`
	background : ${props => props.background || "red"};
`;

function App() => {
	return (
    	<section>
        	<button>버튼1</button>
            <button background="blue">버튼2</button>
        </section>
    )
}
  • 이제는 props를 사용했냐 안했냐를 통해서 색을 정할 수 있습니다. 만약 태그에 props를 주지 않을 경우 background를 red 로 주고, 다른 색을 background 색으로 바꾸고 싶을 때는 태그에 props를 주면 준 색으로 색이 바뀌게 됩니다.

3-3-2. styled-component.attrs

  • 만약 작업 도중에 동일한 속성을 주어야할 때는 어떻게 하면 될까요? 원래는 아래와 같이 하나하나의 태그에 같은 값을 지정해주어야 할 것입니다.
const MainImage = styled.img`
    width: 100px;
    height: 100px;
`

function ProductItem() {
	return (
    	<MainContainer>
            <MainImage src='https://*****' alt='제품 이미지' />
            <MainImage src='https://*****2' alt='제품 이미지' />
            <MainImage src='https://*****3' alt='제품 이미지' />
        </MainContainer>
    )
}
  • 위의 코드를 보시면 이미지 태그에 공통적으로 alt에 "제품 이미지" 라는 값이 들어가는 것을 볼 수 있습니다. 우리는 이 것을 styled-component의 attrs를 이용하면 더욱 쉽게 해결할 수 있습니다.
const MainImage = styled.img`
    width: 100px;
    height: 100px;
`

function ProductItem({alt="제품이미지"}) {
	return (
    	<MainContainer>
            <MainImage src='https://*****' />
            <MainImage src='https://*****2' />
            <MainImage src='https://*****3' />
        </MainContainer>
    )
}
  • 기본 속성 alt를 styled-component에서 선언해주면 자동으로 MainImage를 사용하는 컴포넌트들에게 같은 속성값을 부여할 수 있습니다.

3-3-3. styled-component 확장하여 사용하기.

  • 내가 button에 대한 새로운 스타일링을 하기위해 새롭게 컴포넌트를 만들려고 하는데 만들어두었던 스타일 컴포넌트의 내용을 대부분 가져와야하는 경우가 있을 수 있습니다. 기존에 생성했었던 속성들에 border만 추가 된다거나 border-radius 만 추가된다거나 하는 일 말입니다.

  • 이 때, 그 전의 컴포넌트의 요소를 참조하는 확장된 컴포넌트를 만들 수 있는 방법이 있습니다.

const Button = styled.button`
	width: 100px;
    height : 100px;
`;

function App() => {
	return (
    	<section>
        	<Button>버튼1</Button>
        </section>
    )
}
  • Button이라는 컴포넌트가 있습니다. 이제 여기에 border라는 속성을 추가하고 싶을 때 BorderButton 이라는 컴포넌트를 하나 더 만들어 CSS 속성값을 복사/붙여넣기를 하는 방법도 물론 있지만 같은 CSS를 공유한다면 button을 확장하여 사용할 수 있습니다.
const Button = styled.button`
	width: 100px;
    height : 100px;
`;

const BorderButton = styled(Button)`
	border: 1px solid #fff;
`

function App() => {
	return (
    	<section>
        	<Button>버튼1</Button>
        </section>
    )
}
  • 위와 같은 방식으로 코드를 작성한다면 Button 컴포넌트를 확장한 BorderButton 컴포넌트를 만들 수 있습니다.

3-3-4. 유용한 선택자

  • styled-component들이 자식 요소와 부모요소로 섞여 있는 상황에서 CSS에서는 이 것을 스코프 안에 선택자 스코프로 처리를 합니다. styled-component는 자식 요소에 대한 select를 할 수 있는 방법이 있습니다.
const MainContainer = styled.section`
    display:flex;
    width:100vw;
`

const Memo = styled.div`
    width:300px;
    height:500px;
`

const ShadowMemo = styled(Memo)`
    box-shadow: 2px 4px 8px;
`

funtion Section2 () {
  return(
    <>
    <MainContainer>
      <Memo>Lorem Ipsum</Memo>
      <ShadowMemo>Lorem Ipsum</ShadowMemo>
    </MainContainer>
      <Memo>Lorem Ipsum</Memo>
    </>
  )
}
  • 다음과 같은 예시가 있습니다. 위의 코드에서 MainContainer 컴포넌트 안에 있는 Memo 컴포넌트만 background-color를 black으로 바꾸고 color를 white로 바꾸고 싶을 수 있습니다. 이 때 MainContainer의 하위요소인 Memo만을 선택해서 스타일을 줄 수 있습니다.
const Memo = styled.div`
    width:300px;
    height:500px;
`

const MainContainer = styled.section`
    display:flex;
    width:100vw;
    ${Memo} {
      background-color:black;
      color: white;
    }
`

const ShadowMemo = styled(Memo)`
    box-shadow: 2px 4px 8px;
`

funtion Section2 () {
  return(
    <>
    <MainContainer>
      <Memo>Lorem Ipsum</Memo>
      <ShadowMemo>Lorem Ipsum</ShadowMemo>
    </MainContainer>
      <Memo>Lorem Ipsum</Memo>
    </>
  )
}
  • MainContainer 컴포넌트에서 ${ } 를 사용하여 select하고, MainContainer의 하위 요소의 Memo에만 스타일을 부가할 수 있습니다.
profile
프론트엔드 개발자 지망생입니다.

0개의 댓글