들어가며..
현재 개발 중인 서비스에서 shadow DOM을 생성하고 해당 DOM의 높이를 계산하는 로직을 작성해야 하는 일이 있었습니다. JavaScript 코드만으로 DOM에 스타일을 적용해야 했는데, 여러 스타일 속성을 한꺼번에 적용해야 하다 보니 흔히 사용하던 element.style이나 classList.add 외에 더 나은 방법이 있을지 고민하게 되었습니다. 다른 방법들을 찾아보니, 생각보다 다양한 방식으로 스타일을 적용할 수 있었고, 이번 기회에 각 방법을 정리하고 소개해 보려 합니다.
스타일을 적용하는 방법들은..
1. classList.add 사용하기
classList.add 메서드를 사용하면 하나 이상의 특정 클래스 이름을 요소에 추가할 수 있습니다. HTML의 class속성값을 간편하게 관리할 수 있는 이 방법은 CSS 클래스에 정의된 스타일을 재사용할 수 있어 코드의 가독성을 높이고, 유지보수를 용이하게 합니다.
기본 사용법
const element = document.createElement('div');
element.classList.add('myClass');
// 쉼표로 구분하여 여러 클래스를 한 번에 추가할 수 있으며, 이미 존재하는 class는 중복으로 추가되지 않습니다.
element.classList.add('myClass1', 'myClass2');
// 잘못된 값(null, undefined)을 전달하는 경우에는 에러가 발생합니다.
element.classList.add(null); // ❌ TypeError
2. setAttribute('style', '스타일')
CSS 스타일을 문자열로 전달하여 특정 DOM 요소의 style 속성을 직접 수정하는 방식입니다. 문자열을 파싱하여 CSSStyleDeclaration 객체로 변환한 뒤, 해당 스타일을 적용하는 방식이어서 반드시 문자열 기반으로 스타일링을 해야 합니다. style 속성 자체를 조작하기 때문에 인라인 스타일 전체를 덮어쓰게 되는 특징이 있습니다.
기본 사용법
const element = document.createElement('div');
// 문자열 기반으로 스타일 설정
element.setAttribute('style', 'color: red; background-color: blue;');
// 아래와 같이 객체나 비문자열을 전달하면 에러가 발생합니다.
element.setAttribute('style', { color: 'red' }); // ❌ 에러
3. element.style.property
JavaScript에서 요소의 개별 스타일을 속성을 직접 설정할 수 있는 방법입니다.
기본 사용법
const element = document.createElement('div');
element.style.color = 'red';
element.style.fontSize = '16px';
4. element.style.cssText
JavaScript에서 DOM 요소의 인라인 스타일을 설정하거나 조회하는 데 사용됩니다. 여러 스타일을 문자열 형식으로 설정할 수 있습니다.
기본 사용법
const element = document.createElement('div');
element.style.cssText = "color: blue; font-size: 20px;";
// 다음과 같이 camelCase 스타일은 무시되므로 주의가 필요합니다.
element.style.cssText = "backgroundColor: yellow;"; // ❌
// 가독성을 위해 다음과 같이 사용할 수도 있습니다.
element.style.cssText = `
position: absolute;
padding: 4px;
border: 1px solid black;
white-space: nowrap;
`;
// +=연산자를 사용하여 기존 스타일에 새 스타일을 덧붙일 수 있습니다.
element.style.cssText += " border: 1px solid black;";
5. Object.assign(element.style, { 스타일 속성 })
Object.assign으로 스타일 객체를 병합하여 설정할 수 있습니다. 내부적으로 for-in 루프와 비슷한 방식으로 스타일 속성을 설정하게 됩니다.
기본 사용법
Object.assign(element.style, {
backgroundColor: 'yellow', // camelCase로 작성해야 함
fontWeight: 'bold',
margin: '10px' // 숫자형 값에는 단위 지정이 필수,
fontSize: undefined // ❌ 잘못된 값은 무시됨
});
6. 객체 리터럴 순회 with element.style
스타일을 객체로 정의 후 반복문을 통해 객체 리터럴을 순회하여 스타일 속성을 설정하는 방식입니다.
기본 사용법
const styles = {
color: 'red',
backgroundColor: 'blue',
border: '1px solid black',
};
for (const [key, value] of Object.entries(styles)) {
element.style[key] = value;
}
// 위 방식 이외에, 다양한 방식으로 설정 가능
for (const property in styles) {
element.style[property] = styles[property];
}
Object.entries(styles).forEach(([property, value]) => {
element.style[property] = value;
});
Object.keys(styles).forEach((property) => {
element.style[property] = styles[property];
});
그래서 어떤 방법을 써야 할까..
사실 정답은 없습니다. 프로젝트나 팀의 상황에 따라 적합한 방식이 다르기 때문입니다. 다만, 특정 상황에서는 여러 방법들 중 비교적 더 좋은 방법이 존재하곤 합니다. 각 방법들의 특징과 함께 사용하기 좋은 사례를 간단하게 살펴보겠습니다.
1. classList.add
장점
- CSS에서 미리 정의한 스타일을 재사용 가능
- 유지보수성과 가독성이 높음
- 여러 클래스 추가 가능
- 브라우저가 미리 정의된 CSS 클래스만 처리하므로 CSSOM 접근만으로 처리 가능하므로 효율이 좋을 수 있음
단점
- 세부적으로 한두 가지 속성만 변경하기 어려움
- 동적인 값을 적용하기 어려움
- 한 번에 여러 클래스를 추가할 때 브라우저가 각 클래스에 대해 여러 번 스타일을 다시 계산하므로 계산 비용이 증가함
- css 파일 관리가 필요
사용 사례
- 재사용 가능한 디자인 시스템에서 스타일 적용할 경우 (미리 정의된 스타일 세트 적용 시)
- 상태에 따라 UI를 동적으로 업데이트하는 경우 (예: 활성/비활성 토글)
2. setAttribute('style', '스타일')
장점
- 간단하게 스타일을 지정할 수 있음
- 동적으로 생성된 DOM 요소의 초기 스타일 지정에 적합
- 전체 스타일을 문자열 하나로 한 번에 지정할 수 있음
단점
- 기존 스타일이 전부 덮어씌워지므로, 특정 스타일만 변경할 수 없음
- 스타일이 많은 경우, 문자열 길이가 늘어나기 때문에 가독성과 유지보수성이 좋지 않음
- 문자열로 스타일을 지정하므로, 오타 발생 시 스타일이 지정되지 않는 문제가 있으며 디버깅이 어려움
- 문자열을 파싱하는데에 비용이 들며, 스타일이 많아질수록 성능 저하가 나타날 수 있음
사용 사례
- 특정 요소의 스타일을 고정적으로 설정하는 경우
- 새롭게 생성된 요소에 초기 스타일을 지정할 경우
3. element.style.property
장점
- 직관적이고 간단함
- 동적인 값 적용이 용이
- 세부 속성에 대해 직접적인 수정 가능
단점
- 속성이 많아지면 코드 가독성이 떨어짐
- 여러 속성을 적용할 때 번거로움
사용 사례
- 간단한 스타일 변경할 경우
- 사용자의 인터랙션(클릭, hover)에 따라 특정 속성을 수정할 경우
4. element.style.cssText
장점
- CSS 문법을 그대로 사용 가능
- 여러 스타일 한 번에 적용 가능
- 문자열 템플릿으로 동적 생성 용이
단점
- 기존 인라인 스타일을 덮어쓸 수 있음
- 문자열 조작이 필요해 오류 발생 가능성 있음
- setAttribute('style')처럼 문자열을 파싱하는데에 비용이 들며, 스타일이 많아질수록 성능 저하가 나타날 수 있음
사용 사례
- 간단한 프로토타이핑의 경우
- 초기 DOM 생성 시 간단한 스타일 설정할 경우
- 한 번에 여러 스타일을 적용해야 할 경우
5. Object.assign(element.style, { 스타일 속성 })
장점
- 단일 명령으로 한 번에 여러 속성을 적용할 수 있음
- 코드의 가독성이 높음
- 기존 스타일을 유지하며 새로운 속성을 추가하거나 덮어쓸 수 있음
단점
- style 객체의 특성상 일부 제약이 존재 (커스텀 속성, !important 등 사용불가)
- 스타일 재사용성 저하
사용 사례
- 여러 스타일 속성을 설정해야 하는 경우
- 동적 스타일이 필요한 경우
6. 객체 리터럴 순회 with element.style
장점
- 동적으로 스타일을 생성하거나 조합이 가능
- 유지보수성과 재사용성 높음
단점
- 추가 로직이 필요해 상대적으로 복잡함
- 속성 개수가 많을 수록 js레벨에서 약간의 오버헤드가 발생
사용 사례
- 동적 스타일 적용할 경우
- 스타일 변경 로직을 함수화하는 등 재사용성을 높이고자 하는 경우
그래서 결론은..
JavaScript를 사용해 DOM 스타일을 설정하는 방법은 다양하며, 각 방식은 특정 상황에 적합한 장단점을 가지고 있습니다. 이번 글에서 살펴본 방법들은 모두 유용하지만, 프로젝트의 성격, 팀의 코드 스타일, 그리고 브라우저 성능 최적화 요구에 따라 적절한 방법을 선택해야 합니다.
제 경우에는, element.style.cssText를 사용했습니다. 화면에 렌더링되지 않는 shadow DOM이었고, 높이 계산 후 DOM을 제거하기 때문에 재사용성을 고려할 필요가 없었습니다. 높이 계산만이 목적이었기에 최소한의 스타일만 적용했고, cssText의 단점은 이 경우 문제가 되지 않았습니다. 이러한 맥락에서 cssText가 적합하다 판단하였습니다.
사실 어떤 방법을 선택하든, 자유라고 생각합니다. 프로젝트에 적합한 스타일 적용 방식을 사용하면 된다고 생각합니다. 팀원들과의 협의를 통해 프로젝트 또는 상황에 맞는 표준을 정하면 되겠습니다.
혹시 더 나은 방법이 있다면 공유 부탁드립니다! 또한, 잘못된 점이나 보완이 필요한 내용은 댓글로 의견을 남겨주시면 감사하겠습니다.
'About IT > 웹 개발' 카테고리의 다른 글
Biome에 대해 아세요? (0) | 2025.02.28 |
---|---|
익숙한 듯 익숙하지 않은 쿠키(Cookie)의 보안에 대해 알아보자 (0) | 2025.02.03 |
알고 쓰는 서브 픽셀: 웹 개발자와 디자이너의 협업을 위한 필수 지식 (1) | 2024.12.22 |
Next.js 배포 실패? Vercel에서 Sentry CLI 오류 해결하기 (0) | 2024.11.24 |
ReactQuery로 브라우저 탭 간 데이터 동기화 해결하기 (1) | 2024.10.22 |