프론트엔드

모노레포에서 미디어 쿼리가 무시되는 이유

김민나 2026. 3. 2. 02:32

모노레포 환경에서 공통 UI 패키지(@repo/ui)를 구축할 때  각 패키지가 독립적으로 스타일을 빌드하게 만든다면, sm:px-10 같은 반응형 클래스가 무시되거나, 스타일 우선순위가 뒤엉키는 'Cascade Conflict'가 발생합니다.

 

이번 트러블슈팅을 통해 CSS Cascade(계단식 적용) 원리Tailwind v4의 빌드 메커니즘, 그리고 모노레포에서의 정확한 경로 설정의 중요성을 알아봅니다. 

 

 


 

1. 문제 증상

  • 상황: packages/ui 내부의 Modal 컴포넌트에 px-5.25 sm:px-10.75를 적용함.
  • 현상: 화면 너비가 640px(sm) 이상임에도 불구하고, 개발자 도구에서 sm:px-10.75에 취소선이 그어지고 px-5.25가 최종 적용됨.
  • 특이사항: sm:!px-10.75처럼 !(important)를 붙여야만 정상 작동함.

 


 

2. 원인 분석

2.1 CSS Cascade Order (선언 순서의 역전)

CSS는 나중에 선언된 스타일이 우선 적용됩니다. 

미디어 쿼리는 그 자체로 가중치(Specificity)를 높여주지 않습니다.

  • 문제: packages/ui와 apps/homepage 양쪽에서 @import "tailwindcss";를 호출하고 있었습니다.
  • 결과: 브라우저는 두 개의 별도 CSS 파일(index.css, globals.css)을 로드합니다. 이때 globals.css의 sm: 미디어 쿼리보다 index.css의 일반 px- 클래스가 더 나중에 로드되면, 브라우저는 미디어 쿼리 조건이 맞더라도 나중에 나타난 일반 클래스를 렌더링하게 됩니다. 

2.2 Tailwind v4의 JIT 엔진 스캔 범위와 @source

Tailwind v4는 @import "tailwindcss";가 선언된 프로젝트 내부 파일만 기본으로 스캔합니다.

  • 문제: homepage 앱 빌드 시, 외부 워크스페이스인 ../../packages/ui 폴더는 스캔 대상에서 제외됩니다.
  • 결과: sm:px-10.75 같은 클래스는 실제 CSS 코드로 생성조차 되지 않거나, 엉뚱한 순서로 배치됩니다.

 


 

3. 해결 방법: 단일 엔진 통합 및 정확한 경로 명시

단계 1: UI 패키지에서 Tailwind 엔진 제거하기

packages/ui는 스타일을 생성하는 곳이 아니라 스타일의 가이드를 제공하는 곳이어야 합니다.

중복 엔진 실행을 막기 위해 @import "tailwindcss";를 제거합니다.

/* packages/ui/style.css */
@import "@repo/tailwind-config"; 
/* @import "tailwindcss"; <- 중복 방지를 위해 삭제함

단계 2: 최종 앱에서 외부 경로(@source) 명시

 

테일윈드 공식 문서 참고

 

 

기본적으로 Tailwind는 빌드 명령어를 실행하는 현재 작업 디렉토리(CWD)를 기준으로 파일을 찾습니다. 하지만 모노레포 루트에서 모든 앱을 한꺼번에 빌드하는 경우, 각 앱의 소스 위치가 꼬일 수 있습니다.

이때 @import 문에 source() 함수를 사용하여 스캔의 시작점을 강제로 지정할 수 있습니다.

앱의 globals.css에서 Tailwind v4 엔진을 실행하고, 모노레포 루트를 거쳐 UI 패키지까지 도달하는 정확한 상대 경로를 알려줘야 합니다.

 

/* apps/homepage/src/styles/globals.css */

// 앱 내부에서 정의된 파일을 임포트하기
@import "tailwindcss"; 
@import "@repo/tailwind-config";

@source "../../../../packages/ui/src/**/*.{ts,tsx}";

 

 

단계 3: CSS 임포트 순서 최적화 (Priority)

모든 스타일 유틸리티가 마지막에 배치되어 우선순위를 가질 수 있도록 layout.tsx에서 임포트 순서를 조정합니다.

 

// apps/homepage/src/app/layout.tsx
import "@repo/ui/style.css"; // UI 패키지 기본 스타일 (먼저)
import "@/styles/globals.css"; // Tailwind 유틸리티가 포함된 최종 파일 (나중에 임포트)

 

 


4. 마치며

 

이번 트러블슈팅을 통해 얻은 가장 큰 교훈은 디자인 시스템 패키지는 스타일을 직접 빌드(Build)하는 주체가 아니라, 앱이 스타일을 렌더링할 수 있도록 재료를 제공하는 역할이어야 한다는 점입니다.

 

테일윈드 엔진은 최종 서비스에서 단 한 번만 돌아야 하며, 엔진이 파편화되지 않아야 합니다. 

 

모노레포 환경에서 TailwindCSS v4 를 사용하는 분들에게 도움이 되길 바라며 글을 마칩니다.