본문 바로가기
개발 & 코딩 팁

SCSS 변수와 mixin으로 만드는 반응형 레이아웃 완전 가이드

by eztrend1028 님의 블로그 2025. 10. 5.
SCSS 변수·Mixin

 

CSS 미디어쿼리를 매번 손으로 쓰는 시대는 끝. SCSS의 변수mixin만 잘 잡으면, 브레이크포인트가 많아도 유지보수가 쉬워집니다. 아래 예제들을 그대로 복붙해 프로젝트에 붙여도 바로 동작하도록 구성했습니다.

이 글에서 배우는 것

  • 프로젝트 공통 $breakpoints 설계법
  • @mixin으로 미디어쿼리 문법 통일하기
  • 유틸리티 믹스인(유동 그리드/클램프 타이포/컨테이너) 베스트 프랙티스
  • 실무에서 자주 생기는 실수와 점검 체크리스트

1) 브레이크포인트 변수를 한 곳에 모으기

브레이크포인트는 이름→값 형태의 맵으로 관리하면 변경에 매우 강합니다.

// settings/_breakpoints.scss
$breakpoints: (
  xs: 0,      // mobile-first
  sm: 480px,
  md: 768px,
  lg: 1024px,
  xl: 1280px
) !default;

 
프로젝트 초기에 위 값을 합의하고, 변경은 이 파일에서만 하세요.

2) 미디어쿼리 믹스인: 문법을 팀 표준으로

반복되는 @media 문을 캡슐화해 가독성과 안정성을 동시에 가져갑니다.

// tools/_media.scss
@use "sass:map";
@use "../settings/breakpoints" as *;

@mixin mq($key) {
  $value: map.get($breakpoints, $key);
  @if $value == null {
    @error "Unknown breakpoint `#{$key}`. Check $breakpoints.";
  }
  @media (min-width: #{$value}) {
    @content;
  }
}

 
사용 예:

.card {
  padding: 16px;
  @include mq(md) {
    padding: 24px;
  }
  @include mq(lg) {
    padding: 32px;
  }
}

3) 유틸리티 믹스인: 바로 써먹는 3종 세트

3-1) 유동 그리드

열 수만 바꿔도 유연하게 대응하는 CSS Grid 유틸입니다.

// tools/_grid.scss
@mixin grid($cols, $gap: 16px) {
  display: grid;
  grid-template-columns: repeat(#{$cols}, minmax(0, 1fr));
  gap: $gap;
}
.gallery {
  @include grid(2, 12px);
  @include mq(md) { @include grid(3, 16px); }
  @include mq(lg) { @include grid(4, 20px); }
}

3-2) 클램프 타이포(유동 폰트 크기)

뷰포트에 따라 폰트 크기가 자연스럽게 변하도록 만듭니다.

// tools/_typography.scss
// clamp(min, preferred, max)
@mixin fluid-type($min, $vw, $max) {
  font-size: clamp(#{$min}, #{$vw}, #{$max});
}
h1 {
  @include fluid-type(20px, 4vw, 36px);
  line-height: 1.25;
  font-weight: 700;
}

3-3) 컨테이너 + 패딩

페이지 폭과 좌우 패딩을 일관되게 유지합니다.

// objects/_container.scss
@mixin container($max: 1200px, $pad: 16px) {
  width: min(100% - #{$pad} * 2, #{$max});
  margin-inline: auto;
}
.page {
  @include container(1200px, 20px);
}

4) 컴포넌트 적용 예시: 카드 리스트

@use "tools/media" as *;
@use "tools/grid" as *;
@use "tools/typography" as *;
@use "objects/container" as *;

.list {
  @include container(1100px, 16px);
  @include grid(1, 12px);
  @include mq(md) { @include grid(2, 16px); }
  @include mq(lg) { @include grid(3, 20px); }
}

.card {
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  padding: 16px;
  background: #fff;

  .title {
    @include fluid-type(18px, 2.4vw, 22px);
    margin: 0 0 8px;
  }
  .desc {
    color: #4b5563;
    line-height: 1.6;
  }
}

5) 실무에서 자주 하는 실수 & 체크리스트

  • 브레이크포인트 산재: 파일마다 제각각 선언 → $breakpoints 단일 소스 유지
  • px 혼용: 패딩/폰트 등 단위 일관성 유지 (px, rem 규칙 합의)
  • 남용된 미디어쿼리: 컴포넌트 내부에서만 MQ 남발 금지, 상위 객체에서 레이아웃 우선
  • 테스트 부족: 최소 xs/sm/md/lg/xl 5단계에서 UI 깨짐 점검

핵심 요약표

항목 권장 값/패턴 메모
브레이크포인트 xs 0 / sm 480 / md 768 / lg 1024 / xl 1280 프로젝트 초기에 합의, 한 파일에서 관리
미디어 믹스인 @include mq(md) { ... } 팀 표준 문법 통일
그리드 @include grid(cols, gap) 뷰포트별 cols 변경으로 대응
타이포 @include fluid-type(20px, 4vw, 36px) clamp로 유동 폰트
컨테이너 @include container(1200px, 16px) 폭·패딩 일관성
브레이크포인트에 따른 카드 그리드 변화 예시 (1→2→3열)

관련글

  1. 매일 아침 물 한 잔이 주는 건강 효과 5가지
  2. 집에서 간단히 하는 홈트레이닝 운동법 5가지
  3. 집에서 할 수 있는 허리 통증 완화 스트레칭 5가지