React/타입스크립트로 배우는 리액트(React.js) : 기초부터 최신 기술까지

섹션 8. 컴포넌트 스타일링 (2)

favor 2026. 4. 21. 18:09

tailwind css - 시작하기

tailwind css : Utility-First 기반의 css 라이브러리 

 

Utility-First : 디자인이 미리 완성된 큰 클래스를 가져다 쓰는 대신, 이미 정의된 작은 단위의 유틸리티 클래스를 조합하여 요소를 디자인하는 방식 

 

  1. 패키지 설치 
    • npm install tailwindcss @tailwindcss/vite 명령어를 사용하여 다운로드 
  2. 플러그인 등록 
    • vite.config.ts 파일의 plugins: []에 tailwindcss() 추가 
  3. css 파일 연결
    • src/styles/tailwind.css 파일에 @import "tailwindcss"; 추가
    • src/styles/index.css 파일에 @import "./tailwind.css"; 추가

 

tailwind css - 알아보기

/* index.css */

@import "./global.css";
@import "./tailwind.css";
/* global.css */

.button {
  background-color: oklch(0.723 0.219 149.579);
  color: white;
  padding: 12px 20px;
  border-radius: 0.25rem;
  border: none;
  cursor: pointer;
  transition: background-color 0.3s ease;

}

.button:hover {
  background-color: oklch(0.627 0.194 149.214);
}
/* tailwind.css */

@import "tailwindcss";
// App.tsx

export default function App() {
  return (
    <>
      <div className="flex flex-col items-center justify-center min-h-screen space-y-4">
        <button className="button">Click Me</button>
        <button className="bg-green-500 text-white py-3 px-5 rounded border-none cursor-pointer transition-colors duration-300 hover:bg-green-600">
          Click Me
        </button>
      </div>
    </>
  );
}

^ 스타일링 방식에 따른 구현 비교: 일반 CSS vs Tailwind CSS

 

tailwind css - 디렉티브

디렉티브(Directives) : tailwind 고유의 문법으로, @ 기호로 시작하는 지시어

ㄴ 일반 css 파일 내에서 tailwind의 강력한 기능을 빌려 쓰거나, 빌드 프로세스에 특정 동작을 명령할 때 사용 

 

@apply 

: 여러 개의 tailwind 유틸리티 클래스를 하나의 사용자 정의 클래스 안에 통째로 집어넣을 때 사용하는 디렉티브

ㄴ 여러 요소에 같은 디자인을 반복적으로 적용해야 할 때 사용 

/* tailwind.css */

@import "tailwindcss";

.btns {
  @apply bg-green-500 text-white py-3 px-5 rounded border-none cursor-pointer transition-colors duration-300 hover:bg-green-600;

}
// App.tsx

export default function App() {
  return (
    <>
      <div className="flex flex-col items-center justify-center min-h-screen space-y-4">
        <button className="btns">
          Click Me
        </button>

        <button className="btns">
          Click Me
        </button>

        <button className="btns">
          Click Me
        </button>
      </div>
    </>
  );
}

 

@layer

: 스타일 계층 구조 

  • theme
    • tailwind 기본값을 커스터마이징 하기 위해서 사용하는 계층
  • base
    • 브라우저의 기본 스타일을 초기화하기 위한 계층
  • components
    • 재사용 가능한 UI 컴포넌트의 스타일을 정의하기 위한 계층

 

/* tailwind.css */

@import "tailwindcss";

@layer components {
  .btns {
    @apply bg-green-500 text-white py-3 px-5 rounded border-none cursor-pointer transition-colors duration-300 hover:bg-green-600;

  }
}
// App.tsx

export default function App() {
  return (
    <>
      <div className="flex flex-col items-center justify-center min-h-screen space-y-4">
        <button className="btns">
          Click Me
        </button>

        <button className="btns">
          Click Me
        </button>

        <button className="btns">
          Click Me
        </button>
      </div>
    </>
  );
}

 

tailwind css - 조건부 스타일

className 안에 같은 성격을 가진 유틸리티 클래스가 여러 개 적혀 있다면, 나중에 적힌 클래스가 우선 적용

// App.tsx

export default function App() {
  return (
    <>
      <div className="flex flex-col items-center justify-center min-h-screen space-y-4">
        <button className="bg-green-500 bg-rose-500 text-white py-3 px-5 rounded border-none cursor-pointer transition-colors duration-300 hover:bg-green-600">
          Click Me
        </button>
      </div>
    </>
  );
}

^ bg-green-500과 bg-rose-500 중에 후자가 적용됨 

 

tailwind-merge : 클래스 목록을 분석하여, 성격 중복으로 충돌하는 속성 중 마지막 것만 남기고 나머지는 깔끔하게 삭제해주는 함수

npm i tailwind-merge 명령어를 사용하여 다운로드 

 

className={twMerge(``)}

 

// App.tsx

import { twMerge } from "tailwind-merge";

export default function App() {

  const isRed = false;

  return (
    <>
      <div className="flex flex-col items-center justify-center min-h-screen space-y-4">
        <button
          className={twMerge(
            `bg-green-500  text-white py-3 px-5 rounded border-none cursor-pointer transition-colors duration-300 hover:bg-green-600`, isRed && 'bg-rose-500'
          )}
        >
          Click Me
        </button>
      </div>
    </>
  );
}

 

이미지 렌더링

1. public/images/image.jpg 렌더링

절대 경로 사용 

// App.tsx

export default function App() {
  return (
    <>
      <img src="/images/sample.jpg" alt="bicycle" />
    </>
  );
}

 

2. src/assets/images/image.jpg 렌더링

절대 경로 사용 불가능 

∵ 번들링 프로세스로 인해 발생하는 경로의 변화

 

번들링 프로세스 : 리액트 프로젝트를 build 하면 모든 소스코드는 dist 폴더에 모이게 됨, 이때 src 폴더 내의 이미지들은 파일명에 고유한 해시값이 붙은 채로 이름이 바뀌고 경로도 재배치

--> 이미지 파일을 개별적으로 import, 중괄호를 사용해 변수를 src 속성에 전달하는 방식 사용 

// App.tsx

import sample from "./assets/images/sample.jpg";

export default function App() {
  return (
    <>
      <img src={sample} alt="bicycle" />
    </>
  );
}

 

이미지 렌더링 (CSS)

css를 사용한 이미지 렌더링

 

방법 1. 일반 CSS

1-1. public/images/image.jpg 렌더링

절대 경로 사용 

/* globals.css */

.bg {
  background-image: url("/images/sample.jpg");
  width: 400px;
  height: 400px;
}
// App.tsx

export default function App() {
  return (
    <>
      <div className="bg"></div>
    </>
  );
}

 

1-2. src/assets/images/image.jpg 렌더링

상대 경로 사용

/* globals.css */

.bg {
  background-image: url("../assets/images/sample.jpg");
  width: 400px;
  height: 400px;
}
// App.tsx

export default function App() {
  return (
    <>
      <div className="bg"></div>
    </>
  );
}

 

방법 2. Tailwind CSS

2-1. 외부 URL 렌더링 

// App.tsx

export default function App() {
  return (
    <>
      <div className="bg-[url(https://cdn.pixabay.com/photo/2024/07/16/12/20/pipe-8899206_1280.jpg)] w-[400px] h-[400px]"></div>
    </>
  );
}

 

2. public/images/image.jpg 렌더링

절대 경로 사용

// App.tsx

export default function App() {
  return (
    <>
      <div className="bg-[url(/images/sample.jpg)] w-[400px] h-[400px]"></div>
    </>
  );
}

 

3. src/assets/images/image.jpg 렌더링

* tailwind 클래스 내부에 자바스크립트 변수를 섞어 쓸 수 없음

// App.tsx

import sample from "./assets/images/sample.jpg";

export default function App() {
  return (
    <>
      <div className={`bg-[url(${sample})] w-[400px] h-[400px]`}></div>
    </>
  );
}

 

∴ 인라인 스타일 사용 

== style 속성으로 변수를 전달 

// App.tsx

import sample from "./assets/images/sample.jpg";

export default function App() {
  return (
    <>
      <div
        className={`w-[400px] h-[400px]`}
        style={{ backgroundImage: `url(${sample})` }}
      ></div>
    </>
  );
}

 

구글 폰트 적용하기

 

  1. HTML 연결
    • index.html 파일의 <head> 태그에 복사한 <link> 태그들 붙여넣기
  2. CSS 정의
    • src/styles/fonts.css 파일에 CSS class 코드 붙여넣기 
  3. 스타일 통합
    • src/styles/index.css 파일에 @import "./fonts.css"; 추가
  4. 메인 로드
    • src/main.tsx 파일에 import "./styles/index.css"; 추가