css 가두기

Sming·2024년 1월 1일
12
post-thumbnail

오랜만입니다. 최근에 게임을 열심히 하느라 블로그를 쓰는게 지연됬네요..! 이번에는 제가 공통 모듈을 개발하며 겪었던 style 캡슐화에 대한 이슈를 다뤄볼것 입니당.🫠

현재의 문제

일단 현재 저는 공통 모듈 라이브러리를 개발을 하고 있습니다.

기존에 style을 pure css (.css) 를 이용하고 있었는데요. 그러다 보니 이 프로젝트에 사용되는 특정 모듈을 빼내서 공통 모듈로 만들때 이 css를 그대로 옮겼어야 됬는데요. (css가 천줄 이상 존재하였습니다.)

하지만 css 특성상 global에도 오염되는 문제가 존재하여 해결이 필요했었는데요.

이 공통 모듈은 빠르게 만들어 다른 도메인에 제공해야했기에 이에 대해 해결을 빠르게 진행했어야 됬습니다.

그러면 단 하루만에 어떻게 캡슐화된 css를 적용시켰는지 저의 고민을 함께 보시죠.

module css

일단 처음에 고려했던것은 module css였습니다. 하지만 module css를 변환할때 문제가 있었는데요. 기존 css에서는 className을 부여하고 그거에 대한 stylesheet를 작성했었습니다. 그리고 태그의 자식요소, 형제요소와 같이 참조하도록 하는 선택자들이 꽤 존재하였습니다.

하지만 module css에서는 className을 다음과 같이 styles객체를 통해서 참조하기에 기존 css를 하나하나 이렇게 변경하기에는 무리가 있다고 생각하여 다음방법을 고려했습니다.

import styles from './index.module.css';

const Component = () => {
  return (
    <div className={styles.component}></div>
  )
}

styled-components (css-in-js)

그래서 다음생각한 방법은 styled-components였습니다. styled-components를 이용하면 역시 스타일이 저절로 캡슐화되고, 브라우저의 호환성에 맞도록 webkit등을 넣어주기때문에 이를 이용하여 스타일을 재구축하려고 했습니다.

하지만 역시 common.css를 포함하여 몇천줄이 되는 코드를 styled-components로 옮기는것은 꽤 많은 시간이 걸릴것이라고 예측이 되었습니다. (기존코드가 styled-components로 변경에 쉽지 않은 스타일 시트였습니다..🥲)

shadow-dom 👻

그래서 번뜩이며 생각해낸것이 shadow-dom이였습니다. shadow-dom이란 말그대로 그림자 돔입니다. 그렇기에 실제 돔에 붙어있는게 아니라 숨겨진 dom tree가 기존 dom tree에 붙는 방식으로 동작을 하며, 이 숨겨진 dom tree는 내부의 스타일이 바깥에 영향을 끼치지 않도록 캡슐화를 해버립니다.

그렇기에 Web Component라는 기술에서 핵심적으로 사용되는것이 shadow-dom입니다. 실제로 개발자도구에서 이와 같은것을 찍어보면 shadow-dom으로 구성되어있는것을 확인할 수 있습니다.

const shadowRoot = this.attachShadow({ mode: "open" });

사용방법은 다음과 같이 shadowRoot에 attachShadow를 이용하여 dom을 shadow dom으로 만들어 줄 수 있습니다.

그리고 이 안에 공통모듈을 css와 함께 붙인것을 넣어주면 캡슐화가 완료되는것이죠. 자 이렇게 빠르게 목표를 달성한것 같지만 저는 다음방법을 선택하지 않았습니다. 어떤 이유때문일까요??

shadow-dom 호환성

다음과 같이 can-i-use를 보시면 android chrome에서 120버전 이하의 지원을 하지 않는것을 볼 수 있습니다. ie는 이제는 크게 신경쓰지 않아도 되지만 android chrome은 신경써야될 부분이죠.

물론 shadow-dom polyfill을 이용하면 이를 해결할 수는 있죠. @webcomponents/webcomponentsjs 실제로 이 패키지에서 polyfill을 제공하는데요.

하지만 이를 bundlephobia에 패키지를 검색해보면 125kb 가 나옵니다.

용량이 크다고 난리인 react,react-dom도 합쳐서 135kb 정도이니 매우 큰 용량이죠.
그리고 polyfill에 이 공통 모듈 패키지가 의존되는것은 좋지 않다고 생각되어서 shadow-dom말고 다른 방법으로 할 수 있을지 고민을 이어나갔습니다.

styled-components GlobalStyles

그리고 마지막 고민이자, 현재 공통 모듈에서 이용을 하고 있는 방법인 styled-components의 GlobalStyles를 이용하는것을 채택하였습니다.

이를 선택하게 된것은 단순한 번뜩임이였는데요..! shadow-dom을 하기전 styled-components를 바꾸고 있을때 다음과 같은 생각을 해보았습니다.

common.css는 globalStyle로 이용될텐데 과연 이 globalStyle을 이용하여 common.css를 넣은것은 캡슐화가 될까?

그리고 실제로 확인을 한 결과 캡슐화 하는것이 확인되었습니다. 그래서 다음과 같이 생각을 해보았습니다.

현재 공통 모달을 만들때 이용되는 css를 globalStyles에 넣어서 사용한다면 기존 css를 건드리지 않은 상태로 캡슐화를 진행할 수 있지 않을까?

export const GlobalStyle = createGlobalStyle`
(common.css ...)

(관련도메인.css ...)
`

라고 생각하여 다음과 같이 common.css 와 함께 기존 css를 함께 넣어주니 제대로 동작하는것을 확인하였습니다.

결론

이렇게 실제로 작성해보니 실제 css를 다시 module css, css-in-js처럼 변경하지 않고도 빠르게 캡슐화가 되는 공통 모듈을 만들 수 있었습니다.

목표는 이뤘지만 이것은 공통 모듈을 만들어서 사용하는측에 빠르게 전달하기 위한 야매(?) 방법이기때문에 추후에 pure css로 되어있는것은 styled-components 문법으로 변경할 예정입니다.

그럼에도 불구하고 이런글을 작성하는 이유는 스타일을 캡슐화하는 여러가지 방법에 대한 소개, 그리고 어떤 문제를 겪었을때 어떠한 방법으로든 해결이 가능하다라는것을 공유하고 싶었습니다.

새해복 많이 받으세요~ 🎉

profile
딩구르르

0개의 댓글