본문으로 건너뛰기

폼과 제출

HTML·CSS 목차폼레슨 30 / 93

목차

폼(form)은 입력 칸과 단추를 묶는 요소입니다. 단추를 누르면 브라우저가 칸에 친 값을 모아 주소 뒤에 붙이고 그 주소로 떠납니다. 이 일을 제출(submit)이라고 합니다.

지금까지 만든 페이지는 읽기만 하는 페이지였습니다. 레시피 노트에 후기를 남기거나 레시피를 찾게 하려면, 페이지를 보는 사람이 친 글을 들고 갈 길이 있어야 합니다. 그 길이 폼입니다. 이 레슨에서는 단추를 누른 순간 브라우저가 하는 세 가지 일(모으기 · 붙이기 · 떠나기)과 값을 들고 갈 곳을 정하는 action을 봅니다. 이 단원을 마치면 김치볶음밥 페이지에 이름 · 별점 · 한 줄 평 · 다시 만들 의향을 받는 후기 남기기 폼을 만들 수 있습니다. 이 단원(폼)을 이미 안다면 단원 연습 문제부터 풀고 틀린 레슨만 보세요. 건너뛸지 볼 때는 힌트를 펴지 않고 풉니다.

8단계 중 1단계. 탭에 후기 폼이 있는 review.html이 열려 있습니다. 이름 칸은 비어 있습니다.

1폼은 칸과 단추를 묶는다

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
결과 화면

결과 화면은 칸에 글을 치고 단추를 눌러도 떠나지 않습니다. 결과 화면 머리의 '눌러도 떠나지 않음'이 그 표시입니다. 보내면 무엇이 일어나는지는 위 흐름 그림과 내 파일에서 봅니다.

form 요소 안에 칸과 단추를 넣습니다.

  • input은 한 줄 글을 치는 글자 칸입니다. 내용이 없는 빈 요소라 닫는 태그 없이 />로 끝냅니다. 속성이 길어 한 줄에 하나씩 나눠 적었습니다.
  • label은 칸 앞에 붙는 이름 글자입니다. for와 칸의 id를 같게 적어 짝을 짓습니다 — 셋째 레슨 label로 칸에 이름 붙이기에서 자세히 봅니다.
  • name은 값을 보낼 때 붙이는 이름입니다 — 다음 레슨 name과 value에서 봅니다.
  • 단추의 type="submit"은 '이 단추는 폼을 보낸다'는 뜻입니다.

폼 안의 단추는 type을 적지 않아도 누르면 폼을 보냅니다. 보내지 않을 단추까지 페이지를 새로 불러오는 까닭과 막는 법은 이 단원 끝 레슨 단추의 type에서 봅니다.

2누르면 모으고, 붙이고, 떠난다

이름 칸에 haneul을 치고 '후기 남기기'를 누르면 브라우저는 세 가지 일을 차례로 합니다.

  1. 모으기 — 폼 안 칸에서 값을 모읍니다. 이름 칸의 값은 haneul입니다.
  2. 붙이기 — 지금 페이지 주소 뒤에 ? 기호를 붙이고 nickname=haneul을 잇습니다.
  3. 떠나기 — 그 주소로 페이지를 다시 받아 처음부터 그립니다. 링크를 누를 때처럼 브라우저가 그 주소의 페이지를 받아 지금 탭의 페이지를 바꿉니다(브라우저 규칙 1).

아래 잰 값은 이름 칸에 haneul을 치고 단추를 누른 뒤에 잰 것입니다.

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?nickname=haneul

form의 주소는 떠나 간 주소의 끝입니다. 내 파일에서 해 보면 주소창 끝에 ?nickname=haneul이 붙어 있습니다. 다시 받아 그린 페이지는 파일에 적힌 그대로라, 방금 친 haneul은 칸에 남아 있지 않습니다. 단추를 누르는 순간 화면이 한 번 깜빡이고 칸이 비는 까닭이 이것입니다. 위 결과 화면은 눌러도 떠나지 않아, 친 글이 칸에 남습니다. 글자 칸에서 Enter를 눌러도 같은 일이 일어납니다.

3action은 들고 갈 주소를 정한다

<form action="search.html">
  <label for="q">찾을 요리</label>
  <input id="q" name="q" />
  <button type="submit">
    찾기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소search.html?q=kimchi

찾을 요리 칸에 kimchi를 치고 '찾기'를 누른 뒤의 주소입니다.

  • action에는 값을 들고 갈 주소를 적습니다. 링크의 href처럼, 이 HTML 파일이 있는 폴더에서 출발합니다. 이 폼은 같은 폴더의 search.html로 떠납니다.
  • action을 적지 않으면 지금 페이지 주소로 갑니다. 2절의 주소가 지금 페이지 뒤에 값만 붙은 꼴이었던 까닭입니다.
  • method는 값을 보내는 방법입니다. 적지 않으면 get이고, get은 값을 주소 뒤에 붙입니다. method="post"로 적으면 값을 주소가 아니라 요청 안에 담아 보내는데, 받는 쪽 프로그램을 만들 때 쓰는 방법이라 이 과목에서는 쓰지 않습니다.

search.html이 kimchi로 레시피를 찾아 보이려면 주소의 값을 읽는 프로그램(서버나 JavaScript)이 있어야 합니다. HTML만으로는 받은 값을 쓰지 못합니다.

예제

레시피 노트 목록 페이지 index.html에 둘 후기 폼입니다. 이름과 만든 요리를 받습니다. 이름 칸에 haneul, 요리 칸에 kimchi를 치고 '후기 남기기'를 눌렀습니다.

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <label for="food">요리</label>
  <input
    id="food"
    name="food"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?nickname=haneul&food=kimchi
  • #food의 값(없음)

칸이 둘이면 이름=값 조각을 & 기호로 잇고, 조각의 차례는 폼 안 칸의 차례입니다. #food의 값은 다시 그려진 페이지의 요리 칸에 든 값입니다 — 비어 있습니다.

자주 틀리는 곳

틀린 생각: 제출하면 친 값이 어딘가에 저장된다.

화면이 깜빡이고 칸이 비면, 값이 어딘가로 들어갔다고 여기게 됩니다.

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?nickname=haneul
  • #nick의 값(없음)

값은 떠나 간 주소의 ? 뒤에만 있습니다. 주소창에서 ? 뒤를 지우고 다시 열면 haneul은 어디에도 없습니다. HTML 파일도 바뀌지 않았습니다.

맞는 규칙: 제출은 값을 주소에 붙여 떠나는 일까지입니다(브라우저 규칙 1). 받은 값을 저장하고 쓰는 것은 받는 쪽 프로그램(서버)의 일이고, 이 과목 밖입니다.

틀린 생각: 글자 칸에서 Enter를 누르면 줄이 바뀐다.

문서 편집기에서 Enter는 줄바꿈이라 칸에서도 그럴 것 같습니다.

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?nickname=haneul

이름 칸에서 Enter를 누르자 단추를 누른 것과 같은 주소로 떠났습니다.

맞는 규칙: input 글자 칸은 한 줄 칸이라 Enter가 줄바꿈이 아니라 제출입니다. 여러 줄을 받는 칸은 textarea이고, 그 안의 Enter는 줄바꿈입니다 — 여러 줄 글과 고르는 칸에서 봅니다.

틀린 생각: 같은 페이지에 있는 칸은 모두 함께 보내진다.

<form>
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
<label for="memo">메모</label>
<input id="memo" name="memo" />
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?nickname=haneul

메모 칸에 hi를 쳤지만 주소에 memo=hi가 없습니다. 메모 칸은 </form> 뒤에 있어 폼 밖입니다.

맞는 규칙: 보내지는 것은 그 form 요소 안에 든 칸뿐입니다. 함께 보낼 칸은 form 안으로 옮깁니다.

확인 문제

1. 예제의 후기 폼에서 form 여는 태그만 <form action="thanks.html">⁠로 바꿨습니다. 같은 값(haneul · kimchi)을 치고 '후기 남기기'를 누르면 어디로 떠날까요?

<form action="thanks.html">
  <label for="nick">이름</label>
  <input
    id="nick"
    name="nickname"
  />
  <label for="food">요리</label>
  <input
    id="food"
    name="food"
  />
  <button type="submit">
    후기 남기기
  </button>
</form>
  • ① 지금 페이지 주소 — 뒤에 두 칸의 값이 붙는다
  • ② thanks.html — 뒤에 두 칸의 값이 붙는다
  • ③ thanks.html — 값은 붙지 않는다
힌트

action이 정하는 것과, 모은 값을 붙이는 자리를 3절에서 찾아봅니다.

정답

② — thanks.html 뒤에 두 칸의 값이 붙습니다.

결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소thanks.html?nickname=haneul&food=kimchi

action은 들고 갈 주소를 같은 폴더의 thanks.html로 바꿉니다. 모은 값은 그 주소 뒤 ? 다음에 붙습니다.

  • ① action을 보지 않고 지금 페이지로 간다고 본 것입니다. 지금 페이지로 가는 것은 action이 없을 때입니다.
  • ③ action이 있으면 값은 붙지 않는다고 본 것입니다. method를 적지 않은 폼(get)은 어느 주소로 가든 값을 그 뒤에 붙입니다.

2. 찾은 결과를 보이는 페이지 result.html로 값을 들고 가는 폼입니다. ____ 자리에 들어갈 것을 쓰세요.

<form ____>
  <label for="q">찾을 요리</label>
  <input id="q" name="q" />
  <button type="submit">
    찾기
  </button>
</form>
힌트

들고 갈 주소를 적는 속성을 3절에서 찾아봅니다.

정답

action="result.html"입니다.

<form action="result.html">
  <label for="q">요리</label>
  <input id="q" name="q" />
  <button type="submit">
    찾기
  </button>
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소result.html?q=kimchi

kimchi를 치고 누르면 result.html?q=kimchi로 떠납니다. 정답 칸이 좁아 라벨 글을 '요리'로 줄였습니다. href="result.html"로 적으면 폼은 그 속성을 쓰지 않아 지금 페이지로 갑니다 — 링크의 갈 곳은 href, 폼의 갈 곳은 action입니다.

3. 여행 일정 페이지의 참가 신청 폼입니다. 이름 칸에 minji, 인원 칸에 2를 치고 '신청'을 눌렀더니 주소에 인원이 없습니다. 몇 번 줄을 어디로 옮겨야 할까요?

<form>
  <label for="nm">이름</label>
  <input
    id="nm"
    name="name"
  />
  <button type="submit">
    신청
  </button>
</form>
<label for="pp">인원</label>
<input
  id="pp"
  name="people"
/>
힌트

인원 칸이 어느 요소 안에 들어 있는지 여는 태그와 닫는 태그를 따라가 봅니다.

정답

10번 줄 </form>을 맨 아래(15번 줄 뒤)로 옮깁니다. 인원 칸이 폼 안에 들어갑니다.

결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?name=minji
<form>
  <label for="nm">이름</label>
  <input
    id="nm"
    name="name"
  />
  <button type="submit">
    신청
  </button>
  <label for="pp">인원</label>
  <input
    id="pp"
    name="people"
  />
</form>
결과 화면
잰 값개발자 도구에서 본 값
  • form의 주소?name=minji&people=2

고치기 전에는 인원 칸이 </form> 뒤라 폼 밖이었습니다. 보내지는 것은 form 안의 칸뿐입니다(브라우저 규칙 1). 인원 칸을 단추 위로 옮겨도 됩니다 — 칸이 모두 폼 안이면 주소는 같습니다. 흔한 오답은 인원 칸에 name을 더 적는 답입니다. 인원 칸에는 이미 name="people"이 있습니다. 칸이 폼 밖이면 name이 있어도 보내지 않습니다.

컴퓨터에서 해 보기(선택) — 점수에 들지 않습니다. 폰으로만 보고 있다면 건너뛰세요. 예제의 후기 폼을 html-css-study 폴더에 review.html로 저장하고(문서 뼈대의 body 안에 예제 코드를 넣습니다), 두 칸에 글을 친 뒤 단추를 눌러 주소창 끝을 봅니다. 이어서 이름 칸에서 Enter를 누르면 무엇이 달라질지 먼저 적고, 눌러서 맞춰 봅니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

HTML·CSS 목차로