안동민 개발노트

안동민 개발노트

CSS 모듈 활용Sass 통합CSS-in-JS 솔루션Tailwind CSS 설정 및 사용
본문 시작
  1. 홈
  2. 문서
  3. Next.js
  4. 9장 : 스타일링과 CSS
  5. Sass 통합
  1. Next.js
  2. Sass 통합

Sass 통합

Next.js에 Sass를 설치하고 변수·중첩·모듈화를 활용한 SCSS 모듈로 컴포넌트 스타일을 체계화합니다.

이전 절에서 Next.js의 CSS 모듈을 사용하여 컴포넌트 레벨의 스타일링을 안전하고 효율적으로 관리하는 방법을 살펴보았습니다.

CSS 모듈만으로도 충분히 강력하지만, CSS 전처리기(Pre-processor)인 Sass (Syntactically Awesome Style Sheets)는 CSS의 한계를 넘어서는 기능을 제공해 스타일링 작업을 더욱 효율적이고 체계적으로 만들어 줍니다.

Next.js는 Sass와의 통합을 기본적으로 지원하며, .scss 또는 .sass 확장자를 가진 파일을 CSS 모듈과 함께 사용할 수 있도록 설정되어 있습니다.

이 절에서는 Sass가 무엇인지, 왜 필요한지, 그리고 Next.js 프로젝트에서 Sass를 어떻게 설정하고 활용하는지 자세히 알아보겠습니다.


Sass란 무엇인가요?

Sass는 CSS의 확장 언어로, 프로그래밍적인 기능을 CSS에 도입하여 스타일시트 작성을 더욱 강력하고 유연하게 만들어 줍니다.

Sass는 자체적인 문법을 가지고 있으며, 작성된 Sass 코드는 웹 브라우저가 이해할 수 있는 표준 CSS로 컴파일(transpile)되어야 합니다.

Sass의 주요 기능
  • 변수(Variables): $primary-color: #007bff;와 같이 색상, 폰트 크기, 간격 등 반복적으로 사용되는 값을 변수로 정의하여 관리합니다. 유지보수가 용이하고 일관된 디자인을 유지하는 데 도움이 됩니다.
  • 중첩(Nesting): HTML 구조와 유사하게 CSS 선택자를 중첩하여 작성할 수 있습니다. 이는 코드의 가독성을 높이고, 연관된 스타일을 한눈에 파악하기 쉽게 만듭니다.
  • 믹스인(Mixins): @mixin button-style { ... }과 같이 재사용 가능한 CSS 코드 블록을 정의합니다. 여러 곳에서 동일한 스타일 패턴을 반복해서 사용해야 할 때 유용하며, background-color, padding, border-radius 등 여러 속성을 묶어 한 번에 적용할 수 있습니다.
  • 함수(Functions): @function calculate-rem($px) { ... }와 같이 값을 계산하고 반환하는 함수를 정의합니다. 색상 조정은 sass:color 같은 내장 모듈을 사용할 수 있습니다.
  • 확장/상속(Extend/Inheritance): @extend .base-button;와 같이 한 선택자의 스타일 규칙을 다른 선택자가 상속받을 수 있게 합니다. 중복 코드를 줄이고 코드 효율성을 높입니다.
  • 부분 파일(Partials)과 모듈: _variables.scss 같은 부분 파일을 만들고, 같은 폴더의 파일에서 @use './variables';로 불러와 variables.$primary-color처럼 이름공간을 통해 참조합니다. Sass의 파일 분할과 CSS Modules의 클래스 이름 지역화는 서로 다른 기능입니다.
Sass의 두 가지 문법
  • SCSS (Sassy CSS): CSS와 가장 유사한 문법으로, 중괄호({})와 세미콜론(;)을 사용합니다. 대부분의 Sass 사용자가 선호하는 방식입니다. (.scss 확장자)
  • Sass (Indented Syntax): 중괄호와 세미콜론 없이 들여쓰기와 줄 바꿈으로 구조를 나타내는 문법입니다. (.sass 확장자)

Next.js에서는 주로 SCSS 문법을 가진 .scss 파일을 사용합니다.


왜 Sass를 사용해야 할까요? (이점)

Sass는 기존 CSS의 단점을 보완하고 다음과 같은 이점을 제공합니다.

  • 생산성 향상: 변수, 믹스인, 중첩 등을 통해 반복적인 작업을 줄이고 더 빠르고 효율적으로 스타일을 작성할 수 있습니다.
  • 유지보수성 개선: 전역 변수나 믹스인을 활용하여 디자인 시스템을 쉽게 구축하고, 일관된 스타일을 적용하고 관리할 수 있습니다. 예를 들어, 브랜드 색상이 변경되면 변수 하나만 수정하면 됩니다.
  • 코드의 재사용성: 믹스인, 함수, @extend를 통해 스타일 코드를 재사용하여 중복을 줄이고 코드량을 감소시킵니다.
  • 가독성 향상: 중첩 문법은 HTML/React 컴포넌트 구조와 유사하게 스타일을 조직화하여 코드의 가독성을 높입니다.
  • 코드 조직화: @use로 다른 파일의 변수·함수·믹스인을 명시적으로 가져와 관리할 수 있습니다.

Next.js에서 Sass 통합하기

Next.js는 Sass를 공식적으로 지원하므로, 설정 과정이 매우 간단합니다.

필요한 것은 단 하나, sass 패키지를 설치하는 것입니다.

sass 패키지 설치: 터미널을 열고 다음 명령어를 실행하여 sass 컴파일러를 설치합니다.

npm install sass
# 또는
yarn add sass

Sass 파일 생성 및 사용: 이제 .scss 또는 .sass 확장자를 가진 파일을 생성하여 Sass 문법으로 스타일을 작성하고, 이를 CSS 모듈처럼 임포트하여 사용할 수 있습니다.

실습: Sass 변수와 중첩을 사용한 버튼 스타일링

이전 절의 StyledButton 예제를 Sass로 리팩토링하여 Sass의 기능을 활용해 봅시다.

src/app/sass-integration/page.tsx 파일 생성 (서버 컴포넌트): 이 페이지는 서버 컴포넌트이며, 우리가 만들 클라이언트 컴포넌트 SassStyledButton을 임포트하여 사용합니다.

src/app/sass-integration/page.tsx
import SassStyledButton from './SassStyledButton'; // 클라이언트 컴포넌트 임포트
import pageStyles from './page.module.scss'; // 페이지 요소에 적용할 Sass 모듈 임포트

export default function SassIntegrationPage() {
  return (
    <div className={pageStyles.container}>
      <h1 className={pageStyles.title}>Sass 통합 예제</h1>
      <p className={pageStyles.description}>
        아래 버튼들은 Sass 변수, 중첩, 믹스인 등을 사용하여 스타일링되었습니다.
      </p>
      <div style={{ display: 'flex', gap: '20px', marginTop: '30px', justifyContent: 'center' }}>
        <SassStyledButton label="기본 버튼" />
        <SassStyledButton label="강조 버튼" variant="primary" />
        <SassStyledButton label="경고 버튼" variant="warning" />
      </div>
    </div>
  );
}

src/app/sass-integration/page.module.scss 파일 생성: Sass 문법을 사용하여 페이지의 기본 스타일을 정의합니다.

src/app/sass-integration/page.module.scss
.container {
  padding: 40px;
  max-width: 800px;
  margin: 20px auto;
  background-color: #f8f8f8;
  border-radius: 10px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
  text-align: center;
}

.title {
  color: #333;
  margin-bottom: 15px;
  font-size: 2.5em;
}

.description {
  color: #666;
  font-size: 1.1em;
  line-height: 1.6;
}

src/app/sass-integration/SassStyledButton.tsx 파일 생성 (클라이언트 컴포넌트): Sass 모듈을 임포트하여 스타일을 적용합니다.

src/app/sass-integration/SassStyledButton.tsx
"use client";

import React from 'react';
import buttonStyles from './SassStyledButton.module.scss'; // 🚨 .scss 확장자 사용

interface SassStyledButtonProps {
  label: string;
  variant?: 'default' | 'primary' | 'warning'; // 버튼 종류 추가
  onClick?: () => void;
}

export default function SassStyledButton({ label, variant = 'default', onClick }: SassStyledButtonProps) {
  // variant에 맞는 CSS 모듈 클래스를 선택합니다.
  return (
    <button
      className={`${buttonStyles.btn} ${variant === 'default' ? '' : buttonStyles[variant]}`}
      onClick={onClick}
    >
      {label}
    </button>
  );
}

src/app/sass-integration/SassStyledButton.module.scss 파일 생성: Sass의 변수, 중첩, 믹스인을 사용하여 버튼 스타일을 정의합니다. 기본 색은 .btn에 있고 primary, warning만 추가 클래스를 선택합니다. 원문의 darken()은 폐기 예정인 함수이므로 새 코드에서는 sass:color 모듈의 color.adjust(..., $lightness: -8%, $space: hsl)로 같은 명도 감소를 표현할 수 있습니다.

src/app/sass-integration/SassStyledButton.module.scss
// Sass 변수 정의
$default-color: #007bff;
$primary-color: #28a745;
$warning-color: #ffc107;
$text-light: white;
$text-dark: #333;

// 재사용 가능한 믹스인 정의
@mixin button-base {
  padding: 12px 25px;
  font-size: 1.1em;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.3s ease, transform 0.1s ease, box-shadow 0.3s ease;
  font-weight: bold;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);

  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
  }

  &:active {
    transform: translateY(0);
    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  }
}

.btn {
  @include button-base; // 믹스인 포함

  // 기본 버튼 스타일 (중첩)
  background-color: $default-color;
  color: $text-light;

  &:hover {
    background-color: darken($default-color, 8%); // Sass 함수 사용
  }
}

.primary {
  background-color: $primary-color;
  color: $text-light;

  &:hover {
    background-color: darken($primary-color, 8%);
  }
}

.warning {
  background-color: $warning-color;
  color: $text-dark; // 경고 버튼은 어두운 텍스트

  &:hover {
    background-color: darken($warning-color, 8%);
  }
}
실습 확인

npm install sass 명령어로 sass 패키지를 설치했는지 확인합니다.

src/app/sass-integration 폴더를 만들고 위 파일들을 생성합니다.

개발 서버(npm run dev)를 실행한 후, http://localhost:3000/sass-integration으로 접속합니다.

  • 세 가지 다른 색상의 버튼이 표시되는 것을 확인할 수 있습니다.
  • 개발자 도구에서 생성된 클래스의 규칙과 세 버튼의 기본·hover 색상을 확인합니다. 클래스 이름 확인만으로 모든 Sass 규칙과 상태의 적용을 확인한 것은 아닙니다.

Sass를 활용한 스타일 관리 팁

  • 공유 파일: 변수와 믹스인을 별도 부분 파일로 관리하고 각 사용 파일에서 상대 경로로 @use합니다. _ 접두사 자체가 선택자를 지역화하지는 않습니다. Sass @import와 전역 내장 함수는 Dart Sass 1.80.0부터 폐기 예정입니다.
  • 얕은 중첩: DOM 구조를 그대로 깊게 중첩하기보다 컴포넌트가 책임지는 선택자와 반복 선언을 구분합니다. 믹스인을 여러 곳에 포함하면 최종 CSS 선언도 반복될 수 있습니다.
값과 클래스가 결정되는 시점

값과 클래스가 결정되는 시점을 비교합니다.

값과 클래스가 결정되는 시점
작성 대상결정되는 시점변경을 반영하는 방법
Sass 변수Sass가 CSS를 만드는 동안 값을 계산소스를 바꾸고 다시 컴파일; 브라우저에는 Sass 변수가 남지 않음
CSS 변수브라우저의 CSS 적용·상속 과정에서 값 결정클래스·속성·JavaScript 등으로 CSS 변수 값을 바꿔 테마에 반영 가능
모듈 클래스빌드 도구가 파일별 클래스 이름과 매핑 생성React에서 이미 생성된 클래스들을 선택하여 기본·강조·경고 상태 표현
Sass 변수
결정되는 시점: Sass가 CSS를 만드는 동안 값을 계산
변경을 반영하는 방법: 소스를 바꾸고 다시 컴파일; 브라우저에는 Sass 변수가 남지 않음
CSS 변수
결정되는 시점: 브라우저의 CSS 적용·상속 과정에서 값 결정
변경을 반영하는 방법: 클래스·속성·JavaScript 등으로 CSS 변수 값을 바꿔 테마에 반영 가능
모듈 클래스
결정되는 시점: 빌드 도구가 파일별 클래스 이름과 매핑 생성
변경을 반영하는 방법: React에서 이미 생성된 클래스들을 선택하여 기본·강조·경고 상태 표현

Sass의 변수·믹스인은 CSS 작성 도구이고, CSS Modules는 이름을 지역화하는 도구입니다. .module.scss는 두 기능을 함께 사용합니다.

CSS 모듈 활용

이전 페이지

CSS-in-JS 솔루션

다음 페이지

이 페이지의 목차

Sass란 무엇인가요?왜 Sass를 사용해야 할까요? (이점)Next.js에서 Sass 통합하기Sass를 활용한 스타일 관리 팁