개발 공부 기록하기

Section 5. 폼(Form)과 테이블(table)(2) 본문

프밍/HTML

Section 5. 폼(Form)과 테이블(table)(2)

태영(泰伶) 2022. 11. 27. 14:51

06. 폼(Form) 요소 기초

폼 요소form element란?

그 자체로는 눈에 그렇게 띄지 않지만,

텍스트 입력란, 비밀번호 입력란, 버튼 및 체크박스 등의 개별적인 form control을 품는 컨테이너container로,

아래 그림의 굵은 빨간색 테두리 부분이 폼form이라고 보면 된다.

 

그리고 위 그림의 분홍색 테두리 부분들은 개별적인 컨트롤control 또는 개별 입력란을 나타낸다.

 

그러니까 폼은, 한데 그룹화된 모든 입력란을 포함한 상자인 것이다.

또한, "작성된 폼 내용을 그룹화해서 작은 배송 레이블을 붙인 다음에  내 서버로 보내줘"와 같은

구체적인 지시까지 내릴 수 있는 요소이다.

 

여러 다른 입력란, 즉 폼은 <form> 요소가 감싸고 있는데,

여기서 데이터를 어떻게, 어디로 전송할지 결정하게 된다.

 

Tip: VSCode에서 form을 입력하고   Tab  을 누르면, <form action=""></form>으로 자동 입력되는데,

여기서 action이라는 속성이 상당히 중요한 역할을 해 준다.

폼(입력란)에 입력된 데이터를 보낼 위치와 시간을 지정하는 역할을 맡고 있기 때문이다.

 

폼을 제출하면 HTTP 요청이 전송된다.

action 속성의 또 다른 역할로는 HTTP method를 사용할지 제어하는 것이다.

method라는 속성에는 get과 post라는 두 가지 속성값이 있는데,

 

차차 폼을 공부하면서 그 의미는 이해해보는 걸로 하자.

 

 

 

 

 

07. 일반적인 입력 형식

<input>

가장 일반적인 요소이자 폼 컨트롤이다.

20가지 이상의 다양한 입력란을 만들 수 있을 정도로 엄청 다양하게 활용된다.

체크박스, 색상 선택기, 날짜 선택기, 비밀번호 입력란, 일반 텍스트 입력란 등.

다양한 역할을 하는 폼이어도 <input> tag를 사용하는 것은 똑같지만,

다른 점은 <input>에 들어가는 속성인 type의 속성값이다. 이것이 폼의 작동 방식을 크게 바꾸는 요인이 된다.

닫는 태그가 별도로 없다.

요소 형태 실제 입력해볼 수 있는 폼
<input type="text" />
<input type="password" />
<input type="color" />
<input type="number" />
<input type="date" />
<input type="time" />
<input type="search" />

이외에도 많다. 

그리고, 이러한 폼의 형태는 브라우저에 따라 다른 모양으로 나타난다.

 

<input> tag에는 type이라는 속성도 있지만,

placeholder라는 속성도 존재한다.

그러니까,

우리가 제일 흔하게 만날 수 있는 로그인 창을 예시로 들자면

라거나,

와 같은 입력란이 비어있을 때 임시로 보여주는 텍스트를 넣는 셈이다.

(그러나 모든 입력란에 작용하는 속성은 아니다.)

 

 

<input type="number" />에는 min과 max 속성을 쓸 수 있다.

단어 뜻에서도 알 수 있듯, 최솟값과 최댓값을 설정하는 것인데,

설정해두면 아무리 스핀박스의 화살표를 눌러대도

최댓값을 초과해서는 숫자가 올라가지 않으며, 반대로 최솟값 미만으로는 숫자가 내려가지 않는다.

 

 

 

 

 

08. 레이블

굳이 필요하지 않은 요소라고 여겨질 수도 있지만,

*접근성을 높이고 폼을 쓰기 편하게 해준다는 점에서

    * 접근성: 남녀노소, 장애 유무와 상관없이 모두가 동등하게 불편 없이 이용할 수 있도록 제품, 서비스, 환경 등을 디자인하는 것

<label>은 매우 중요한 역할을 하고 있다.

 

위의 질문 Do you like cheese?와 같은 레이블label은 시각적으로 텍스트를 보여주는 것 이상의 기능을 한다.

위의 질문을 <label>이 아니라 <p>, <span>이나 다른 텍스트를 나열하는 요소로 작성했다면,

해당 질문이 체크박스와 연결된 질문이라는 사실을 스크린 리더는 알아채지 못할 것이다.

 

즉, <label> 요소는 실제로 특정 입력값 또는 form control 아니면 텍스트와 직접적으로 연결되어 있다는 것이다.

단순히 스크린 리더 기능에 도움을 주거나, 스크린 리더 사용자들의 경험을 개선하는 점 말고도

꼭 체크박스를 누르지 않고 레이블을 클릭했을 때에도 연결된 체크박스에 체크가 될 수 있게 해주는 기능이 있다. 

 

이렇게 직접 연결이 되기 위해서는

<label for="username">Username: </label>

<input id="username" type="text" placeholder="Enter your username"/>

이렇게 for와 id의 속성값이 같아야 연결이 된다.

이렇게 되면 Username: 부분을 클릭했을 경우, 연결된 <input>의 텍스트 쓰는 란에 커서가 놓이게 된다.

 

 

위처럼 말이다.

 

Tip: VSCode의 Emmet을 이용해서

label을 쓰고   Tab  을 누르면 자동으로 <label for=""></label>이 입력된다.

 

 

위의 for과 id를 이용하는 방법을 대신해서 레이블과 입력란을 연결할 수 있는 방법이 한 가지 더 있다.

(자주 쓰이지는 않지만 쓸 수는 있다.)

 

바로

<label> 요소의 안에 <input> 요소를 넣어 중첩시키는 방법이다.

이 방법을 쓰면 아직 학습하지 않은 for와 id를 쓰지 않아도 된다.

(자주 쓰지 않는 이유는 아무래도 중첩되어있지 않아야 각각의 스타일을 따로 지정하기 편해서 그런 것 같다.)

 

하지만 먼저 다룬 for와 id를 이용하고, <label>과 <input>을 중첩하지 않는 것이 표준이며,

더 흔히 쓰인다.

중첩이 더 짧고 쉬워보이더라도 표준을 따르는 것을 권한다.

 

 

 

 

 

09. 버튼 요소

웹 페이지에는 흔히 보이는 버튼도 tag를 이용하여 만들 수 있다.

바로 <button>.

 

로그인할 때, 회원가입할 때, 하물며 어떤 결제방법을 선택할 때도 수없이 만나는 것이 버튼들이다.

<button>은 열린 태그와 닫힌 태그를 모두 사용해주어야 한다.

 

그리고 <button>과 </button> 사이에 들어가는 모든 텍스트는 버튼에 레이블을 지정하게 된다.

(그러니까... 글씨를 눌러도 버튼이 눌리는 효과가 난다...이거지?)

 

<button> 요소 역시 다른 폼 요소들과 마찬가지로 브라우저마다 기본값 스타일이 있지만 바꿀 수 있다.

 

   ↓↓    <button>제출</button> 을 실행시키면 나오는 모습.

 

 

<button>은 아무런 속성도 지정하지 않을 경우에 기본적으로 폼을 '제출' 기능을 갖는다.

(그러니까 <form> 안에 쓰인 <button>의 경우 제출 기능을 갖는다는 뜻이다.

<form> 바깥에 <button>을 쓰게 되면 기본값 동작은 없다)

 

하지만 여기서 속성을 추가해서

<button type="button">너는 그냥 버튼</button>

을 쓰게 되면 누르는 재미만 느낄 수 있는 버튼이 생성되게 된다.

 

그리고 제출 버튼을 생성하는 다른 방법도 있다.

 

<input type="submit"/>

 

닫는 태그가 없는 <input>을 이용한 방법이라서, 강사님은 별로 좋아하시지는 않는다고 한다.

<button>을 쓰면 닫는 태그 앞의 텍스트를 바꾸는 것만으로도 버튼 안의 내용을 바꿀 수 있는 반면,

<input>을 쓰게 되면 value라는 속성을 별도로 사용해서

<input type="submit" value="Click me!"/>와 같이 써야 하기 때문이라고...

     ↑↑    이게 바로 <input>으로 만든 버튼이다. (사실상 별 차이 없어 보인다.)

 

 

 

 

 

10. 이름 속성

이름 속성name attribute은 입력값에 매우 중요한 속성이다.

 

검색창에 검색어를 입력하고  검색  버튼을 누르게 되면

(갑자기 웬 분홍색의 버튼 모양이냐고 한다면.. 그냥.. 검색 버튼 모양처럼 이쁘게 만들어보고 싶었다... << 갑자기...??)

<form> tag의 속성으로 썼던 action의 속성값에 적힌 곳으로 HTTP 요청을 보내게 된다.

 

이렇게 HTTP 요청을 보낼 때 서버로 전송되는 이름을 이름 속성에 넣게 된다.

 

reddit 페이지에서는 q가 name의 속성값이 된다.

아래쪽 개발자 도구의 음영처리가 된 줄에서 name="q"라고 적힌 것처럼 말이다.

 

이러한 name 속성은 추가하기 쉽지만 정말 중요한 역할을 한다.

서버로 데이터를 전송할 때 사용하게 되기 때문이다.

서버로 데이터가 전송될 때, 즉 URL에 내가 입력한 값이나 검색어가 표시되게끔 해준다.

 

지금은 어떠한 예시를 만들더라도 내 수준에서는 그닥 중요해보이지는 않지만 아무튼!

나중에 중요하다고 하니까, <input>에서는 꼭 써야하는 속성이라고 하니까 알아둬야겠다.

 

 

 

 

 

 

11. 구글과 레딧 검색하기

검색하는 폼을 만들어보기로 했다.

Google에 검색하는 것과 같은 폼을 만들기 위해서

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8">
         <title>검색폼만들기</title>
      </head>
      <body>
         <form action="https://www.google.co.kr/search">
            <input type="text" name="q"/>
            <button>SEARCH</button>
         </form>
      </body>
   </html>

                 ↓

바로 위 검색창에 검색어를 입력하고 SEARCH를 누르면 정말 google에 검색한 것처럼 페이지가 뜬다.

 

 

Google과는 조금 다르게, Youtube 검색창을 만든다면,

name 값이 좀 달라진다.

 

<!DOCTYPE html>
   <html lang="ko">
      <head>
         <meta charset="UTF-8">
         <title>검색폼만들기2</title>
      </head>
      <body>
         <form action="https://www.youtube.com/results">
            <input type="text" name="search_query"/>
         </form>
      </body>
   </html>

            ↓

이렇게 검색버튼이 없게도 만들 수 있는데, 이럴때는 검색어를 입력하고 Enter를 누르면 폼이 제출된다!

(버튼이 있어도 Enter가 폼을 제출할 수 있다)

 

 

이렇게 웹 사이트마다 검색 구조를 어떻게 짜는지는 전적으로 각 회사에 달렸기 때문에,

그 규칙을 파악해서 따르면 된다.

 

 

 

 

 

12. 라디오 박스, 체크박스와 선택창

<input>의 속성 중에서 위에서는 다루지 않았던 것들이 있다.

요소 형태 실제 폼
<input type="checkbox" />
<input type="radio" />
<select>
   <option></option>
</select>


 

checkbox

보통 체크박스를 삽입할 때는 name 속성과 id 속성을 입력해서 <label>과 연결지어야 한다.

아니면 무엇과 관련되어 있는지 알아보기 힘들기 때문이다.

(tos는 terms of service의 약자라고 한다. 무슨 뜻인지 찾아보니 '서비스 약관'이라는 뜻이라고 한다. 아아.. 회원가입할 때 흔히 보는 그런 약관을 말하는 건가...?)

<form>
<input type="checkbox" name="agree_tos" id="agree" />
<label for="agree">I agree to everything.</label>
<button>Submit</button>
</form>

 

또한 미리 체크되어 있도록 속성 checked를 넣을 수도 있다.

아래 코드는 위에 쓴 코드에서 checked만 추가한 것이다.

<form>
<input type="checkbox" name="agree_tos" id="agree" checked />
<label for="agree">I agree to everything.</label>
<button>Submit</button>
</form>

 

 

 

radio

체크박스와 다른 점은 오로지 1개만 선택할 수 있다는 점이다.

  cf, 체크박스는 복수선택이 가능하다.

 

Tip,

VSCode에서 inp를 쓰고  Tab 을 누르면 <input type="text" name="" id=""/>가 자동으로 출력된다.

type이야 자동으로 text로 나온대도 내 마음대로 바꾸면되니까!

 

 

오로지 1개만 선택할 수 있는 건 name의 속성값이 동일할 때, 그 그룹 내에서 1개만 선택되는 것이다.

value 속성의 속성값이, 제출 버튼을 눌렀을 때 실제로 서버에 전송되는 값이다. (이건 사용자의 눈에는 보이지 않는다.)

<form>
<h3>What's your size?</h3>
<p>
   <label for="XS">XS</label>
   <input type="radio" name="size" id="XS" value="XS" />
</p>
<p>
   <label for="S">S</label>
   <input type="radio" name="size" id="S" value="S" />
</p>
<p>
   <label for="M">M</label>
   <input type="radio" name="size" id="M" value="M" />
</p>
<button>Submit</button>
</form>

 

 

 

select

사실상 드롭다운 메뉴를 말한다.

드롭다운 메뉴는 <select>와 <option>이 함께 작동해서 나온다.

<option>이 모두 <select>요소 안에 포함되어야 한다.

 

<p>
   <label for="meal">Please Select an Entree.</label>
   <select name="meal" id="meal">
      <option value="">---Please Choose a Option---</option>
      <option value="fish">Fish</option>
      <option value="veg">Vegeterian</option>
      <option value="steak">Steak</option>
   </select>
</p>

 

 

한 가지 옵션이 미리 선택되어 있도록 하려면, 

<option> tag 안에 selected 속성을 쓰면 된다.

<p>
   <label for="meal">Please Select an Entree.</label>
   <select name="meal" id="meal">
      <option value="">---Please Choose a Option---</option>
      <option value="fish">Fish</option>
      <option value="veg" selected>Vegeterian</option>
      <option value="steak">Steak</option>
   </select>
</p>

 

 

 

 

 

13. 범위 및 텍스트 영역

range

슬라이더를 만드는 방법이다. (최댓값, 최솟값은 지정 가능)

<label for="cheese">Amount of Cheese</label>
<input type="range" id="cheese" name="cheese level" min="0" max="100" step="5" value="20"/>

위의 <label>에서 했던대로 for의 속성값과 <input>의 id 속성값이 같아야 <label>과 <input>이 연결되는 것이고,

name이 저 슬라이더가 뭘 의미하는지 써 주는 것,

min과 max는 단어 뜻에도 볼 수 있듯 최솟값, 최댓값을 나타내며,

step은 점프하는 단위, 즉, 슬라이더를 한 칸씩 옮길때마다 늘어나는 숫자가 된다.

(즉, 맨 왼쪽 0에서 한 칸을 옮기면 5로 설정된다는 뜻!)

그리고 마지막 속성 value는 기본으로 설정되어 있는 값을 말한다.

그러니까 위의 그림에서 이미 파란색 슬라이더가 오른쪽으로 얼마큼 옮겨져 있는데, 옮겨진 그 위치 값이 20이라는 것이다.

 

 

 

textarea

여러 줄의 텍스트를 입력할 수 있는 상자를 만든다.

<textarea></textarea>로 열린 태그, 닫힌 태그로 구성된다.

<label for="requests">추가 요청 사항</label>
<textarea id="requests" name="requests" rows="10" cols="60" placeholder="Type something here."></textarea>

rows는 가로줄 수를 의미한다. (이 속성을 쓰지 않으면 기본값으로는 2줄이 생성된다.)

cols는 한 줄에 들어가는 글자 수를 의미한다. 알파벳 기준으로 몇 글자가 들어가는지 써 주는 셈인데, 이마저도 글씨체나 다른 속성에 따라서 달라질 수 있다. (이 속성을 쓰지 않으면 기본값으로는 40이 설정된다.)

줄 수를 10으로 설정했는데, 그 이상을 작성하게 되면 자동으로 스크롤바가 생성된다.

 

 

 

 

 

14. 코딩 연습 6: Forms Practice Exercise

과제물은,

아이디와 비밀번호 입력란을 만들고, Register버튼을 아래 만드는 것이다.

<div>
   <label for="username">Username</label>
   <input type="text" id="username" placeholder="username" />
</div>
<div>
   <label for="password">Password</label>
   <input type="password" id="password" placeholder="password" />
</div>
<button>Register</button>

성공ㅎㅎ

 

 

 

 

 

15. HTML5 폼의 유효성 검사

유효성 검사는 일반적으로 제한을 추가하거나,

사용자가 입력한 데이터의 유효성을 확인하는 것을 말한다.

 

어떤 칸은 절대로 비어있으면 안 된다거나,

비밀번호는 8자리 이상이어야 한다거나

비밀번호는 영문, 숫자, 특수문자를 모두 포함하고 있어야 한다거나

이메일을 입력하는 칸에 작성한 데이터가 이메일 형식이 아니라고 뜬다거나 그런 것들..

(숱하게 봐온 것들이 그런 것이었다..)

 

 

 

이러한 유효성 검사를 하는 것 중

필수 입력을 하는 방법은 required 속성을 이용하는 것이다.

<h2>Validation Demo</h2>
   <form action="/dummy">
      <label for="first">Enter First Name.</label>
      <input type="text" name="first" id="first" required />
      <button>Submit</button>
   </form>

아무것도 입력하지 않고 Submit을 누르면 경고메시지가 뜬다. (경고메시지의 형태는 브라우저에 따라 다르며, 경고메시지가 아예 뜨지 않는 브라우저도 있다)

 

minlength, maxlength

minlength는 최소 글자 수, maxlength는 최대 글자 수를 말한다.

<h2>Validation Demo</h2>
   <form action="/dummy">
      <label for="username">Username</label>
      <input type="text" name="username" id="username" minlength="5" maxlength="20" />
      <button>Submit</button>
   </form>

minlength로 설정한 값보다 글자 수를 적게 입력하고 Submit을 눌렀더니 경고메시지가 떴다..ㅎㅎ

설정한 maxlength인 20자 이상을 써보려고 했더니 경고메시지는 뜨지 않고, 20자 이상 입력이 아예 안 됐다..ㅎㅎ;;

 

 

 

이러한 유효성 검사를 기본적으로 시행하는 것들이 몇 가지 있다. pattern이 있는 경우가 그러한데, 

이것을 추가한 것을 정규 표현식regular expression이라고 부른다. (일종의 정의된 패턴)

굉장히 유용하긴 한데, 아직은 너무 어려우니 설명은 pass.

 

^( ?=.*\d ) ( ?=.*[a-z] ) ( ?=.*[A-Z] ) ( ?=.*[a-zA-Z] ).{8,}$

 

'위에 적힌 외계어(?)가 숫자 하나 이상, 소문자 1개 이상, 대문자 1개 이상, 비밀번호는 8자리 이상이어야 하고, 특수문자를 포함해야 한다'

라는 뜻이라고 한다.... 왐마 어려버라....🫣

내가 언젠가 저걸 온전히 이해하는 날이 올까...ㅋㅋㅋㅋㅋ

 

 

이번에는 유효한 이메일 형식인지 검사하는 방법이다.

(별도로 처리해 주는 것은 없다. 기본적으로 유효성 검사가 내장되어 있나보다.

또한, 실존하는 이메일인지도 확인하지 못한다.

그저 @ ← 이 녀석이 있는지와, @ 이후로도 글자가 더 있는지를 확인할 뿐이다.)

<form>
<input type="email" required/>
<button>Submit</button>
</form>

이메일 형식을 지키지 않았더니 저런 경고메시지들이 떴다...ㅋㅋ

 

코드블럭을 입력해보다 깨달은 사실..!!!

위의 코드에 <form>과 </form>을 써주지 않고 <input>만 적으면 저런 경고메시지가 안뜬다는 점..!! (동작 안 하는 거 같음)

 

 

 

URL도 이메일과 마찬가지로 패턴만 확인한다.

<form>
<input type="URL" required/>
<button>Submit</button>
</form>

아무것도 안쓰고 Submit 눌렀을 때.. required때문에 뜨는 메시지다.
url스럽지 않으니까 뜨는 경고메시지..
https://를 써주니까 Submit을 눌렀을 때 동작했다. 당연히 연결한 서버같은 게 없으니 오류 화면으로 넘어갔지만..ㅎ

 

 

 

 

 

16. 마라톤 선수 등록 양식 만들기

문제를 먼저 말해주는 강의에서 말로만 가볍게 이야기해 준 것을 따라서 나타난 html 파일을 내가 만든 건 아래와 같다.

<!DOCTYPE html>
   <html lang="ko">
	   <head>
         <meta charset="UTF-8">
         <title>Marathon Register Form</title>
      </head>
      <body>
         <h1>Race Registration!</h1>
         <form>
            <div>
               <label for="first">First Name</label>
               <input type="text" name="first-name" id="first" />
               <label for="last">Last Name</label>
               <input type="text" name="last-name" id="last"/>
            </div>

            <p>Select a Race:</p>
            <div>
               <input type="radio" name="race" value="5k" id="5k"/>
               <label for="5k">Fun Run 5k</label><br />
               <input type="radio" name="race" value="half" id="half"/>
               <label for="half">Half Marathon</label><br />
               <input type="radio" name="race" value="full" id="full"/>
               <label for="full">Full Marathon</label><br />
				
               <label for="email">Email</label>
               <input type="email" name="email" id="email"/>
               <label for="password">Password</label>
               <input type="password" name="password" id="password"/>
               <br />
               Select Age Group
               <select>
                  <option>under 18</option>
                  <option>18-30</option>
                  <option>30-50</option>
                  <option>50+</option>
               </select><br />
               <button>Register!</button>
            </div>
         </form>
      </body>
   </html>

강사님이 의도한 대로 만든 건지는 모르겠으나, 겉보기에는 똑같다.

 

아래의 코드는 강사님이 이야기해주신 정답.

<!DOCTYPE html>
   <html lang="ko">
	   <head>
         <meta charset="UTF-8">
         <title>Marathon Register Form</title>
      </head>
      <body>
         <h1>Race Registration!</h1>
         <form action="">
            <div>
               <label for="first">First Name</label>
               <input type="text" name="first-name" id="first" registered />
               <label for="last">Last Name</label>
               <input type="text" name="last-name" id="last" registered />
            </div>

            <p>Select a Race:</p>
            <div>
               <input type="radio" name="race" value="funrun" id="funrun"/>
               <label for="funrun">Fun Run 5k</label>
            </div>
            <div>
               <input type="radio" name="race" value="half" id="half"/>
               <label for="half">Half Marathon</label>
            </div>
            <div>
               <input type="radio" name="race" value="full" id="full"/>
               <label for="full">Full Marathon</label>
            </div>
            <div>
               <label for="email">Email</label>
               <input type="email" name="email" id="email" registered/>
               <label for="password">Password</label>
               <input type="password" name="password" id="password" registered />
            </div>
            <div>
               <label for="division">Select Age Group</label>
               <select name="division" id="division">
                  <option value="kids">under 18</option>
                  <option value="ya">18-30</option>
                  <option value="adults">30-50</option>
                  <option value="seniors">50+</option>
               </select>
            </div>
            <button>Register!</button>
         </form>
      </body>
   </html>

id 값은 숫자로 시작하면 안 된다고 한다..!

그냥 <label>의 for 속성값과 맞추기만 하면 되는 줄 알았는데...

그니까 id="5k"가 아닌 다른 것으로 써주었다.

 

선택창을 써줄 때, <label for="">을 빼먹었고, <select>와 <label>을 연결짓지도 않았네....

거기다 <option>에 value를 빼먹었다...ㅎㅎ;;

 

구획을 나누어줄 때 강사님은 <div>를 사용했다.

뭐, 이건 여기서 크게 상관이 없다고 하셔서, 내가 쓴 <p>와 <br />로도 커다란 문제가 일어나거나 그러진 않은 것 같다.

변명하자면 라디오버튼과 아래 입력란들 간의 간격이 <p>로 구분하니까 너무 넓어져서, <br />을 쓰니까 간격이 좁혀지길래 썼다..ㅠㅠㅠ

 

겉보기에는 똑같아 보였는데.. 힝ㅠㅠ 틀린 점이 적지 않다.....

 

 

VSCode 이용 Tip!

input:radio 쓰고 Tab을 누르면 <input type="radio" name="" id=""/>가 자동으로 생긴다.

 

 

 

 

 

요 단원 마치는 데 나흘이나 걸렸다..??ㅠ

정신 차려!! 다시 열심히 가자!!!!

헛둘헛둘

'프밍 > HTML' 카테고리의 다른 글

Section 5. 폼(Form)과 테이블(table)(1)  (0) 2022.11.20
Section 4. HTML의 다음 단계(2)  (0) 2022.11.17
Section 4. HTML의 다음 단계(1)  (0) 2022.11.15
Section 3. HTML 기초(3)  (0) 2022.11.12
Section 3. HTML 기초(2)  (0) 2022.11.12
Comments