ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Styled-Components 사용하고 CSS 파일을 줄여보자
    Studying/React 2023. 5. 15. 17:54

    들어가기 전에...

    지금까지는 컴포넌트/페이지마다 css파일을 만든 뒤 클래스명으로 구분 지어서 관리 했었다. Header 컴포넌트의 class들은 전부 header-* 로 시작한다든지 그랬다. 그런데 이번에 코치님께서 그렇게 하면 돔이 많아졌을 때 너무 복잡해져 이슈가 발생해도 빠르게 처리가 불가능하다는 피드백을 받았다. 그래서 지금껏 피해온 Styled Components에 익숙해지고자 한다.

     

     

     

    Styled Components

    Styled Components에 대해 이해하기 위해서는 CSS in JS 개념에 대해 알아야 한다. 이는 말 그대로 CSS를 JS 파일 안에 작성하는 것이다. 대두되면서 탄생한 라이브러리이다. HTML+JS+CSS를 묶어서 하나의 JS파일에 넣은 뒤 컴포넌트 단위로 개발할 수 있게 만들어준다.

     

    styled-components는 이러한 라이브러리 중 가장 인기있다.

     

     

    설치하기

    # with npm
    $ npm install --save styled-components
    
    # 버전이 안 맞아서 에러가 날 경우 가장 최신 버전으로 설치
    $ npm install styled-components@latest
    
    # with yarn
    $ yarn add styled-components

     

    Styled Components는 pakage.json에 다음 코드를 추가하도록 권장한다.

    여러 버전의 Styled Components가 설치되어 발생하는 문제를 줄여준다.

     

    {
      "resolutions": {
        "styled-components": "^5"
      }
    }

     

     

    그리고 Styled Components를 사용할 파일에 아래와 같이 import하면 준비는 끝난다.

    import styled from "styled-components"

     

     

     

     

    기본 문법

     

    1. 컴포넌트 만들기

    아래 이미지와 같은 문법을 사용하여 컴포넌트를 정의할 수 있다.

     

    컴포넌트를 정의하는 법

     

    import styled from "styled-components";
    
    //Styled Components로 컴포넌트를 만든다.
    const BlueButton = styled.button`
      background-color: blue;
      color: white;
    `;
    
    export default function App() {
      // React 컴포넌트를 사용하듯이 사용하면 된다.
      return <BlueButton>Blue Button</BlueButton>;
    }

     

    Styled Component 또한 컴포넌트이기 때문에 첫글자를 무조건 대문자로 시작해야 한다

     

    템블릿 리터럴(`)안에 작성을 하느라 문자열처럼 표시 돼 자동완성도 안 되고 구분이 힘들 수 있는데,  vscode-styled-components 익스텐션을 설치하면 편리해진다.

     

     

    2. 컴포넌트를 재활용해서 새로운 컴포넌트 만들기

    아래 문법을 사용하면 속성이 비슷한 컴포넌트를 재활용 할 수 있다.

     

    컴포넌트 재활용 방법

     

     

    //만들어진 컴포넌트를 재활용한다.
    const BigBlueButton = styled(BlueButton)`
      padding: 10px;
      margin-top: 10px;
    `;
    
    //재활용한 컴포넌트를 재활용할 수도 있다.
    const BigRedButton = styled(BigBlueButton)`
      background-color: red;
    `;
    
    export default function App() {
      return (
        <>
          <BlueButton>Blue Button</BlueButton>
          <br />
          <BigBlueButton>Big Blue Button</BigBlueButton>
          <br />
          <BigRedButton>Big Red Button</BigRedButton>
        </>
      );
    }

     

    이렇게 사용하면 코드 중복을 줄여준다.

     

     

     

    3. Props 사용하기

    Styled Component로 만든 컴포넌트 또한 React Component처럼 props를 내려줄 수 있다.

     

    내려준 props 값에 따라서 컴포넌트를 조건부 렌더링하는 식으로 사용한다.

     

    styled-component에서 props를 사용하여 조건부 렌더링 하는 방법

     

    이렇게 props를 줄 수도, 안 줄 수도 있다.

     

    const Button1 = styled.button`
      background: ${(props) => (props.skyblue ? "skyblue" : "white")};
    `;
    
    export default function App() {
      return (
        <>
          <Button1>Button1</Button1>
          <Button1 skyblue>Button1</Button1>
        </>
      );
    }

     

    혹은 이렇게 활용하는 방법도 있다.

     

    const Button = styled.button`
    	background: ${(props)=> props.color ? props.color : "white"}
        /* background: ${(props) => props.color || "white"}; */
    `;
    
    <Button color="orange">Button1</Button>
    <Button color="tomato">Button2</Button>

     

     

     

    4. 전역 스타일 설정하기

    UI를 구현하기 전, margin:0, padding:0 같은 전역 스타일을 세팅하곤 한다. styled-components에서도 이러한 전역 스타일을 지원한다.

     

    우선 전역 스타일 설정을 위한 createGlobalStyle 함수를 불러온다.

    import { createGlobalStyle } from "styled-components";

     

    그리고 css파일에서 작성하는 것처럼 설정하고 시싶은 스타일을 작성한다.

    const GlobalStyle = createGlobalStyle`
        button {
            padding : 0;
            margin : 0;
        }
    `

     

    이렇게 만든 <GlobalStyle> 컴포넌트를 최상위에 사용해주면 전역에 Global 컴포넌트의 스타일이 적용된다.

    function App() {
    	return (
            <>
                <GlobalStyle />
                <Button>전역 스타일 적용하기</Button>
            </>
        );
    }

     

     

     

    5. 조건부 CSS 보여주기

    조건에 따라 CSS를 다르게 보여주고 싶다면 styled-components 라이브러리에서 css 를 사용하면 된다.

     

    import { css, styled } from 'styled-components';
    
    const Button = styled.button`
        width: 50px;
        background-color: white;
        ${(props) =>
        	props.isClicked ?
            css`
            	background-color: purple;
            `;
        }
    `;

     

    위 코드는 인자로 받은 props에 따른 background-color 조건부 렌더링을 구현한 모습이다.

     

     

     

    6. 자주 사용하는 css 따로 관리하기

    아까와 같이 css 를 사용하면 된다. 아래와 같이 자주 사용하는 CSS를 변수로 관리하면 코드 중복을 줄이는 데 용이하다.

    cosnt FlexCenter = css`
        display: flex;
        justify-content: center;
        align-items: center
    `;
    
    const Flexbox = div`
    	${FlexCenter}
    `;
    
    // 이렇게 인자를 주고 작성하면 가독성이 더 좋다
    const RingVariant = (radius, stroke = "10") => css`
        height: ${radius * 2}px;
        width: ${radius * 2}px;
        border: ${stroke}px solid black;
    `;

     

     

     

    7. CSS 셀렉터 사용하기

    styled-component 에서 셀렉터 사용은 다음과 같다. & 는 현재 요소를 뜻한다.

    // 컴포넌트 위에 마우스가 올라갈때
      &:hover {
        color: red;
      }
    
      // 바로 옆은 아니지만 형제요소일 때
      & ~ & {
        background: tomato;
      }
    
      // 현재 요소 바로 옆에 현재 요소가 붙어있을 때
      & + & {
        background: lime;
      }
      
      // 현재 요소가 something이라는 클래스를 갖고있을 때
      &.something {
        background: orange;
      }
      
      // something-else라는 클래스를 가진 부모안에 있을 때
      .something-else & {
        border: 1px solid;
      }

     

     

     

     

    Styled-Components로 Header 컴포넌트 만들기

    솔로 프로젝트 COZ Shopping의 헤더를 styled-components를 사용하여 구현해본다.

     

    Header 이미지

     

    위 목업을 보고 Header를 아래와 같이 분류할 수 있다.

     

    • Header Container 컴포넌트
    • Logo Wrapper 컴포넌트
    • Hamburger Button 컴포넌트
    • Hamburger Menu 컴포넌트

     

     

    Header Container 컴포넌트

    가장 먼저 Header의 본체가 되는 HeaderContainer를 작성한다.

    const HeaderContainer = styled.div`
            width: 100vw;
            height: 50px;
            padding: 0 60px;
            position: fixed;
            justify-content: space-between;
            align-items: center;
            border: 1px red solid;
            display: flex;
        `;

    불과 작년까지만 해도 헤더에서 왼쪽 자리를 차지하는 로고 이미지와 오른쪽 자리를 차지하는 메뉴 버튼을 float: left; float right; 으로 배치했는데, 이제는 flex를 활용하여 더 명확하게 영역을 구분짓는다.

     

     

    Logo Wrapper

    로고 이미지를 감싸줄 wrapper 컴포넌트를 정의한다.

    const LogoImageWrapper = styled.div`
        float: left;
        display: flex;
        gap: 10px;
        &:hover {
            cursor: pointer;
        }
    `;

     

    • &:hover { } : 해당 요소가 hover 되었을 때 CSS

     

     

    Logo 이미지

    const LogoImg = styled.img`
        height: 25px;
    `;

     

     

    Logo 옆 Title

    const LogoTitle = styled.div`
        font-weight: 600;
        font-size: 1.2rem;
    `;

     

     

    햄버거 메뉴 아이콘

    const MenuIcon = styled.img`
        height: 18px;
        &:hover {
            cursor: pointer;
        }
    `;

     

     

     

    최종 결과

    <HeaderContainer>
        <Link to="/">
            <LogoImageWrapper >
                <LogoImg src="./images/logo/로고.png"/>
                <LogoTitle>COZ Shopping</LogoTitle>
            </LogoImageWrapper>
        </Link>
        <MenuIcon src="./images/icons/hamburger.png"></MenuIcon>
    </HeaderContainer>

     

    근데 간단하게 연습용으로 작성해봤을 뿐이지만, CSS in JS 방식이 훨씬 깔끔하고 좋다는 걸 깨달았다. className을 짓느라 고생하던 시간이 사라져서 좋았고, 가장 좋은 건 엄청난 스크롤의 CSS 파일을 이리저리 돌아다니며 수정할 필요가 없다는 거다.

     

    그런데, 또 무조건적으로 CSS 파일은 쓰지 않고 Styled-Component만 사용하는 건 아니라고 한다. 뭐든 상황에 따라 최선의 방법을 찾을줄 알아야겠다.

     

     

     

     

    공식 문서

    더 자세하게 공부하고 싶다면 역시 공식 문서를 통해 실습하는 게 가장 좋다고 생각한다.

     

    styled-components

    CSS for the <Component> Age

    styled-components.com

     

Designed by Tistory.