폼 요소에는 form, input, button 과 같은 태그가 있으며 회원가입, 로그인, 검색창, 게시판, 파일업로드 등 사용자의 입력을 받아서 처리하는 경우에 사용한다. 폼 요소에서 입력받은 데이터는 서버로 전달되어 데이터베이스나 백엔드에서 해당 데이터를 처리한다. 실무에서는 백엔드 개발자와 협의하며 작성하는 것이 좋다.
우선 비주얼 스튜디오 편집기(vsc)의 File 메뉴에서 New Window 메뉴를 선택하여 새로운 편집기 창을 연다. html-class 폴더와 동일한 위치에 html-class-practice 폴더를 생성한다. 이후 연습작업은 여기서 하고 html-class 에서는 배운 내용을 웹사이트에 적용해보는 형태로 수업을 진행할 예정이다. 새 편집기 창의 File 메뉴에서 Open Folder 메뉴를 클릭해서 새로 만든 html-class-practice 폴더를 선택한다. 해당 폴더 안에 index.html 파일을 생성한다.
기본 폼 구조 - input 태그
html-class-practice 폴더 안의 index.html 파일을 다음과 같이 작성하자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<input type="text">
</body>
</html>
input 태그를 사용하여 사용자 입력을 받을 수 있는 입력창을 만들고 type 속성값으로 text 를 설정한다. 이렇게 하면 입력창은 텍스트를 입력받는다. index.html 파일을 우클릭하면 Open With Live Server 메뉴가 나온다. 클릭하면 Port 5500 이 아니라 새로운 포트인 5501 에서 서버가 실행된다. 그럼 아래와 같이 사용자가 데이터를 입력할 수 있는 입력창이 나온다.
입력창에 마우스를 클릭하면 커서가 깜빡이면서 입력창의 경계선이 찐하게 변한다. 이를 input 포커스(focus) 라고 한다.
입력창에 글자를 입력할 수 있다.
하지만 사용자에게 무엇을 입력하길 원하는지에 대한 안내문구가 없다. input 태그의 placeholder 속성을 사용하면 사용자에게 입력에 대한 안내를 할 수 있다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<input type="text" placeholder="아이디를 입력하세요.">
</body>
</html>
이전과 다르게 웹페이지가 처음 화면에 나타날때 입력창에 "아이디를 입력하세요" 라는 안내문구가 보인다. 내가 뭔가를 입력하기 시작하면 안내문구는 사라지고, Backspace 키로 입력한 텍스트를 모두 삭제하면 다시 안내문구가 나타난다.
기본 폼 구조 - label 태그
이렇게 하더라도 뭔가 부족한 느낌이다. 해당 입력창에 대한 제목이 필요할 것 같다. label 태그는 input 태그와 짝을 이루어 해당 입력창에 대한 제목을 작성할 수 있도록 도와준다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</body>
</html>
짝이 되는 input 태그에 id 값을 설정하고 해당 id 값을 동일하게 label 태그의 for 속성값으로 설정해주면 "사용자 이름:"이라는 문구를 클릭할때 아래와 같이 label 과 짝이 되는 input 요소에 포커스가 되면서 커서가 깜빡인다. 즉, label 태그는 짝이 되는 input 요소에 대한 제목을 작성함과 동시에 클릭시 input 요소에 글자를 입력할 수 있도록 포커스된다.
이번에는 비밀번호를 입력할 수 있는 입력창을 추가해보자! input 태그의 type 속성값을 password 로 설정한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</body>
</html>
이렇게 하면 비밀번호 입력시 아래와 같이 검은색 점으로 표시된다.
폼 세로 정렬하기
만약 사용자 이름을 입력하는 폼과 사용자 비밀번호를 입력하는 폼을 세로로 나열하고 싶으면 아래와 같이 p 태그를 이용하여 label 과 input 태그를 묶어주면 된다. p 태그는 블록레벨 요소이기 때문에 브라우저의 가로 한줄을 다 차지한다. 그렇기 때문에 p 태그로 묶은 각각의 폼은 각각 한줄에 표시된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
</body>
</html>
물론 아래와 같이 목록을 나열해주는 ul, li 태그를 사용해도 폼이 세로로 나열된다. li 태그도 블록레벨 요소이기 때문이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<ul>
<li>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</li>
<li>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</li>
</ul>
</body>
</html>
하지만 아래와 같이 들여쓰기되고 검은색 점(bullet)이 생기기 때문에 CSS 로 따로 스타일링해주어야 한다.
다시 p 태그를 사용하는 방식으로 변경해준다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
</body>
</html>
전송버튼 추가
이제 사용자가 입력한 아이디와 비밀번호를 서버로 전송하여 회원가입을 요청하는 "가입하기" 버튼을 만들어보자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<input type="submit" value="가입하기">
</p>
</body>
</html>
"가입하기" 버튼은 input 태그와 button 태그 두가지 모두 가능하다. 우선 input 태그로 전송버튼을 만드는 경우 input 태그의 type 속성값으로 submit 을 설정해준다. 버튼에 표시되는 문구는 input 태그의 value 속성값으로 설정한다. button 태그로 작성하는 경우 type 속성값으로 submit 을 설정해주고 "가입하기" 문구는 button 태그의 컨텐츠로 설정해주면 된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="post">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<button type="submit">가입하기</button>
</p>
</form>
</body>
</html>
서버로 사용자 입력 데이터 전송하기 - form 태그
하지만 가입하기 버튼을 클릭해도 아무런 변화가 없다. type 속성값이 submit 인 input 요소는 form 태그 안에서 사용될때 제대로 동작하기 때문이다. 그러므로 아래와 같이 p 요소들을 form 태그로 묶어주자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="" method="">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
이렇게 작성하고 사용자 이름과 비밀번호를 입력한 다음 가입하기 버튼을 클릭하면 웹페이지가 새로고침되면서 입력한 데이터는 초기화된다. 그리고 http://127.0.0.1:5501/index.html? 처럼 도메인 주소 뒤에 물음표(?)가 붙는다.
form 태그의 action 속성
<form action="" method="">
</form>
form 태그의 action 속성값은 사용자가 입력하고 전송한 데이터를 전달받아 처리할 서버 파일의 경로 또는 서버주소(URL)를 설정하면 된다. 예를 들어 php 에서는 server.php, 파이썬 장고나 플라스크에서는 server.py, node.js 에서는 server.js 파일의 경로가 action 속성값으로 설정된다. 현재 server.js 파일은 작성되어 있지 않지만 한번 설정하고 사용자 데이터를 입력한 다음 가입하기 버튼을 다시 클릭해보자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
아래와 같이 server.js 라는 해당 서버파일을 찾을수 없다는 문구와 함께 에러가 발생한다. 또한, 브라우저 주소창의 주소가 http://127.0.0.1:5501/server.js? 로 변경된다. 만약 제대로된 서버파일이 작성되어 있고 파일경로가 유효하다면 사용자가 입력하고 전송한 데이터는 해당 서버파일로 전달되어 처리가 가능하다. 전달된 데이터는 데이터 유효성을 검증하고 데이터베이스와 연동하여 처리된다.
form 태그의 method 속성
http://www.tcpschool.com/html-tag-attrs/form-method
그 다음으로 form 태그에서 설정되는 method 속성값은 크게 GET(get) 과 POST(post) 두가지 방식이 있다. 대문자로 작성하나 소문자로 작성하나 크게 문제될건 없다.
method 는 서버로 데이터를 전송할때 어떤 방식으로 전달할지 설정하는 것이다. get 방식은 브라우저 주소창에 사용자가 입력하고 전송하려는 데이터가 노출된다. 즉, 보안에 취약하다. post 방식은 브라우저 주소창에 데이터가 노출되지 않고 요청(request) 헤더의 본문(body)에 실려서 전송된다.
get 과 post 방식의 차이점은 아래에 상세하게 기술한다.
get 방식 | 브라우저 주소창에 데이터가 실려 전송됨 (보안에 취약함) |
전송시 데이터의 길이에 제한이 있음 | |
브라우저에 캐쉬되어 저장됨 | |
데이터베이스에 저장된 데이터를 조회할때 주로 사용함 | |
검색 키워드나 페이지 번호 등을 보여주는 용도 | |
post 방식 | 요청(request) 헤더의 본문(body)에 실려 전송됨 (보안에 좋음) |
전송시 데이터의 길이에 제한이 없음 | |
브라우저에 캐쉬되지 않음 | |
데이터베이스의 데이터를 생성, 변경, 삭제할때 주로 사용함 | |
회원가입, 로그인, 게시물 생성 등의 용도 |
얼핏보면 post 방식이 get 방식보다 좋아보이지만 각각의 용도에 맞게 설정하는 것이 좋다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="get">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
먼저 form 태그의 method 속성값을 get 으로 설정하고 사용자 이름과 비밀번호를 입력한 다음 가입하기 버튼을 클릭해보자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="post">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username">
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword">
</p>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
그런 다음 form 태그의 method 속성값을 post 로 설정하고 사용자 이름과 비밀번호를 입력한 다음 가입하기 버튼을 클릭해보자!
현재는 두 가지 경우 모두 server.js 파일이 존재하지 않으므로 제대로 동작하지 않는다. 하지만 구글이나 네이버 페이지에 접속해서 get 방식과 post 방식의 차이를 좀 더 살펴보도록 하자!
구글에서 form 이라는 키워드로 검색하면 아래와 같이 브라우저 주소창에 oq 라는 속성으로 검색한 키워드가 노출되는 것을 확인할 수 있다. 이것은 구글 검색이 get 방식을 사용하기 때문이다. https://www.google.com/search?q=form&oq=form&aqs=chrome..69i57j69i59l2j69i65l3j69i60l2.13461j0j7&sourceid=chrome&ie=UTF-8 이런식이다.
네이버에서도 동일한 방식으로 검색창에서 form 으로 검색해보자! 검색하면 브라우저 주소창에 https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=form 이라고 주소가 변경된다. query 속성에 보여지는 form 이라는 텍스트가 우리가 검색한 키워드이다. 즉, 네이버도 검색에 get 방식을 사용한다.
아래는 네이버 검색창에서 마우스 우클릭을 하고 검사를 선택하여 개발자 도구에서 form 태그의 method 방식을 확인한 화면이다.
이번에는 네이버 로그인 페이지로 이동하여 아래와 같이 개발자 도구에서 로그인 페이지에 사용된 폼 요소의 method 방식을 확인해보자.
네이버의 로그인 폼에서 form 태그에 적용된 method 는 post 방식이라는 것을 확인할 수 있다.
필수 입력 설정하기
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="get">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username" required>
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required>
</p>
<p>
<button type="submit">가입하기</button>
</p>
</form>
</body>
</html>
서버로 데이터를 전송하기 전에 사용자가 입력창에 반드시 입력해줘야 하는 데이터가 있는 경우 input 태그의 required 속성을 설정하면 된다. 사용자 이름과 비밀번호를 빠뜨리지 않고 사용자가 반드시 입력하게 유도하려면 required 속성을 설정하면 되고 결과는 아래와 같다. 사용자 이름과 비밀번호 중 어느 하나라도 입력하지 않으면 브라우저에서 아래와 같은 문구를 화면에 보여준다.
하지만 주의할 점은 input 태그의 required 속성은 반드시 input 태그가 form 태그 안에 있을때만 제대로 동작한다는 점이다.
이메일 입력창 추가하기
회원가입시 사용자 이름은 동명이인이 존재할 수 있으므로 이메일을 입력할 수 있도록 입력창을 추가해보자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="get">
<p>
<label for="username">사용자 이름: </label>
<input type="text" placeholder="아이디를 입력하세요." id="username" required>
</p>
<p>
<label for="useremail">이메일 주소: </label>
<input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required>
</p>
<p>
<label for="userpassword">사용자 비밀번호: </label>
<input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required>
</p>
<p>
<button type="submit">가입하기</button>
</p>
</form>
</body>
</html>
이메일 주소창은 input 태그의 type 속성값을 email 로 설정한다.
<p>
<label for="useremail">이메일 주소: </label>
<input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required>
</p>
그리고 입력창에 데이터를 입력하고 가입하기 버튼을 클릭하면 브라우저는 아래와 같은 문구를 보여준다. 이메일 주소에 @을 추가하라는 문구이다. 이는 input 태그의 type 속성값을 email 로 설정하고 required 속성을 동시에 설정해준 덕분이다.
폼 요소의 데이터 유효성 검증하기
폼 필드 가로 정렬하기
폼 필드를 가로로 정렬하는 방법은 table 태그를 이용하는 방법과 CSS 의 flexbox 를 사용하는 방법이 있다. 여기서는 table 태그를 이용하여 폼 필드를 정렬해보자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="server.js" method="get">
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</form>
</body>
</html>
p 태그 대신에 table, tr, td 태그를 이용하면 아래와 같이 가로로 이쁘게 정렬된다.
관련된 폼 필드 그룹으로 묶기
서로 연관이 있는 폼 요소들을 그룹으로 묶으려면 fieldset 태그를 사용하면 된다. 아래는 사용자 정보(이름, 이메일, 비밀번호)를 입력하는 폼 필드를 하나의 그룹으로 묶고 legend 태그를 사용하여 그룹으로 묶인 폼필드에 제목을 설정한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
fieldset, legend 태그로 폼필드를 그룹화하면 아래와 같이 가는선으로 구분해준다.
옵션 사항에 대한 폼요소 작성
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
</fieldset>
</form>
</body>
</html>
아래 뼈대 코드를 추가하여 옵션 사항에 대한 폼 요소들을 추가해보자!
<fieldset>
<legend>옵션 사항</legend>
</fieldset>
옵션 사항 - 주소
https://developer.mozilla.org/ko/docs/Web/HTML/Element/select
https://developer.mozilla.org/ko/docs/Web/HTML/Element/optgroup
사용자의 주소를 선택하기 위한 옵션 사항은 select, option 태그를 사용하여 드롭다운 메뉴 형태로 보이게 할 예정이다. 참고로 select, option 태그로 드롭다운 메뉴를 만들면 브라우저마다 스타일이 약간씩 차이가 나며 세세한 스타일링을 커스터마이징하기 힘들다는 단점이 있다. 그럼에도 불구하고 손쉽게 드롭다운 메뉴를 만들수 있다는 점은 장점이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
</fieldset>
</form>
</body>
</html>
옵션사항에 사용자의 주소를 입력받기 위한 드롭다운 메뉴를 추가한다. input 의 label 처럼 select 의 label 도 짝을 이뤄 for, id 속성값을 동일하게 설정해준다. 이렇게 하면 "주소: " 라는 label 을 클릭할때 드롭다운 메뉴가 포커스(focus)된다.
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
select 의 name 속성값은 서버로 전송된 데이터를 조회하기 위한 데이터 이름이다. option 태그의 value 속성값은 브라우저 화면에서는 보이지 않으며 사용자가 특정 메뉴옵션을 선택한 경우 서버로 전송하기 위한 값이다. 즉, 사용자가 드롭다운 메뉴에서 특정메뉴를 선택하면 데이터의 이름은 name (여기서는 address) 이고 데이터의 값은 선택된 option 요소의 value 값이다. 예를 들어 부산광역시를 선택하면 데이터 address = busan 으로 할당되어 서버로 전송된다. 물론 form 과 submit 버튼으로 전송하는 경우이다. option 의 value 값을 지정하지 않으면 option 에 있는 텍스트가 데이터의 값이 된다.
optgroup 태그를 사용하면 관련된 option 태그들을 그룹으로 묶을수 있다.
옵션사항 - 성별
https://developer.mozilla.org/ko/docs/Web/HTML/Element/input/radio
사용자의 성별을 선택할 옵션사항을 라디오 버튼으로 만들어보자! 사용자의 성별은 남성, 여성 중 어느 하나이므로 옵션중 하나만 선택할 수 있는 라디오 버튼을 사용하기로 한다. 라디오 버튼은 input 태그의 type 속성값을 radio 로 설정하면 만들수 있다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" value="여성">
</p>
</fieldset>
</form>
</body>
</html>
label 태그로 해당 라디오 버튼이 무엇을 의미하는지 사용자에게 알려준다. 동그라미로 표시된 라디오 버튼을 클릭하면 버튼 안에 색상이 채워지면서 선택이 된다. label 의 for 속성값과 input 의 id 속성값을 동일하게 설정하면 라디오 버튼 자체를 클릭할때처럼 해당 label 을 클릭하더라도 짝이 되는 라디오 버튼이 선택된다. 이전에 label 을 선택할때 입력창이 포커스되는 것과 동일한 원리다.
문제는 라디오 버튼 중 하나만 선택이 되어야 하는데 위와 같이 전부 선택이 된다는 것이다. 성별은 하나이기 때문에 하나만 선택되어야 한다. 이를 해결하려면 input 태그의 type 속성값이 radio 로 설정된 경우 input 태그에 반드시 name 속성이 포함되어야 한다. 그리고 관련된 라디오 버튼 (여기서는 남성, 여성) 들의 name 속성값은 동일해야 한다.
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
성별을 선택하는 모든 라디오버튼 (input 태그) 에 gender 라는 동일한 name 속성값을 설정해준다.
이렇게 하는 이유는 select, option 과 동일하다. select, option 태그를 사용한 드롭다운 메뉴에서 사용자가 특정 옵션메뉴를 선택하고 서버로 전송하면 서버로 전송되는 데이터의 이름은 select 에 설정된 name 의 속성값이고 데이터의 실제 값은 사용자가 선택한 option 의 value 속성값이다.
라디오 버튼도 마찬가지로 사용자가 특정 버튼을 선택하고 선택된 값을 서버로 전송하면 전송되는 데이터의 이름은 라디오 버튼(input 태그)의 name 속성값이고, 전송되는 데이터의 실제 값은 라디오 버튼(input 태그)의 value 속성값이다. 예를 들어 남성을 선택하면 서버로 전송되는 데이터의 이름은 gender 이고 데이터의 값은 "남성"이 된다. 여성을 선택한 경우도 마찬가지 원리다. 그래서 남성을 선택하든 여성을 선택하든 성별을 의미하는 데이터이므로 gender 라는 동일한 이름으로 데이터의 이름을 설정하는 것이다.
이제는 위와 같이 하나의 라디오 버튼만 선택되는 것을 확인할 수 있다.
옵션사항 - 관심사
https://developer.mozilla.org/ko/docs/Web/HTML/Element/input/checkbox
회원가입시 사용자의 관심사에 대한 옵션 사항은 체크박스로 구현해보자! 사용자는 다양한 영역에 관심을 가지고 있을수 있으므로 다중 선택이 가능하도록 체크박스(checkbox) 버튼으로 만들기로 한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
</fieldset>
</form>
</body>
</html>
input 태그의 type 속성값을 checkbox 로 설정하면 체크박스 버튼이 만들어진다. label 의 for 속성값과 input 의 id 속성값을 동일하게 설정하면 label 의 텍스트를 선택하더라도 체크박스가 선택된다. 체크박스는 토글(toggle) 된다. 토글이란 한번 클릭하면 선택이 되고 다시 한번 클릭하면 선택이 해제된다. 그리고 반복된다.
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
한가지 주목할 점은 라디오 버튼의 name 속성값은 동일하게 설정했지만 체크박스 버튼의 name 속성값은 모두 다르게 설정했다는 점이다. 이유는 라디오 버튼인 경우 하나만 선택되므로 하나의 데이터 이름과 하나의 데이터 값이 일대일 매칭된다. 하지만 체크박스 버튼은 다중 선택이 되므로 여러개의 데이터가 서버로 전송된다. 이때 만약 name 속성값을 동일하게 설정하면 다중 선택된 데이터 값들을 구분하지 못한다. 그러므로 체크박스 버튼으로 선택된 데이터의 값과 데이터 이름을 일대일 매칭시켜주기 위하여 name 속성값을 다르게 설정한다.
옵션사항 - 인사말
https://developer.mozilla.org/ko/docs/Web/HTML/Element/textarea
사용자가 회원가입시 하는 인사말은 보통 한줄이 아니라 여러줄에 걸쳐 길게 작성되기 때문에 여러줄의 텍스트를 입력할 수 있는 textarea 태그를 사용한다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
</fieldset>
</form>
</body>
</html>
비주얼 스튜디오 편집기(vsc)에서 textarea 태그를 추가하면 기본적으로 cols 속성과 rows 속성이 추가된다. cols 속성값 30 은 가로로 30자까지 글을 작성할 수 있고 30자가 넘어가면 다음줄에 작성이 된다는 의미다. rows 속성값 10은 10줄의 텍스트를 입력할 수 있는 크기로 입력창이 생성된다는 의미다. 즉, 30자 10줄을 입력할 수 있는 폼이 생성된다. 실험해보면 가로줄은 영문 기준 30자인것 같고, 세로줄은 영문 & 한글 공통적으로 10줄인것 같다. 10줄을 넘겨 작성하면 기본적으로 스크롤이 생긴다. label 태그의 인사말 텍스트를 클릭하면 textarea 가 포커스(focus)된다.
name 속성값은 서버로 인사말을 전송할때 인사말(텍스트)이라는 데이터의 고유한 이름(identity)이다. 즉, 서버로 전송되는 데이터의 이름은 name 속성의 값(message)이고, 실제 전송되는 데이터의 값은 사용자가 입력한 인사말이다.
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
textarea 요소는 기본적으로 사용자가 크기를 조절할 수 있게 되어있다. 우측하단 모서리를 마우스로 드래그하면 크기변경이 가능하다. 하지만 사용자가 임의로 크기를 조정하는 것을 원하지 않는다면 아래와 같이 스타일을 설정할 수 있다.
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
<style>
textarea {
resize: none;
}
</style>
</head>
완성된 인사말 폼은 아래와 같다.
textarea 태그 사용시 한가지 주의할 점이 있다. 아래와 같이 작성하면 커서가 중간에서 시작한다.
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10">
</textarea>
</p>
옵션사항 - 파일 업로드
https://developer.mozilla.org/ko/docs/Web/HTML/Element/input/file
사용자는 회원가입시 자신의 프로필 사진이라든지 자신을 표현하는 대표 이미지 등의 파일을 업로드하고 싶을수 있다. 이때 input 태그의 type 속성값을 file 로 설정해주면 된다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
</fieldset>
</form>
</body>
</html>
추가된 코드는 아래와 같다.
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
기본적으로 "파일 선택" 버튼을 클릭하면 아래와 같이 업로드할 파일을 선택할 수 있는 창이 뜬다. label 태그의 for 속성값과 input 태그의 id 속성값을 동일하게 설정하면 "프로필 사진" 이라는 글자를 선택해도 파일 업로드 창이 뜬다.
name 속성값은 여러번 설명했듯이 서버로 파일 데이터를 전송할때 해당 데이터의 고유한 이름이다. 즉, 내가 프로필 사진을 서버로 전송하면 서버에서는 사진 데이터의 실제 값을 profile 이라는 데이터 이름으로 조회할 수 있다.
accept 는 파일 업로드 창이 떴을때 accept 속성값에 설정된 파일 타입만 추출해서 보여준다. 즉, image/png, image/jpeg 라고 설정하면 파일 업로드 창에서 파일을 탐색할때 해당 폴더에 여러 타입(pdf, mp3, text, xls 등)의 파일 중 확장자가 png, jpeg 인 파일만 추려서 사용자가에게 보여준다. png, jpeg 파일만 업로드가 가능하다는 의미가 아니다. 다른 파일도 얼마든지 선택이 가능하다.
전체코드
회원가입 버튼이 빠져 있어서 다시 추가하였다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="#" method="get">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
</fieldset>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
회원가입 폼 테스트
get 방식 테스트
필수사항과 옵션사항을 입력하고 가입하기 버튼을 한번 클릭해보자!
가입하기 버튼을 클릭하면 아래와 같이 브라우저 화면이 새로고침되고 주소창에는 아래와 같은 문구가 보여진다. form 태그의 method 속성값이 get 방식이기 때문에 사용자가 입력한 데이터는 브라우저 URL 입력창에 노출되어 서버로 전송된다.
이때 사용자 이름, 이메일 주소, 사용자 비밀번호는 서버로 전송되지 않고, URL 주소창에도 나타나지 않는다. 이유는 아래와 같이 name 속성이 존재하지 않기 때문이다.
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
아래와 같이 name 속성을 추가하고 다시 가입하기 버튼을 클릭하면 서버로 사용자 이름 정보가 전송되고, URL 주소창에도 노출된다.
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" name="username" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
사용자의 주소는 address=seoul 이다. 데이터 이름은 address 이고 데이터 값은 seoul 이다. 서울특별시를 선택했기 때문이다.
사용자의 성별은 gender=남성 이다. 데이터 이름은 gender 이고 데이터 값은 "남성" 이라는 텍스트이다. 남성을 선택했기 때문이다.
사용자의 관심사는 html=HTML&javascript=JAVASCRIPT 이다. 데이터 이름은 html 이고 데이터 값은 HTML 이다. 데이터 이름은 javascript 이고 데이터 값은 JAVASCRIPT 이다. 다중선택이기 때문에 여러개의 데이터가 전송된다.
사용자의 인사말은 message=안녕하세요.%0D%0A저는+웹개발자입니다.%0D%0A잘+부탁드립니다+%3A%29 이다. 데이터 이름은 message 이고 데이터 값은 "안녕하세요.%0D%0A저는+웹개발자입니다.%0D%0A잘+부탁드립니다+%3A%29"이다.
https://it-eldorado.tistory.com/143
https://it-eldorado.tistory.com/61
https://curryyou.tistory.com/347
이렇게 전송되는 이유는 우리가 작성한 인사말(한글)은 서버로 전송되기 전 URL 인코딩되기 때문이다. 자세한 설명은 생략한다.
사용자가 업로드한 파일은 profile=바탕화면+배경.png 이다. 데이터 이름은 profile 이고 데이터 값은 파일 자체이다.
https://newcodingman.tistory.com/entry/%EC%BF%BC%EB%A6%AC-%EC%8A%A4%ED%8A%B8%EB%A7%81Query-String
form 태그에서 get 방식으로 데이터를 전송할때 아래와 같이 브라우저 주소창에서 물음표(?) 뒤에 오는 문자열을 쿼리 스트링(Query String)이라고 한다. 쿼리스트링은 & 기호로 데이터를 구분한다. 그리고 구분된 데이터는 key=value 쌍으로 표현된다.
address=seoul&gender=남성&html=HTML&javascript=JAVASCRIPT&message=안녕하세요.%0D%0A저는+웹개발자입니다.%0D%0A잘+부탁드립니다+%3A%29&profile=바탕화면+배경.png
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>폼 태그</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="/" method="post">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
</fieldset>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
post 방식 테스트
이번에는 form 태그의 action 과 method 속성값을 아래와 같이 수정한다.
<form action="/" method="post">
중략...
</form>
회원가입 페이지에서 F12 를 눌러 개발자 도구를 연다. 개발자 도구에서 Network 탭을 클릭한다. 그런 다음 아래와 같이 회원가입 폼을 작성하고 "가입하기" 버튼을 클릭해보자!
그러면 아래와 같이 붉은색으로 보이는 URL 주소(127.0.0.1)를 클릭하고 Payload 탭을 선택하면 아래와 같이 POST 방식으로 서버로 전송된 데이터를 확인할 수 있다. 서버로 전송되는 데이터를 페이로드(Payload) 라고 한다. 페이로드는 Header 의 본문(body)에 실려서 전송된다.
Header 탭을 선택하면 Content-Length 는 340 이고, Content-Type 은 application/x-www-form-urlencoded 라고 나온다.
Content-Length 는 말그대로 POST 방식으로 서버로 전송되는 데이터의 사이즈이다. Content-Type 은 요청 헤더(request header) 에 실어 보내는 데이터의 종류를 명시한 것이다. 요청 헤더는 캡쳐화면에서 보고 있는 것이고 전송하는 데이터는 form 태그로 작성된 데이터이므로 브라우저는 application/x-www-form-urlencoded 으로 설정한다. 요청 헤더는 브라우저가 서버에게 전달하는 메세지 같은 것이다.
https://jw910911.tistory.com/117
기존 프로젝트에 회원가입 페이지 추가
https://github.com/sssssqew/html-css-class
앵커 태그 수업에서 만든 프로젝트에 회원가입 페이지를 추가해보자! 프로젝트의 html 폴더에 register.html 파일을 생성하고 오늘 수업에서 만든 회원가입 페이지 코드를 복사붙여넣기 한다. 그리고 register.html 파일을 제외한 모든 html 파일의 header 부분에 회원가입 링크를 추가하자!
<header>
<a href="/index.html">
<img src="/imgs/brand-logo.jpg" alt="sample logo" width="50" height="40">
SunriseBucks
</a>
<nav>
<ul>
<li><a href="/html/home.html">Home</a></li>
<li><a href="/html/about.html">About</a></li>
<li><a href="/html/service.html">Service</a></li>
<li><a href="/html/contact.html">Contact</a></li>
<li><a href="/html/register.html">Register</a></li>
</ul>
</nav>
</header>
HTML5 에서 새롭게 정의된 타입들
옵션사항 - 사용자 웹사이트 추가
사용자는 회원가입시 자신의 웹사이트 URL 주소를 추가하고 싶을수도 있다. 이 부분을 구현해보자! 지금부터는 앵커 태그 수업에서 진행한 프로젝트에 코드를 곧바로 추가하도록 한다. register.html 파일을 다음과 같이 업데이트하자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Register 페이지</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="/" method="post">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
<p>
<label for="website">웹사이트: </label>
<input type="url" id="website" name="website">
</p>
</fieldset>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
input 태그의 type 속성값을 url 로 설정하면 사용자가 http:// 나 https:// 로 시작하는 URL 주소를 입력하지 않고 서버로 데이터를 전송하려고 하면 브라우저가 캡쳐화면과 같은 오류 메세지를 보여준다. 즉, input 태그의 type 속성값을 url 로 설정하면 데이터 전송시 브라우저는 URL 주소의 유효성을 검증해준다.
<p>
<label for="website">웹사이트: </label>
<input type="url" id="website" name="website">
</p>
옵션사항 - 사용자 생년월일
회원가입시 사용자의 생년월일을 저장하려고 한다. register.html 파일을 다음과 같이 업데이트하자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Register 페이지</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="/" method="post">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
<p>
<label for="website">웹사이트: </label>
<input type="url" id="website" name="website">
</p>
<p>
<label for="birth">생년월일: </label>
<input type="date" id="birth" name="birth">
</p>
</fieldset>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
input 태그의 type 속성값을 date 로 설정하면 달력에서 날짜를 선택할 수 있는 폼이 만들어진다. 이는 브라우저마다 다른 스타일을 가진다. 하지만 인터넷 익스플로러에서는 동작하지 않는다. 이렇게 HTML5 에서 새롭게 등장한 type 들은 일부 브라우저에서 지원하지 않는 경우가 있으니 주의가 필요하다.
<p>
<label for="birth">생년월일: </label>
<input type="date" id="birth" name="birth">
</p>
생년월일 달력은 아래와 같다.
옵션사항 - 좋아하는 과일
https://developer.mozilla.org/ko/docs/Web/HTML/Element/datalist
회원가입시 사용자가 좋아하는 과일을 서버에 저장하고 싶다고 가정하자! 그래서 드롭다운 메뉴를 만들어서 좋아하는 과일을 선택하도록 하고 싶은데 옵션메뉴에 사용자가 좋아하는 과일이 없으면 직접 입력할 수 있도록 하고 싶다. select 태그를 사용하면 사용자는 정해진 option 중에서만 고를수 있지만 datalist 태그를 사용하면 option 중에서 고를수도 있지만 원하는 옵션이 없는 경우 직접 입력이 가능하다. register.html 파일을 아래와 같이 업데이트하자!
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Register 페이지</title>
<style>
textarea {
resize: none;
}
</style>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="/" method="post">
<fieldset>
<legend>필수 사항</legend>
<table>
<tr>
<td><label for="username">사용자 이름: </label></td>
<td><input type="text" placeholder="아이디를 입력하세요." id="username" required></td>
</tr>
<tr>
<td><label for="useremail">이메일 주소: </label></td>
<td><input type="email" placeholder="이메일 주소를 입력하세요." id="useremail" required></td>
</tr>
<tr>
<td><label for="userpassword">사용자 비밀번호: </label></td>
<td><input type="password" placeholder="비밀번호를 입력하세요." id="userpassword" required></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>옵션 사항</legend>
<p>
<label for="address">주소: </label>
<select name="address" id="address">
<option value="seoul">서울특별시</option>
<option value="busan">부산광역시</option>
<option value="deagu">대구광역시</option>
</select>
</p>
<p>
<span>성별: </span>
<label for="male">남성</label>
<input type="radio" id="male" name="gender" value="남성">
<label for="female">여성</label>
<input type="radio" id="female" name="gender" value="여성">
</p>
<p>
<span>관심사: </span>
<label for="html">HTML</label>
<input type="checkbox" id="html" name="html" value="HTML">
<label for="css">CSS</label>
<input type="checkbox" id="css" name="css" value="CSS">
<label for="javascript">JAVASCRIPT</label>
<input type="checkbox" id="javascript" name="javascript" value="JAVASCRIPT">
</p>
<p>
<label for="message">인사말</label>
<textarea name="message" id="message" cols="30" rows="10"></textarea>
</p>
<p>
<label for="profile">프로필 사진</label>
<input type="file" id="profile" name="profile" accept="image/png, image/jpeg">
</p>
<p>
<label for="website">웹사이트: </label>
<input type="url" id="website" name="website">
</p>
<p>
<label for="birth">생년월일: </label>
<input type="date" id="birth" name="birth">
</p>
<p>
<label for="fruit-choice">좋아하는 과일: </label>
<input id="fruit-choice" name="fruit-choice" list="fruit-flavors">
<datalist id="fruit-flavors">
<option value="apple">
<option value="banana">
<option value="orange">
<option value="mango">
<option value="watermelon">
</datalist>
</p>
</fieldset>
<p>
<input type="submit" value="가입하기">
</p>
</form>
</body>
</html>
datalist 태그는 select 태그와 동일하게 option 태그를 자식요소로 가진다. option 태그에 사용자가 선택할 옵션메뉴를 작성하면 된다. input 요소는 옵션메뉴 중 마음에 드는 항목이 없는 경우 사용자 입력을 받을수 있도록 하기 위함이다. label 의 for 속성값과 input 의 id, name 속성값은 동일하게 설정하였다. 또한, input 의 list 속성값과 datalist 의 id 속성값은 동일하게 설정해준다.
<p>
<label for="fruit-choice">좋아하는 과일: </label>
<input id="fruit-choice" name="fruit-choice" list="fruit-flavors">
<datalist id="fruit-flavors">
<option value="apple">
<option value="banana">
<option value="orange">
<option value="mango">
<option value="watermelon">
</datalist>
</p>
완성하면 아래와 같이 드롭다운 메뉴에서 좋아하는 과일을 선택할 수도 있고 직접 입력할 수도 있다. 한가지 눈에 띄는 점은 직접 입력할때 자동완성 기능이 동작한다는 점이다. m 이라고 입력하면 m 알파벳을 가진 mango 와 watermelon 두 단어가 자동완성으로 검색이 된다. 그리고 추가로 a 를 입력하면 mango 만 검색이 된다.
https://caniuse.com/?search=datalist
해당 사이트에 가면 datalist 를 지원하는 브라우저를 확인할 수 있다. 2023년 6월 시점으로 인터넷 익스플로러를 제외한 모든 최신 브라우저에서 해당 태그를 지원한다.
https://github.com/mfranzke/datalist-polyfill
폴리필(polyfill) 은 구형 브라우저에서도 동작하게 해준다.
연습과제
오늘 배운 폼 수업을 바탕으로 아래 링크로 설정된 간단한 폼을 한번 디자인해보세요.
1. 개발자 도구를 참고하셔서 폰트나 이미지 링크는 그대로 쓰면 되요!
2. 기본 디자인에서 조금 변경하셔도 되요!
3. 배경은 글래스모피즘 디자인을 위하여 색상을 흰색으로 처리하고 알파값으로 투명도를 조절해주세요!
4. 폼 뒷배경을 불투명(blur) 처리하기 위하여 filter 나 backdrop-filter 속성에 blur 함수를 이용해주세요!
https://codepen.io/tylernj42/pen/BoxzaQ/
'프론트엔드 > HTML & CSS 강의' 카테고리의 다른 글
2. 색상과 단위 (0) | 2023.06.12 |
---|---|
1. CSS 문법 (0) | 2023.06.12 |
10. 이미지(image) 보여주기 (1) | 2023.06.10 |
9. 앵커(Anchor)의 표현 (0) | 2023.06.09 |
8. 표를 만드는 테이블 요소 (0) | 2023.06.09 |