새로 시작한 프로젝트에서 styled-component 남용을 방지하기 위해 emotion을 도입하여 사용하기로 했다.
Emotion 도입 이유
간단한 스타일이 필요한 요소는 별도로 styled-component로 생성하지 않고 시맨틱 태그와 함께 inline style을 적용하여 구현한다면 코드도 더욱 간결해지고 시멘틱 태그의 적절한 사용으로 더나은 SEO에 기여할 수 있을 것으로 생각되었기 때문이다.
에러발생 코드
...
import { css } from '@emotion/react';
const Layout = ({ children }: LayoutProps) => {
return (
<div
css={css`
width: 90%;
margin: 0 auto;
`}
>
<Navbar />
{children}
<Floating />
</div>
);
};
위와 같이 Layout 컴포넌트에 emotion을 사용하여 inline-style을 적용하려고 했는데, 에러가 발생했다.
Error Message
Type '{ children: Element[]; css: SerializedStyles; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'. Property 'css' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
해결방법
처음엔 에러메시지를 보고 type 설정을 제대로 해주지 않아서 발생한 에러 혹은 airbnb-style-guide 로 인한 에러일 것으로 판단하고 구글링을 했다.
airbnb-style-guide 관련해서는 별다른 해결방법을 찾을 수 없었고, Layout 컴포넌트에서 @emotion/react 를 import 하고 tsconfig.json 파일 compileOptions에 "types": ["@emotion/core"] 속성을 추가해서 해결했다는 글을 발견 했으나, 이 방법의 경우 또 다른 에러를 출력했다.
다른 자료를 찾아보니 아래와 같이 tsconfig.json 파일 CompileOptions 의 jsx의 값을 reac-jsx로 수정하고, "jsxImportSource": "@emotion/react" 속성을 추가하는 것으로 간단하게 해결할 수 있었다.
자료를 조금 더 찾아보았지만 정확히 어떤 로직으로 문제가 해결되는지는 이해하지 못했으나 react에서 jsx를 컴파일해서 사용하고, emotion/react를 사용하여 해당 jsx 를 import 하는 것을 config에 지정을 해줘야 한다고 어림 짐작이 된다.
타입스크립트 핸드북을 한번 훑어보긴 했는데, 이런 부분을 전혀 캐치하지 못했다. 프로젝트를 진행하면서 이런 이해가 안되는 부분을 기억하고 추후 다시 핸드북을 학습하면서 중점적으로 학습해야겠다.
참고
https://www.typescriptlang.org/tsconfig#jsxImportSource
https://github.com/emotion-js/emotion/issues/2111#issuecomment-732763318
Environment Information
- react: 18.2.0
- next: 12.2.5
- typescript: 4.7.4
- @emtion/react: 11.10.0