CSS에 함수가? 네이티브 @function 시대가 열렸다

CSS 전처리기(Sass, Less) 없이도 CSS만으로 함수를 정의할 수 있는 시대가 왔습니다. 바로 @function at-rule 덕분이죠. 이 기능은 CSS Custom Functions and Mixins Module Level 1 명세에 정의되어 있으며, 우리가 Sass에서 쓰던 @function과 비슷해 보이지만 완전히 다른 네이티브 기능입니다.

핵심 차이점: Sass @function은 컴파일 타임에 동작하지만, CSS 네이티브 @function런타임에 브라우저가 직접 평가합니다. 즉, 동적 환경(뷰포트 크기, 컨테이너 쿼리 등)에 반응하는 함수를 만들 수 있습니다.

이 글에서는 CSS @function의 문법부터 실전 활용, 주의사항, 그리고 브라우저 지원 현황까지 모두 다룹니다. 함께 보면 좋은 글로 Azure IaaS 방어 심층(DiD) 아키텍처, SFI 원칙으로 완성하는 클라우드 보안 실전 가이드도 참고하세요.

기본 문법: 함수 이름부터 결과 반환까지

함수 이름은 반드시 --(대시 두 개)로 시작해야 합니다. 이는 CSS 커스텀 프로퍼티와 동일한 네이밍 규칙이며, 대소문자를 구분합니다.

/* 가장 기본적인 함수: 절반 값을 반환 */
@function --half(--size) {
  result: calc(var(--size) / 2);
}

.container {
  margin-inline: --half(20px); /* 10px로 평가됨 */
}

함수 구성 요소

  • --function-token: --half처럼 두 개의 대시로 시작하는 식별자
  • (): 인자 목록 (선택 사항, 여러 개 가능)
  • returns: 반환 타입 명시 (선택 사항, 명시하지 않으면 모든 타입 허용)
  • result: 실제 반환값을 정의하는 디스크립터 (필수)

타입 체크: 안전한 함수를 위한 첫걸음

JavaScript처럼 CSS 함수도 인자와 반환값의 타입을 지정할 수 있습니다. @property와 유사한 방식으로 꺾쇠괄호(< >)를 사용합니다.

/* 숫자만 입력받고, 퍼센트를 반환하는 함수 */
@function --progression(--current, --total) returns {
  result: calc(var(--current) / var(--total) * 100%);
}

.progress-bar {
  width: --progression(3, 5); /* 60% */
}

여러 타입을 허용하려면 type() 함수와 | 구분자를 사용합니다.

@function --transparent(--color, --alpha type(|)) {
  result: rgb(from var(--color) r g b / var(--alpha));
}

실무 팁: 타입 체크는 대규모 프로젝트에서 버그를 조기에 발견하는 데 매우 유용합니다. 특히 디자인 시스템의 토큰 값을 계산할 때 강력합니다.

고급 기능: 리스트, 기본값, 중첩, 캐스케이드

쉼표로 구분된 리스트 처리

CSS 함수 호출 시 쉼표는 인자 구분자로 사용됩니다. 리스트 자체를 하나의 인자로 전달하려면 중괄호 {}로 감싸고, 매개변수에 # 접미사를 붙입니다.

@function --get-range(--list#, --n) {
  result: calc(max(var(--list)) - min(var(--list)) + var(--n));
}

div {
  padding-block: --get-range({10px, 100px, 50px, 25px}, 200px); /* 290px */
}

기본값 설정

함수 인자에 기본값을 지정할 수 있습니다. 콜론(:) 뒤에 기본값을 작성합니다.

@function --brand-glass(--opacity: 0.5) returns {
  result: rgb(10 120 255 / var(--opacity));
}

.header {
  background: --brand-glass();       /* 0.5 적용 */
}
.header:hover {
  background: --brand-glass(0.8);    /* 0.8 오버라이드 */
}

함수 중첩 및 지역 변수

함수 안에서 다른 함수를 호출하거나 지역 스코프의 커스텀 프로퍼티를 사용할 수 있습니다. 지역 변수는 함수 밖으로 새지 않아 안전합니다.

@function --square(--n) {
  result: calc(var(--n) * var(--n));
}

@function --circle-area(--radius) {
  --pi: 3.14159;
  result: calc(var(--pi) * --square(var(--radius)));
}

.blob {
  width: calc(--circle-area(10) * 1px); /* 314.159px */
}

CSS 캐스케이드와 조건부 로직

result 디스크립터는 CSS 캐스케이드 규칙을 따릅니다. 따라서 @media, @container, @supports 안에 result를 중첩하여 조건부 반환값을 만들 수 있습니다.

@function --suitable-font-size() returns {
  result: 16px;
  @media (width > 1000px) {
    result: 20px;
  }
}

body {
  font-size: --suitable-font-size(); /* 1000px 초과면 20px, 아니면 16px */
}

주의: 마지막에 선언된 result가 우선합니다. 위 예제에서 @media 블록 밖에 result: 16px를 먼저 쓰고, 미디어 쿼리 안에 result: 20px를 쓰면 항상 16px만 반환됩니다.

브라우저 지원 현황 및 폴백 전략

현재(2025년) @function은 **Chrome 148+**에서만 실험적으로 지원됩니다. Firefox, Safari, Edge는 아직 미지원입니다. 따라서 프로덕션에서 사용하려면 폴백이 필수입니다.

/* @supports로 기능 감지 */
@supports (at-rule(@function)) {
  .container {
    margin-inline: --half(20px);
  }
}

/* 폴백: @function이 지원되지 않으면 기본값 사용 */
.container {
  margin-inline: 10px; /* 폴백 */
}

아이러니: @supports 자체도 모든 브라우저에서 완전히 지원되지 않습니다. CSS Drafts Issue #2463에서 논의가 진행 중이니, 실제 사용 전에 Can I Use 등을 반드시 확인하세요.

CSS @function의 한계와 주의사항

  1. 부수 효과(Side Effect) 불가: 함수는 오직 하나의 값만 반환할 수 있습니다. 여러 속성을 한 번에 생성하거나 스타일을 변경하는 것은 불가능하며, 이는 제안된 @mixin at-rule이 해결할 예정입니다.
  2. 순환 참조 금지: 함수 A가 B를, B가 A를 호출하면 브라우저가 감지하고 두 함수를 무효화합니다. 커스텀 프로퍼티를 통한 간접 순환도 마찬가지입니다.
  3. 현재 브라우저 지원 협소: 프로덕션 사용은 아직 시기상조입니다. 학습 목적으로 미리 익혀두되, 실제 서비스에는 폴백을 반드시 포함하세요.

한국 개발 생태계에서의 적용 맥락

국내에서는 아직 CSS 전처리기(Sass, Less) 의존도가 높은 편입니다. 하지만 네이티브 @function이 브라우저 지원을 확대하면, 다음과 같은 상황에서 강력한 도구가 될 수 있습니다.

  • 디자인 시스템 토큰 계산: 반응형 타이포그래피 스케일, 간격 시스템 등을 CSS 함수로 정의하여 빌드 도구 없이 동적 계산 가능
  • 런타임 테마 전환: 사용자 선호도(다크모드 등)에 따라 함수 결과가 달라지도록 설계
  • CDN 기반 CSS 라이브러리: 빌드 단계 없이 바로 사용할 수 있는 경량 CSS 유틸리티

다음 단계 학습 방향

  1. 공식 명세서 CSS Custom Functions and Mixins Module Level 1 읽기
  2. @mixin at-rule 제안 따라가기 (함수와 달리 여러 스타일을 생성 가능)
  3. Chrome Canary에서 직접 실험해보고, CSS Tricks의 @function 알마낙 참고 (해당 글의 원문)

이 글이 도움이 되셨다면, 전통적인 소프트웨어 테스트는 끝났다 에이전틱 개발 시대의 JiTTest 혁명 글도 함께 읽어보세요. CSS의 패러다임 변화와 소프트웨어 개발 방법론의 변화는 생각보다 연결되어 있습니다.

CSS custom function @function at-rule syntax example on code editor Technical Structure Concept

실전 예제: 반응형 그리드 시스템을 CSS 함수로 만들기

다음은 @function을 활용한 반응형 그리드 시스템 예제입니다. 컨테이너 너비와 컬럼 수를 인자로 받아 각 컬럼의 너비를 계산합니다.

/* 그리드 컬럼 너비 계산 함수 */
@function --grid-column-width(--container-width, --columns) returns {
  result: calc(var(--container-width) / var(--columns));
}

/* 기본값을 가진 갭 계산 함수 */
@function --grid-gap(--base-gap: 16px) returns {
  result: var(--base-gap);
}

.grid {
  display: grid;
  grid-template-columns: 
    --grid-column-width(1200px, 12) 
    var(--grid-gap()) 
    --grid-column-width(1200px, 12);
  
  /* 1200px / 12 = 100px, gap은 16px */
  /* 결과: 100px 16px 100px */
}

/* 반응형: 컨테이너 쿼리와 조합 */
@container (min-width: 800px) {
  .grid {
    grid-template-columns: repeat(3, --grid-column-width(100%, 3));
  }
}

이 예제는 현재 브라우저에서 동작하지 않지만, 미래의 CSS 아키텍처가 어떻게 변할지 보여줍니다. 지금부터 개념을 익혀두면, 브라우저 지원이 확대되었을 때 바로 활용할 수 있습니다.

Developer testing native CSS @function on browser developer tools Programming Illustration

CSS @function vs Sass @function 비교표

항목CSS @functionSass @function
평가 시점런타임 (브라우저)컴파일 타임
동적 환경 반응가능 (미디어 쿼리, 컨테이너 쿼리 등)불가능 (정적)
타입 체크returns 디스크립터로 명시적 타입 검증없음 (JavaScript 함수처럼 동적)
부수 효과불가능 (값만 반환)불가능 (값만 반환)
순환 참조 감지브라우저가 자동 감지 및 무효화컴파일러가 감지 (에러 발생)
브라우저 지원Chrome 148+ (실험적)모든 환경 (전처리기 사용 시)
생태계명세 초기 단계, 라이브러리 부족성숙함 (Bourbon, Compass 등)

주의사항 요약

  • 프로덕션 사용 금지: 현재는 Chrome 148+에서만 동작합니다. 학습 목적으로만 사용하세요.
  • 폴백 필수: @supports로 감지하거나, 전처리기와 병행 사용을 고려하세요.
  • 순환 참조 조심: 함수 간 호출 그래프를 항상 체크하세요.
  • 이름 충돌: --로 시작하는 이름은 커스텀 프로퍼티와 동일한 네임스페이스를 공유합니다. 의도치 않은 오버라이드에 주의하세요.

Modern CSS architecture with custom functions and cascade layers IT Technology Image

결론: CSS의 미래는 지금부터 준비하자

CSS @function은 단순한 문법 추가 이상입니다. 이는 CSS가 정적 선언 언어에서 동적 계산이 가능한 프로그래밍 언어로 진화하는 신호탄입니다. 비록 지금은 브라우저 지원이 제한적이지만, 1~2년 안에 주요 브라우저에 탑재될 가능성이 높습니다.

지금부터 @function의 개념과 문법을 익혀두면, 미래의 CSS 아키텍처 설계에 큰 도움이 될 것입니다. 특히 디자인 시스템, 반응형 컴포넌트, 테마 관리 등에서 강력한 무기가 될 수 있습니다.

한 줄 요약: CSS @function은 아직 실험 단계이지만, 'CSS로 함수를 작성한다'는 패러다임 변화를 이해하는 것이 중요합니다. 폴백 전략과 함께 천천히 학습을 시작해보세요.

함께 보면 좋은 글:

본 콘텐츠는 신뢰할 수 있는 출처를 바탕으로 AI 도구를 활용하여 초안이 작성되었으며, 편집자의 검토를 거쳐 발행되었습니다. 전문가의 조언을 대체하지 않습니다.