웹과 멀티미디어
HTML5 이전에는 웹에서 멀티미디어 콘텐츠를 재생하기 위해 플러그인(Plug-in)의 도움이 필요했다. <object>와 <embed>가 바로 그런 역할을 하는 태그였다.
<object>: 오디오, 비디오, PDF, Java 애플릿 등 다양한 외부 콘텐츠를 삽입할 때 사용하던 범용적인 태그<embed>: 주로 플래시(Flash)와 같은 특정 플러그인 콘텐츠를 삽입할 때 사용
HTML5의 등장 이후, 오디오와 비디오는 아래에 설명할 <audio>, <video> 태그를 사용하는 것이 표준이 되었다. 현재 <object>와 <embed>는 PDF 뷰어 등 특수한 외부 콘텐츠를 삽입하는 경우에 제한적으로 사용된다.
오디오 & 비디오 재생하기
HTML5에서는 플러그인 없이도 웹 브라우저 자체적으로 오디오와 비디오를 재생할 수 있는 표준 태그를 제공한다.
<audio>와 <video> 태그
<audio>: 오디오 파일을 재생한다.<video>: 비디오 파일을 재생한다.
주요 속성
src: 재생할 미디어 파일의 경로를 지정한다.controls: 재생, 정지, 볼륨 조절 등 제어 막대를 표시한다.autoplay: 페이지 로딩 시 자동으로 재생한다. (최근 브라우저에서는muted속성과 함께 사용해야 동작하는 경우가 많다.)muted: 음소거 상태로 재생한다.loop: 재생이 끝나면 자동으로 다시 시작한다.poster: (video 전용) 비디오가 재생되기 전에 표시될 이미지(썸네일) 경로를 지정한다.
<source>와 <track> 태그
<source>: 브라우저별로 지원하는 미디어 포맷이 다를 수 있기 때문에, 이 태그를 사용해 여러 형식의 파일을 제공할 수 있다. 브라우저는 위에서부터 순서대로 지원 가능한 첫 번째 파일을 재생한다.type속성을 지정하면 브라우저가 파일을 다운로드하기 전에 지원 여부를 판단해 대역폭을 절약한다.<track>: 비디오에 자막, 캡션 등 시간 기반 텍스트 트랙을 추가할 때 사용한다.
예시 코드
<audio controls>
<source src="music.mp3" type="audio/mpeg">
<source src="music.ogg" type="audio/ogg">
브라우저가 audio 태그를 지원하지 않습니다.
</audio>
<video controls poster="thumbnail.jpg" width="600">
<source src="movie.mp4" type="video/mp4">
<source src="movie.webm" type="video/webm">
<track kind="subtitles" src="subtitles_ko.vtt" srclang="ko" label="한국어">
<track kind="subtitles" src="subtitles_en.vtt" srclang="en" label="English">
브라우저가 video 태그를 지원하지 않습니다.
</video>controls 속성을 주면 브라우저가 아래처럼 재생·정지·볼륨 막대를 자동으로 만들어 준다. (오디오 파일은 연결되어 있지 않아 재생되지는 않는다)
<audio controls>
<video controls poster="..."> — poster가 재생 전 썸네일
다재다능한 CSS3 선택자
기본 선택자보다 더 정교하게 요소를 선택할 수 있는 강력한 선택자들이다.
선택자 | 이름 | 설명 | 예시 |
|---|---|---|---|
| 하위 | A 요소 안에 있는 모든 B 요소 |
|
| 자식 | A 요소의 직계 자식인 B 요소만 |
|
| 인접 형제 | A 요소 바로 다음에 오는 형제 B 요소 하나만 |
|
| 형제 | A 요소 다음에 오는 모든 형제 B 요소 |
|
| 속성 | 특정 속성을 가진 모든 요소 |
|
| 속성=값 | 속성 값이 정확히 일치하는 요소 |
|
| 속성~=값 | 속성 값에 특정 단어가 포함된 요소 |
|
| 속성^=값 | 속성 값이 특정 문자열로 시작하는 요소 |
|
| 속성$=값 | 속성 값이 특정 문자열로 끝나는 요소 |
|
| 속성*=값 | 속성 값에 특정 문자열이 포함된 요소 |
|
가상 클래스와 가상 요소
가상 클래스 (Pseudo-classes): 요소의 특정 상태에 따라 스타일을 적용한다. (: 한 개 사용)
:hover: 마우스 커서를 올렸을 때:active: 마우스로 클릭하고 있는 동안:focus:<input>등이 포커스를 받았을 때:first-child: 형제 요소 중 첫 번째 요소:last-child: 형제 요소 중 마지막 요소:nth-child(n): 형제 요소 중 n번째 요소 (예:li:nth-child(2n)은 짝수 번째li선택):not(selector): 괄호 안 선택자에 해당하지 않는 요소 (예:li:not(.active)는active클래스가 아닌li):disabled/:checked/:required/:placeholder-shown: 폼 요소의 상태에 따라 스타일을 적용. 비활성화된 입력 연한 색, 체크된 항목 강조, 필수 필드 표시 등에 활용.
가상 요소 (Pseudo-elements): 요소의 특정 부분에 스타일을 적용한다. (CSS3부터 :: 두 개 사용 권장)
::before: 요소의 콘텐츠 시작 부분에 새로운 콘텐츠를 추가한다. (content속성 필수)::after: 요소의 콘텐츠 끝 부분에 새로운 콘텐츠를 추가한다. (content속성 필수)::first-letter: 단락의 첫 글자에 스타일을 적용한다.::first-line: 단락의 첫 줄에 스타일을 적용한다.::selection: 사용자가 드래그하여 선택한 텍스트에 스타일을 적용한다.
/* 링크에 마우스를 올리면 밑줄이 생김 */
a:hover {
text-decoration: underline;
}
/* 리스트의 홀수 번째 항목 배경색 변경 */
li:nth-child(odd) {
background-color: #f2f2f2;
}
/* 모든 p 태그 앞에 '참고: ' 라는 텍스트 추가 */
p::before {
content: "참고: ";
font-weight: bold;
color: blue;
}li:nth-child(odd) — 홀수 줄 배경색
첫째 줄 (홀수)
둘째 줄
셋째 줄 (홀수)
넷째 줄
p::before { content: "참고: " }
참고: 가상 요소로 앞에 글자를 붙였습니다.
p::first-letter — 첫 글자만 크게
멋진 첫 글자 강조 효과입니다. 잡지 본문에서 자주 보이는 스타일입니다.
플렉스 박스 레이아웃 (Flexbox)
Flexbox는 복잡한 레이아웃을 쉽고 유연하게 구현하기 위한 1차원 레이아웃 모델이다. 가로 또는 세로 방향 중 한쪽 방향으로 아이템들을 정렬하고 배치하는 데 매우 강력하다.
Flex Container:
display: flex;가 적용된 부모 요소Flex Items: Flex Container의 자식 요소들
주요 Container 속성
flex-direction: 아이템이 정렬될 주축(main-axis)의 방향을 결정한다.row(기본값): 가로 (왼쪽에서 오른쪽)row-reverse: 가로 역순column: 세로 (위에서 아래)column-reverse: 세로 역순
flex-wrap: 아이템들이 한 줄에 모이지 않을 때 어떻게 할지 결정한다.nowrap(기본값): 강제로 한 줄에 들어감 (아이템이 좁아질 수 있음)wrap: 공간이 부족하면 다음 줄로 넘어감
justify-content: 주축(main-axis) 방향으로 아이템들을 정렬하는 방법을 결정한다.flex-start(기본값): 시작점으로 정렬flex-end: 끝점으로 정렬center: 가운데 정렬space-between: 첫 아이템은 시작점, 마지막 아이템은 끝점에 붙고 나머지는 균등한 간격으로 정렬space-around: 모든 아이템 둘레에 균등한 간격을 만듦space-evenly: 아이템 사이와 양 끝 여백을 완전히 균등하게 만듦
align-items: 교차축(cross-axis) 방향으로 아이템들을 정렬하는 방법을 결정한다.stretch(기본값): 아이템들이 교차축 방향으로 컨테이너를 가득 채우도록 늘어남flex-start: 시작점으로 정렬flex-end: 끝점으로 정렬center: 가운데 정렬baseline: 텍스트의 기준선(baseline)으로 정렬
gap: 아이템 사이의 간격을 지정한다. 과거에는margin으로 처리했지만 현재는gap이 표준.
주요 Item 속성
flex:flex-growflex-shrinkflex-basis를 한 번에 지정하는 단축 속성.flex: 1로 쓰면 아이템들이 남은 공간을 동등하게 나눠 가진다.align-self: 개별 아이템에만align-items를 재정의한다 (auto,flex-start,center등).order: 아이템의 표시 순서를 변경한다 (HTML 마크업을 수정하지 않고).
.container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 200px;
background-color: lightgray;
}flex-direction — 주축 방향
row (기본)
1
2
3
column
1
2
3
justify-content — 주축(가로) 정렬
flex-startABC
centerABC
flex-endABC
space-betweenABC
space-aroundABC
space-evenlyABC
align-items — 교차축(세로) 정렬
flex-start
AB
center
AB
flex-end
AB
stretch
AB
가운데 정렬의 정석
justify-content: center + align-items: center를 함께 쓰면 자식을 가로·세로 정중앙에 놓을 수 있다. 가장 많이 쓰는 Flexbox 패턴이다.
반응형 웹 기초 및 미디어 쿼리 맛보기
반응형 웹 디자인(Responsive Web Design, RWD)은 데스크톱, 태블릿, 모바일 등 다양한 디바이스의 화면 크기에 맞춰 웹 페이지의 레이아웃과 콘텐츠가 최적화되어 보이도록 하는 웹 디자인 기법이다.
미디어 쿼리(Media Query)는 반응형 웹을 구현하는 핵심 기술로, 특정 조건(예: 화면 너비)에 따라 다른 CSS 스타일을 적용하게 해준다.
같은 콘텐츠라도 화면 너비에 따라 카드 배치가 아래처럼 달라진다.
📱 모바일
(~767px) 1열
카드
카드
카드
📲 태블릿
(768~991px) 2열
카드
카드
카드
💻 데스크톱
(992px~) 3열
카드
카드
카드
@media 규칙
@media (조건) { /* 조건이 참일 때 적용될 CSS */ } 형식으로 사용한다.
모바일 우선 vs 데스크탑 우선 전략
min-width: 768px는 모바일 우선(mobile-first) 전략으로, 기본 스타일은 모바일용으로 작성하고 점점 큰 화면을 대응.max-width: 767px는 데스크탑 우선(desktop-first) 전략으로, 기본 스타일은 데스크탑용으로 작성하고 작은 화면을 대응.최근에는 모바일 우선이 권장됨.
반응형 웹의 필수 코드
HTML <head>에 아래 viewport 메타 태그를 추가해야 디바이스의 화면 너비를 기준으로 페이지가 올바르게 표시된다.
<meta name="viewport" content="width=device-width, initial-scale=1.0">예시 코드
.container {
display: flex;
}
.item {
flex: 1;
padding: 20px;
}
/* 화면 너비가 768px 이하일 때 적용될 스타일 */
@media (max-width: 768px) {
.container {
/* 가로 정렬을 세로 정렬로 변경 */
flex-direction: column;
}
}aspect-ratio 활용
반응형 카드에서 세로/가로 비율을 유지하고 싶을 때 aspect-ratio 속성이 유용하다. 예: .thumbnail { aspect-ratio: 16 / 9; }는 너비가 바뀌어도 16:9 비율을 자동으로 유지한다. 프로필 이미지, 동영상 영역, 제품 카드 등에 활용.
종합 실습: 반응형 카드 레이아웃 만들기
Flexbox와 미디어 쿼리를 사용하여 화면 크기에 따라 유연하게 변하는 카드 UI 레이아웃을 만들어 본다.
요구사항
여러 개의 카드를 담는 Flex Container를 만든다.
데스크톱 화면 (992px 이상)에서는 한 줄에 3개의 카드가 표시된다.
태블릿 화면 (768px ~ 991px)에서는 한 줄에 2개의 카드가 표시된다.
모바일 화면 (767px 이하)에서는 한 줄에 1개의 카드만 표시된다.
카드에 마우스를 올리면(
:hover) 그림자 효과가 진해지는 효과를 준다.PDF 파일 링크(
[href$=".pdf"])에 특별한 아이콘을::before가상 요소를 이용해 추가한다.
완성 코드
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>반응형 카드 레이아웃</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>Our Services</h1>
<div class="card-container">
<div class="card">
<h2>웹 개발</h2>
<p>최신 기술을 사용한 반응형 웹사이트를 제작합니다.</p>
<a href="service-web.pdf">소개서 다운로드</a>
</div>
<div class="card">
<h2>앱 개발</h2>
<p>iOS와 Android 앱을 위한 솔루션을 제공합니다.</p>
<a href="#">자세히 보기</a>
</div>
<div class="card">
<h2>디자인</h2>
<p>사용자 중심의 직관적인 UI/UX를 디자인합니다.</p>
<a href="#">자세히 보기</a>
</div>
</div>
</body>
</html>style.css
body {
font-family: sans-serif;
margin: 0;
background-color: #f4f4f4;
}
h1 {
text-align: center;
margin: 40px 0;
}
/* Flex Container */
.card-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 20px;
padding: 20px;
}
.card {
background-color: white;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
padding: 20px;
transition: box-shadow 0.3s ease;
}
/* :hover 효과 */
.card:hover {
box-shadow: 0 8px 12px rgba(0,0,0,0.2);
}
.card h2 {
margin-top: 0;
}
/* 속성 선택자 + 가상 요소 */
.card a[href$=".pdf"]::before {
content: "📄 ";
}
/* --- 미디어 쿼리 --- */
/* 데스크톱 화면 (3열) */
@media (min-width: 992px) {
.card {
width: calc(33.333% - 40px);
}
}
/* 태블릿 화면 (2열) */
@media (min-width: 768px) and (max-width: 991px) {
.card {
width: calc(50% - 40px);
}
}
/* 모바일 화면 (1열) */
@media (max-width: 767px) {
.card {
width: 100%;
}
}데스크톱 화면에서의 완성 모습 (마우스를 올리면 그림자가 진해지고, PDF 링크 앞에는 📄 아이콘이 붙는다):
웹 개발
최신 기술을 사용한 반응형 웹사이트를 제작합니다.
앱 개발
iOS와 Android 앱을 위한 솔루션을 제공합니다.
디자인
사용자 중심의 직관적인 UI/UX를 디자인합니다.
↑ 세 번째 카드는 :hover 상태(그림자 진함)를 예시로 표현