티스토리 뷰

1. 이번 목표:
    form으로 get, post 요청을 보내보자!

 

2. 배운 내용 요약

  1. form

클라이언트가 서버에 정보(입력된 데이터를 한번에)를 전달할 때 사용

 

  1-1. 기본적인 <form> 태그 구조

<form action="/submit" method="POST">
  <!-- form 내용 -->
</form>

 

  • action: 폼 데이터가 전송될 URL을 지정. 기본값은 현재 페이지의 URL.
  • method: 폼 데이터 전송 방식을 지정. 주로 GET 또는 POST가 사용됨.

 

 

  1-2. GET Method

- 정보를 가져오거나 검색할 때 사용.
- 백엔드(서버)의 값이나 상태를 변경하지 않을 때 사용.
- Get 요청시 백엔드로 보내야 하는 데이터가 있다면 URL 쿼리 문자열에 데이터 실어 전송.
  (URL에 데이터가 노출됨)
  ex) http://localhost:8080?name=gildong&gender=male

 

  1-3. POST Method

- 뭔가를 생성하거나 어떤 정보를 보낼 때 사용.
- 보내야 하는 데이터는 요청(request)의 본문(body)에 실어 전송. => URL보다 많은 데이터 전송 가능
  (URL에 데이터가 노출되지 않음)

 

body-parser

더보기


- 데이터를 쉽게 처리할 수 있도록 도와주는 미들웨어.

- 요청의 body를 해석해서 req.body 객체로 받을 수 있게 도와준다.

- express 4.x 이상 버전부터 body-parser가 내장되어 있기 때문에 별도 설치는 필요 없음!

app.use(express.urlencoded({extended: true}));
app.use(express.json());

 

  1-4. form의 주요 속성

name

폼에 이름을 지정할 때 사용. 이 이름은 JavaScript로 해당 폼을 참조할 때 유용.

<form name="myForm" action="/submit" method="POST">
  <!-- form 요소들 -->
</form>

 

target

폼 데이터가 제출된 후 결과가 표시될 창 또는 프레임을 지정.

  • _self: 현재 창 (기본값)
  • _blank: 새 창
  • _parent: 부모 프레임
  • _top: 최상위 프레임
<form action="/submit" target="_blank">
  <!-- form 요소 -->
</form>

 

enctype

파일 전송시 폼 데이터의 인코딩 방식 지정.

<form action="/submit" method="POST" enctype="multipart/form-data">
  <!-- form file upload 요소 -->
</form>

 

 

  1-5. 입력 요소

 

텍스트 입력

type="text": 일반 텍스트 입력 필드.
name: 서버로 전송될 데이터의 이름을 지정.
<label for="username">Username:</label>
<input type="text" id="username" name="username">

 

비밀번호 입력

type="password" : 입력한 내용이 별표(*)로 표시
<label for="password">Password:</label>
<input type="password" id="password" name="password">

 

체크박스

type="checkbox": 여러 개의 값을 선택할 수 있는 체크박스.
value: 체크박스가 선택되었을 때 서버로 전송될 값.
<label for="subscribe">Subscribe:</label>
<input type="checkbox" id="subscribe" name="subscribe" value="yes">


라디오 버튼

type="radio": 여러 옵션 중 하나만 선택할 수 있는 라디오 버튼.
name: 같은 그룹에서 하나만 선택되도록 하는데 사용.
<label for="gender-male">Male:</label>
<input type="radio" id="gender-male" name="gender" value="male">
<label for="gender-female">Female:</label>
<input type="radio" id="gender-female" name="gender" value="female">

 

제출 버튼

type="submit": 폼을 제출.
value: 버튼에 표시될 텍스트.
<input type="submit" value="Submit">

 

파일 업로드

type="file": 파일을 업로드할 수 있는 입력 필드
<label for="file-upload">Upload File:</label>
<input type="file" id="file-upload" name="file">

 

텍스트영역

rows: 텍스트 영역의 높이.
cols: 텍스트 영역의 너비.
<label for="comments">Comments:</label>
<textarea id="comments" name="comments" rows="4" cols="50"></textarea>

 

드롭다운

<select>: 드롭다운 목록을 생성.
<option>: 드롭다운 목록의 각 항목을 정의.
<label for="country">Country:</label>
<select id="country" name="country">
  <option value="usa">United States</option>
  <option value="canada">Canada</option>
  <option value="uk">United Kingdom</option>
</select>

 

날짜

type="date": 날짜를 선택할 수 있는 입력 필드
<label for="birthdate">Birth Date:</label>
<input type="date" id="birthdate" name="birthdate">

 

 

그룹화

<fieldset>: 폼 요소들을 시각적으로 묶을 수 있는 테두리 박스.
<legend>: fieldset의 제목을 지정.
<fieldset>
  <legend>Personal Information</legend>
  <label for="first-name">First Name:</label>
  <input type="text" id="first-name" name="first-name"><br><br>
  
  <label for="last-name">Last Name:</label>
  <input type="text" id="last-name" name="last-name"><br><br>
</fieldset>

 

  1-6. HTML 폼 요소 속성

- placeholder: 입력 필드에 기본 텍스트를 표시

- disabled: 입력 필드를 비활성화하여 사용자가 값을 입력할 수 없게

- readonly: 입력 필드를 읽기 전용으로 설정하여 값을 수정할 수 없게

- minlength / maxlength: 입력할 수 있는 최소 / 최대 문자 수를 설정

- autofocus: 폼이 로드될 때 자동으로 해당 필드에 포커스를 설정

- required: 필수 입력 항목을 지정

<input type="text" name="username" required placeholder="Enter your username" disabled readonly minlength="5" maxlength="20" autofocus>

 

  1-7.폼 유효성 검사(validation)

  • required: 필수 값
  • minlength / maxlength: 최소/최대 문자 수
  • min / max: 최소/최대 값
  • type: 입력받는 정보 타입
  • pattern: 정규식으로 검사

pattern 속성 정규식

더보기

이메일 주소 형식이 맞는지 확인

pattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"

  • ^[a-zA-Z0-9._%+-]+: 이메일의 첫 부분으로, 알파벳 대소문자, 숫자, 점, 언더스코어, 퍼센트 기호, 더하기 기호, 빼기 기호가 포함될 수 있다.
  • @: 이메일의 '@' 기호.
  • [a-zA-Z0-9.-]+: '@' 뒤의 도메인 이름 부분으로, 알파벳, 숫자, 점, 하이픈이 포함될 수 있다.
  • \.[a-zA-Z]{2,}$: 도메인의 최상위 도메인(TLD) 부분으로, 점(.) 뒤에 2글자 이상의 알파벳이 있어야 한다.

전화번호 형식 (xxx-xxx-xxxx) 검증

pattern="^\d{3}-\d{3}-\d{4}$"

  • \d{3}: 3개의 숫자.
  • -: 하이픈 구분자.
  • \d{4}: 4개의 숫자.

위 코드는 사용자가 xxx-xxx-xxxx 형식의 전화번호를 입력해야만 제출이 가능

 

 

  2. Express.js에서 GET과 POST 요청을 처리하는 예시

  1. app.js (서버 코드)

Express 애플리케이션을 설정하고,GET과 POST요청을 처리하는 라우트를 정의.
ejs템플릿 엔진을 사용하여 HTML을 렌더링.
const express = require('express');
const app = express();
const path = require('path');

// 1. 뷰 엔진으로 ejs 설정
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// 2. POST 요청에서 데이터를 처리할 수 있도록 body-parser 미들웨어 설정
app.use(express.urlencoded({ extended: true })); // form 데이터를 파싱할 수 있도록 설정

// 3. GET 요청 처리
app.get('/getForm', (req, res) => {
    console.log(req.query); // 쿼리 파라미터로 넘어온 데이터 출력
    res.render('result', { data: req.query }); // 쿼리 파라미터를 result.ejs로 전달
});

// 4. POST 요청 처리
app.post('/postForm', (req, res) => {
    console.log(req.body); // 폼 데이터 출력
    res.render('result', { data: req.body }); // 폼 데이터(result.ejs로 전달)
});

// 5. 서버 시작
app.listen(8080, () => {
    console.log('서버가 http://localhost:8080 에서 실행 중입니다.');
});
- app.set('view engine', 'ejs')를 사용하여 EJS 템플릿 엔진을 설정.
- express.urlencoded({ extended: true })는 POST 요청 시 req.body로 전달된 데이터를 파싱하는 미들웨어
- /getForm 라우트는 GET 요청을 처리하며, 쿼리 파라미터를 받아서 result.ejs로 전달.
- /postForm 라우트는 POST 요청을 처리하며, 폼 데이터를 받아서 result.ejs로 전달.

 

   2. views/result.ejs (결과를 표시하는 EJS 템플릿 파일)

GET 또는 POST 요청으로 전달된 데이터를 화면에 출력하는 역할
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>결과 페이지</title>
</head>
<body>
    <h1>폼 제출 결과</h1>
    <h2>전송된 데이터:</h2>

    <!-- 쿼리 파라미터나 폼 데이터를 보여주기 -->
    <ul>
        <% for (let key in data) { %>
            <li><strong><%= key %>:</strong> <%= data[key] %></li>
        <% } %>
    </ul>

    <a href="/">다시 돌아가기</a>
</body>
</html>
- data 객체는 app.js에서 전달된 req.query 또는 req.body 데이터를 포함.
- for 루프를 사용하여 data 객체의 키와 값을 모두 출력.
- a 태그를 사용하여 홈으로 돌아갈 수 있는 링크를 제공.

 

 

   3. views/index.ejs (폼 입력 페이지)

폼을 만들어서 GET과 POST 요청을 보낼 수 있는 페이지를 작성
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>폼 입력</title>
</head>
<body>
    <h1>폼 입력 페이지</h1>

    <!-- GET 요청을 위한 폼 -->
    <h2>GET 요청 보내기</h2>
    <form action="/getForm" method="get">
        <label for="name">이름:</label>
        <input type="text" id="name" name="name">
        <br><br>
        <label for="age">나이:</label>
        <input type="number" id="age" name="age">
        <br><br>
        <button type="submit">GET 요청 보내기</button>
    </form>

    <!-- POST 요청을 위한 폼 -->
    <h2>POST 요청 보내기</h2>
    <form action="/postForm" method="post">
        <label for="name">이름:</label>
        <input type="text" id="name" name="name">
        <br><br>
        <label for="age">나이:</label>
        <input type="number" id="age" name="age">
        <br><br>
        <button type="submit">POST 요청 보내기</button>
    </form>

</body>
</html>
- 첫 번째 폼은 GET 방식으로 데이터를 전송하며, action="/getForm"과 method="get"을 사용.
- 두 번째 폼은 POST 방식으로 데이터를 전송하며, action="/postForm"과 method="post"를 사용.
- name과 age를 입력할 수 있는 필드가 있다.

 

  4. express에서의 http 비동기 통신 방법

    4-1. AJAX (XMLHttpRequest)

클라이언트 측에서 비동기적으로 데이터를 요청하는 방식.
 서버에서는 res.send()로 응답을 보냄.
// 클라이언트 측에서 AJAX를 사용하여 서버로 데이터를 요청하는 예시
function fetchDataWithAjax() {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', '/api/posts', true);
  
  xhr.onload = function() {
    if (xhr.status === 200) {
      console.log(JSON.parse(xhr.responseText));  // 서버 응답 처리
    } else {
      console.error('Request failed with status ' + xhr.status);
    }
  };
  
  xhr.onerror = function() {
    console.error('Request failed');
  };
  
  xhr.send();
}
const express = require('express');
const app = express();
const PORT = 8080;

app.get('/api/posts', (req, res) => {
  // 클라이언트의 AJAX 요청에 대한 응답
  res.json([{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }]);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

응답 예시

[
  { "id": 1, "title": "Post 1" },
  { "id": 2, "title": "Post 2" }
]

 

 

 

    4-2. Axios ( 클라이언트에서 Express 서버로 요청 )

Promise기반의 HTTP 클라이언트로, Express에서 외부 API와 비동기 통신을 할 때 자주 사용.
Axios를 사용하여 서버에 요청하거나, 서버 측에서 외부 API에 요청을 보내는 방식으로 활용할 수 있다.
async/await와 함께 사용하여 비동기 요청을 처리할 수 있다.
<!-- axios CDN -->   
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
async function fetchDataWithAxios() {
  try {
    const response = await axios.get('/api/posts');  // GET 요청
    console.log(response.data);  // 응답 데이터 출력
  } catch (error) {
    console.error('Error:', error);
  }
}
const express = require('express');
const app = express();
const port = 8080;

app.get('/api/posts', (req, res) => {
  // JSON 데이터를 응답으로 보내는 예시
  res.json([{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }]);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

응답예시

{
  data: [
    { id: 1, title: 'Post 1' },
    { id: 2, title: 'Post 2' }
  ],
  status: 200,
  statusText: 'OK',
  headers: { ... },
  config: { ... }
}

// response.data, response.status 등의 속성으로 접근

 

    4-3. Fetch ( 클라이언트에서 Express 서버로 요청 )

Express 서버에서 클라이언트 측의 요청을 처리할 때 사용.
fetch는 Promise를 반환하며, async/await와 함께 사용하여 비동기 요청을 처리할 수 있다.
async function fetchDataWithFetch() {
  try {
    const response = await fetch('/api/posts');  // GET 요청
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    const data = await response.json();  // 응답 데이터를 JSON 형식으로 변환
    console.log(data);  // 응답 데이터 출력
  } catch (error) {
    console.error('Error:', error);
  }
}
const express = require('express');
const app = express();
const port = 8080;

app.get('/api/posts', (req, res) => {
  // JSON 데이터를 응답으로 보내는 예시
  res.json([{ id: 1, title: 'Post 1' }, { id: 2, title: 'Post 2' }]);
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

응답예시

{
  ok: true,
  status: 200,
  statusText: 'OK',
  headers: { ... },
  url: 'http://localhost:8080/api/posts'
}

// Fetch의 응답은 Response 객체로 반환되며, json() 메서드를 사용하여 데이터를 파싱

 

특성 AJAX(XMLHttpRequest) Axios Fetch
응답 데이터 xhr.responseText로 응답 데이터
(수동 파싱 필요)
response.data로 응답 데이터
(자동 JSON 파싱)
response.json()으로 데이터 파싱
(수동 파싱 필요)
상태 코드 xhr.status로 응답 상태 코드 확인 response.status로 상태 코드 확인 response.status로 상태 코드 확인
에러 처 리 onerror 또는 onload에서 처리 catch블록에서 처리 catch블록에서 처리
응답 객체 XMLHttpRequest객체 응답객체
(data, status, headers 포함)
Response객체
(상태코드, 헤더 정보 포함)
데이터를 파싱하려면
json()이나 text() 메서드를 사용

 

 

 

3. 회고

더보기

폼을 사용한 GET, POST 요청의 차이를 배우면서, GET 요청은 데이터가 URL에 포함되어 전송되기 때문에 간단한 데이터 전달에는 유용하지만, 민감한 정보에는 적합하지 않다는 점을 배웠다. 반면, POST 요청은 데이터를 요청 본문에 포함시켜 보낼 수 있어, 보안이 중요한 데이터를 안전하게 처리할 수 있다는 점에서 유용하다는 것을 알게 됐다. Express 서버에서 비동기 HTTP 통신을 처리하는 방법을 배우면서, 비동기 방식인 axios와 fetch를 사용하여 외부 API와 데이터를 주고받는 과정을 배웠다. 특히, async/await를 사용한 비동기 처리 방식이 코드의 가독성을 높여주고, 오류 처리 시 try/catch를 통해 발생할 수 있는 문제를 적절히 처리하는 것이 중요하다는 점을 깨달았다.

async와 await는 여태껏 프로젝트를 하면서 남발하던 비동기 방식이었는데. 무조건적으로 async/await만이 좋은 것이 아니라 각 통신 방식에 따라 장단점이 따른다는 것을 배울 수 있었다. 이번 주 수업 너무 유익하고 재미있었다!

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/06   »
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
글 보관함