프론트엔드 스터디 11주차: React 기초 2 —.
useEffect로 사이드 이펙트를 다루고, 이벤트 처리와 폼 상태 관리까지 — React로 실제 동작하는 앱을 만들기 위한 핵심 기술을 배웁니다.
<strong>학습 구간:</strong> [04:28:10 ~ 05:28:02] 배경 이미지 제어부터 Flexbox
레이아웃까지
<strong>강의 바로가기:</strong>
---
---
/* 하나씩 쓰는 방식 */
.hero {
background-image: url("hero.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
/* 단축 속성으로 합치기 */
.hero {
background: url("hero.jpg") center / cover no-repeat;
}/* 1. static (기본값): 문서 흐름대로 배치, top/left 등 무시 */
.box-static {
position: static;
}
/* 2. relative: 원래 위치를 기준으로 이동, 원래 자리는 유지 */
.box-relative {
position: relative;
top: 10px; /* 원래 위치에서 아래로 10px */
left: 20px; /* 원래 위치에서 오른쪽으로 20px */
}
/* 3. absolute: positioned 조상을 기준으로 배치, 문서 흐름에서 빠짐 */
.box-absolute {
position: absolute;
top: 0;
right: 0; /* 기준 요소의 우상단에 붙음 */
}
/* 4. fixed: 뷰포트(화면)를 기준으로 고정, 스크롤해도 안 움직임 */
.box-fixed {
position: fixed;
bottom: 20px;
right: 20px; /* 화면 우하단에 고정 */
}<!-- absolute의 올바른 사용 패턴 -->
<div style="position: relative;">
<!-- 이 div가 기준점 역할 -->
<span style="position: absolute; top: 5px; right: 5px;"> NEW </span>
</div>.background-layer {
z-index: 1;
}
.content-layer {
z-index: 10;
}
.modal-layer {
z-index: 100;
}
.tooltip-layer {
z-index: 1000;
}/* 내비게이션 바: 로고는 왼쪽, 메뉴는 오른쪽 */
.navbar {
display: flex;
justify-content: space-between; /* 주축: 양 끝에 배치 */
align-items: center; /* 교차축: 세로 가운데 */
}
/* 카드 목록: 일정 간격으로 가로 배치, 넘치면 줄바꿈 */
.card-list {
display: flex;
flex-wrap: wrap; /* 넘치면 다음 줄로 */
gap: 16px; /* 카드 사이 간격 */
}
/* 완벽한 정중앙 배치 (가장 자주 쓰이는 패턴) */
.center-box {
display: flex;
justify-content: center; /* 가로 가운데 */
align-items: center; /* 세로 가운데 */
height: 100vh; /* 화면 전체 높이 */
}/* 사이드바(고정) + 메인 콘텐츠(나머지 전부) 레이아웃 */
.sidebar {
flex: 0 0 250px; /* 안 늘어남, 안 줄어듦, 250px 고정 */
}
.main-content {
flex: 1; /* 남은 공간 전부 차지 (flex: 1 0 0의 단축) */
}
/* 3등분 레이아웃 */
.column {
flex: 1; /* 세 요소가 균등하게 1:1:1 */
}<strong>Layout (Reflow)</strong>: 각 요소의 크기와 위치를 계산합니다. width,
height, margin, padding, position 등이 변경되면 이 단계가 다시 실행됩니다.
<strong>Paint (Repaint)</strong>: 계산된 위치에 색상, 그림자, 테두리 등
시각적인 부분을 칠합니다. background-color, box-shadow, color 등이 변경되면 이 단계가 다시 실행됩니다.
<strong>Composite</strong>: 여러 레이어를 합성해서 최종 화면을 만듭니다.
transform, opacity 변경은 이 단계만 다시 실행합니다.
/* 느린 방법: 매 프레임마다 Reflow 발생 */
.box-slow {
position: relative;
transition: top 0.3s;
}
.box-slow:hover {
top: -10px;
}
/* 빠른 방법: Composite만 발생 */
.box-fast {
transition: transform 0.3s;
}
.box-fast:hover {
transform: translateY(-10px);
}/* 기본 문법: transition: 속성 시간 타이밍함수 지연시간; */
.button {
background-color: #3b82f6;
color: white;
padding: 12px 24px;
border-radius: 8px;
transition: background-color 0.2s ease;
}
.button:hover {
background-color: #1d4ed8; /* 0.2초에 걸쳐 부드럽게 변함 */
}<strong>transition-property</strong>: 어떤 속성에 전환 효과를 줄지 (all,
background-color, transform 등)
<strong>transition-duration</strong>: 전환에 걸리는 시간 (0.3s, 200ms)
<strong>transition-timing-function</strong>: 전환의 속도 곡선 (ease,
linear, ease-in-out)
<strong>transition-delay</strong>: 전환이 시작되기 전 대기 시간 (0s,
0.1s)
/* 여러 속성에 각각 다른 전환 적용 */
.card {
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-4px); /* 위로 살짝 뜨는 효과 */
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15); /* 그림자 추가 */
}
/* 모든 속성에 한 번에 적용 (간편하지만 의도치 않은 속성도 전환될 수 있음) */
.link {
transition: all 0.2s ease;
}/* 1. 버튼 호버: 배경색 변화 */
.btn {
transition: background-color 0.2s ease;
}
/* 2. 카드 호버: 위로 떠오르는 효과 */
.card {
transition:
transform 0.3s ease,
box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
}
/* 3. 페이드 효과 */
.fade {
transition: opacity 0.3s ease;
opacity: 0;
}
.fade.visible {
opacity: 1;
}
/* 4. 사이드바 슬라이드 */
.sidebar {
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.sidebar.open {
transform: translateX(0);
}/* 기본: 모바일 (작은 화면) */
.card-list {
display: flex;
flex-direction: column;
gap: 16px;
}
/* 태블릿 이상: 768px부터 2열 */
@media (min-width: 768px) {
.card-list {
flex-direction: row;
flex-wrap: wrap;
}
.card-list > .card {
flex: 1 1 calc(50% - 16px);
}
}
/* 데스크톱: 1024px부터 3열 */
@media (min-width: 1024px) {
.card-list > .card {
flex: 1 1 calc(33.333% - 16px);
}
}<strong>트래픽</strong>: 전 세계 웹 트래픽의 약 60%가 모바일에서 발생합니다. <strong>성능</strong>: 모바일 기기는 성능이 제한적이므로, 기본 스타일을 가볍게
유지하고 큰 화면에서만 추가 스타일을 로드하는 것이 효율적입니다.
<strong>점진적 향상</strong>: 단순한 것에서 복잡한 것으로 확장하는 것이,
복잡한 것에서 기능을 빼는 것보다 쉽습니다.
| 구분 | 브레이크포인트 | 대상 기기 |
|---|---|---|
| <strong>sm</strong> | 640px | 큰 스마트폰 |
| <strong>md</strong> | 768px | 태블릿 |
| <strong>lg</strong> | 1024px | 작은 데스크톱 / 태블릿 가로 |
| <strong>xl</strong> | 1280px | 데스크톱 |
| 미디어 특성 | 용도 | 예시 |
|---|---|---|
prefers-color-scheme | 사용자의 다크/라이트 모드 감지 | @media (prefers-color-scheme: dark) |
prefers-reduced-motion | 애니메이션 줄이기 설정 감지 | @media (prefers-reduced-motion: reduce) |
orientation | 세로/가로 방향 감지 | @media (orientation: landscape) |
hover | 호버가 가능한 기기인지 감지 | @media (hover: hover) |
pointer | 포인팅 장치의 정밀도 감지 | @media (pointer: coarse) |
print | 인쇄 시 스타일 분기 | @media print |
/* 다크 모드일 때 배경색 변경 */
@media (prefers-color-scheme: dark) {
body {
background-color: #1a1a1a;
color: #f0f0f0;
}
}
/* 사용자가 "움직임 줄이기"를 켰을 때 애니메이션 제거 */
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
/* 터치 기기(스마트폰, 태블릿)에서는 호버 효과 제거 */
@media (hover: none) {
.button:hover {
background-color: inherit;
}
}
/* 인쇄할 때 불필요한 요소 숨기기 */
@media print {
.navbar,
.sidebar,
.footer {
display: none;
}
}Post Q&A
프론트엔드 스터디 4주차: 자유자재 레이아웃 (포지션과 플렉스박스) 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!
지금 당장 읽지 않아도 됩니다. React를 배우면서 에러 처리가 필요해지거나 면접 대비가 필요할 때 참고하세요.