HTML/CSS 학습법: 결과 화면 먼저 보고 소스코드를 확인하자
UI와 UX
UX(User Experience; 사용자 경험): 사용자 편의성
ex: 링크에 hover했을 때 커서가 손모양으로 바뀌어야 한다.
UI(User Interface): 기능을 하는 화면이 있는가
- HTML 선언:
<!DOCTYPE html>
- 태그는 계층구조로 되어 있다. 시작태그와 끝태그라고 하고, 태그 사이의 내용은 HTML 콘텐츠라고 한다.
<head>
태그와<body>
사이에 컨텐츠를 넣는 것처럼 문법에 맞지 않게 HTML 코드를 작성한다고 해도 브라우저는 관대하게 봐준다. (컴파일러와 다르다) 그러나 브라우저가 관대하다고 해서 그것이 옳다고 생각하면 안 된다. html에는<head>
와<body>
만 존재해야 한다.<body>
안에는 몸체 컨텐츠가 있다.<head>
에는 실제 출력되는 내용에 대한 부가정보가 들어 있다.<html>
요소는 HTML문서 루트(최상단 요소)를 나타내며, 루트 요소라고도 부른다. 모든 다른 요소는<html>
요소의 후손이어야 한다.<html>
은 이와 같이 노드들의 연결로 표현한다. 이는 가지치기와 비슷하다고 해서 트리라고 부른다. 특히 이를 하나의 객체처럼 표현하는데 이를 DOM(DOCUMENT Object Model
)트리라고 부른다.- tag = element
DOM이란? 문서 객체 모델(The Document Object Model)은 HTML, XML 문서의 프로그래밍 interface 이다. DOM은 문서의 구조화된 표현(structured representation)을 제공하여 프로그래밍 언어가 DOM 구조에 접근할 수 잇는 방법을 제공하여 그들이 문서 구조, 스타일, 내용 등을 변경할 수 잇게 돕는다. DOM은 구조화된 nodes와 property와 method들이 갖고 있는 objects로 문서를 표현한다. 이들은 웹 페이지를 스크립트 또는 프로그래밍 언어들에서 사용될 수 있게 연결시켜주는 역할을 담당한다.
웹 페이지는 일종의 문서(document)이다. 구글 검색 엔진이 이 문서를 읽어들여서 문서의 내용이 무엇인지 판단을 내린다. 만약 제목을 <h1>
등 헤더 태그가 아니라 <p>
태그를 사용한다면, 구글 검색 엔진에서 해당 요소가 제목인지 아닌지 판단할 길이 없다. 따라서 HTML을 작성할 때는 데이터의 의미와 역할을 표현하는 태그를 사용하는 것이 중요하다. 사용자가 볼 때는 똑같지만 검색을 할 때는 다르다. 따라서 검색에 잘 걸리기 위해서는 의미 있는 태그를 사용한다.이게 바로 시멘틱 웹이다. 데이터를 표현할 때 아무 태그 쓰지 말고 그 데이터의 의미를 잘 표현할 수 있는 태그를 사용한다.
시멘틱 html
- 검색 엔진은 의미론적 마크업을 페이지의 검색 랭킹에 영향을 줄 수 있는 중요한 키워드로 간주한다.
- 시각 장애가 있는 사용자가 화면 판독기로 페이지를 탐색할 때 의미론적 마크업을 푯말로 사용할 수 있다.
- 의미 없고 클래스 이름이 붙여져있거나 그렇지 않은 끊임없는
div
들을 탐색하는 것보다, 의미 있는 코드 블록을 찾는 것이 훨씬 쉽다. - 개발자에게 태그 안에 채워질 데이터 유형을 제안한다.
- 의미있는 이름짓기(Semantic naming)은 적절한 사용자 정의 요소 구성 요소의 이름짓기(naming)를 반영한다.
1
2
3
4
5
6
7
8
9
10
<h1>Lorem ipsum</h1>
<h2>dolor sit amet</h2>
<hr />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<br />
<p>In porttitor lorem at justo feugiat aliquet.</p>
<br />
<p>Nunc id massa at magna semper hendrerit.</p>
<br />
<p>Vivamus rhoncus eros vel ante suscipit non facilisis risus rutrum.</p>
- HTML에서 줄바꿈 기호를 사용하는 것은 아무런 의미가 없다.
원래 HTML은 논문을 읽는 용도로 만들어졌다.
<p>
: paragraph(문단): 같은 주제의 내용
여기서 <hr/>
, <br/>
을 <hr>
, <br>
로 바꿔도 정상적으로 보인다.
- 기존 HTML4.3: 시멘틱하게 작성하지 않아 검색에 잘 걸리지 않는 문서가 많았다.
- XHTML의 탄생: html문서에 xml 문법을 적용하여 강력하게 문법 제한을 하자는 요구가 나왔다. 그래서 기존 HTML4에 xml문법을 더한 것이 XHTML이다.
- 그러나 문제는 엄격한 문법이 개발자들에게는 받아들여지지만, 디자이너나 일반인에게는 엄격한 작성이 받아들여지지 않는다는 점이다. 이전에는 문법이 느슨해도 출력이 잘 되었는데 안되기 시작하니까 아예 XHTML을 사용하지 않게 되었다.
- HTML5은 XHTML처럼 써도 되고, 이전 HTML4.3처럼 사용해도 관대하게 다 허용하였고, 인기가 많아졌다. 추가적으로 의미 있는 HTML태그들을 추가했다.
<br>
: 강제 줄바꿈. 기본은 화면 옆으로 계속 늘어나다가 화면 끝이 닿으면 아래로 내려지는 구조이다. 줄바꿈이 없다.
<a>
1
2
<a href="http://hanbit.co.kr">Hanbit</a><br />
<a href="https://github.com/">Github</a><br />
이 사이트가 어디에 정박(닿: anchor)하고 있는지 그 정박지의 주소를 가리킨다.
href
속성: html reference(hypertext reference)- 이걸 클릭하면 이 사이트로 요청을 보낸다.
- 보통 주소창에 주소를 쳐야 요청을 보내고 응답을 받는다. 그러면 주소를 치는 대신 자동으로 주소창에 해당 URL을 넣어서 대신해서 요청하는 것이 링크(a 엘리먼트)이다. 이 태그는 개발자를 대신해서 HTTP 요청을 한다. 게시글 목록에서 제목을 눌렀을 때
/detail
페이지로 이동하도록 만들 때 사용한다. - 태그로 지정된 URL로 요청을 하는 일을 한다.
엘리먼트의 종류
- 블록 엘리먼트: 콘텐츠가 꽉 차든 안차든 한 줄을 독점한다.
<p>
- 인라인 엘리먼트:
<a>
<a>
태그로 문서 내 특정 위치로 이동할 수도 있다.
같은 위치 내 바로 이동할 수 있다. 우선 해당 위치마다 id
를 부여한다. 아이디는 숫자로 시작하지 않고 영문으로 시작하고 중간에 단어와 단어 사이를 구분할 때 _
가 들어갈 수는 있다.
마크다운 문법에서는 헤더에
id
를 자동으로 부여한다. 따라서 해당 헤더 위치로 링크를 걸 수 있는 것이다.HTML, CSS로 무엇을 할 수 있는지 파악할 수 있어야 한다.
인라인 텍스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<h1>
Lorem ipsum <b>dolor sit</b> amet
</h1>
<h1>
Lorem ipsum <i>dolor sit </i>amet
</h1>
<h1>
Lorem ipsum <small>dolor sit</small> amet
</h1>
<h1>
Lorem ipsum <sub>dolor</sub> sit amet
</h1>
<h1>
Lorem ipsum <sup>dolor sit</sup> amet
</h1>
<h1>
Lorem ipsum <ins>dolor sit</ins> amet
</h1>
<h1>
Lorem ipsum <del>dolor sit</del> amet
</h1>
<hr />
Lorem ipsum <b>dolor sit</b> amet<br/>
Lorem ipsum <i>dolor sit </i>amet<br/>
Lorem ipsum <small>dolor sit</small> amet<br/>
Lorem ipsum <sub>dolor</sub> sit amet<br/>
Lorem ipsum <sup>dolor sit</sup> amet<br/>
Lorem ipsum <ins>dolor sit</ins> amet<br/>
Lorem ipsum <del>dolor sit</del> amet<br/>
1
2
3
4
<ruby>
<span>大韓民國</span>
<rt>대한민국</rt>
</ruby>
HTML5에서는 개발자가 임의적으로 태그를 만들어도 허락한다. 단 웹 브라우저에서 출력할 때는 기본 디폴트값이 적용된다.
1
2
<food>Custom food Tag</food>
<rice>Custom rice Tag</rice>
아무런 의미가 없는 것이 아니다! 여기에 스타일은 개발자가 임의로 지정하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
food {
display: block;
font-weight: bold;
font-style: italic;
color: crimson;
font-size: 2em;
}
</style>
<body>
<food>Custom food Tag</food>
<rice>Custom rice Tag</rice>
</body>
콘텐츠를 구성할 때 HTML을 사용한다면, CSS(Cascading Style Sheet)는 콘텐츠의 모양을 제어할 때 사용하고, JavaScript는 콘텐츠의 동작을 제어할 때 사용한다.
Cascading: 폭포수처럼 떨어진다는 뜻이다. 설정이 그 다음 자식 태그, 그 다음 자식 태그에도 적용된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<ul>
<li>HTML5
<ol>
<li>Multimedia Tag</li>
<li>Connectivity</li>
<li>Device Access</li>
</ol>
</li>
<li>CSS3
<ul>
<li>Animation</li>
<li>3D Transform</li>
</ul>
</li>
</ul>
ol
: ordered listul
: unordered listimageli
: list item
1
2
3
4
5
6
7
8
9
10
<dl>
<dt>HTML5</dt>
<dd>Multimedia Tag</dd>
<dd>Connectivity</dd>
<dd>Device Access</dd>
<dt>Milk</dt>
<dd>Animation</dd>
<dd>3D Transform</dd>
</dl>
dl
: definition list(정의 목록): 용어를 설명하는 목록을 만든다.dt
: definition term(정의 용어): 정의되는 용어의 제목을 넣을 때 사용한다.dd
: definition description(정의 설명): 용어를 설명하는 데 사용한다.
HTML 태그 안에 스타일을 넣지 말아야 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<table border="1">
<caption>Caption</caption>
<colgroup>
<col span="2" style="background: red" />
<col style="background: blue" />
</colgroup>
<thead style="background: green">
<tr>
<th>Table Header</th>
<th>Table Header</th>
<th>Table Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>Table Data</td>
<td>Table Data</td>
<td>Table Data</td>
</tr>
<tr>
<td>Table Data</td>
<td>Table Data</td>
<td>Table Data</td>
</tr>
<tr>
<td>Table Data</td>
<td>Table Data</td>
<td>Table Data</td>
</tr>
</tbody>
<tfoot style="background: yellow">
<tr>
<td>Table Data</td>
<td>Table Data</td>
<td>Table Data</td>
</tr>
</tfoot>
</table>
개발자도구의 Element에 있는 HTML은 오리지널 소스코드가 아니라 브라우저가 완전하게 재구성한 HTML이다. 이것이 DOM 이다. 예를 들어, 소스코드에 tbody
태그를 넣지 않고 table
밑에 바로 tr
태그를 넣는다고 해도, 브라우저가 HTML규격에 맞춰 재구성할 때 tbody
태그를 자동으로 넣는다. 따라서 자바스크립트로 DOM 요소를 찾을 때 소스코드의 태그를 찾기보다는 개발자 도구의 Element 코드를 보는 것이 낫다.
- 페이지 소스 보기에서 보여지는 코드는 서버로부터 전달받은 코드이다.
- 개발자 도구의 Elements에서 확인 가능한 코드는 서버에서 전달받은 코드에서 JavaScript등을 실행하여 변환된 코드이다. DOM을 이용해 html에서 원하는 attribute에 접근하여 속성을 변화시킨다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<table border="1">
<tr>
<!-- 열을 3칸 병합 -->
<th colspan="3">Table Data</th>
<!-- 행을 3칸 병합 -->
<th rowspan="3">Table Data</th>
</tr>
<tr>
<td>Table Data</td>
<!-- 행을 2칸 병합 -->
<td rowspan="2">Table Data</td>
<td>Table Data</td>
</tr>
<tr>
<td>Table Data</td>
<!-- 이미 점유된 td는 넘어간다!!! -->
<td>Table Data</td>
</tr>
</table>
이 td
는 행을 병합한다. 이때 rowspan
을 사용한다. 이미 점유된 td는 넘어간다. 만약 행과 열로 병합을 하고 싶다면 ` colspan과
rowspan` 속성 값을 동시에 설정하면 된다. 표는 1 행씩 만들면 된다.
스판: 늘어나는 성질의 옷
<img>
브라우저는 이미지 파일을 한 번에 받는 것이 아니라 html을 받은 후 화면에 렌더링하는 도중에 img
태그를 만나면 별도 스레드를 띄워 서버로 별도 요청하고 다운로드 받아 그 스레드가 해당 화면에 이미지를 렌더링한다.
루트 사진
1
2
3
<!-- 잘못된 사진 경로를 준다 -->
<img src="../photo.jpeg" alt="연예인" width="300" />
<img src="Nothing" alt="그림이 존재하지 않습니다." width="300" />
그림이 출력이 되지 않으면 그림 대신 옆에 alt 속성값이 나온다. (대안 텍스트)
그리고 시각 장애인을 위해 화면 판독기가 이 대안텍스트를 읽는다.
다른 서버의 사진
1
2
3
<img src="http://placehold.it/300x200" />
<img src="http://placehold.it/200x150" />
<img src="http://placehold.it/100x100" />
요청이 한 번만 발생하는 것이 아니라 여러번 발생한다.
<audio>
controls 속성
값과 관계 없이 속성의 존재 여부만 체크하는 속성
1
<audio src="Kalimba.mp3" controls="controls"></audio>
1
<audio src="Kalimba.mp3"></audio>
위 코드는 화면에 아무것도 출력되지 않는다.
1
<audio src="Kalimba.mp3" controls></audio>
controls
만 해도``controls=”controls” 를 한 것과 같이 화면에 음악재생기가 출력된다. html에서 속성이 존재하는 것만으로 의미가 있는 경우가 있는데,
audio 태그의
controls 속성이 이에 해당한다. 값이 어떤 지는 상관이 없다. 즉
controls 속성에
false 값을 주더라도
controls=”controls”`를 한 것과 같은 결과를 얻는다.
보통 속성명과 속성값이 같으면 값과 관계 없이 속성의 존재 여부만 체크한다.
autoplay 속성
1
<audio src="Kalimba.mp3" controls="controls" autoplay="autoplay"></audio>
보통 브라우저에서 이 속성을 막아 놓았다. 자동으로 음악이 재생하면 곤란할 수 있기 때문이다.
1
<audio src="Kalimba.mp3" controls autoplay></audio>
속성이 존재하는 것만으로 의미가 있기 때문에 위와 같이 작성해도 된다.
source 태그
1
2
3
4
<audio controls="controls">
<source src="Kalimba.mp3" type="audio/mp3" />
<source src="Kalimba.ogg" type="audio/ogg" />
</audio>
똑같은 음성 파일을 두개를 둔다. 브라우저, 운영체제, 디바이스에 따라서 플레이할 수 있는 것을 고려하여 여러 개의 소스를 넣을 수 있다. 가 첫번째를 플레이할 것이고, 플레이할 수 없다면 다음 것을 플레이할 것이다.
동영상
1
2
3
4
<video poster="http://placehold.it/640x360" width="640" height="360" controls="controls">
<source src="Wildlife.mp4" type="video/mp4" />
<source src="Wildlife.webm" type="video/webm" />
</video>
외부 라이브러리
- CSS 라이브러리
<link>
는 끝태그 안 적는 것이 규칙
- 자바스크립트 라이브러리
<script>
는 끝태그 적는 것이 규칙- 자바스크립트 함수, 객체, 변수들이 들어 있음
1
2
3
4
5
6
7
8
9
10
11
12
<head>
<title>Video.js Basic</title>
<link href="http://vjs.zencdn.net/4.9/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.9/video.js"></script>
</head>
<body>
<video controls="controls" width="640" height="360"
class="video-js vjs-default-skin" data-setup="{}">
<source src="Wildlife.mp4" type="video/mp4" />
<source src="Wildlife.webm" type="video/webm" />
</video>
</body>
CSS는 가져다 쓰는 것이다.
1
2
3
4
5
6
7
8
<video width="640" height="360" controls="controls">
<source src="Wildlife.mp4" type="video/mp4" />
<source src="Wildlife.webm" type="video/webm" />
<track kind="subtitles" src="track.srt" srclang="ko" label="Korean" />
<track kind="subtitles" src="track.srt" srclang="en" label="English" />
<track kind="subtitles" src="track.srt" srclang="jp" label="Japanese" />
<track kind="subtitles" src="track.srt" srclang="ch" label="Chinese" />
</video>
<form>
1
2
<input type="text" name="search" />
<input type="submit" />
여기서 name 속성값의 이름으로 서버에게 값을 보낸다. http://localhost:8080/bitcamp-web-project/source/ch2/2-35.html?search=
. 만약 name 속성을 추가하지 않는다면 submit 버튼을 눌렀을 때 주소창이 http://localhost:8080/bitcamp-web-project/source/ch2/2-35.html?
이렇게만 변한다. 즉 서버에게 값을 보낼 수 없다.
웹 브라우저가 웹 서버에 값을 보내는 방법
HTTP 프로토콜은 중간에 주거니 받거니가 안되고 딱 한번 요청하고 딱 한번 응답한다.
입력 폼은 한번의 데이터 전달에 적합하다.
method=”get”
1
2
3
4
<form method="get">
<input type="text" name="search" />
<input type="submit" />
</form>
적지 않으면 method 속성 기본값은 get이다.
http://localhost:8080/bitcamp-web-project/source/ch2/2-36-1.html?search=xxx
요청 구조: Request Line
GET일 때는 Content Type과 Content Length도 없다. 데이터가 URL에 붙어서 가기 때문이다.
1
2
3
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html
<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
응답 구조(Status Line, Headers, CRLF, Message Body)
method=”post”
1
2
3
4
<form method="post">
<input type="text" name="search" />
<input type="submit" />
</form>
제출 시 주소 변화: http://localhost:8080/bitcamp-web-project/source/ch2/2-36-2.html
포스트 방식은 yyy를 적고 제출햇는데도 주소창에 보이지 않는다.
결론
- GET은 모든 파라미터를 URL로 보내는 것 (눈에 보임)
- POST는 전달하려는 정보가 HTTP body에 포함되어 전달되는 것 (눈에 보이지 않음)
1
2
3
4
5
6
<form>
<input type="text" name="name" /><br />
<input type="password" name="password" /><br />
<input type="file" name="file" /><br />
<input type="submit" />
</form>
get 요청에서는 파일 이름만 보낼 수 있고 파일 자체는 보낼 수 없다.
1
Request URL: http://localhost:8080/bitcamp-web-project/source/ch2/2-37.html?name=%ED%85%8C%EC%8A%A4%ED%8A%B8&password=1010&file=bio-photo.jpg
피들러: 웹 디버깅 프록시 (자바로 만들어졌다.)
1
2
3
4
<form>
<label>이름</label>
<input type="text" />
</form>
<textArea>
1
2
3
4
<textarea>
Hello Textarea
Hello Textarea
</textarea>
텍스트 에디터에서 HTML을 작성할 때 이렇게 공백이 있으면 안된다. 다음과 같이 하도록 하자.
<textarea>Hello Textarea
Hello Textarea</textarea>
<button>
form안에 넣어야 서버에 보낼 수 있다. 이름이 없으면 보낼 수 없다. 타입을 안 적어도 submit
이고, submit
이라고 적어도 submit
이다. <button>
타입에는 button, submit, reset 세 가지가 있다.
1
2
3
4
5
6
7
8
9
<form>
<select multiple="multiple" name="food">
<option value="kim">김밥</option>
<option>떡볶이</option>
<option selected>순대</option>
<option selected>오뎅</option>
</select>
<button>제출</button>
</form>
multiple 속성일 때는 주소가 ?food=순대&food=오뎅
와 같이 같은 이름으로 서버에 여러 개의 값이 간다. 이때 어떻게 받을 지 서버 측에서 결정해야 한다.
1
2
3
4
5
6
7
8
9
10
11
<select>
<optgroup label="HTML5">
<option>Multimedia Tag</option>
<option>Connectivity</option>
<option>Device Access</option>
</optgroup>
<optgroup label="CSS3">
<option>Animation</option>
<option>3D Transform</option>
</optgroup>
</select>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<form>
<fieldset>
<legend>입력 양식</legend>
<table>
<tr>
<td><label for="name">이름</label></td>
<td><input id="name" type="text" /></td>
</tr>
<tr>
<td><label for="mail">이메일</label></td>
<td><input id="mail" type="email" /></td>
</tr>
</table>
<input type="submit" />
</fieldset>
</form>
<div>
- UI를 그룹으로 묶을 때 사용한다.
- 블럭 요소(division): 한 줄 전체를 점유한다.
<span>
- UI를 묶는 것이 아니라 text를 구분하는 용도로 사용한다.