본문 바로가기

CSS 프레임워크 활용

컴포넌트 중심 Bootstrap과 유틸리티 중심 Tailwind를 비교해 디자인 자유도와 개발 속도에 맞게 선택합니다.

지금까지 CSS의 기본부터 Flexbox와 Grid, 트랜지션과 애니메이션, 변수와 calc(), 아키텍처와 Sass까지, 화면을 순수 CSS로 만드는 데 필요한 것들을 익혔습니다. 실제 개발에서는 여기에 더해, 미리 만들어진 스타일과 컴포넌트, 반응형 그리드를 모아 둔 CSS 프레임워크를 쓰는 경우가 많습니다. 모든 CSS를 처음부터 쓰는 대신, 만들어진 부품을 조립하듯 페이지를 구성할 수 있기 때문입니다.

이 글에서는 CSS 프레임워크가 무엇이고 왜 쓰는지 살펴본 뒤, 컴포넌트 중심의 Bootstrap과 유틸리티 중심의 Tailwind CSS를 비교합니다. 이 글은 Bootstrap 5.3.8과 Tailwind CSS 4.3을 기준으로 하며, 마지막에는 Bootstrap으로 반응형 페이지를 만들어 봅니다.

CSS 도구 선택: 후보를 같은 화면에서 비교한다

CSS FRAMEWORKS · COMPARISON

CSS 도구 선택: 후보를 같은 화면에서 비교한다

컴포넌트 제공과 유틸리티 조합은 출발점의 차이다. 속도·디자인 자유도만으로 자동 결정하지 않고, 현재 시스템과 후보를 같은 요구사항으로 비교한다.

기존 시스템 · 자체 CSS

이미 필요한 tokens·components가 있다면 확장 비용을 기준선으로 잡는다. 작은 화면에서는 필요한 규칙만 직접 관리하는 선택도 가능하다.

Bootstrap형 · 컴포넌트

준비된 form·nav·modal·grid로 시작한다. 디자인 변경 범위, 사용하는 JavaScript 동작과 필요한 CSS만 포함하는 구성을 확인한다.

Tailwind형 · 유틸리티

유틸리티와 tokens를 조합해 디자인한다. 재사용 컴포넌트·접근성 동작은 직접 설계하며 build가 실제 사용하는 완전한 클래스 이름을 감지해야 한다.

세 후보를 같은 요구사항으로 비교한다현재 CSS 기준선, 컴포넌트 후보, 유틸리티 후보의 세 독립 노드가 같은 요구사항·화면 비교 노드로 연결된다. 순서나 자동 승자를 뜻하지 않으며 접근성, JavaScript, CSS 크기와 유지 비용을 확인해 도입, 제한된 실험 또는 유지를 선택한다.현재 CSS기준선컴포넌트 후보대표 화면유틸리티 후보대표 화면같은 요구사항·같은 화면으로 비교도입 · 제한된 실험 · 현재 시스템 유지
세 후보를 같은 요구사항으로 비교한다현재 CSS 기준선, 컴포넌트 후보, 유틸리티 후보의 세 독립 노드가 같은 요구사항·화면 비교 노드로 연결된다. 순서나 자동 승자를 뜻하지 않으며 접근성, JavaScript, CSS 크기와 유지 비용을 확인해 도입, 제한된 실험 또는 유지를 선택한다.현재 CSS기준선컴포넌트 후보대표 화면유틸리티 후보대표 화면같은 조건으로 비교접근성 · JS · CSS 크기도입 / 실험 / 유지

공통 도입 기준을 만족하는 선택을 한다

키보드·스크린 리더 동작, 필요한 runtime JavaScript, production CSS 크기와 업그레이드 책임을 확인한다. 조건을 충족하면 도입하고, 불확실하면 한 화면에서 검증하며, 비용이 크면 현재 시스템을 유지한다.

CDN 실습과 production 빌드를 구분한다. Bootstrap도 커스터마이징할 수 있고 Tailwind도 빠른 UI 조합에 사용할 수 있다. 실제 버전·빌드·컴포넌트 구성을 기준으로 비교한다.

위 그림은 프레임워크를 고르는 과정을 보여 줍니다. 지금 쓰는 자체 CSS를 기준선으로 두고, 폼, 내비게이션, 모달, 그리드처럼 준비된 컴포넌트로 시작하는 Bootstrap형과, 작은 유틸리티 클래스와 디자인 토큰을 조합하는 Tailwind형을 후보로 놓습니다. 세 가지를 같은 요구 사항과 같은 대표 화면으로 비교한 뒤, 도입하거나 한 화면에서만 시험해 보거나 지금의 방식을 유지합니다.

그림 아래의 설명처럼 비교할 때는 키보드와 스크린 리더의 동작, 필요한 자바스크립트, 운영 환경의 CSS 크기, 업그레이드를 누가 맡을지를 확인합니다. Bootstrap도 테마를 바꿀 수 있고 Tailwind도 화면을 빠르게 조합할 수 있으므로, 도구의 이름만으로 속도나 디자인 자유도가 정해지지는 않습니다. 또 학습용 CDN과 운영 환경의 빌드는 구분합니다.


CSS 프레임워크란

CSS 프레임워크(CSS framework)는 페이지를 꾸미는 데 쓸 CSS 코드와 컴포넌트, 그리드 시스템을 미리 만들어 모아 둔 라이브러리입니다. 반복되는 CSS를 직접 쓰는 대신, 프레임워크가 제공하는 클래스 이름을 HTML 요소에 붙여 스타일을 적용합니다. 프레임워크를 쓰면 다음과 같은 점이 좋습니다.

  • 빨리 만듭니다: 버튼, 폼, 내비게이션 바, 카드 같은 컴포넌트와 레이아웃이 준비되어 있어 페이지를 빠르게 구성합니다.
  • 디자인이 일관됩니다: 프레임워크의 디자인 체계를 따르므로, 여러 사람이 작업하거나 프로젝트가 커져도 모습이 고르게 유지됩니다.
  • 반응형을 쉽게 만듭니다: 대부분 모바일 우선의 그리드를 갖추고 있어, 화면 크기에 맞는 레이아웃을 쉽게 만듭니다.
  • 브라우저 차이를 덜 신경 씁니다: 여러 브라우저에서 같게 보이도록 다듬어져 있습니다.
  • 자료가 많습니다: 널리 쓰이는 프레임워크는 문서와 예제, 커뮤니티가 풍부합니다.

Bootstrap: 컴포넌트 중심

Bootstrap은 미리 디자인한 컴포넌트와 그리드를 제공하는 CSS와 자바스크립트 프레임워크입니다. 다음과 같은 특징이 있습니다.

  • 컴포넌트가 준비되어 있습니다: 내비게이션 바, 캐러셀, 모달, 드롭다운, 폼 컨트롤 같은 컴포넌트가 CSS와 자바스크립트로 만들어져 있습니다.
  • 12열 그리드를 씁니다: col-sm-*, col-md-*, col-lg-* 같은 클래스로 화면 너비마다 열의 수를 정합니다.
  • 동작은 자바스크립트가 맡습니다: Bootstrap 5는 jQuery 없이 동작합니다. 메뉴를 접고 펴는 Collapse 같은 동작은 CSS 클래스만으로는 실행되지 않고, Bootstrap의 자바스크립트와 data-bs-* 속성의 연결이 필요합니다.
  • Sass로 만들어졌습니다: Sass의 변수와 믹스인을 바꿔 색이나 간격을 원하는 대로 조정할 수 있습니다.

기본적인 화면을 빠르게 만들 수 있고, 컴포넌트가 많으며, 커뮤니티가 넓어 자료를 찾기 쉽고, 기본 디자인이 정해져 있어 통일감 있는 사이트를 만들기 좋습니다. 반면 모든 기능을 넣으면 CSS와 자바스크립트 파일이 커지고, 쓰지 않는 컴포넌트의 CSS까지 포함될 수 있으며, 기본 테마를 그대로 쓰면 다른 사이트와 비슷해 보입니다. 필요한 부분만 골라 빌드하고 테마를 바꾸면 이런 단점을 줄일 수 있습니다.

다음은 Bootstrap으로 만든 간단한 카드입니다. CSS와 자바스크립트를 CDN에서 불러오며, integrity 속성에는 Bootstrap 공식 문서에 실린 5.3.8 파일의 해시를 적었습니다. 브라우저는 받은 파일의 해시가 이 값과 다르면 파일을 쓰지 않으므로, 버전을 바꿀 때는 CSS, 자바스크립트, 해시를 함께 바꿉니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bootstrap 카드 예시</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
</head>
<body>
    <div class="container mt-5">
        <div class="row">
            <div class="col-md-4">
                <div class="card" style="width: 18rem;">
                    <div class="card-body">
                        <h5 class="card-title">카드 제목</h5>
                        <p class="card-text">이것은 Bootstrap 프레임워크를 사용하여 만든 간단한 카드 컴포넌트입니다. 미리 정의된 클래스로 쉽게 스타일링할 수 있습니다.</p>
                        <a href="#" class="btn btn-primary">자세히 보기</a>
                    </div>
                </div>
            </div>
            <div class="col-md-4">
                <div class="card" style="width: 18rem;">
                    <div class="card-body">
                        <h5 class="card-title">또 다른 카드</h5>
                        <p class="card-text">Bootstrap의 그리드 시스템을 사용하여 컬럼으로 배치된 다른 카드입니다.</p>
                        <a href="#" class="btn btn-success">구매하기</a>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
</body>
</html>

container, row, col-md-4, card, card-body, card-title, card-text, btn, btn-primary처럼 미리 정의된 클래스를 HTML에 붙이기만 했는데, 여백과 테두리, 둥근 모서리가 있는 카드와 색이 칠해진 버튼이 만들어집니다. col-md-4는 화면 너비가 768px 이상일 때 부모 row의 12열 가운데 4열을 차지합니다.

더 깊이: integrity에 crossorigin이 함께 붙는 이유

integrity 속성을 이용한 확인을 하위 자원 무결성(Subresource Integrity, SRI)이라고 합니다. 값은 sha384- 같은 해시 알고리즘 이름 뒤에 파일 내용의 해시를 Base64로 적은 것이며, 알고리즘으로는 sha256, sha384, sha512를 쓸 수 있습니다. 공백으로 여러 해시를 함께 적으면 브라우저는 그 가운데 가장 강한 알고리즘의 해시만 비교합니다. 해시가 맞지 않으면 브라우저는 네트워크 오류로 처리해, 스크립트는 실행하지 않고 스타일 시트는 적용하지 않습니다.

다른 출처에서 받는 파일에 SRI를 쓰려면 CORS가 필요합니다. crossorigin 속성이 없으면 브라우저는 그 파일을 no-cors 방식으로 요청하는데, 이렇게 받은 응답은 페이지가 내용을 확인할 수 없는 응답이라 무결성 검사에 쓸 수 없고 요청은 항상 실패합니다. 그래서 예제처럼 crossorigin="anonymous"를 붙여 쿠키 같은 자격 증명 없이 CORS로 요청하고, CDN은 Access-Control-Allow-Origin 헤더로 이를 허용해야 합니다.

SRI가 막는 것은 CDN이 공격당해 파일이 바뀌는 공급망 공격입니다. 반대로 처음부터 잘못된 파일의 해시를 적었다면 SRI는 그 파일을 그대로 믿으므로, 해시는 공식 문서나 직접 내려받은 파일에서 계산해 넣습니다. 규칙은 MDN의 하위 자원 무결성 설명에 정리되어 있습니다.


Tailwind CSS: 유틸리티 우선

Tailwind CSS는 유틸리티 우선(utility-first) 방식의 프레임워크입니다. 완성된 컴포넌트 대신 flex, pt-4, text-center, rounded-lg처럼 CSS 속성과 값 하나를 나타내는 작은 유틸리티 클래스를 제공하며, 이것들을 조합해 화면을 만듭니다. 다음과 같은 특징이 있습니다.

  • 클래스 하나가 스타일 하나입니다: 예를 들어 mt-4는 margin-top: 1rem입니다.
  • 완성된 컴포넌트가 없습니다: 모든 UI를 유틸리티 클래스를 조합해 직접 만듭니다.
  • CSS로 설정합니다: Tailwind CSS 4는 CSS 파일의 @theme 블록에 색, 간격, 글꼴 같은 디자인 토큰을 선언하고, 그 값으로 유틸리티를 만듭니다.
  • 쓴 클래스만 만듭니다: 소스 파일에서 찾은 클래스 이름에 해당하는 CSS만 만들어 최종 파일이 작습니다. 다만 'bg-' + color + '-500'처럼 코드에서 이어 붙여 만든 이름은 찾지 못하므로, 클래스 이름은 소스에 완전한 형태로 적어야 합니다.
  • 반응형을 클래스로 적습니다: sm:, md:, lg: 같은 접두사를 붙여 화면 너비마다 다른 스타일을 줍니다.

디자인에 제약이 없어 원하는 모습을 자유롭게 만들 수 있고, 쓴 스타일만 들어가 CSS가 작으며, 정해진 간격과 색의 체계를 따르므로 일관성을 지키기 쉽고, CSS 파일을 직접 쓸 일이 줄어듭니다. 반면 요소 하나에 클래스가 많이 붙어 HTML이 길어지고, 클래스 이름을 익히는 데 시간이 걸리며, 재사용할 컴포넌트는 직접 만들어야 합니다. 그래서 React나 Vue 같은 컴포넌트 기반 프레임워크와 함께 쓰며, 클래스 조합을 컴포넌트 안에 감추는 경우가 많습니다.

다음은 Tailwind CSS 4로 만든 같은 모양의 카드입니다. 공식 문서가 안내하는 브라우저용 빌드(Play CDN)를 불러와, 브라우저가 페이지의 클래스를 읽어 CSS를 즉석에서 만들게 했습니다. <style type="text/tailwindcss"> 안의 @theme은 --color-brand라는 색 토큰을 선언하며, 이렇게 선언한 색은 bg-brand처럼 유틸리티 이름으로 쓸 수 있습니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tailwind CSS 카드 예시</title>
    <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
    <style type="text/tailwindcss">
        @theme {
            --color-brand: #3498db;
        }
    </style>
</head>
<body>
    <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
            <div class="bg-white rounded-lg shadow-md overflow-hidden">
                <div class="p-6">
                    <h3 class="text-xl font-semibold mb-2 text-gray-900">카드 제목</h3>
                    <p class="text-gray-700 text-base mb-4">이것은 Tailwind CSS 유틸리티 클래스를 조합하여 만든 카드 컴포넌트입니다. CSS를 직접 작성하지 않고 HTML에서 스타일링합니다.</p>
                    <button class="bg-brand hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md">
                        더 읽기
                    </button>
                </div>
            </div>
            <div class="bg-white rounded-lg shadow-md overflow-hidden">
                <div class="p-6">
                    <h3 class="text-xl font-semibold mb-2 text-gray-900">또 다른 카드</h3>
                    <p class="text-gray-700 text-base mb-4">Tailwind는 높은 자유도를 제공하며, 컴포넌트가 아닌 유틸리티 클래스들의 조합으로 스타일을 구성합니다.</p>
                    <button class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-md">
                        구매하기
                    </button>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

max-w-7xl, mx-auto, grid, md:grid-cols-2, gap-6 같은 레이아웃 클래스와 bg-white, rounded-lg, shadow-md, text-gray-700, hover:bg-blue-700 같은 스타일 클래스를 조합해 화면을 만들었습니다. 카드는 좁은 화면에서 한 열, 768px 이상에서 두 열, 1024px 이상에서 세 열로 놓입니다. 브라우저용 빌드는 페이지를 열 때마다 CSS를 만드므로 학습과 시험에만 쓰고, 운영 환경에서는 Tailwind CLI나 Vite 같은 빌드 도구로 CSS를 미리 만들어 배포합니다.

두 예제를 서로 다른 HTML 파일로 저장해 비교해 보세요. 두 CDN은 외부 서버에서 파일을 받으므로 인터넷에 연결되어 있어야 합니다. 페이지가 스타일 없는 HTML처럼 보이면, 클래스의 철자를 고치기 전에 Network 패널에서 CDN 요청이 성공했는지 먼저 확인합니다. 두 예제의 버튼과 # 링크에는 동작이 없어 모양만 확인할 수 있습니다.

Bootstrap 예제의 카드에는 width: 18rem이 고정되어 있습니다. 화면이 768px 이상 992px 미만이면 기본 container의 너비가 720px이고 col-md-4는 그 3분의 1인 240px인데, 루트의 글자 크기가 16px이면 18rem은 288px이라 카드가 열보다 넓어집니다. 992px 이상에서는 container가 960px 이상으로 넓어져 카드가 열 안에 들어갑니다. 카드의 고정 너비와 그리드의 열 비율은 서로 다른 규칙이기 때문입니다. 두 카드의 style="width: 18rem;"을 지우고 w-100 클래스를 붙이면, 카드가 열의 너비를 따르게 됩니다.


어떤 프레임워크를 고를까

Bootstrap은 디자인에 큰 공을 들이지 않고 프로토타입이나 관리자 페이지를 빨리 만들어야 할 때, 다양한 UI 컴포넌트가 필요하지만 직접 만들 시간이 부족할 때, 독창적인 디자인보다 표준적인 화면과 일관성이 중요할 때, CSS를 깊이 알지 못해도 쉽게 시작하고 싶을 때 알맞습니다. 대신 파일이 커질 수 있고, 기본 디자인에서 벗어나려면 덮어쓰는 CSS를 더 써야 합니다.

Tailwind CSS는 독창적인 디자인을 만들면서 디자인 체계를 직접 세울 생각이 있을 때, 최종 CSS의 크기를 줄이고 싶을 때, CSS 파일을 따로 쓰지 않고 HTML에서 바로 스타일을 정하는 방식을 좋아할 때, React나 Vue 같은 컴포넌트 기반 프레임워크와 함께 쓸 때 알맞습니다. 대신 HTML이 길어지고, 클래스 이름을 익혀야 하며, 재사용할 컴포넌트를 따로 만들어야 합니다.

이런 기준은 후보를 좁히는 출발점일 뿐입니다. 실제로 고를 때는 같은 대표 화면을 두 방식으로 만들어 보고, 필요한 디자인 수정의 양, 키보드 동작, 자바스크립트 의존성, 실제로 만들어지는 CSS의 크기, 앞으로 유지할 비용을 비교합니다.


실습: Bootstrap으로 만드는 반응형 페이지

Bootstrap으로 내비게이션 바, 헤더, 본문, 사이드바, 푸터가 있는 반응형 페이지를 만들어 봅니다. Tailwind CSS를 좋아한다면 앞의 예제와 공식 문서를 참고해 같은 구조를 만들어 봐도 좋습니다. web-dev-practice 폴더에 framework_layout.html을 만들고 다음 코드를 씁니다.

framework_layout.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Bootstrap 반응형 레이아웃 실습</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
    <style>
        /* 실습을 위한 간단한 커스텀 스타일 (선택 사항) */
        body {
            background-color: #f8f9fa;
        }
        .header-section {
            background-color: #343a40;
            color: white;
            padding: 40px 0;
            text-align: center;
            margin-bottom: 30px;
        }
        .content-box {
            background-color: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
            margin-bottom: 20px;
        }
        .footer-section {
            background-color: #343a40;
            color: white;
            padding: 20px 0;
            text-align: center;
            margin-top: 50px;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
        <div class="container-fluid">
            <a class="navbar-brand" href="#">내 사이트</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="메뉴 열기">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
                <ul class="navbar-nav ms-auto">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page" href="#">홈</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">서비스</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">포트폴리오</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">문의</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>

    <header class="header-section">
        <div class="container">
            <h1 class="display-4">CSS 프레임워크를 활용한 빠른 개발</h1>
            <p class="lead">Bootstrap의 그리드와 컴포넌트를 사용하여 반응형 웹 페이지를 만들어봅시다.</p>
            <a href="#" class="btn btn-primary btn-lg mt-3">더 알아보기</a>
        </div>
    </header>

    <main class="container">
        <div class="row">
            <div class="col-12 col-md-8">
                <div class="content-box">
                    <h3>메인 콘텐츠 제목</h3>
                    <p>이 영역은 주된 내용이 들어가는 공간입니다. Bootstrap의 반응형 그리드 시스템을 사용하여 다양한 화면 크기에 맞춰 레이아웃이 자동으로 조절됩니다. <code>col-12</code>는 모든 화면에서 12열(꽉 채움)을 의미하며, <code>col-md-8</code>은 중간(md) 화면 크기 이상에서 8열을 차지하도록 합니다.</p>
                    <p>화면 크기를 조절하며 어떻게 레이아웃이 변화하는지 확인해보세요. 작은 화면에서는 사이드바가 아래로 내려올 것입니다.</p>
                    <button class="btn btn-info">정보 버튼</button>
                </div>

                <div class="row">
                    <div class="col-12 col-sm-6">
                        <div class="content-box">
                            <h5>서브 섹션 1</h5>
                            <p>여기서는 <code>row</code> 안에 다시 <code>col-12 col-sm-6</code>을 사용하여 2개의 컬럼을 만들었습니다. 이는 중첩된 그리드 사용 예시입니다.</p>
                        </div>
                    </div>
                    <div class="col-12 col-sm-6">
                        <div class="content-box">
                            <h5>서브 섹션 2</h5>
                            <p>모바일 화면에서는 이 두 컬럼이 세로로 쌓이고, 작은 태블릿 화면 이상에서는 가로로 배치됩니다.</p>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-12 col-md-4">
                <div class="content-box">
                    <h4>사이드바</h4>
                    <ul class="list-group">
                        <li class="list-group-item">항목 1</li>
                        <li class="list-group-item">항목 2</li>
                        <li class="list-group-item">항목 3</li>
                    </ul>
                </div>

                <div class="content-box">
                    <h4>최신 소식</h4>
                    <p>프레임워크를 사용하면 디자인과 기능 구현에 드는 노력을 크게 줄일 수 있습니다.</p>
                    <span class="badge bg-primary">새로운 기능</span>
                </div>
            </div>
        </div>
    </main>

    <footer class="footer-section">
        <p>&copy; 2026 CSS 프레임워크 실습. All rights reserved.</p>
    </footer>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
</body>
</html>

Live Server로 framework_layout.html을 열고 창의 너비를 바꿔 봅니다. Bootstrap 5의 기본 기준 너비는 sm이 576px, md가 768px, lg가 992px이며, 이 페이지에서는 클래스마다 다른 기준이 적용됩니다. 본문과 사이드바의 8 대 4 배치는 768px부터, 본문 안 두 서브 섹션의 6 대 6 배치는 576px부터, navbar-expand-lg의 메뉴 펼침은 992px부터 적용됩니다. 그래서 800px 화면에서는 본문과 사이드바가 나란히 놓이지만, 메뉴는 아직 햄버거 버튼 안에 접혀 있습니다.

메뉴 버튼의 data-bs-target="#navbarNav"는 같은 id를 가진 접히는 영역을 가리킵니다. 버튼을 누르면 Bootstrap의 자바스크립트가 메뉴를 펼치고 aria-expanded를 true로 바꿔, 스크린 리더에 메뉴가 펼쳐졌다는 것을 알립니다. 아래쪽의 <script> 요청이 실패하거나 그 줄을 지우면 그리드는 CSS라 그대로 동작하지만, 접힌 메뉴는 펼쳐지지 않습니다. 정보 버튼에는 따로 붙인 동작이 없습니다.


정리

  • CSS 프레임워크는 미리 만든 스타일, 컴포넌트, 그리드를 제공해 화면을 빠르고 일관되게 만들게 합니다.
  • Bootstrap은 컴포넌트 중심이며, 12열 그리드와 자바스크립트로 동작하는 컴포넌트를 클래스와 data-bs-* 속성으로 씁니다.
  • Tailwind CSS는 유틸리티 우선이며, 속성 하나씩을 나타내는 클래스를 조합하고, 4에서는 @theme으로 디자인 토큰을 정합니다.
  • Tailwind는 소스에 완전한 형태로 적힌 클래스만 만들며, 브라우저용 빌드는 학습용이고 운영에서는 빌드 도구로 CSS를 만듭니다.
  • CDN에서 파일을 불러올 때 integrity를 적으면 브라우저가 파일이 바뀌지 않았는지 확인합니다.
  • 프레임워크는 같은 대표 화면으로 접근성, 자바스크립트, CSS 크기, 유지 비용을 비교해 고릅니다.

연습 문제

1. 열 비율 바꾸기

실습 페이지의 768px 기준은 유지하면서, 본문을 9열, 사이드바를 3열로 바꾸려고 합니다. 클래스를 어떻게 바꿔야 할까요? 바꾼 뒤 575px, 600px, 800px, 1000px 화면에서 본문과 사이드바, 서브 섹션, 메뉴는 각각 어떻게 보일까요?

해설 보기

본문의 col-md-8을 col-md-9로, 사이드바의 col-md-4를 col-md-3으로 바꿉니다. 9 + 3 = 12라 한 줄에 들어갑니다.

575px에서는 본문과 사이드바, 서브 섹션이 모두 세로로 쌓입니다. 600px에서는 본문과 사이드바는 세로지만 서브 섹션은 576px 이상이라 6 대 6으로 나란히 놓입니다. 800px에서는 본문과 사이드바가 9 대 3으로, 서브 섹션이 6 대 6으로 나란히 놓이지만, 메뉴는 992px 미만이라 접혀 있습니다. 1000px에서는 메뉴도 펼쳐진 상태로 보입니다.

2. 스크립트가 빠진 페이지

실습 페이지에서 맨 아래의 bootstrap.bundle.min.js 줄을 실수로 지웠습니다. 화면 너비 600px에서 무엇이 정상으로 동작하고 무엇이 동작하지 않을까요?

해설 보기

그리드와 카드, 버튼의 모양은 모두 CSS가 만들므로 그대로 보입니다. 600px에서는 서브 섹션이 나란히 놓이고, 본문과 사이드바는 세로로 쌓입니다.

하지만 메뉴를 펼치는 동작은 자바스크립트가 하므로, 햄버거 버튼을 눌러도 메뉴가 펼쳐지지 않고 aria-expanded도 바뀌지 않습니다. 600px은 992px 미만이라 메뉴가 접혀 있으므로, 이 화면의 사용자는 메뉴 링크를 쓸 수 없게 됩니다.

3. 이어 붙인 클래스 이름

Tailwind CSS를 빌드 도구로 쓰는 프로젝트에서, 버튼의 색을 자바스크립트로 정하려고 button.className = 'bg-' + color + '-500';이라고 썼습니다. color에 'red'를 넣었는데 버튼에 색이 칠해지지 않습니다. 왜 그럴까요?

해설 보기

Tailwind는 소스 파일을 읽어 완전한 형태로 적힌 클래스 이름만 찾아 CSS를 만듭니다. 'bg-' + color + '-500'은 실행할 때 비로소 bg-red-500이 되므로, 빌드할 때는 이 이름을 찾지 못해 해당 CSS가 만들어지지 않습니다.

const colors = { red: 'bg-red-500', green: 'bg-green-500' };처럼 쓸 클래스 이름을 소스에 완전한 형태로 적어 두고, 그중 하나를 고르게 하면 됩니다.

이것으로 4장을 마칩니다. 4장에서는 트랜지션과 애니메이션, CSS 변수와 calc(), CSS 아키텍처와 방법론, Sass, CSS 프레임워크로 CSS를 더 풍부하고 관리하기 쉽게 만드는 방법을 살펴봤습니다. 다음 장의 변수, 데이터 타입, 연산자부터는 웹 페이지에 동작을 더하는 자바스크립트를 다룹니다.