form
관련 요소는 웹 페이지가 서버와 서로 상호작용할 수 있다는 점에서 사용 의의가 있다. HTML에서는 검색어를 입력할 수 있는 상자나, 값을 선택할 수 있는 라디오 버튼 등 다양한 방식으로 사용을 지원하고 있다. 그리고 실제로 많은 곳에서 form
관련 요소들을 유용하게 사용하고 있는 만큼 잘 알고 있을 필요가 있을 것이다. 그러나 스스로 그 구체적인 사용 방법에 대해서는 스스로 좀 무지하다고 느꼈기에 form
관련 요소에 대해 전체적으로 살펴보는 시간을 가져보고자 한다.
앞서 form
요소가 웹 문서와 서버의 상호작용을 담당한다고 했다. 그렇다면 이를 어떤 과정으로 수행하고 있는 것일까?
💡
form
요소의 동작 과정(1) 사용자가 웹 페이지를 방문
(2) 웹 페이지의form
내용 입력
(3)form
의 데이터를 브라우저가 서버로 보냄
(4) 웹 서버가form
데이터를 처리하기 위해 PHP, JSP 등의 웹 프로그램으로 넘김
(5) 웹 프로그램이form
데이터를 처리함
(6) 웹 프로그램이 처리 결과에 따라 새로운 HTML 문서를 웹 서버에 보냄
(7) 웹 서버가 받은 HTML 문서를 다시 브라우저에게 보냄
(8) 브라우저가 받은 HTML 문서를 렌더링하여 사용자에게 보여줌
복잡해보이지만 결국 웹 서버가 브라우저와 웹 프로그램 사이에서 가교 역할을 함으로써, 사용자는 입력한 form
데이터를 바탕으로 변경된 HTML 문서를 볼 수 있는 것이다.
그렇다면 지금부터는 구체적으로 form
관련 요소에 어떤 것들이 있고, 어떻게 사용해야 하는지에 대해 살펴보고자 한다.
먼저 form
은 사용자가 데이터를 입력할 수 있는 form
서식의 영역을 지정할 때 사용하는 태그이다. form
요소에 사용할 수 있는 속성은 다음과 같다.
💡
action
: 필수 속성이며, 값으로는 상호작용하기 위한 웹 서버의 스크립트 파일 주소를 지정
💡
method
: 웹 서버와 데이터를 주고 받을 방식을 설정
: 값으로GET
이나POST
중에 선택할 수 있음
💡
accept-cherset
: 데이터 전송에 사용할 문자 인코딩 값을 설정할 수 있는 속성
💡
autocomplete
: 자동 완성 기능의 활성화 여부를 선택할 수 있는 속성
:on
또는off
값 중에 선택할 수 있음
💡
enctype
:
form
전송 데이터의 MIME 타입
💡
name
: 서버가
form
을 식별하기 위한 이름을 값으로 지정하는 속성
💡
target
:
_blank
값을 설정하면action
에서 지정한 스크립트 파일을 다른 창에서 열도록 지정
💡
novalidate
: 데이터를 전송할 때 입력하는 데이터 값의 검증을 수행하지 않도록 지정하는 속성
위의 속성을 모두 사용하여 예제 코드를 만들어보면 다음과 같이 사용할 수 있겠다.
<form action="data.php" method="GET" name="userData"
accept-charset="UTF-8" autocomplete="on"
target="_blank" novalidate="novalidate">
</form>
앞서 form
요소의 속성에 대해 살펴볼 때 생소한 개념이 있었다. 바로 method
속성의 값인 GET
과 POST
가 그것이다. method
는 웹 서버와 데이터를 주고 받는 방식을 정의하는 속성이라고 했다. 그렇다면 구체적으로 GET
과 POST
는 방식에 있어 어떤 차이가 있는 것일까?
GET
과 POST
의 차이를 아주 간단하게 설명하려면 값의 이름을 보면 된다. 직역해보면 GET
은 무엇인가를 획득한다는 의미이고, POST
는 무엇인가를 붙이고 게시한다는 의미이다. 즉 보편적으로 GET
은 데이터를 읽을 때, POST
는 데이터를 수정할 때 사용하는 방식이라고 볼 수 있다.
그러나 단순히 GET
과 POST
를 데이터를 읽는 방식, 수정하는 방식으로 이해하기 보다는 구체적인 특징을 파악하고 있는 것이 사용에 도움이 되리라 생각한다. MDN에 명시되어 있는 GET
과 POST
방식의 차이를 통해 이를 살펴보고자 한다.
💡
GET
요청의 특징: 불필요한 요청의 제한을 위해 요청이 캐시에 저장될 수 있음
: 데이터 요청시 내용이 노출되므로 민감한 데이터를 다룰 때 사용해서는 안 됨
: 브라우저 기록에 저장됨
: 북마크에 추가할 수 있음
: 데이터 길이에 대한 제한이 있음
: 데이터를 수정할 수 없음
: idempotent함
💡
POST
요청의 특징: 요청이 캐시에 저장되지 않음
: 브라우저 기록에 저장되지 않음
: 북마크에 추가할 수 없음
: 데이터 길이에 대한 제한이 없음
: 요청했을 때 리소스를 생성하면 201 HTTP 응답 코드(Created)를 반환
: idempotent하지 않음
💡
GET
과POST
요약 비교
GET
POST
캐시 O X 브라우저 기록 O X 북마크 추가 O X 데이터 길이 제한 O X HTTP 응답 코드 200(OK) 201(Created) 사용 상황 리소스 요청 리소스 생성 전달 방식 쿼리 스트링 HTTP Body idempotent O X
위와 같이 각각의 특징을 구체적으로 살펴보면 새롭게 보이는 것들이 있다. 특징적인 지점을 짚고 넘어가자면, 먼저 GET
으로 데이터를 요청하는 경우 내용이 노출된다는 점이다. 정확히 어떤 방식으로 내용이 노출되는 것일까?
GET
으로 데이터 요청을 하는 경우 URL 끝에 파라미터로 포함되어 전송되는데, 이 부분을 쿼리 스트링(QureyString)이라고 일컫는다. 예를 들면 다음과 같다.
ex) www.example.com/datas?name1=value1&name2=value2
위의 예시 url을 살펴보면 /
뒤에 붙은 파라미터를 통해 어떤 폴더에서 어떤 값을 받아오는지 전부 노출된다. 이처럼 보안에 취약하기 때문에 민감한 데이터라면 POST
방식을 사용해야 하는 것이다.
POST
방식은 데이터를 송신할 때 GET
과 달리 HTTP 메시지의 Body에 담아서 전송한다. 그러므로 값이 노출되지도 않고, 데이터의 길이 제한이 없기 때문에 대용량 데이터를 전송할 수 있는 것이다. 그러나 POST
요청도 사용자의 눈에 가시적으로 보이지 않을 뿐이지, 개발자 도구를 사용하면 요청 내용을 확인할 수 있기 때문에 민감한 데이터를 따로 암호화하는 과정이 필요할 것이다.
앞서 살펴본 GET
과 POST
의 특징 중 정말 생소한 단어가 하나 있다. 바로 'idempotent'라는 개념이다. 직역하면 '멱등성'이라는 뜻인데, 큰일이다. 직역을 해봐도 무슨 의미인지 전혀 유추할 수가 없다. 이해를 돕기 위해 일단 사전적 정의를 살펴보면 다음과 같다.
💡 idempotent란?
: 멱등성, 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로, 연산을 여러번 적용하더라도 결과가 달라지지 않는 성질
즉 쉽게 말하면 연산을 여러번 수행하더라도 동일하게 결과를 도출한다는 것이다. 이를 바탕으로 GET
과 POST
의 특징을 살펴보면, 먼저 GET
은 멱등성이 있다. 이 말인 즉슨 GET
요청을 보낼 때 항상 동일한 결과를 반환해야 한다는 것이다. 잘 생각해보면 당연하다. GET
은 주로 데이터를 조회할 때 사용한다. 데이터를 조회할 때마다 동일한 데이터가 달라져서는 안 될 것이다. 따라서 GET
요청으로 조회하는 데이터는 멱등성, 즉 항상 동일한 결과 값을 가져야 한다는 것이다. 반면 POST
의 경우 주로 데이터를 수정할 때 사용한다. 만약 데이터를 수정하는 요청을 전송했는데도 데이터의 결과가 바뀌지 않는다면, 그것은 잘못된 요청이다. 그러므로 POST
요청으로 수정하는 데이터는 멱등성을 가지지 않는, 즉 가변적인 결과 값을 가져야 하는 것이다.
다시 돌아와서, form
관련 요소의 종류를 더 알아보겠다. fieldset
과 legend
는 여러 개의 form
요소를 좀 더 구조적으로 만들기 위해 사용한다.
구체적으로 살펴보면, fieldset
요소를 사용할 때 주위에 자동으로 아웃라인이 생성되어 그 안에 있는 콘텐츠가 form
과 관련되었다는 사실을 쉽게 식별할 수 있다. legend
요소는 fieldset
에 포함된 서식에 대한 설명을 제목 형식으로 알려주는 역할을 한다. 다만 legend
요소를 사용할 때의 주의점이 있는데, 이는 다음과 같다.
💡
legend
태그 사용시 주의점:
fieldset
요소의 자식 요소로 한 번만 사용할 수 있음
: 크로스 브라우징 관점에서 브라우저마다 다르게 적용되므로 스타일링시 어려움이 있을 수 있음
<form action="user_data.php" method="get">
<fieldset>
<legend>유저 데이터 리스트</legend>
</fieldset>
</form>
fieldset
과 legend
의 구체적인 사용법을 예제 코드로 확인해보면 위와 같다.
또 하나 주목할 점으로 HTML5에서는 fieldset
요소에 form
속성이 추가되었다. fieldset
요소의 form
속성 값을 form
요소의 id
값과 연결시키면 form
외부에 fieldset
이 있는 구조여도 서로 연결시킬 수 있다. 예제 코드로 확인해보면 다음과 같다.
label
은 button
, input
, keygen
, meter
, output
, progress
, select
, textarea
와 같은 form
관련 요소에 대한 연관 관계와 설명을 추가함으로써 접근성을 향상시키기는 역할을 한다. 크기가 작은 라디오 버튼이나 체크 박스 같은 경우, label
로 연관 관계를 명시해주면 label
만 선택해도 연관된 form
요소가 선택되기 때문에 접근하기가 쉬워진다.
이처럼 웹 접근성 측면에서 label
은 아주 중요한 역할을 한다. form
요소만 사용하면 정확히 무엇을 입력해야 하는지 알 수 없기 때문에 반드시 label
로 그에 대한 설명을 명시하는 것이 중요하다.
그렇다면 구체적으로 form
관련 요소와의 연관 관계를 어떻게 명시할 수 있을까? label
의 for
속성을 사용해야 한다. for
속성 값과 연결하려는 form
관련 요소의 id
값을 동일하게 설정하면 명시적으로 연관 관계를 표현할 수 있다. 바로 다음과 같은 방식으로 말이다.
앞서 label
을 사용해 연관 관계를 명시적으로 나타내는 방법을 살펴보았는데, 암시적으로 연관 관계를 나타내는 방법도 존재한다. label
요소의 하위 요소로 form
관련 요소를 작성하면 된다. 예제 코드로 확인해보겠다.
그렇다면 명시적 레이블링과 암시적 레이블링, 둘 중 어떤 방법을 사용하는 것이 바람직할가? 결론부터 말하자면 명시적 레이블링을 사용하는 것이 더 좋다. 그 이유는 크게 두 가지가 있는데, 먼저 오래된 장치에서 암시적 레이블링 방식을 인식하지 못하는 경우가 있기도 하다. 두 번째로는 스타일링의 유연성이다. 아무래도 하위 요소로 상속된 상황은 개별적으로 마크업한 상황보다 스타일링시 고려해야 하는 부분이 늘어날 수밖에 없을 것이다.
다음으로 form
요소의 핵심, input
에 대해 살펴보고자 한다. 말 그대로 input
은 사용자로부터 데이터를 입력받기 위한 목적으로 사용된다. HTML5에서는 기존보다 input
에 사용할 수 있는 type
속성의 값이 늘어났기 때문에, 다양한 상황에서 적절한 값을 사용할 수 있게 되었다. 또한 HTML5에서는 type
속성 외에도 autocomplete
, placeholder
등 편의를 제공할 수 있는 속성들이 다수 추가되었다.
input
요소는 설정한 type
속성의 값에 따라 서식의 종류가 결정된다는 특징이 있기 때문에, 각각의 특징을 잘 살펴볼 필요가 있을 것이다. 그러므로 type
속성의 값을 하나씩 살펴보고자 한다.
💡
text
: 기본 값, 한 줄 글 상자를 나타낼 때 사용
💡
password
: 비밀번호처럼 민감한 데이터 입력시 사용
:text
와 기본적으로 동일하지만, 화면에 입력 결과가 출력되지 않음
💡
search
:
text
와 기본적으로 동일하지만, 줄바꿈을 포함한 문자열 값이 입력되면 줄바꿈 제거
: 브라우저에 따라 user agent style이 다르게 적용되므로 크로스 브라우징 이슈 발생할 수 있음
💡
tel
:
text
와 동일하지만 입력 값이 전화번호라는 것을 의미함
: 모바일에서tel
에 값을 입력하려고 하면 자동으로 키보드의 숫자 입력 모드가 트리거되어 사용성이 향상됨
💡
url
:
text
와 동일하지만 입력 값이 URL이라는 것을 의미함
:url
의 값으로 줄바꿈을 포함한 문자열이 들어온다면 브라우저가 이를 자동으로 제거함
: 값으로 상대 경로는 입력할 수 없음, 절대 경로 URL만 입력 가능
: 부적절한 URL을 입력했다면form
전송시 에러 메시지를 출력함
: 모바일에서는 입력시 키보드의 영문 및 숫자 입력 모드가 트리거됨
💡
:
text
와 동일하지만 입력 값이 이메일이라는 것을 의미함
: 입력 값으로 이메일 주소만 가능
: 부적절한 이메일 주소를 입력했다면form
전송시 에러 메시지 출력
: 모바일에서는 입력시 키보드의 영문 및 숫자 입력 모드가 트리거됨
💡
date
: 날짜를 입력할 때 사용
: 보편적으로 브라우저에서 날짜를 입력할 수 있는 서식을 자동 제공하지만, 제공하지 않는 브라우저도 있음
:min
과max
속성을 추가 사용하여 입력 날짜의 범위 지정 가능
:step
속성을 추가 사용하여 입력 최소 단위 지정 가능
💡
month
,week
,time
: 서식은
date
타입과 동일하지만 각각 월, 주, 시간을 입력할 때 사용한다는 차이점이 있음
: 함께 사용할 수 있는 속성도date
와 동일
💡
datetime
,datetime-local
: 날짜와 시간을 함께 입력할 때 사용
: 입력시 타임 존을 UTC로 설정하기 때문에 한국 시간과 비교하면 9시간 늦은 시간이 됨
:date
와 마찬가지로min
,max
,step
사용 가능
:datetime-local
은 타임 존이 없는 날짜와 시간을 입력할 때 사용한다는 차이점 외에datetime
과 동일
💡
number
: 숫자를 입력할 때 사용
:min
과max
함께 사용하여 최소값, 최대값 지정 가능
:step
속성으로 입력 단위 지정 가능
💡
range
: 사용 목적은
number
와 동일
: 다만range
는 슬라이드 형태의 UI로 렌더링된다는 차이점
:min
,max
,step
함께 사용 가능
💡
color
: 색상을 입력할 때 사용
: 모든 웹 브라우저가 지원하지는 않지만, 지원하는 웹 브라우저에서 Color Picker 형태로 렌더링됨
💡
radio
: 라디오 버튼 서식을 제공할 때 사용
:checked
속성 지정하면 미리 선택된 상태로 렌더링됨
💡
file
: 로컬 컴퓨터의 파일을 업로드할 수 있는 서식을 제공할 때 사용
:accept
속성을 함께 사용하여 서버에서 수신할 파일의 형식을 지정할 수 있음
:multiple
속성을 함께 사용하여 여러 개의 파일을 업로드할 수도 있음
💡
hidden
: 설정하면 브라우저에 렌더링되지 않음
: 자바스크립트를 이용해야 내용을 변경할 수 있음
: 사용자가 보면 안 되는 데이터를 함께 전송할 때 유용하게 사용
:name
속성 값으로 charset 값을 지정하면form
의 문자 인코딩 값이 서버로 전달됨
💡
submit
: 전송 버튼을 나타내는 속성
: 데이터를 서버로 전송하는 역할
:value
와 함께 사용하여 버튼에 표시될 문자열 입력 가능
💡
reset
: 말 그대로 리셋,
form
요소의 데이터를 모두 초기화하는 역할
:value
와 함께 사용하여 버튼에 표시될 문자열 입력 가능
💡
button
: 단순한 버튼으로 자바스크립트 등을 실행하는 역할
:value
와 함께 사용하여 버튼에 표시될 문자열 입력 가능
💡
image
:
submit
과 동일하게 전송의 역할
: 다른 점이 있다면 버튼에 이미지 지정할 수 있음
:src
속성으로 경로 지정,alt
속성으로 대체 텍스트 지정
앞서 살펴봤듯 HTML5로 넘어와서 input
의 type
속성에 사용할 수 있는 값이 정말 다양해졌다. 이번에는 type
과 함께 input
사용에 편의성을 더해주는 속성 몇 가지를 살펴보고자 한다.
💡
autocomplete
: 자동 완성 기능 사용 여부, 값으로
on
또는off
:on
으로 지정하면 이전에 입력한 데이터를 브라우저가 후보 값으로 제공
💡
list
:
autocomplete
처럼 후보 값을 제공하는 기능은 동일
: 개발자가 직접 후보 값을 제공한다는 점에서 차이가 있음
: 후보 값은datalist
요소로 마크업하고,datalist
의id
와list
의 값을 연결시켜야 함
💡
readonly
: 읽기 전용으로 지정하기 위해 사용
: 사용자가input
의 값을 변경할 수 없음
💡
size
:
input
의 크기를 지정하는 속성
: 브라우저마다 크기가 달라질 수 있기 때문에 CSS로 설정하는 것이 바람직함
💡
required
: 해당 서식이 필수적인지 아닌지 지정하는 속성
: 설정한 경우 입력 값이 없는 상태로 서버에 데이터를 전송하면 에러 메시지가 출력됨
💡
placeholder
: 사용자에게 입력 값에 대한 힌트 제공
: 사용자가 새로운 값을 입력하면placeholder
는 사라짐
💡
pattern
: 입력 값의 정규 표현식을 지정할 수 있음
:title
속성으로 정규 표현식에 대한 설명 제공하는 것이 좋음
💡
multiple
: 2개 이상의 값을 지정할 때 사용
:type
의 값이file
인 경우 사용 가능
💡
maxlength
: 입력할 수 있는 최대 글자 수를 지정할 때 사용
💡
autofocus
: 설정하면 웹 페이지가 렌더링되자마자 바로 포커스가 서식으로 이동
💡
step
: 서식에 지정할 수 있는 값의 단위,
type
값에 따라 달라짐
💡
max
,min
:
max
는 입력의 최대값,min
은 입력의 최소값을 설정할 수 있음
💡
disabled
: 서식을 사용하지 못하도록 지정할 때 사용
💡
name
: 서식의 이름을 의미, 서버로 데이터를 전송할 때 그 데이터의 이름을 가리키기 위한 목적
button
태그는 말 그대로 버튼 서식이다. input
과 동일하게 type
속성을 지정할 수 있는데, 그 종류로는 submit
, reset
, button
이 있다. 각각의 속성은 input
의 type
과 기능이 동일하다.
여기서 잠깐 드는 의문점이 하나 있다. label
과 input
을 1:1 관계로 작성하여 명시적 레이블링을 해주는 것이 웹 접근성 측면에서 좋다고 했는데, 그렇다면 button
도 input
요소와 마찬가지로 레이블링을 해야 할까? 잠깐 생각해봤을 때는 둘 다 form
요소의 하위 범주에 해당하므로 button
역시 레이블링이 필수적일 것 같지만, 그렇지 않다. type
속성과 value
속성의 값을 통해 button
은 자체적으로 어떤 콘텐츠인지 파악할 수 있기 때문에 굳이 레이블링을 해줄 필요가 없는 것이다.
select
태그는 사용자가 항목을 선택할 수 있는 서식이다. size
속성으로 표시할 항목의 수를 결정할 수 있고, multiple
속성으로 다중 선택 허용 여부를 결정할 수 있다.
각각의 항목은 select
의 하위 요소로서option
태그로 마크업할 수 있고, optgroup
태그는 option
을 그룹화할 때 사용한다. optgroup
에는 label
속성을 사용하여 그룹의 역할에 대한 정보를 제공할 수 있다.
HTML5에 새로 추가된 태그로, 사용자에게 input
요소 입력 값의 후보 목록을 그룹화할 때 사용한다. datalist
와 input
을 연결시키려면 각각 id
와 list
속성의 값을 동일하게 설정해야 한다. 각 후보 값은 앞서 살펴본 option
태그의 value
속성을 통해 제공할 수 있다.
여러 줄의 텍스트를 입력 받을 때 textarea
태그를 사용한다. input
과는 줄 바꿈 여부에서 차이가 있다. input
은 한 줄 글상자로 줄 바꿈이 되지 않는다는 특징이 있지만, textarea
사용시 줄 바꿈 여부를 지정할 수 있다. wrap
속성을 사용하여 줄 바꿈 여부를 수동으로 지정할 수도 있다. 기본 값인 soft
는 줄 바꿈을 설정하지 않을 때, hard
는 줄 바꿈을 설정할 때 사용한다.
텍스트 상자의 크기는 cols
, rows
속성으로 지정할 수 있다. 그러나 브라우저 설정이나 폰트 크기에 영향을 받으므로 정확한 크기는 CSS의 width
, height
값으로 조절하는 것이 바람직하다.
keygen
은 서식을 서버로 전송할 때 키를 생성하고, 따라서 전자 인증에 주로 사용한다. 생성하는 키에는 비밀 키와 공개 키가 있다. 이때 비밀 키는 웹 브라우저에 저장되고 공개 키는 서버에 전송된다. HTML5에서 keygen
요소의 type
으로는 rsa
방식만 지원한다.
output
은 계산 결과, input
요소의 출력 값을 나타내는 역할을 한다. 요소 사용시 form
과 fieldset
으로 감싸서 영역을 구분해주어야 정상적으로 동작한다.
HTML5에 추가된 progress
는 요소의 진행 상황을 나타낼 때 사용한다. value
속성의 값을 0 ~ 1 사이로 설정하여 진행 정도를 나타낼 수 있다.
progress
와 혼동할 수 있지만, meter
는 진행 상황이 아니라 한정된 범위의 값을 나타낼 때 사용한다. max
로 최대값, min
으로 최소값을 설정할 수 있고, value
로 설정 값을 지정할 수 있다.
추가적으로 low
, high
, optimum
속성을 사용할 수 있다. 먼저 low
는 min
값보다 커야 하며, 범위 내에서 낮은 값으로 간주될 값을 명시하는 역할이다. 따로 설정하지 않으면 min
과 동일하게 설정된다. high
는 max
값보다 작아야 하며, 범위 내에서 높은 값으로 간주될 값을 명시하는 역할이다. 마지막으로 optimum
은 범위 내의 최적값으로 간주될 값을 명시하는 역할이다. 따로 설정하지 않으면 max
와 min
의 중간 값으로 설정된다.
지금까지 살펴본 form
관련 요소는 그 종류가 정말 어마어마하다. 공식 문서를 천천히 다 읽어보면 하위 요소나 속성에 대한 정보가 꼬리에 꼬리를 물고 쏟아지는 것을 알 수 있다.
내용이 워낙 많기 때문에 이를 다 외워서 사용할 수는 없겠지만, 적어도 한 번 찾아보고 코드로 짜본 상태와 그렇지 않은 상태는 천지 차이라고 생각한다. 이왕 공부하는 거 확실하게 해보자고 끝까지 이번 글에서 form
요소를 집중 공략해보았는데, 덕분에 확실히 나중에 form
을 좀 더 익숙하게 사용할 수 있을 것 같다.
🙏 출처
https://developer.mozilla.org/ko/docs/Web/HTML/Element/form
https://www.w3schools.com/tags/ref_httpmethods.asp
https://seulbinim.github.io/WSA/form.html#button-%EC%9A%94%EC%86%8C