Sass를 공부하던중 저 혼자 Equality Operator의 작동 결과가 다른것을 알게 됐습니다.

문제

@debug 1px != 1rem;
@debug 1 != 1px;
@debug 1px != 1rem;
@debug 1 != 1px;

아주 간단한 코드입니다. 전자의 경우 당연히 true가 나와야 할 것이고, 후자의 경우에도 true가 나오는게 당연할거라고 생각했습니다.

공식 문서에는 true라고 돼있습니다.

그런데...

node-sass에서는_false

보시다시피 @debug 1 != 1px;false가 나오고 있습니다.

1 == 1px 이라고...??

버전을 체크해보자

node-sass 버전

제가 사용한 node-sass의 버전입니다. node-sass는 7.0.3으로 최신 버전이 맞는데, 밑에 libsass라는 Sass Compiler의 버전이 3.5.5라고 나와 있습니다.

LibSass 버전 3.6.5 변경사항

LibSass는 Sass 코드를 컴파일 할 수 있는 컴파일러로, C와 C++로 만들어진 라이브러리입니다. 즉 node-sasslibsass의 도움을 받아 .scss 코드들을 .css로 변환해주고 있는 것입니다. (node-sass를 wrapper(=implementer)라고 부르는 이유입니다.)

LibSass Repo

그런데 위 레포지토리를 보면, 가장 최신 버전은 21년 5월에 올라온 버전 3.6.5 입니다. 대체 어떤게 달라졌기에 3.5.5에서는 1 == 1px이라고 했다가, 1 != 1px로 바뀐걸까요?

버전 3.6 대의 Changelog를 한번 살펴보다가 버전 3.6.5의 수정 내역중 이런 문구를 발견했습니다.

libsass changelog

밑에서 네번째 줄에 보시면 Fix edge case regarding unit-less number equality as object keys 라는 문구가 있습니다. 해석하면 '단위가 없는 숫자의 동일성을 객체의 키로 인식하는 edge case 수정' 정도가 될 것 같습니다. (edge case란 디버깅 혹은 단위 테스트에서 사용되는 용어로 여기에서는 '특이 케이스'정도로 생각할 수 있겠습니다.)

제 레벨에서는 이해하기 어려운 문제이지만, 일단 조금 읽어본 바로는 Sass 컴파일러 내부에서 unordered map 형식의 데이터는 equality check에서 hash 싱크 체크를 건너 뛰는 문제가 있는 것 같았습니다.

관련 issues

이슈 넘버 3094

이슈 넘버 1667

그러다보니 한 쪽이 unit-less일 경우 반대쪽의 단위로 이상한걸 막 써놔도 숫자만 같으면 같다고 판단해버립니다...

1shiwoo

결론: Dart Sass를 쓰자

저같은 초보는 깊게 이해할 수는 없으니 'LibSass 버전 3.6.5에서 Equality Operator 관련 변경사항이 있었구나' 정도만 알고 넘어가도 좋겠습니다.

다만, 이 과정에서 또 알게된 중요한 사실은 LibSass가 deprecated 됐다는 점입니다. Sass 공식 문서에서는 Dart Sass를 이용할 것을 권장하고 있습니다.

libsass changelog

Mac에서 Dart Sass 설치하기

공식 문서

저는 MacOS 환경을 사용하고 있으므로, 공식 문서에서 소개하고 있는 홈브루를 이용하는 방식으로 설치할 수 있습니다. 홈브루가 설치돼 있다면 간단하게 이렇게만 입력하면 끝입니다.

brew install sass/sass/sass
brew install sass/sass/sass

Ruby Virtual Machine (RVM)이 설치된 환경이라면 ruby-sass를 모든 가상환경에서 지워줘야 합니다! ruby-sass도 deprecated 됐습니다.

가장 최근 버전은 1.55.0입니다!

sass 설치 완

package.jsonscripts를 아래와 같은 형식으로 변경하고

{
  "scripts": {
    "sass": "sass --watch scss/scss_실습.scss:src/scss_실습.css"
  }
}
{
  "scripts": {
    "sass": "sass --watch scss/scss_실습.scss:src/scss_실습.css"
  }
}

이제 아래의 코드를 다시 돌려보면...

@debug 1px != 1rem;
@debug 1 != 1px;
@debug 1px != 1rem;
@debug 1 != 1px;

잘 나와요!

짜잔~! 이제 잘 나오네요! 🙌🙌

Sass 공식문서 Contribution도 노려봤습니다

sass-site 레포지토리에 issue 올리고 PR 날려봤습니다. 어떻게 될지는 모르겠지만 이렇게 대형 프로젝트에 기여해보려고 한건 처음이라 두근두근 하네요!

10/4 업데이트: PR 실패ㅠㅠ

알고보니 해당 내용이 이미 공식 문서에 토글 버튼으로 숨어있더라고요ㅎㅎ 비록 성공하지는 못했지만 좋은 도전이었고 앞으로 오픈 소스 기여에 계속 도전해보겠습니다!!