처음 만난 리액트 문서


15.2 styled-components

styled-components는 CSS 문법을 그대로 사용하면서 결과물을 스타일링 된(styled) 컴포넌트(component) 형태로 만들어주는 오픈소스 라이브러리입니다. 특히 컴포넌트 개념을 사용하기 때문에 리액트와 굉장히 궁합이 잘 맞으며, 전세계적으로 리액트 개발에 굉장히 많이 사용되고 있습니다. 마지막 장에서 미니 프로젝트를 진행할 때 styled-components를 사용할 예정이기 때문에 간단하게 배우고 넘어가도록 하겠습니다.

15.2.1 styled-components 설치하기

먼저 styled-components를 사용하기 위해서는 프로젝트에 설치를 해줘야 합니다. 아래 명령어를 통해서 최신 버전의 styled-components를 설치할 수 있습니다.

# npm을 사용하는 경우
npm install styled-components

# yarn을 사용하는 경우
yarn add styled-components

설치가 끝났다면 리액트 프로젝트에서 아래처럼 MainPage라는 이름의 간단한 컴포넌트를 하나 만들어서 실제로 styled-components가 잘 돌아가는지 확인해볼 수 있습니다.

import styled from 'styled-components';

const Wrapper = styled.div`
    padding: 1em;
    background: grey;
`;

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

function MainPage(props) {
    return (
        <Wrapper>
            <Title>
                안녕, 리액트!
            </Title>
        </Wrapper>
    )
}

export default MainPage;

스타일이 잘 적용되었다면, 회색 배경에 흰색 글씨로 "안녕, 리액트!" 라는 문자열이 잘 출력되는 것을 볼 수 있을 것입니다.

15.2.2 styled-components 기본 사용법

styled-componentstagged template literal을 사용하여 구성 요소의 스타일을 지정합니다. 여기서 template literal이라는 것이 등장하는데, template literal은 자바스크립트에서 제공하는 문법중 하나입니다. template literal에 대해 설명하기 전에 먼저 literal에 대해서 알아야 하는데, 프로그래밍에서 리터럴(literal)은 소스 코드의 고정된 값을 의미합니다. 흔히 상수(constant)와 헷갈려 하는데 둘은 다른 개념입니다. 아래 그림을 한 번 보도록 하겠습니다.

Literals

위 그림을 보면 대입 연산자(=)의 왼쪽에는 number라는 이름의 변수(variable)가 등장하고, 오른쪽에는 정수 20이 등장합니다. 여기에서 오른쪽에 있는 정수 20이 바로 리터럴입니다. 소스 코드 상에 있는 고정된 값을 의미하는 것이죠. 다른 예시 코드를 살펴보도록 하겠습니다.

// 정수 리터럴 (Integer literal)
const myNumber = 10;

// 문자열 리터럴 (String literal)
const myStr = 'Hello';

// 배열 리터럴 (Array literal)
const myArray = [];

// 객체 리터럴 (Object literal)
const myObject = {};

위 코드에는 여러가지 종류의 리터럴들이 나와 있습니다. 또한 변수를 선언할 때 varlet을 사용하지 않고, 상수를 의미하는 const를 사용했는데, 이렇게 선언하게 되면 해당 변수들이 모두 상수(constant)가 됩니다. 상수는 변하지 않는 수를 의미합니다. 한 번 선언된 이후에는 값을 바꿀 수 없는 것이죠. 그리고 대입 연산자(=)의 오른쪽에 있는 값들이 모두 리터럴이 됩니다.

그렇다면 템플릿 리터럴(template literal)은 무엇일까요? 템플릿 리터럴은 말 그대로 리터럴(literal)을 템플릿(template) 형태로 사용하는 자바스크립트의 문법인데, backticks(`)를 사용하여 문자열을 작성하고 그 안에 대체 가능한 expression들을 넣는 방법입니다. 여기서 이 expression들을 **대체**라는 뜻을 가진 substitution이라고 부릅니다. 템플릿 리터럴은 또 크게 Untagged template literalTagged template literal로 나뉩니다. 아래 예시 코드를 한 번 보도록 하겠습니다.

// Untagged template literal
// 단순한 문자열
`string text`

// 여러줄(Multi-line)에 걸친 문자열
`string text line 1
 string text line 2`

// 대체 가능한 expression이 들어있는 문자열
`string text ${expression} string text`


// Tagged template literal
// myFunction의 파라미터로 expression으로 구분된 문자열 배열과 expression이 순서대로 들어간 형태로 호출됨
myFunction`string text ${expression} string text`;

위 코드에 나온 것처럼 Untagged template literal은 보통 문자열을 여러줄에 걸쳐서 작성하거나, 포맷팅(formatting)을 하기 위해서 사용합니다. 그리고 Tagged template literal은 앞에 나와있는 tag function이라고 부르는 함수를 호출하여 결과를 리턴합니다. 여기서 tag function의 파라미터로는 expression으로 구분된 문자열 배열과 expression이 순서대로 들어가게 됩니다. 조금 더 쉬운 이해를 위해서 아래 예시 코드를 보도록 하겠습니다.

const name = '인제';
const region = '서울';

function myTagFunction(strings, nameExp, regionExp) {
    let str0 = strings[0];  // "제 이름은  "
    let str1 = strings[1];  // "이고, 사는 곳은 "
    let str2 = strings[2];  // "입니다."

    // 여기에서도 template literal을 사용하여 리턴할 수 있음
    return `${str0}${nameExp}${str1}${regionExp}${str2}`;
}

const output = myTagFunction`제 이름은 ${name}이고, 사는 곳은 ${region}입니다.`;

// 출력결과
// 제 이름은 인제이고, 사는 곳은 서울입니다.
console.log(output);

위 코드는 Tagged template literal을 사용한 예시입니다. tag function에 파라미터가 어떻게 들어가는지 한 눈에 파악이 되죠? 이처럼 Tagged template literal을 사용하면 문자열과 expression들을 tag function에 파라미터로 넣어 호출한 결과를 받게 됩니다. 더 자세한 내용이 궁금하면 아래 링크를 참고하세요.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals

styled-componentstagged template literal을 사용하여 CSS 속성이 적용된 리액트 컴포넌트를 만들어 줍니다. styled-components를 사용하는 기본적인 방법은 아래와 같이 backticks(`)로 둘러싸인 문자열 부분에 CSS 속성들을 넣고, tag function 위치에는 styled.<HTML태그>형태로 사용합니다. 그렇게 하면 해당 HTML 태그에 CSS 속성들이 적용된 형태의 리액트 컴포넌트가 만들어집니다.

import styled from 'styled-components';

const Wrapper = styled.div`
    padding: 1em;
    background: grey;
`;

15.2.3 styled-componentsprops 사용하기

styled-components에서는 조건이나 동적으로 변하는 값을 사용해서 스타일링 할 수는 없을까요? 물론 가능합니다. 그리고 그걸 위해서 제공하는 기능이 바로 props입니다. 리액트 컴포넌트의 props와 같은 개념으로 이해하면 되는데, 아래에서 실제 예시 코드를 한 번 볼까요?

import styled from 'styled-components';

const Button = styled.button`
    color: ${props => props.dark ? "white" : "dark"};
    background: ${props => props.dark ? "black" : "white"};
    border: 1px solid black;
`;

function Sample(props) {
    return (
        <div>
            <Button>Normal</Button>
            <Button dark>Dark</Button>
        </div>
    )
}

export default Sample;

위 코드에서는 Button이라는 컴포넌트가 등장하는데, 이 컴포넌트는 styled-components를 사용해서 만들어진 것입니다. 그리고 styled-components를 사용하는 부분의 CSS 속성들을 보면 내부에 props가 사용된 것을 볼 수 있습니다. 여기서의 props는 해당 컴포넌트에 사용된 props를 의미합니다. 그래서 실제 Button컴포넌트를 사용하는 부분의 코드를 보면, <Button dark>Dark</Button>처럼 propsdark를 넣어주는 것을 볼 수 있습니다. 그리고 이렇게 들어간 props는 그대로 styled-components로 전달됩니다. 이 기능을 사용하면 다양한 스타일들을 styled-components를 사용해서 자유자재로 구현해낼 수 있습니다.

15.2.4 styled-components의 style 확장하기

앞에서 styled-components를 사용하면 리액트 컴포넌트가 생성된다고 설명했습니다. 그렇다면 이렇게 생성된 컴포넌트를 기반으로 추가적인 스타일을 적용하고 싶을 경우에는 어떻게 해야 할까요? styled-components에서는 이를 위해서 스타일 확장 기능을 제공합니다. 아래 예시 코드를 한 번 보도록 하겠습니다.

import styled from 'styled-components';

// Button컴포넌트
const Button = styled.button`
    color: grey;
    border: 2px solid palevioletred;
`;

// Button에 style이 추가된 RoundedButton컴포넌트
const RoundedButton = styled(Button)`
    border-radius: 16px;
`;

function Sample(props) {
    return (
        <div>
            <Button>Normal</Button>
            <RoundedButton>Rounded</RoundedButton>
        </div>
    )
}

export default Sample;

위 코드를 보면 Button컴포넌트와 RoundedButton컴포넌트가 나옵니다. 먼저 Button컴포넌트는 HTML의 button태그를 기반으로 만들어진 단순한 버튼입니다. 그런데 RoundedButton컴포넌트를 만드는 부분을 자세히 보면 HTML태그가 빠져있고, Button컴포넌트가 괄호로 둘러싸인채로 들어가 있는 것을 볼 수 있습니다. 이 부분이 바로 다른 컴포넌트의 스타일을 확장해서 사용하도록 하는 부분입니다. RoundedButton컴포넌트는 Button컴포넌트에서 모서리를 둥글게 만든 컴포넌트입니다.

더 다양한 형태로 스타일을 확장할 수 있지만, 이 문서에서는 기본적인 내용만을 다뤘습니다. 그리고 이 문서에서 다루지 않은 styled-components의 기능들이 굉장히 많기 때문에, 관심이 있는 분들은 아래 공식 문서를 통해서 학습하길 바랍니다.

https://styled-components.com/docs


마지막 업데이트: 2025년 08월 21일 09시 05분

이 문서의 저작권은 이인제(소플)에 있습니다. 무단 전재와 무단 복제를 금합니다.

On this page