Environment variables/Using environment variables

김동현·2026년 3월 21일

mdn 학습 번역 - CSS

목록 보기
89/190

안녕하세요! 오늘 살펴볼 문서는 모바일 웹 개발이나 PWA(Progressive Web App)를 개발할 때, 꼭 알아두어야 할 필수 개념인 환경 변수(Environment Variables)env() 함수에 대한 가이드입니다.

특히 아이폰(iPhone)의 노치(Notch) 디자인이나 다이내믹 아일랜드 때문에 웹 페이지 위쪽이나 아래쪽이 가려지는 문제를 겪어보신 적 있으신가요? 프론트엔드 개발자 면접에서도 "모바일 기기의 노치 영역에 콘텐츠가 가려지는 현상을 CSS로 어떻게 해결하나요?"라는 질문이 가끔 등장하는데, 이 문서가 바로 그 질문에 대한 완벽한 정답이 되어줄 것입니다.

그럼 MDN 문서를 함께 읽어볼까요?


환경 변수 사용하기 (Using environment variables)

CSS 환경 변수 모듈(CSS environment variables module)은 CSS에 환경 변수라는 개념을 도입하고, 이 환경 변수를 사용할 수 있게 해주는 env() 함수를 정의하고 있습니다. 이 가이드에서는 환경 변수가 무엇인지, 브라우저가 정의한 환경 변수들은 무엇이 있는지, 그리고 env() 함수를 통해 환경 변수를 어떻게 사용하는지 예제를 통해 알아보겠습니다.

이 문서에서 다룰 내용 (In this article)


환경 변수란 무엇인가? (What are environment variables?)

CSS 환경 변수는 글로벌(전역) 변수입니다. 전체 문서에 걸쳐 전역적으로 스코프(범위)가 지정되어 있죠. 이 변수들은 사용자 에이전트(브라우저)에 의해 정의됩니다. 환경 변수는 여러분의 스타일이 사용자의 기기(디바이스)나 현재 상황(context)에 맞게 적응(adapt)하도록 도와주기 위해 브라우저나 운영체제(OS)가 제공하는 특별한 값들입니다. 이 값들에는 env() 함수를 사용하여 접근할 수 있습니다.

환경 변수는 커스텀 속성(custom properties, --*)이나 var() 함수와 비슷하게 작동하지만, 전역적으로 정의되고 스코프가 지정된다는 점이 다릅니다. 즉, 특정 요소(element)에만 스코프가 한정되는 커스텀 속성과 달리, 환경 변수는 언제나 전체 문서에 적용됩니다. 게다가 커스텀 속성은 우리가 마음대로 값을 바꿀 수 있는(mutable) 반면, 환경 변수는 오직 읽기 전용(read-only)입니다.

커스텀 속성과 마찬가지로 환경 변수 역시 대소문자를 엄격히 구분(case-sensitive)합니다. 속성 선언부 외부에서는 사용할 수 없는 커스텀 속성과는 달리, env() 함수는 속성값의 어느 부분이든, 심지어는 미디어 쿼리(Media query rules)와 같은 설명자(descriptor)의 일부로도 자유롭게 사용할 수 있습니다.

역사 (History)

애플(Apple)은 개발자들이 둥근 모서리나 노치(notch) 같은 불규칙한 디바이스 디스플레이에 맞춰 레이아웃을 최적화할 수 있도록 iOS Safari 브라우저에 환경 변수를 가장 먼저 도입했습니다. 최초의 safe-area-inset-* 환경 변수들은 사용자가 어떤 기기나 브라우저를 쓰든 간에, 개발자가 뷰포트 내의 '안전한 영역(safe area)'에 콘텐츠를 배치할 수 있도록 해줍니다.

사용 사례 (Use cases)

환경 변수를 사용해서 해결할 수 있는 일반적인 문제들은 다음과 같습니다:

  • 기기의 시스템 알림(예: 아이폰의 하단 홈 바 등)이 앱의 유저 인터페이스(UI) 일부를 가려버리는 현상 방지.
  • 동적인 온스크린 키보드(가상 키보드)가 나타나고 사라질 때 뷰포트 크기가 변경되는 상황 처리.
  • 설치된 프로그레시브 웹 앱 (PWAs)에서 원래 타이틀 바(title bar)가 있던 위치에 요소를 배치할 때, 그 콘텐츠가 창 제어 버튼(최소화, 최대화, 닫기 등)을 가리지 않도록 보장하기. 이 문제는 특히 데스크톱 브라우저 환경에서 큰 이슈가 됩니다.

브라우저가 정의한 환경 변수 (Browser-defined environment variables)

CSS 환경 변수 명세서는 대소문자를 구분하는 몇 가지 변수들을 정의하고 있습니다. 주요 변수들은 다음과 같습니다:

preferred-text-scale

preferred-text-scale 환경 변수는 사용자가 선호하는 텍스트 배율(scale factor)을 나타냅니다. 이것은 운영체제나 사용자 에이전트의 "기본" 폰트 크기에 적용된 조정값입니다. [`text-size-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/text-size-adjust) 속성이 작동하는 기기나 브라우저에서는, text-size-adjust: auto에 의해 적용되는 배율이 바로 이 값입니다. 예를 들어, text-size-adjust: auto로 인해 텍스트 크기가 2배로 커진다면, env(preferred-text-scale) 값은 2로 해석됩니다.

safe-area-inset-*

안전 영역 여백(safe area inset)을 나타내는 네 개의 환경 변수 - safe-area-inset-top, safe-area-inset-right, safe-area-inset-bottom, safe-area-inset-left - 는 뷰포트의 가장자리로부터 위, 오른쪽, 아래, 왼쪽으로 쑥 들어간 직사각형 형태의 '안전 영역'을 정의합니다. 콘텐츠를 이 영역 안에 배치하면 직사각형이 아닌 디스플레이(노치, 둥근 모서리 등) 모양 때문에 콘텐츠가 잘려나가는 일 없이 안전하게 보여줄 수 있습니다. 일반적인 데스크톱이나 노트북 모니터처럼 잘려나가는 부분이 없는 완전한 직사각형 뷰포트에서는 이 네 개의 값이 모두 0이 됩니다. 반면, 전체 화면을 덮는 둥근 모서리를 가진 기기나 둥근 화면의 스마트 워치 등 비직사각형 디스플레이에서는, 사용자 에이전트(브라우저)가 지정한 이 네 개의 값이 하나의 직사각형을 형성하여, 그 직사각형 안의 모든 콘텐츠가 가려짐 없이 온전히 보이도록 보장해 줍니다.

safe-area-max-inset-*

최대 안전 영역 여백(safe area maximum inset)을 나타내는 네 개의 환경 변수 - safe-area-max-inset-top, safe-area-max-inset-right, safe-area-max-inset-bottom, safe-area-max-inset-left - 는 위에서 설명한 동적인 safe-area-inset-* 변수들이 가질 수 있는 정적인 최댓값을 나타냅니다. 즉, 동적으로 변하는 모든 유저 인터페이스(예: 브라우저 주소창 등)가 사라졌을 때 가지게 되는 safe-area-inset-*의 최댓값입니다. 예를 들어, 특정 플랫폼에서는 화면을 스크롤할 때 버튼 바가 나타났다 사라지며 safe-area-inset-* 값이 동적으로 바뀔 수 있습니다. 이렇게 현재 보이는 콘텐츠 영역이 바뀜에 따라 safe-area-inset-* 값은 수시로 변하지만, safe-area-max-inset-* 값은 항상 고정된 채로 유지됩니다.

viewport-segment-*

이 변수들은 화면이 접히는 폴더블(foldable) 폰처럼 여러 개의 세그먼트(화면 분할 영역)를 가진 기기에서만 의미가 있습니다. viewport-segment-bottom, viewport-segment-left, viewport-segment-right, viewport-segment-top 변수들은 viewport-segment-height, viewport-segment-width와 함께 논리적으로 분리된 뷰포트 영역의 위치와 크기를 정의합니다. 이 변수들은 뷰포트가 최소 두 개 이상의 세그먼트로 나뉘어 있을 때만 정의됩니다. 다중 세그먼트 기기에서 UI의 여러 부분들을 각 세그먼트 영역에 딱 맞게 배치하여, 화면이 접히는 경첩(fold) 부분에 콘텐츠가 잘리거나 걸치지 않게 피하기 위해 사용됩니다.

이 외의 다른 명세서들에서도 추가적인 환경 변수들을 정의하고 있습니다.

창 컨트롤 오버레이 API (Window Controls Overlay API)WindowControlsOverlay 인터페이스를 정의하는데, 이는 데스크톱 기기에 설치된 프로그레시브 웹 애플리케이션 (PWA)의 타이틀 바(title bar) 영역의 기하학적 정보를 노출합니다. PWA 매니페스트에서 window-controls-overlay display_override 값을 사용할 때, 다음과 같은 환경 변수들이 정의됩니다:

titlebar-area-*

titlebar-area-x, titlebar-area-y, titlebar-area-width, titlebar-area-height 변수들은 데스크톱 환경에서 실행되는 설치된 웹 애플리케이션에서 일반적으로 타이틀 바가 차지하는 영역을 정의합니다. 콘텐츠가 창 제어 버튼(최소화, 최대화, 닫기 버튼)과 겹치지 않도록 하려면 이 titlebar-area-* 변수들을 사용하세요.

keyboard-inset-*

keyboard-inset-top, keyboard-inset-right, keyboard-inset-bottom, keyboard-inset-left, keyboard-inset-width, keyboard-inset-height 변수들은 화면에 나타나는 가상 키보드(virtual keyboard)의 위치와 크기에 대한 정보를 제공합니다. 구체적으로는 뷰포트 가장자리로부터 위, 오른쪽, 아래, 왼쪽으로 얼마나 들어와 있는지(inset)를 나타냅니다 (너비와 높이 inset은 다른 inset 값들로부터 계산됩니다). 더 자세한 내용은 가상 키보드 API (VirtualKeyboard API) 문서를 참고하세요.

눈치채셨겠지만, 지금까지 살펴본 모든 변수 이름에는 left, right, top, bottom, height, width와 같은 물리적(physical) 용어들이 포함되어 있습니다. 이 변수 이름들이 화면에 표시되는 웹사이트의 논리적 방향이 아니라 기기 하드웨어 자체의 물리적 특성을 가리키기 때문에 논리적 대응 속성(logical equivalents, 예: start, end 등)이 굳이 필요하지 않은 것입니다.


env() 함수 (The env() function)

env() 함수는 환경 변수의 값을 CSS 구문 내에 삽입할 때 사용됩니다. env() 함수는 어떤 요소의 어떤 속성값이든, 혹은 어떤 @규칙의 어떤 설명자(descriptor) 값이든 그 일부를 대체하는 데 사용할 수 있으며, 심지어 커스텀 속성(CSS 변수) 값 안에서도 사용할 수 있습니다. 기본적으로 CSS 값이 들어갈 수 있는 곳이라면 어디든 사용이 가능합니다.

기본 문법은 다음과 같습니다:

env( <environment-variable-name> )
env( <environment-variable-name>, <fallback-value> )

이 함수는 대소문자를 구분하는 환경 변수 이름을 첫 번째 인자로 받습니다. 그리고 선택 사항이지만 가급적 제공하는 것이 강력히 권장되는 대체 값(fallback value)을 두 번째 인자로 받을 수 있습니다.

line-height: env(preferred-text-scale, 2);
margin: env(safe-area-inset-top, 0) env(safe-area-inset-right, auto)
  env(safe-area-inset-bottom, 3em) env(safe-area-inset-left, auto);

첫 번째 인자는 삽입할 환경 변수의 이름입니다. 쉼표(,) 뒤에 오는 인자는 (제공된 경우) 대체 값(fallback value)이며, 첫 번째 인자로 참조한 환경 변수가 해당 환경에 존재하지 않을 때 대신 사용됩니다.
위의 예제에서, 만약 브라우저에 preferred-text-scale 환경 변수가 존재하지 않는다면 line-height2로 설정됩니다. 그리고 브라우저가 safe-area-inset-* 값들을 지원하지 않는다면, marginmargin: 0 auto 3em auto로 설정될 것입니다.

대체 값(fallback)의 문법은 커스텀 속성(var())의 문법과 비슷해서, 내부에 여러 개의 쉼표를 허용합니다. 첫 번째 쉼표부터 함수의 끝 부분 사이에 있는 모든 내용이 통째로 대체 값으로 간주됩니다. 단, 쉼표를 지원하지 않는 속성이나 설명자에 사용할 경우 그 값은 유효하지 않은 것으로 처리됩니다.

속성이나 설명자에 문법적으로 유효한 env() 함수가 포함되어 있다면, 파싱(parse) 시점에는 유효한 것으로 간주됩니다. 실제로 문법 검사가 이루어지는 것은 계산 시점(computed-time)으로, env() 함수가 브라우저가 제공하는 실제 값으로 모두 대체된 이후에 진행됩니다. 만약 첫 번째 매개변수로 전달된 환경 변수가 인식할 수 없는 이름이라면, 그 자리는 대체 값으로 교체됩니다. 이 대체 값 안에는 또 다른 환경 변수가 들어갈 수도 있고, 그 환경 변수 역시 자신만의 대체 값을 가질 수 있습니다. 만약 인식할 수 없는 환경 변수를 썼는데 대체 값조차 제공하지 않았다면, env() 함수를 포함한 그 속성이나 설명자는 계산 시점에 무효화(invalid)됩니다.


env()를 사용한 환경 변수 사용 예제 (Using environment variables with env() example)

우리는 환경 변수를 활용하여, 기기 하단에 알림(또는 홈 인디케이터 바)이 떴을 때 화면 하단에 고정된 앱 툴바가 가려지지 않도록 안전장치를 마련할 수 있습니다.

화면 하단에 알림을 표시하는 기기에서는, 브라우저가 safe-area-inset-bottom 환경 변수값을 뷰포트를 가리고 있는 것의 맨 윗부분부터 뷰포트의 맨 아랫부분까지의 거리로 설정해 줍니다. 이 예제의 경우, 떠 있는 알림의 높이가 곧 그 값이 될 것입니다. 반면 직사각형의 일반 데스크톱 모니터에서는 safe-area-inset-bottom 값이 기본적으로 0입니다. 우리는 이 환경 변수값을 활용해서 뷰포트 하단에 공간을 여유 있게 확보함으로써, 알림이 뜨더라도 우리 앱의 콘텐츠가 가려지지 않게 만들 것입니다.

HTML 구조를 보면, <body>는 두 개의 자식을 가지고 있습니다. <main>은 툴바 역할을 하는 <footer>를 제외한 애플리케이션의 전체 내용을 담고 있습니다.

<body>
  <main>Application</main>
  <footer>Toolbar</footer>
</body>

<body>는 뷰포트 높이(100vh)를 가득 채우는 플렉스 컨테이너로 정의되어 있습니다. <main> 애플리케이션 영역은 형제 요소인 <footer> 툴바가 차지하고 남은 나머지 공간을 꽉 채우도록(grow) 설정되었습니다.

body {
  display: flex;
  flex-flow: column nowrap;
  height: 100vh;
}

main {
  flex: 1; /* 남은 공간을 모두 차지함 */
  padding: 1em;
  overflow-y: auto; /* 내용이 넘치면 자체 스크롤 발생 */
}

<footer>는 뷰포트 하단에 딱 달라붙어 있도록(stuck) 위치가 지정됩니다. position: sticky 선언은 bottom: 0을 기준으로, 요소의 스크롤 조상이자 컨테이닝 블록<body>에 상대적으로 푸터를 오프셋 시킵니다. 우리는 <footer>의 네 면 모두에 1empadding 값을 주었습니다. 그리고 나서 가장 중요한 부분인 padding-bottom1emsafe-area-inset-bottom 환경 변수값을 더해줍니다. (만약 브라우저가 이 환경 변수를 지원하지 않을 경우를 대비해 1em을 대체 값으로 함께 적어줍니다.)

footer {
  position: sticky;
  bottom: 0;
  padding: 1em;
  /* 핵심 코드! 기본 패딩 1em에 기기의 안전 영역 마진을 더해줍니다. */
  padding-bottom: calc(1em + env(safe-area-inset-bottom, 1em));
}

(간결함을 위해 추가적인 CSS는 생략했습니다.)

💡 강사의 모바일 웹 개발 팁!
아이폰 X 이후로 화면 하단에 둥근 모서리와 홈 인디케이터(Home Indicator) 바가 생기면서, 뷰포트 하단에 딱 붙어있는 네비게이션 바(GNB)의 텍스트나 버튼이 이 홈 바와 겹쳐서 눌리지 않는 문제가 빈번하게 발생합니다. 위의 padding-bottom: calc(1em + env(safe-area-inset-bottom, 0px)); (대체값은 0px 추천) 코드는 이 문제를 완벽하게 해결해 주는 실무 필수 코드입니다! 면접에서 이 지식을 어필한다면 현장 경험이 풍부한 개발자로 인정받으실 수 있습니다.

이 코드가 적용되면, safe-area-inset-bottom 환경 변수값이 0보다 큰 기기(예: 최신 아이폰 등)에서는 푸터의 하단 패딩이 기본 1em을 넘어서 더 길게 늘어납니다. 이 CSS는 화면 하단의 알림, 디스플레이의 노치 디자인, 또는 기기의 둥근 모서리 등 어떤 이유로든 콘텐츠가 가려지는 것을 막기 위해 푸터 하단에 필요한 만큼의 추가 패딩을 유연하게 제공합니다.

미래에는 개발자가 직접 정의할 수 있는 커스텀 환경 변수가 지원될 수도 있지만, 아직 이에 대한 표준이 정의되거나 구현되지는 않았습니다.


같이 보기 (See also)


MDN 개선에 참여하기 (Help improve MDN)

이 페이지가 도움이 되셨나요?

기여하는 방법 알아보기 (Learn how to contribute)

이 페이지는 MDN 기여자들에 의해 2025년 11월 7일에 마지막으로 수정되었습니다 (MDN contributors).

profile
프론트에_가까운_풀스택_개발자

0개의 댓글