🛠️ 프로젝트/🐻 곰곰 다이어리

[곰곰 다이어리] Style을 반환해주는 유틸 함수 만들기 (타입스크립트에서 css module import 하기)

썸머몽 2025. 8. 6. 00:32
728x90

곰곰 다이어리는 css module을 쓰고 있다.

 

답장 리스트를 보는 화면에는 조건에 따라 텍스트의 색이 바뀌어야 한다.

 

예를 들어,

내가 다이어리의 주인이다 -> 검정색

내가 한 답장이다 -> 분홍색

className={
  person._id === correctAnswerer
    ? Styles.correctAnswerer
    : person._id === diaryId
    ? Styles.notOwner
    : Styles.owner
}

 

이런 식으로 되어 있는데 (사실상 notOwner는 쓰지 않는다;)

person._id에 따라 className을 바꿔주고 있다.

 

이걸 Style을 뱉어내는 유틸 함수로 바꿔서 JSX에는 함수를 실행하기만 하도록 수정해봤다.

className={getClassNameForAnswerer({
  userId: person._id,
  correctAnswerer: correctAnswerer,
  diaryId: diaryId,
  Style: Style,
})}
const getClassNameForAnswerer = (props: IAnswererClassName): string | undefined => {
  const { userId, correctAnswerer, diaryId, Style } = props;

  if (!correctAnswerer || !diaryId) {
    return undefined;
  }

  if (userId === correctAnswerer) {
    return Style.correctAnswerer;
  }

  return Style.owner;
};

 

Style의 type은 뭘까?

처음엔 단순히 string이라고 생각했는데 Style에서 타입을 읽지 못해 에러가 떴다.

Style에 호버해보니 Style의 type은 CSSModuleClasses였다.

 

interface IAnswererClassName {
  userId: string;
  correctAnswerer: string | undefined;
  diaryId: string | undefined;
  Style: CSSModuleClasses;
}

 

생각해보니 vite를 쓰지 않고 리팩토링을 했을 때 타입스크립트가 Style의 타입을 이해하지 못해 에러가 많이 떴었다.

그때 한참 src/global.d.ts에 다음과 같이 적어 타입을 선언해줘야 했었는데,

declare module '*.module.css' {
  const content: { [key: string]: string };
  export = content;
}
type CSSModuleClasses = {
    readonly [key: string]: string;
}

 

이게 그거였다!


 

CSS Modules는 CSS 파일의 클래스 이름을 자동으로 고유하게 만들어서 전역적인 이름 충돌을 방지한다.

/* MyComponent.module.scss */
.container {
  background-color: #f0f0f0;
}
// MyComponent.tsx
import styles from './MyComponent.module.scss';

export const MyComponent = () => {
  // `styles.container`는 고유한 클래스명으로 변환됩니다.
  // 예: `MyComponent_container__abc12`
  return <div className={styles.container}>...</div>;
};

 

여기서 import styles from ~ 을 보면 꼭 자바스크립트 파일처럼 CSS 파일을 가져와 객체로 사용하는 걸 알 수 있다.

 

이 객체는 CSS 파일에 정의된 클래스명(예제에서는 container)를 key로, 

자동으로 생성되는 고유한 클래스명 (MyComponent_container__abc12)을 value로 가진다.

 

그런데 타입스크립트는 이 styles 객체에 어떤 키가 있는지 알지 못하기 때문에 단순히 string으로 접근할 수 없게 된다.

styles는 특정 클래스명들을 key로 가지고 있는 객체기 때문이다.

 

vite에는 client.d.ts에 자동으로 저 CSSModuleClasses 인터페이스가 선언되어 있다!

 

제대로 알고 쓰자...

728x90