정찬명

건강한 CSS 설계 원칙

내가 추구하는 건강한 CSS 설계 원칙을 정리해 보았다. 실수 투성이었던 과거의 나에게 이런 편지를 보내고 싶다.

첫째, 적용 범위를 명확하게 하자

common.css는 보통 모든 페이지에서 참조하는 스타일로 수많은 코드가 쓰레기다. 지금 당장 common.css 파일이 몇 줄인 지, 그리고 얼마나 많은 코드를 낭비하는지 확인해 보길 바란다.

크롬 개발자 도구에서 명령어 실행 창(Cmd-Shift-P)을 열어 Show Coverage 탭을 활성화한 다음 유효한 CSS 코드가 몇 줄이나 되는지 점검해 보자. 그래프에서 붉은색으로 표시한 영역이 낭비한 CSS 코드 비율이고 친절하게 몇 ‘%’ 수준인지 알려준다.

사용하지 않는 코드를 참조하지 않는 것이 중요하다. common.css 파일에 코드가 늘어날수록 이틀 뒤 너의 한숨도 늘어날 것이다. 외부 스타일(external style)을 사용하는 것은 더 이상 미덕이 아니다. 내장 스타일(embeded style)로 책임 범위를 명확하게 줄이는 것이 성능과 유지 보수에 도움이 된다.

A 페이지와 B 페이지가 같은 스타일을 공유할 때 C 페이지에서는 절대로 참조하지 않도록 한다. 차라리 중복 코드가 발생하더라도 내장 스타일을 쓰는 게 낫다.

이런 규칙을 적용하면 네가 작성한 CSS 코드의 책임 범위가 명확해진다. 유지 보수할 때 사이드 이펙트를 줄일 수 있고 생명 주기가 끝난 코드를 안전하게 제거할 수 있다.

둘째, 다른 코드를 덮어쓰지 말자

reset.css 따위의 전역 스타일로 공용 선택자 또는 타입 선택자를 초기화하는 경우가 있다. 꼭 필요한 경우는 극히 제한적인데 과도한 초기화가 문제다. 다시 덮어쓸 수 있는 속성은 선언하지 말고 이미 선언한 속성은 다시 덮어쓰지 말자.

공용 선택자 ‘*‘를 초기화하면 이 선택자에 적용한 속성은 언젠가 틀림없이 덮어쓰게 된다. 한두 번 정도가 아니라 덮어쓰기를 계속해서 반복할 것이다. 반복해서 덮어써야 하는 속성을 초기화하는 게 맞는지 고민해 볼 필요가 있다. 타입 선택자를 초기화하는 것도 마찬가지다.

개발자 도구에서 Styles 탭을 열어 얼마나 많은 코드에 취소선이 그어져 있는지 확인해 보자. 취소선은 기존에 작성한 코드가 더 이상 유효하지 않은 상태라는 것을 의미한다.

취소한 코드는 쓰레기다. 쓰레기 밭에서 뭔가 발견하려고 애쓰던 수많은 시간이 안타깝다. 덮어쓰기를 안 할 수는 없다. 극도로 지양하는 것이 좋다.

셋째, 단일 선택자를 사용하자

누군가 내 선택자를 덮어쓸 수 있다는 것을 염두하면 내가 작성하는 선택자의 명시도(specificity)는 가능한 낮게 유지해야 한다. 기본으로 10점을 유지하고 최대 20점을 초과하지 않도록 한다. 명시도 점수 계산기.

선택자를 보면 내용을 이해할 수 있는 시멘틱한 표현이 좋다. 스타일을 연상하는 이름은 피하는 게 좋다. 스타일은 언제든 변경의 여지가 있으니까.

id 선택자는 JavaScript에서 DOM을 선택하는 용도로 사용하고, class 선택자는 스타일을 위해 사용한다.

// DO NOT
// 명시도 30점, 표현, 각진 붉은 스타일로 바꾸면 선택자 이름도 바꿔야
.box.round.blue { ... }

// DO THIS
// 명시도 10점, 내용, 다른 스타일로 변경해도 선택자 이름은 유효하다
.news__item { ... }

이런 고민을 하다가 만난 것이 BEM(Block-Element-Modifier)이다. BEM은 선택자를 의미 있는 이름으로 작성하도록 하고 명시도를 낮추는 데 효과적이었다.

결론

처음 CSS를 접했을 때 한 번 선언한 코드를 여러 곳에서 다시 조립하여 재사용할 수 있는 것이 축복처럼 느껴졌다. 하지만 이제는 쓰레기 더미에서 진주알을 찾는 기분이다. CSS 코드의 책임 범위를 명확하게 축소하자. 유효한 코드보다 쓰레기와 취소선이 더 많은 디스토피아를 만들지 않기를 바란다.

마지막으로 오랜 경험에 따라 꼭 필요했던 속성을 초기화하고 선택자 명시도를 ‘0점’으로 만든 나만의 reset.css를 공유해 본다. 나는 매 프로젝트마다 이 코드에서 점진적으로 불필요한 코드를 제거하고 필요한 코드를 몇 줄 추가하는 편이다.