문득 생각이 들었다.
사실 이전엔 class
가 예약어이기 때문이라는 이유로 안된다고 하고 넘어갔었는데 다시 곱씹어보면 이상하다.
공식문서에서도 예약어로 다루고 있다. https://ko.react.dev/learn/writing-markup-with-jsx
근데 곰곰히 생각해보면, jsx로 된 컴포넌트를 렌더링(실행) 하면, React.createElement함수를 실행하는 것이다. 그리고 React.createElement가 어떻게 되었든, 결국 dom api
를 내부적으로 동작시킬 것이다. 결국, dom api
의 attribute
를 활용하여 element
를 만들게 될 것이다.
'이러한 부분을 고려하여 만들어진게 아닐까?' 라고 생각하고 접근하기 시작했다.
react가 js로 html
을 만들어내는 과정을 추상화 하고 있다면, jsx의 html
에 들어가는 tag
들에 attribute
를 넣는 과정은 dom api
를 통해 attribute
를 추가하는 과정과 일맥상통한다.
그래서 dom api
를 살펴보면, setAttribute
과정에 class
는 없다. className
은 존재하지만, class
는 없다.
label
을 만들어보면 이 과정에서도 htmlFor
있지만, for
은 없다.
그러니까 기본적으로 dom api
를 만들때부터, dom api
를 통해 생성하는 과정에서 key
로 받을 값들에 className
과 htmlFor
가 존재한 것이다.
근데 여기서 의문이 있다.
react 이정도도 모를까? 당연히 알고 있지 않을까? 그리고 이걸 해결하는 과정이 크게 안 복잡할 것 같다고 생각했다.
그리고 실제로 찾아보니 그들은 당연히 이 문제를 알고 있었다. 그리 어렵지 않다는 사실도 알고 있었고, 멘탈 모델상 class
를 className
대신 써야 한다는 입장도 많았던 것 같다.
나도 동의한다. jsx를 사용하는 결과가 js객체로의 변환이어도, 사용성에 있어서는 html
태그와 js코드를 혼합해서 작성한다.
멘탈모델
에 있어서 html
태그에 기입하는 그대로 작성할 수 있도록 해놓는 것이 사용성에 있어서 더 맞지 않을까??라는 고민은 당연히 했듯이
리액트를 시작할때 마크업에 class
를 사용해서 만들어도 문제가 되지 않은 겨험들이 있을 것 이다. 이 부분은 lint
에서는 에러가 발생하지만, class
사용해도 문제없이 동작한다.
react 16버전부터는 class로 작성해도 가능하도록 해놓았다.
물론 lint
가 빨간줄을 그어버리기 때문에 불편하지만, 그 마저도 수정하면 변경할 수 있긴하다.
16이전의 react-dom.development.js
var HTMLDOMPropertyConfig = {
...중략 ...
autoPlay: HAS_BOOLEAN_VALUE,
capture: HAS_BOOLEAN_VALUE,
cellPadding: 0,
cellSpacing: 0,
charSet: 0,
challenge: 0,
checked: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE,
cite: 0,
classID: 0,
className: 0,
... 중략 ...
}}
16이후 react-dom.development.js
var possibleStandardNames = {
// HTML
...중략 ...
capture: 'capture',
cellpadding: 'cellPadding',
cellspacing: 'cellSpacing',
challenge: 'challenge',
charset: 'charSet',
checked: 'checked',
children: 'children',
cite: 'cite',
// 여기 있다.
class: 'className',
classid: 'classID',
classname: 'className',
...중략...
strokedasharray: 'strokeDasharray',
'stroke-dasharray': 'strokeDasharray',
strokedashoffset: 'strokeDashoffset',
'stroke-dashoffset': 'strokeDashoffset',
strokelinecap: 'strokeLinecap',
'stroke-linecap': 'strokeLinecap',
strokelinejoin: 'strokeLinejoin',
'stroke-linejoin': 'strokeLinejoin',
strokemiterlimit: 'strokeMiterlimit',
'stroke-miterlimit': 'strokeMiterlimit',
strokewidth: 'strokeWidth',
'stroke-width': 'strokeWidth',
strokeopacity: 'strokeOpacity',
}
if (possibleStandardNames.hasOwnProperty(lowerCasedName)) {
var standardName = possibleStandardNames[lowerCasedName];
if (standardName !== name) {
error('Invalid DOM property `%s`. Did you mean `%s`?', name, standardName);
warnedProperties$1[name] = true;
return true;
}
}
Invalid DOM property
이 부분은 익숙하다 %s
. Did you mean %s
?'Invalid DOM property
이걸로 만났었던 에러가 여기 있다. warning은 발생하지만 동작하는 것은 알 수 있다. warn에 넣어둔걸 보면 권장하지는 않는것 같다.class
. Did you mean className
잘 살펴보면, stroke-linecap
같이 늘 복붙해오면 딸려오는 마크업이 lint
에서 에러를 뱉어내지만, 리액트 코드 내부적으로 해당 코드가 동작할 수 있게 작성해놓은 걸 알 수 있다.