LogoSEO Jing
  • All Posts
  • SEO Jing
  • KD Team
  • CLab CoreTeam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

프론트엔드스터디CSS박스모델레이아웃

프론트엔드 스터디 3주차: 프론트엔드의 첫 번째 벽, 박스 모델과 스타일링

2026년 4월 6일·33분 읽기

3주차 영상

  • 학습 구간: [02:59:19 ~ 04:28:10] 폰트/색상 제어부터 박스 모델까지
  • 강의 바로가기:

    제대로 파는 HTML & CSS - 3주차 진도 시청하기

안녕하세요. 프론트엔드 스터디 3주차에 오신 것을 환영합니다. 이번 주차에서는 CSS의 본격적인 스타일링에 들어갔습니다. 글꼴과 색상을 제어하고, HTML 요소가 화면에서 어떻게 공간을 차지하는지를 결정하는 인라인 vs 블록 개념, 그리고 프론트엔드 초심자가 가장 먼저 부딪히는 벽인 박스 모델(마진·패딩·보더)을 배웠습니다. 이 개념을 잡아야 "왜 여백이 이상하지?" 라는 의문에서 벗어날 수 있습니다.


스킵 진단 문제

아래 10문제를 막힘없이 풀 수 있다면,

이번 주 학습 영상을 생략하거나, 필요한 부분만 선택적으로 시청하셔도 좋습니다.

바로 하단의 제가 추가로 알면 좋은 개념들을 확인해보세요.

Quiz1 / 10
Q.CSS에서 글꼴을 지정할 때, 사용자의 컴퓨터에 첫 번째 폰트가 없을 경우를 대비해 여러 폰트를 나열하는 속성은 무엇일까요?

1. 폰트 단위 px, em, rem — 뭘 써야 할까?

CSS에서 글꼴 크기를 지정할 때 px, em, rem 세 가지를 자주 마주칩니다. 셋 다 크기를 정하는 단위이지만, 기준점이 다릅니다.

  • px: 화면의 물리적 픽셀을 기준으로 합니다. font-size: 16px이면 어디서든 16픽셀입니다. 직관적이지만, 사용자가 브라우저 기본 글꼴 크기를 변경해도 반응하지 않습니다.
  • em: 부모 요소의 font-size를 기준으로 합니다. 부모가 16px일 때 1.5em은 24px입니다. 중첩이 깊어지면 계산이 복잡해지는 단점이 있습니다.
  • rem: 루트 요소(<html>)의 font-size를 기준으로 합니다. 중첩과 무관하게 항상 같은 기준이라 예측이 쉽습니다.
css
html {
  font-size: 16px;
} /* 루트 기준 설정 */

.parent {
  font-size: 20px;
}
.child-px {
  font-size: 14px;
} /* 항상 14px */
.child-em {
  font-size: 1.5em;
} /* 부모 20px × 1.5 = 30px */
.child-rem {
  font-size: 1.5rem;
} /* 루트 16px × 1.5 = 24px */

실무에서는 rem을 기본 단위로, px은 1~2px 같은 미세한 값에 사용하는 것이 일반적입니다. em은 부모에 상대적으로 커지거나 작아져야 하는 특수한 경우(예: 버튼 안의 아이콘 크기)에 유용합니다.

2. CSS 상속 — 부모의 스타일이 자식에게 전달되는 규칙

CSS에는 부모 요소에 적용한 스타일이 자식 요소에 자동으로 전달되는 상속(Inheritance) 개념이 있습니다. 하지만 모든 속성이 상속되는 것은 아닙니다. 규칙을 알아야 "왜 이 스타일이 적용 안 되지?"라는 혼란을 피할 수 있습니다.

상속되는 속성과 상속되지 않는 속성의 구분은 직관적입니다.
  • 상속되는 속성 (주로 텍스트 관련): color, font-family, font-size, line-height, text-align, visibility, cursor 등
  • 상속되지 않는 속성 (주로 레이아웃/박스 관련): margin, padding, border, width, height, background, display, position 등
css
.parent {
  color: #333; /* 자식에게 상속됨 */
  font-family: "Pretendard", sans-serif; /* 자식에게 상속됨 */
  border: 1px solid black; /* 자식에게 상속 안 됨 */
  padding: 20px; /* 자식에게 상속 안 됨 */
}

만약 상속되지 않는 속성을 강제로 상속시키고 싶거나, 반대로 상속을 끊고 싶을 때 사용하는 키워드가 있습니다.

  • inherit: 부모의 값을 강제로 상속받습니다. 상속되지 않는 속성에도 사용할 수 있습니다.
  • initial: 해당 속성의 CSS 초기값(브라우저 기본값이 아닌 CSS 스펙에서 정의한 값)으로 되돌립니다.
  • unset: 상속되는 속성이면 inherit처럼, 상속되지 않는 속성이면 initial처럼 동작합니다. "원래대로 돌려놔"라는 뜻입니다.
css
.child {
  border: inherit; /* 부모의 border를 강제로 가져옴 */
  color: initial; /* color의 CSS 초기값(보통 검정)으로 되돌림 */
  margin: unset; /* margin은 상속 안 되므로 initial처럼 동작 → 0 */
}

React / Tailwind에서는?

Tailwind CSS에서 상속은 동일하게 작동합니다. 부모에 text-gray-700을 주면 자식 텍스트도 해당 색상을 상속받습니다. CSS-in-JS 라이브러리(styled-components 등)에서도 마찬가지입니다. 상속 규칙은 CSS 자체의 동작이므로 어떤 도구를 쓰든 동일합니다. "왜 부모에 배경색을 줬는데 자식에는 안 넘어가지?"라는 질문의 답이 바로 여기 있습니다. 배경색은 상속되지 않는 속성이기 때문입니다.

3. 인라인 vs 블록, 진짜 차이를 체감하는 법

강의에서 인라인과 블록의 차이를 배웠지만, 실제로 코드를 짤 때 "이 요소가 왜 내 말을 안 듣지?" 싶은 순간이 옵니다. 가장 흔한 함정을 정리해보겠습니다.

css
/* 인라인 요소에 width/height를 줘도 무시됩니다 */
span {
  width: 200px; /* 적용 안 됨 */
  height: 100px; /* 적용 안 됨 */
  margin-top: 20px; /* 적용 안 됨 */
  margin-bottom: 20px; /* 적용 안 됨 */
  margin-left: 10px; /* 이건 적용 됨! */
  margin-right: 10px; /* 이건 적용 됨! */
}

/* 해결: display를 바꿔줍니다 */
span {
  display: inline-block; /* 인라인처럼 나란히 + 블록처럼 크기 제어 */
  width: 200px;
  height: 100px
핵심 규칙을 정리하면 이렇습니다.
  • 인라인(Inline): 좌우 margin만 적용, width/height 무시, 상하 margin 무시 - 블록(Block): width/height 적용, 상하좌우 margin 모두 적용, 항상 새 줄 시작 - 인라인 블록(Inline-block): 나란히 배치 + width/height/margin 모두 적용

"이 요소에 크기를 주고 싶은데 안 먹힌다"면, 십중팔구 인라인 요소에 width/height를 주고 있는 겁니다. display: inline-block 또는 display: block으로 바꿔주면 해결됩니다.

4. 마진 겹침(Margin Collapsing) — 여백이 사라지는 미스터리

박스 모델을 처음 배우면 가장 당황스러운 현상이 바로 마진 겹침 입니다. 분명 위 요소에 margin-bottom: 40px, 아래 요소에 margin-top: 30px을 줬는데, 실제 간격은 70px이 아니라 40px만 생깁니다.

css
.box-a {
  margin-bottom: 40px;
}
.box-b {
  margin-top: 30px;
}
/* 실제 간격: 70px이 아니라 40px (둘 중 큰 값) */

이것은 CSS가 의도적으로 설계한 동작입니다. 수직 방향으로 인접한 마진은 합쳐지지 않고, 둘 중 큰 값만 적용됩니다. 이 규칙이 왜 존재할까요? 문단(<p>) 태그를 생각해보면 이해가 됩니다. 각 문단에 margin-top: 20px과 margin-bottom: 20px이 있다면, 겹침 없이는 문단 사이 간격이 40px로 벌어지겠죠. 마진 겹침 덕분에 20px로 자연스러운 간격이 유지됩니다.

마진 겹침이 발생하는 세 가지 경우를 기억해두세요.
  • 인접 형제 요소: 위 요소의 margin-bottom과 아래 요소의 margin-top이 겹침 - 부모와 첫째/마지막 자식: 부모에 padding이나 border가 없으면, 자식의 margin이 부모 밖으로 "새어 나감" - 빈 블록 요소: 콘텐츠가 없는 요소의 margin-top과 margin-bottom끼리 겹침
css
/* 부모-자식 마진 겹침 방지 */
.parent {
  /* 아래 중 하나만 적용해도 해결됩니다 */
  padding-top: 1px; /* 패딩으로 경계 만들기 */
  border-top: 1px solid transparent; /* 보더로 경계 만들기 */
  overflow: hidden; /* BFC(Block Formatting Context) 생성 */
}

5. box-sizing: border-box — 현대 CSS의 필수 설정

CSS 박스 모델의 기본 동작(content-box)에서는 width: 200px을 지정하면, 여기에 padding과 border가 추가로 더해집니다. 즉, padding: 20px과 border: 5px을 주면 실제 너비는 200 + 40 + 10 = 250px이 됩니다. 계산이 너무 복잡하죠.

css
/* content-box (기본값): width = 콘텐츠 영역만 */
.box-content {
  box-sizing: content-box;
  width: 200px;
  padding: 20px;
  border: 5px solid black;
  /* 실제 화면 너비: 200 + 20*2 + 5*2 = 250px */
}

/* border-box: width = 콘텐츠 + 패딩 + 보더 전부 포함 */
.box-border {
  box-sizing: border-box;
  width: 200px;
  padding: 20px;
  border: 5px solid black;
  /* 실제 화면 너비: 정확히 200px */
}

border-box를 사용하면 "내가 200px이라고 썼으니, 화면에서도 200px"이라는 직관적인 결과를 얻습니다. 그래서 현대 웹 개발에서는 거의 모든 프로젝트가 아래 리셋 코드로 시작합니다.

css
/* 현대 CSS 프로젝트의 첫 줄이라 해도 과언이 아닙니다 */
*,
*::before,
*::after {
  box-sizing: border-box;
}

이 한 줄을 초반에 넣어두면, 이후 모든 요소에서 패딩과 보더 때문에 레이아웃이 밀리는 문제를 겪지 않습니다. 강의에서 직접 경험해보셨겠지만, 이 설정 없이 레이아웃을 짜면 "분명 300px인데 왜 삐져나오지?" 라는 상황을 계속 마주하게 됩니다.

6. overflow — 콘텐츠가 상자를 넘칠 때

박스 모델에서 width와 height로 요소의 크기를 고정하면, 내부 콘텐츠가 그보다 클 때 넘침(overflow)이 발생합니다. overflow 속성으로 이 상황을 제어할 수 있습니다.

css
/* 넘치는 부분을 잘라냄 (가장 많이 쓰임) */
.box-hidden {
  overflow: hidden;
}

/* 항상 스크롤바 표시 */
.box-scroll {
  overflow: scroll;
}

/* 넘칠 때만 스크롤바 표시 (권장) */
.box-auto {
  overflow: auto;
}

/* 넘쳐도 그대로 보여줌 (기본값) */
.box-visible {
  overflow: visible;
}

실무에서 overflow가 가장 빛나는 순간은 텍스트 말줄임(Ellipsis)입니다. 긴 제목이 카드 밖으로 삐져나가는 것을 방지할 때 자주 씁니다.

css
/* 한 줄 말줄임 (세 속성이 세트) */
.title-one-line {
  white-space: nowrap; /* 줄바꿈 금지 */
  overflow: hidden; /* 넘치는 부분 숨김 */
  text-overflow: ellipsis; /* 잘린 부분에 ... 표시 */
}

/* 여러 줄 말줄임 (2줄까지 보여주고 나머지는 ...) */
.title-two-lines {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

한 줄 말줄임은 white-space, overflow, text-overflow 세 속성이 반드시 함께 사용되어야 합니다. 하나라도 빠지면 ...이 나타나지 않습니다.

React / Tailwind에서는?

Tailwind CSS에서 한 줄 말줄임은 truncate 하나면 됩니다. 위의 세 속성을 한 번에 적용해줍니다. 여러 줄 말줄임은 line-clamp-2 같은 유틸리티로 제공합니다. React 컴포넌트에서 긴 텍스트를 표시할 때 매우 자주 사용되는 패턴입니다.

7. 요소 숨기기 세 가지 방법 — 같아 보이지만 전혀 다른 결과

CSS로 요소를 "보이지 않게" 만드는 방법은 세 가지가 있고, 각각 완전히 다른 결과를 만듭니다.

css
/* 1. display: none — 완전히 제거 */
.hidden-display {
  display: none;
}

/* 2. visibility: hidden — 자리는 차지하지만 안 보임 */
.hidden-visibility {
  visibility: hidden;
}

/* 3. opacity: 0 — 투명하지만 자리도 차지하고 클릭도 됨 */
.hidden-opacity {
  opacity: 0;
}
세 가지의 차이를 표로 정리하면 이렇습니다.
방법공간 차지클릭 가능스크린 리더전환 애니메이션
display: noneXXX불가능
visibility: hiddenO
  • 완전히 제거하고 싶으면 → display: none - 자리는 유지하되 보이지만 않게 → visibility: hidden - 페이드인/페이드아웃 애니메이션을 주고 싶으면 → opacity

display: none은 요소를 DOM에서 차지하는 공간까지 제거하기 때문에, 보였다가 안 보였다가 할 때 주변 레이아웃이 흔들릴 수 있습니다. 반면 opacity: 0은 투명할 뿐 여전히 클릭 이벤트를 받으므로, 숨긴 버튼이 의도치 않게 클릭되는 문제가 생길 수 있습니다. 이때는 pointer-events: none을 함께 사용합니다.

React / Tailwind에서는?

Tailwind CSS에서는 hidden(display: none), invisible(visibility: hidden), opacity-0으로 각각 사용합니다. React에서는 조건부 렌더링

jsx
return { show && <Component />; }

이 display: none과 유사하게 동작하지만, DOM에서 아예 제거된다는 차이가 있습니다. 토글 애니메이션이 필요하면 Framer Motion 같은 라이브러리에서 AnimatePresence를 사용합니다.

8. CSS 리셋과 Normalize — 브라우저마다 다른 기본 스타일

아무런 CSS를 작성하지 않아도 <h1>은 크고 굵게, <p>에는 위아래 여백이, <ul>에는 점이 찍혀 나옵니다. 이것은 브라우저가 기본으로 적용하는 스타일(User Agent Stylesheet) 때문입니다. 문제는 이 기본 스타일이 브라우저마다 조금씩 다르다는 점입니다.

크롬에서는 멀쩡한데 사파리에서는 여백이 다르고, 파이어폭스에서는 또 다르고… 이런 차이를 해결하기 위해 두 가지 접근법이 있습니다.

  • CSS Reset: 브라우저의 기본 스타일을 전부 제거합니다. 모든 요소의 margin, padding, font-size 등을 0으로 밀어버리고, 백지 상태에서 시작합니다. -Normalize.css: 기본 스타일을 제거하는 대신 브라우저 간 차이만 통일합니다. 유용한 기본 스타일은 살려두되, 브라우저마다 다른 부분만 맞춰줍니다.
css
/* CSS Reset 스타일 예시 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* 이 위에 원하는 스타일을 자유롭게 쌓아갑니다 */
body {
  font-family: "Pretendard", sans-serif;
  line-height: 1.6;
  color: #333;
}

최근 실무에서는 완전한 Reset보다는 Normalize.css를 기반으로 하면서 필요한 부분만 추가로 리셋하는 방식이 많이 쓰입니다. 어떤 방법을 선택하든, 프로젝트 초반에 기본 스타일을 정리하고 시작하는 습관이 중요합니다.

9. 가상 요소 (::before, ::after) — HTML 없이 장식 추가하기

CSS에는 실제 HTML 태그를 추가하지 않고도 요소의 앞이나 뒤에 콘텐츠를 삽입할 수 있는 가상 요소(Pseudo-element)가 있습니다. ::before는 요소의 내용 앞에, ::after는 뒤에 가상의 요소를 만들어줍니다.

css
/* 필수 항목 옆에 빨간 별표 추가 */
.required::after {
  content: " *";
  color: red;
}

/* 링크 앞에 아이콘 추가 */
.external-link::before {
  content: "🔗 ";
}

/* 장식용 밑줄 */
.title::after {
  content: "";
  display: block;
  width: 60px;
  height: 3px;
  background-color: #3b82f6;
  margin-top: 8px

가상 요소를 사용할 때 반드시 기억해야 할 규칙이 하나 있습니다. content 속성이 필수입니다. 텍스트가 필요 없더라도 빈 문자열(content: "")을 반드시 넣어야 가상 요소가 화면에 나타납니다. content를 빼먹으면 아무것도 렌더링되지 않습니다.

실무에서는 HTML에 의미 없는 장식용 태그를 추가하는 대신 ::before/::after로 처리하는 것이 깔끔합니다. 단, 가상 요소는 스크린 리더가 읽을 수도 읽지 않을 수도 있으므로, 중요한 콘텐츠는 반드시 HTML에 작성하고 가상 요소는 장식 용도로만 사용하세요. Tailwind CSS에서는 before:content-['*'], after:block 같은 유틸리티로 가상 요소를 다룰 수 있어서, 직접 CSS를 작성하는 빈도는 줄어들지만 내부 동작 원리는 동일합니다.

10. BFC (Block Formatting Context) — 마진 겹침이 풀리는 원리

3번 섹션에서 마진 겹침을 방지하기 위해 overflow: hidden을 사용했습니다. "왜 overflow가 마진 겹침을 해결하는 거지?" 라는 의문이 들었을 수 있습니다. 그 답이 바로 BFC(Block Formatting Context)입니다.

BFC는 쉽게 말하면 "독립된 레이아웃 영역"입니다. BFC가 생성된 요소의 내부 레이아웃은 외부에 영향을 주지 않고, 외부 레이아웃도 내부에 영향을 주지 않습니다. 마진 겹침은 같은 BFC 안에서만 발생하기 때문에, 새로운 BFC를 만들면 겹침이 차단됩니다.

BFC를 생성하는 대표적인 방법들입니다.
  • overflow: hidden (또는 auto, scroll)
  • display: flex 또는 display: grid
  • display: flow-root — BFC 생성만을 위해 만들어진 속성
  • position: absolute 또는 fixed
css
/* 마진 겹침 방지: 가장 명확한 방법 */
.parent {
  display: flow-root; /* BFC 생성, 부작용 없음 */
}

/* 또는 이미 사용 중인 방법 */
.parent {
  overflow: hidden; /* BFC 생성, 넘치는 콘텐츠가 잘릴 수 있음 */
}

display: flow-root는 BFC 생성만을 목적으로 하기 때문에 가장 부작용이 적습니다. overflow: hidden은 콘텐츠가 넘칠 때 잘리는 부작용이 있을 수 있으므로, 상황에 맞게 선택하면 됩니다.

참고로 Tailwind CSS를 사용하면 flex, grid, gap, space-y 등의 유틸리티를 쓰는 과정에서 BFC가 자동으로 생성되고 마진 겹침도 자연스럽게 회피되기 때문에, 실무에서 BFC를 직접 다룰 일은 많지 않습니다. 다만 순수 CSS를 작성하거나 디버깅할 때 "마진이 이상하게 동작하면 BFC를 의심해봐야 한다"는 것은 기억해두세요.

11. cursor와 pointer-events — 마우스 커서로 UX 힌트 주기

cursor와 pointer-events는 둘 다 CSS 속성입니다. JavaScript 없이 HTML 요소에 CSS를 적용하는 것만으로 마우스 커서 모양과 클릭 동작을 제어할 수 있습니다.

cursor — 커서 모양 바꾸기

cursor 속성을 요소에 적용하면, 사용자가 해당 요소 위에 마우스를 올렸을 때 커서 모양이 바뀝니다. "이 요소는 클릭할 수 있어요" 또는 "지금 처리 중이에요" 같은 시각적 힌트를 줍니다.

html
<!-- HTML -->
<div class="card">클릭하면 상세 페이지로 이동합니다</div>
<button class="btn-submit" disabled>제출 불가</button>
<p class="loading-text">데이터를 불러오는 중...</p>
css
/* 클릭 가능한 카드: 손가락 커서 (링크처럼 보임) */
.card {
  cursor: pointer;
}

/* 비활성화된 버튼: 금지 표시 커서 */
.btn-submit:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

/* 로딩 중: 대기 커서 */
.loading-text {
  cursor: wait;
}
자주 쓰이는 cursor 값을 정리하면 이렇습니다.
값커서 모양언제 쓰나
pointer손가락클릭 가능한 요소 (카드, 커스텀 버튼)
not-allowed금지 표시비활성화된 요소
wait모래시계/스피너로딩 중인 영역

pointer-events — 클릭 자체를 차단하기

cursor: not-allowed는 커서 모양만 바꿀 뿐, 실제로 클릭은 여전히 됩니다. 클릭 이벤트 자체를 막으려면 pointer-events: none을 사용해야 합니다.

html
<!-- 로딩 중에 버튼 클릭 완전 차단 -->
<button class="btn-loading">처리 중...</button>

<!-- 오버레이 뒤의 콘텐츠 클릭 방지 -->
<div class="overlay"></div>
css
/* 버튼 클릭 완전 차단: 커서 모양 + 이벤트 차단 */
.btn-loading {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none; /* 마우스 클릭, 호버 등 모든 포인터 이벤트 무시 */
}

/* 모달 뒤 배경 클릭 방지 */
.overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
}

정리하면 cursor는 "어떻게 보이게 할 것인가"(시각적 피드백)이고, pointer-events는 "클릭이 되게 할 것인가"(동작 제어)입니다. 비활성화된 버튼에는 보통 둘 다 함께 사용합니다.

React / Tailwind에서는?

Tailwind CSS에서는 cursor-pointer, cursor-not-allowed, pointer-events-none 같은 유틸리티 클래스로 바로 적용합니다. React에서 버튼을 비활성화할 때는 HTML의 disabled 속성과 Tailwind의 disabled: 의사 클래스를 함께 사용하는 것이 깔끔합니다.

html
<!-- Tailwind + React 예시 -->
<button
  disabled
  class="bg-blue-500 text-white disabled:opacity-50 disabled:cursor-not-allowed"
>
  제출하기
</button>

📝 3주차 스터디 인증 미션

아래 질문 중 하나를 직접 찾아보고 답을 댓글로 남겨주세요.
Quiz1 / 3
Q.box-sizing: content-box(기본값) 상태에서 width: 300px, padding: 20px, border: 10px solid black을 준 요소의 실제 화면 너비는 몇 px인가요? 직접 계산 과정을 쓰세요.

포스트 목록

/study/clab-26-1
파일 13개, 폴더 2개
프론트엔드 스터디 1주차: 마크업 그 이상, 실무를 위한 중급 HTML 가이드프론트엔드 스터디 2주차: 사용자와 소통하는 폼 & CSS의 시작프론트엔드 스터디 3주차: 프론트엔드의 첫 번째 벽, 박스 모델과 스타일링프론트엔드 스터디 4주차: 자유자재 레이아웃 (포지션과 플렉스박스)프론트엔드 스터디 5주차: JavaScript 시작 — 타입, 변수, 그리고 JS가 이상한 이유프론트엔드 스터디 6주차: 객체, 함수, 그리고 스코프프론트엔드 스터디 7주차: 불변성, 프로토타입, 타입 체크프론트엔드 스터디 8주차: 클로저, Promise, async/await프론트엔드 스터디 9주차: React 입문 전 필수 JS 문법 — map, 구조 분해, 스프레드프론트엔드 스터디 10주차: React 기초 1 — 컴포넌트, JSX, props, useState프론트엔드 스터디 11주차: React 기초 2 — useEffect, 이벤트 처리, 폼프론트엔드 스터디 심화: this, 실행 컨텍스트, 이터러블프론트엔드 스터디 심화: 에러 처리와 정규 표현식
;
}
X
X
가능
opacity: 0OOO가능
;
}
textI-beam텍스트 선택 가능 영역
grab / grabbing손 / 주먹드래그 가능 요소
default기본 화살표일반 영역