현대에 널리 쓰이는 CSS-in-JS 라이브러리는 스타일을 동적으로 삽입한다.
초기 CSS 파일의 용량을 최소화할 수 있다.
(CSS-in-JS-라이브러리에-대한-고찰 참고)

프로젝트에서 해당 기능을 가볍게 사용하고 싶지만, 라이브러리를 추가하기엔 부담스러울 때가 있다.
이때 JavaScript으로 직접 구현해 볼 수 있다.

방법은 간단하다.
<style> 태그를 만들고 <head> 태그에 삽입하면 된다.

const styleEl = document.createElement('style');
styleEl.textContent = `
/* ... */
`;
document.head.appendChild(styleEl);

하지만 현실에서는 여러가지에 대해서 대응을 해야 한다.

1. CSS 압축

브라우저 렌더링 성능을 개선하기 위함이다.
브라우저가 CSS를 파싱해서 화면을 그리기 때문에 압축된 CSS는 파싱에 유리하다.

export const compressCSS = (styleSheet) => {  
    return styleSheet  
        .replace(/\s+/g, ' ') // 연속된 공백을 단일 공백으로 변경
        .replace(/:\s+/g, ':') // 콜론(:) 주변의 공백 제거
        .replace(/\s*{\s*/g, '{') // 중괄호({}) 주변의 공백 제거
        .replace(/\s*}\s*/g, '}') 
        .replace(/\s*;\s*/g, ';') // 세미콜론(;) 주변의 공백 제거
        .replace(/\s*,\s*/g, ',') // 쉼표(,) 주변의 공백 제거
        .trim(); // 문자열 앞뒤의 공백 제거
};

2. 중복 스타일 로드 방지

스타일이 중복으로 로드되는 것 자체가 비효율적이다.
여러가지 방법으로 이 문제에 접근할 수 있지만, 여기서는 기존 스타일을 덮어씌워지도록 하자.

const styleId = "uniqueID";
 
const existStyleEl = document.getElementById(styleId);
 
if (existStyleEl) {
	existStyleEl.remove(); // 기존 스타일 태그 제거
}
 
const styleEl = document.createElement('style');
styleEl.id = styleId;

최종 코드

이제 이를 appendStyles로 유틸화하여 쉽게 활용 할 수 있다.

/**  
 * CSS 문자열을 압축합니다.  
 * 이 함수는 불필요한 공백을 제거하고 CSS 구문을 최소화하여 문자열의 크기를 줄입니다.  
 * @param {string} styleSheet - 압축할 CSS 문자열  
 * @returns {string} 압축된 CSS 문자열  
 */  
export const compressCSS = (styleSheet) => {  
    return styleSheet  
        .replace(/\s+/g, ' ') // 연속된 공백을 단일 공백으로 변경
        .replace(/:\s+/g, ':') // 콜론(:) 주변의 공백 제거
        .replace(/\s*{\s*/g, '{') // 중괄호({}) 주변의 공백 제거
        .replace(/\s*}\s*/g, '}') 
        .replace(/\s*;\s*/g, ';') // 세미콜론(;) 주변의 공백 제거
        .replace(/\s*,\s*/g, ',') // 쉼표(,) 주변의 공백 제거
        .trim(); // 문자열 앞뒤의 공백 제거
};
 
/**
 * 스타일을 문서의 <head> 요소에 추가합니다.
 * 만약 같은 ID를 가진 스타일 요소가 이미 존재한다면, 기존 요소를 제거하고 새로운 요소로 대체합니다.
 *
 * @param {string} styleId - 스타일 요소의 고유 ID
 * @param {string} styleSheet - 추가할 CSS 스타일 문자열
 * @returns {HTMLStyleElement} 새로 생성되어 문서에 추가된 스타일 요소
 *
 * @example
 * const styles = `
 *   .my-class {
 *     color: red;
 *     font-size: 16px;
 *   }
 * `;
 * appendStyles('my-styles', styles);
 *
 */
export const appendStyles = (styleId, styleSheet) => {
    const existStyleEl = document.getElementById(styleId);
 
    if (existStyleEl) {
        existStyleEl.remove();
    }
 
    const styleEl = document.createElement('style');
    styleEl.id = styleId;
    styleEl.textContent = compressCSS(styleSheet);
    document.head.appendChild(styleEl);
 
    return styleEl;
};