Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Tags
more
Archives
Today
Total
관리 메뉴

개발자입니다

[비트캠프] 48일차(10주차3일) - Java: (backend, frontend)-app-03 본문

네이버클라우드 AIaaS 개발자 양성과정 1기/Java

[비트캠프] 48일차(10주차3일) - Java: (backend, frontend)-app-03

끈기JK 2023. 1. 11. 10:33

 

postman

 

'postman' 검색 후  Windows 64-bit 다운로드

 

Collections > '게시글 REST API 테스트' 추가한다.

 

add new request 또는 우측 창 + 눌러서 요청을 추가한다.

 

POST(Create) : 게시글 등록은 POST 방식이며 주소 입력 후 Body에 보낼 데이터의 KEY : VALUE 입력하고 Send 한다.

그러면 아래에 응답 결과가 표시된다.

 

GET(Read) : 게시글 목록 조회

 

GET(Read) : 게시글 상세 조회

 

PUT(Update) : 게시글 변경

 

DELETE(Delete): 게시글 삭제

 

 

 

 

백엔드

 

 

HTTP 요청

 

① Query String 방식으로 데이터 보내기

     브라우저가 URL을 cache에 보관 → 외부 노출 → 보안에 취약

 

② Message-body 방식으로 데이터 보내기

     브라우저 cache에 보관하지 않는다 → 직접적인 외부 노출 방지

 

 

 

Query String 또는 Message Body의 no=1&name=aaa&... 를 SpringBoot가 obj.setNo(Integer.parseInt("1"), obj.setName("aaa"), ... 한다. 

→ property(getter/setter)가 있는 항목만 get, set 글자 빼고 맨 앞글자 소문자로 만들어서 들어온 값을 Member 인스턴스 필드에 저장한다.  field가 있어도 property가 없으면 저장하지 않는다.

class Member { - } 에서 field는 int no, string name, ... 등이다.

                                      property(getter/setter)는 getNo(), setNo(), getTel(), ... 등이다.

get만 있으면 read only, set만 있으면 write only가 된다.

 

 

 

backend-app 소스

 

 

MemberController.java
package bitcamp.bootapp.controller;

import java.sql.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import bitcamp.bootapp.dao.MemberDao;
import bitcamp.bootapp.vo.Member;

@CrossOrigin(origins = {"http://127.0.0.1:5500", "http://localhost:5500"})
@RestController
public class MemberController {

  MemberDao memberDao = new MemberDao();

  @PostMapping("/members")
  public Object addMember(
      String name,
      String tel,
      String postNo,
      String basicAddress,
      String detailAddress,
      boolean working,  // ..&working=xxx&..  => 파라미터가 있으면 true, 없으면 false,
      // "on"=true/"off"=false, "1"=true/"0"=false, 그 밖에 문자열은 변환 오류 발생!
      char gender,  // ..&gender=M&..  => 문자 1개의 문자열 변환, null 또는 그 밖에 문자열은 변환 오류 발생!
      byte level  // ..&level=1&..  => Byte.parseByte("1") => 1, null 또는 byte 범위를 초과하는 숫자는 변환 오류 발생
      ) {
    //@RequestParam(name = "name", required = false) String name 로도 가능
    // String title 로 @를 생략할 수 있다.

    System.out.printf("%s,%s,%s,%s,%s,%b,%c,%d\n",
        name, tel, postNo, basicAddress, detailAddress, working, gender, level);

    Member m = new Member();
    m.setName(name);
    m.setTel(tel);
    m.setPostNo(postNo);
    m.setBasicAddress(basicAddress);
    m.setDetailAddress(detailAddress);
    m.setWorking(working);
    m.setGender(gender);
    m.setLevel(level);
    m.setCreatedDate(new Date(System.currentTimeMillis()).toString());

    this.memberDao.insert(m);

    Map<String, Object> contentMap = new HashMap<>();
    contentMap.put("status",  "success");

    return contentMap;

  }


  @GetMapping("/members")
  public Object getMembers() {

    Member[] members = this.memberDao.findAll();

    Map<String, Object> contentMap = new HashMap<>();
    contentMap.put("status",  "success");
    contentMap.put("data",  members);

    return contentMap;
  }

  @GetMapping("/members/{memberNo}")
  public Object getMember(@PathVariable int memberNo) {

    Member m = this.memberDao.findByNo(memberNo);

    Map<String, Object> contentMap = new HashMap<>();

    if (m == null) {
      contentMap.put("status", "failure");
      contentMap.put("message", "해당 번호의 회원이 없습니다.");
    } else {
      contentMap.put("status",  "success");
      contentMap.put("data", m);
    }

    return contentMap;
  }

  @PutMapping("/members/{No}")  // No 가 Member 클래스의 프로퍼티로 있으면 member 에서 받을 수 있다.
  public Object updateMember(
      //      @PathVariable int memberNo,  // Member 인스턴스로 직접 받을 수 있다.
      Member member) {

    Map<String, Object> contentMap = new HashMap<>();

    Member old = this.memberDao.findByNo(member.getNo());
    if (old == null) {
      contentMap.put("status",  "failure");
      contentMap.put("data",  "회원이 없습니다.");
      return contentMap;
    }

    member.setCreatedDate(old.getCreatedDate());

    this.memberDao.update(member);

    contentMap.put("status", "success");

    return contentMap;
  }


  @DeleteMapping("/members/{memberNo}")
  public Object deleteMember(
      // 낱개로 받을 때는 @PathVariable 애노테이션을 생략하면 안된다.
      @PathVariable int memberNo) {

    Member m = this.memberDao.findByNo(memberNo);

    Map<String, Object> contentMap = new HashMap<>();

    if (m == null) {
      contentMap.put("status", "failure");
      contentMap.put("message", "회원이 없습니다.");
    } else {
      this.memberDao.delete(m);
      contentMap.put("status",  "success");
    }

    return contentMap;
  }

}

 

 

 

frontend-app 소스

 

 

list.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>회원</h1>
  <a href="form.html">새 회원</a>
  <table border="1">
    <thead>
      <tr>
        <th>번호</th>
        <th>이름</th>
        <th>전화</th>
        <th>재직</th>
        <th>전공</th>
      </tr>
    </thead>
    <tbody>
    </tbody>
  </table>

  <script>
    var tbody = document.querySelector('tbody');

    function getLevelTitle(level) {
      switch (level) {
        case 0: return "비전공자";
        case 1: return "준전공자";
        case 2: return "전공자";
        default: return "";
      }
    }
    
    fetch('http://localhost:8080/members')
      // method: 생략하면 GET 요청이다.
      .then((response) => { return response.json(); })
      .then((obj) => {
        var html = '';
        for(var m of obj.data) {
          html += `<tr>
            <td>${m.no}</td>
            <td><a href="view.html?no=${m.no}">${m.name} </a></td>
            <td>${m.tel}</td>
            <td>${m.working ? "예" : "아니오"}</td>
            <td>${getLevelTitle(m.level)}</td>
            </tr>\n`;
        }
        tbody.innerHTML = html;

      })
      .catch(() => {
        alert("서버 요청 오류!")
        console.log(err);
      });
  </script>
</body>
</html>

 

 

form.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>새 회원</h1>
  <form>
  <table border="1">
    <tbody>
      <tr>
        <th>이름</th>
        <td><input type="text" name="name" id="f-name"></td>
      </tr>
      <tr>
        <th>전화</th>
        <td><input type="text" name="tel" id="f-tel"></td>
      </tr>
      <tr>
        <th>우편번호</th>
        <td><input type="text" name="postNo" id="f-postNo"></td>
      </tr>
      <tr>
        <th>기본주소</th>
        <td><input type="text" name="basicAddress" id="f-basicAddress"></td>
      </tr>
      <tr>
        <th>상세주소</th>
        <td><input type="text" name="detailAddress" id="f-detailAddress"></td>
      </tr>
      <tr>
        <th>재직여부</th>
        <td>
          <input type="checkbox" name="working" value="true" id="f-working"> 재직중
        </td>
      </tr>
      <tr>
        <th>성별</th>
        <td>
          <input type="radio" name="gender" value="W" id="f-gender-w" checked> 여성
          <input type="radio" name="gender" value="M" id="f-gender-m"> 남성
        </td>
      </tr>
      <tr>
        <th>전공</th>
        <td>
          <select name="level" id="f-level">
            <option value="0">비전공자</option>
            <option value="1">준전공자</option>
            <option value="2">전공자</option>
          </select>
        </td>
      </tr>

    </tbody>
  </table>
  <button id="add-btn" type="button">등록</button>
  <button id="cancel-btn" type="button">취소</button>
  </form>

  <script>
    document.querySelector('#add-btn').onclick = (e) => {
      var name = encodeURIComponent(document.querySelector('#f-name').value);
      var tel = document.querySelector('#f-tel').value;
      var postNo = document.querySelector('#f-postNo').value;
      var basicAddress = encodeURIComponent(document.querySelector('#f-basicAddress').value);
      var detailAddress = encodeURIComponent(document.querySelector('#f-detailAddress').value);
      var working = document.querySelector('#f-working').checked;
      var gender = document.querySelector('#f-gender-w').checked ? 'W' : 'M';
      var level = document.querySelector('#f-level').value;

      // console.log(`name=${name}&tel=${tel}&postNo=${postNo}&basicAddress=${basicAddress}`
      // +`&detailAddress=${detailAddress}&working=${working}&gender=${gender}&level=${level}`);
      
      fetch('http://localhost:8080/members', {
        method: 'POST',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded'
        },
        body: `name=${name}&tel=${tel}&postNo=${postNo}&basicAddress=${basicAddress}`
         + `&detailAddress=${detailAddress}&working=${working}&gender=${gender}&level=${level}`
      })
      .then((response) => response.json())
      .then((obj) => {
          location.href = "list.html";
        })
        .catch(() => {
          alert("서버 요청 오류!")
          console.log(err);
      });
      
    };
    document.querySelector('#cancel-btn').onclick = (e) => {
      location.href = "list.html";
    }

  </script>
</body>
</html>

 

 

view.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <h1>회원</h1>
  <form>
  <table border="1">
    <tbody>
      <tr>
        <th>번호</th>
        <td><input type="text" name="no" id="f-no" readonly></td>
      </tr>
      <tr>
        <th>이름</th>
        <td><input type="text" name="name" id="f-name"></td>
      </tr>
      <tr>
        <th>전화</th>
        <td><input type="text" name="tel" id="f-tel"></td>
      </tr>
      <tr>
        <th>우편번호</th>
        <td><input type="text" name="postNo" id="f-postNo"></td>
      </tr>
      <tr>
        <th>기본주소</th>
        <td><input type="text" name="basicAddress" id="f-basicAddress"></td>
      </tr>
      <tr>
        <th>상세주소</th>
        <td><input type="text" name="detailAddress" id="f-detailAddress"></td>
      </tr>
      <tr>
        <th>재직여부</th>
        <td>
          <input type="checkbox" name="working" value="true" id="f-working"> 재직중
        </td>
      </tr>
      <tr>
        <th>성별</th>
        <td>
          <input type="radio" name="gender" value="W" id="f-gender-w" checked> 여성
          <input type="radio" name="gender" value="M" id="f-gender-m"> 남성
        </td>
      </tr>
      <tr>
        <th>전공</th>
        <td>
          <select name="level" id="f-level">
            <option value="0">비전공자</option>
            <option value="1">준전공자</option>
            <option value="2">전공자</option>
          </select>
        </td>
      </tr>
        <th>등록일</th>
        <td><span id="f-createdDate"></span></td>
      </tr>
  
    </tbody>
  </table>
  <button id="update-btn" type="button">변경</button>
  <button id="delete-btn" type="button">삭제</button>
  <button id="list-btn" type="button">목록</button>
  </form>

  <script>

    var values = location.href.split("?");
    if (values.length != 2) {
      alert("올바른 페이지 주소가 아닙니다.")
      throw "no 파라미터 값이 누락되었습니다.";
    }
    
    var values2 = values[1].split("=");
    if (values2.length != 2 || values2[0] != "no") {
      alert("올바른 페이지 주소가 아닙니다.")
      throw "no 파라미터 값이 누락되었습니다.";
    }
    
    var no = parseInt(values2[1]);
    if (isNaN(no)) {
      alert("게시글 번호가 옳지 않습니다.")
      throw "no 파라미터 값이 숫자가 아닙니다.";
    }

    fetch(`http://localhost:8080/members/${no}`)
      .then((response) => response.json())
      .then((obj) => {
        if (obj.status == "failure") {
          alert("서버 요청 오류!");
          console.log(obj.data);
          return;
        }

        document.querySelector('#f-no').value = obj.data.no;
        document.querySelector('#f-name').value = obj.data.name;
        document.querySelector('#f-tel').value = obj.data.tel;
        document.querySelector('#f-postNo').value = obj.data.postNo;
        document.querySelector('#f-basicAddress').value = obj.data.basicAddress;
        document.querySelector('#f-detailAddress').value = obj.data.detailAddress;
        document.querySelector('#f-working').checked = obj.data.working;
        if (obj.data.gender == 'W') {
          document.querySelector('#f-gender-w').checked = true;
        } else {
          document.querySelector('#f-gender-m').checked = true;
        }
        document.querySelector('#f-level').value = obj.data.level;
        document.querySelector('#f-createdDate').innerHTML = obj.data.createdDate;
      })
      .catch((err) => {
        alert("서버 요청 오류!");
        console.log(err)
      });

    document.querySelector('#update-btn').onclick = (e) => {
      var name = encodeURIComponent(document.querySelector('#f-name').value);
      var tel = document.querySelector('#f-tel').value;
      var postNo = document.querySelector('#f-postNo').value;
      var basicAddress = encodeURIComponent(document.querySelector('#f-basicAddress').value);
      var detailAddress = encodeURIComponent(document.querySelector('#f-detailAddress').value);
      var working = document.querySelector('#f-working').checked;
      var gender = document.querySelector('#f-gender-w').checked ? 'W' : 'M';
      var level = document.querySelector('#f-level').value;

      fetch(`http://localhost:8080/members/${no}`, {
        method: 'PUT',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded'
        },
        body: `name=${name}&tel=${tel}&postNo=${postNo}&basicAddress=${basicAddress}`
        + `&detailAddress=${detailAddress}&working=${working}&gender=${gender}&level=${level}`
        })
        .then((response) => response.json())
        .then((obj) => {
          if (obj.status == "failure"){
            alert("회원 변경 오류!\n" + obj.data);
            console.log(obj.data);
            return;
          }
          location.href = "list.html";
        })
        .catch(() => {
          alert("서버 요청 오류!")
          console.log(err);
        });
    };

    document.querySelector('#delete-btn').onclick = (e) => {
      
      fetch(`http://localhost:8080/members/${no}`, {
        method: 'DELETE'
      })
        .then((response) => response.json())
        .then((obj) => {
          if (obj.status == "failure") {
            alert("회원 삭제 오류!\n" + obj.data);
            console.log(obj.data);
            return;
          }
          location.href = "list.html";
        })
        .catch(() => {
          alert("서버 요청 오류!")
          console.log(err);
        });
    }
    
    document.querySelector('#list-btn').onclick = (e) => {
      location.href = "list.html";
    }
  </script>
</body>
</html>

 

 

 

 

03. 강사 관리 추가하기

 

 

backend-app 소스

 

 

TeacherController.java
package bitcamp.bootapp.controller;

import java.sql.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RestController;
import bitcamp.bootapp.dao.TeacherDao;
import bitcamp.bootapp.vo.Teacher;

@CrossOrigin(origins = {"http://127.0.0.1:5500", "http://localhost:5500"})
@RestController  // @Controller 하면 return할때 json으로 변환하지 않는다.
public class TeacherController {

  TeacherDao teacherDao = new TeacherDao();

  @PostMapping("/teachers")
  public Object addTeacher(Teacher teacher) {

    teacher.setCreatedDate(new Date(System.currentTimeMillis()).toString());

    this.teacherDao.insert(teacher);

    Map<String,Object> contentMap = new HashMap<>();
    contentMap.put("status", "success");

    return contentMap;
  }


  @GetMapping("/teachers")
  public Object getTeachers() {

    Teacher[] teachers = this.teacherDao.findAll();

    Map<String,Object> contentMap = new HashMap<>();
    contentMap.put("status", "success");
    contentMap.put("data", teachers);

    return contentMap;
  }


  @GetMapping("/teachers/{no}")
  public Object getTeacher(@PathVariable int no) {

    Teacher b = this.teacherDao.findByNo(no);

    Map<String,Object> contentMap = new HashMap<>();

    if (b == null) {
      contentMap.put("status", "failure");
      contentMap.put("data", "강사가 없습니다.");
    } else {
      contentMap.put("status", "success");
      contentMap.put("data", b);
    }

    return contentMap;
  }

  @PutMapping("/teachers/{no}")
  public Object updateTeacher(Teacher teacher) {

    Map<String,Object> contentMap = new HashMap<>();

    Teacher old = this.teacherDao.findByNo(teacher.getNo());
    if (old == null) {
      contentMap.put("status", "failure");
      contentMap.put("data", "강사가 없습니다.");
      return contentMap;
    }

    teacher.setCreatedDate(old.getCreatedDate());

    this.teacherDao.update(teacher);

    contentMap.put("status", "success");

    return contentMap;
  }

  @DeleteMapping("/teachers/{no}")
  public Object deleteTeacher(@PathVariable int no) {

    Teacher m = this.teacherDao.findByNo(no);

    Map<String,Object> contentMap = new HashMap<>();

    if (m == null) {
      contentMap.put("status", "failure");
      contentMap.put("data", "강사가 없습니다.");

    } else {
      this.teacherDao.delete(m);
      contentMap.put("status", "success");
    }

    return contentMap;
  }
}

 

 

TeacherDao.java
package bitcamp.bootapp.dao;

import java.util.Arrays;
import bitcamp.bootapp.vo.Teacher;

public class TeacherDao {
  private static final int SIZE = 100;

  private int no;
  private int count;
  private Teacher[] teachers = new Teacher[SIZE];

  public void insert(Teacher teacher) {
    teacher.setNo(++no);
    this.teachers[this.count++] = teacher;
  }

  public Teacher[] findAll() {
    return Arrays.copyOf(teachers, count);
  }

  public Teacher findByNo(int no) {
    for (int i = 0; i < this.count; i++) {
      if (this.teachers[i].getNo() == no) {
        return this.teachers[i];
      }
    }
    return null;
  }

  public void update(Teacher teacher) {
    this.teachers[this.indexOf(teacher)] = teacher;
  }

  public void delete(Teacher teacher) {
    for (int i = this.indexOf(teacher) + 1; i < this.count; i++) {
      this.teachers[i - 1] = this.teachers[i];
    }
    this.teachers[--this.count] = null; // 레퍼런스 카운트를 줄인다.
  }

  private int indexOf(Teacher teacher) {
    for (int i = 0; i < this.count; i++) {
      if (this.teachers[i].getNo() == teacher.getNo()) {
        return i;
      }
    }
    return -1;
  }
}

 

 

Teacher.java
package bitcamp.bootapp.vo;

public class Teacher {
  private int no;
  private String name;
  private String tel;
  private String email;
  private int degree;
  private String school;
  private String major;
  private int wage;
  private String createdDate;

  public int getNo() {
    return no;
  }
  public void setNo(int no) {
    this.no = no;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getTel() {
    return tel;
  }
  public void setTel(String tel) {
    this.tel = tel;
  }
  public String getEmail() {
    return email;
  }
  public void setEmail(String email) {
    this.email = email;
  }
  public int getDegree() {
    return degree;
  }
  public void setDegree(int degree) {
    this.degree = degree;
  }
  public String getSchool() {
    return school;
  }
  public void setSchool(String school) {
    this.school = school;
  }
  public String getMajor() {
    return major;
  }
  public void setMajor(String major) {
    this.major = major;
  }
  public int getWage() {
    return wage;
  }
  public void setWage(int wage) {
    this.wage = wage;
  }
  public String getCreatedDate() {
    return createdDate;
  }
  public void setCreatedDate(String createdDate) {
    this.createdDate = createdDate;
  }

}

 

 

 

frontend-app 소스

 

 

list.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<h1>강사</h1>
<a href="form.html">새 강사</a>
<table border="1">
  <thead>
    <tr>
      <th>번호</th>
      <th>이름</th>
      <th>전화</th>
      <th>학위</th>
      <th>전공</th>
      <th>시강료</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>

<script>
var tbody = document.querySelector("tbody");

function getDegreeTitle(level) {
  switch (level) {
    case 1: return "고졸";
    case 2: return "전문학사";
    case 3: return "학사";
    case 4: return "석사";
    case 5: return "박사";
    case 0: return "기타";
    default: return "";
  }
}

fetch('http://localhost:8080/teachers')
  .then((response) => {return response.json();})
  .then((obj) => {
    var html = '';
    for (var t of obj.data) {
      html += `<tr>
        <td>${t.no}</td>
        <td><a href="view.html?no=${t.no}">${t.name} </a></td>
        <td>${t.tel}</td>
        <td>${getDegreeTitle(t.degree)}</td>
        <td>${t.major}</td>
        <td>${t.wage}</td>
        </tr>\n`;
    }
    tbody.innerHTML = html;
  })
  .catch((err) => {
    alert("서버 요청 오류!");
    console.log(err);
  });  
</script>
</body>
</html>

 

 

form.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<h1>새 강사</h1>
<form>
<table border="1">
  <tbody>
    <tr>
      <th>이름</th>
      <td><input type="text" name="name" id="f-name"></td>
    </tr>
    <tr>
      <th>전화</th>
      <td><input type="tel" name="tel" id="f-tel"></td>
    </tr>
    <tr>
      <th>이메일</th>
      <td><input type="email" name="email" id="f-email"></td>
    </tr>
    <tr>
      <th>학위</th>
      <td>
        <select name="degree" id="f-degree">
          <option value="1">고졸</option>
          <option value="2">전문학사</option>
          <option value="3" selected>학사</option>
          <option value="4">석사</option>
          <option value="5">박사</option>
          <option value="0">기타</option>
        </select>
      </td>
    </tr>
    <tr>
      <th>학교</th>
      <td><input type="text" name="school" id="f-school"></td>
    </tr>
    <tr>
      <th>전공</th>
      <td><input type="text" name="major" id="f-major"></td>
    </tr>
    <tr>
      <th>강의료</th>
      <td><input type="number" name="wage" id="f-wage">원/시간</td>
    </tr>
  </tbody>
</table>
<button id="add-btn" type="button">등록</button>
<button id="cancel-btn" type="button">취소</button>
</form>

<script>
document.querySelector('#add-btn').onclick = (e) => {
  var name = encodeURIComponent(document.querySelector('#f-name').value);
  var tel = document.querySelector('#f-tel').value;
  var email = document.querySelector('#f-email').value;
  var degree = document.querySelector('#f-degree').value;
  var school = encodeURIComponent(document.querySelector('#f-school').value);
  var major = encodeURIComponent(document.querySelector('#f-major').value);;
  var wage = document.querySelector('#f-wage').value;

  // console.log(`name=${name}&tel=${tel}&email=${email}&degree=${degree}&school=${school}` +
  //   `&major=${major}&wage=${wage}`);

  fetch('http://localhost:8080/teachers', {
    method: 'POST',
    headers: {
      'Content-type': 'application/x-www-form-urlencoded'
    },
    body: `name=${name}&tel=${tel}&email=${email}&degree=${degree}&school=${school}` +
      `&major=${major}&wage=${wage}`
  })
  .then((response) => {return response.json();})
  .then((obj) => {
    location.href = "list.html";
  })
  .catch((err) => {
    alert("서버 요청 오류!");
    console.log(err);
  });
};

document.querySelector('#cancel-btn').onclick = (e) => {
  location.href = "list.html";
};

</script>
</body>
</html>

 

 

view.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
<h1>회원</h1>
<form>
<table border="1">
  <tbody>
    <tr>
      <th>번호</th>
      <td><input type="text" name="no" id="f-no" readonly></td>
    </tr>
    <tr>
      <th>이름</th>
      <td><input type="text" name="name" id="f-name"></td>
    </tr>
    <tr>
      <th>전화</th>
      <td><input type="tel" name="tel" id="f-tel"></td>
    </tr>
    <tr>
      <th>이메일</th>
      <td><input type="email" name="email" id="f-email"></td>
    </tr>
    <tr>
      <th>학위</th>
      <td>
        <select name="degree" id="f-degree">
          <option value="1">고졸</option>
          <option value="2">전문학사</option>
          <option value="3" selected>학사</option>
          <option value="4">석사</option>
          <option value="5">박사</option>
          <option value="0">기타</option>
        </select>
      </td>
    </tr>
    <tr>
      <th>학교</th>
      <td><input type="text" name="school" id="f-school"></td>
    </tr>
    <tr>
      <th>전공</th>
      <td><input type="text" name="major" id="f-major"></td>
    </tr>
    <tr>
      <th>강의료</th>
      <td><input type="number" name="wage" id="f-wage">원/시간</td>
    </tr>
    <tr>
      <th>등록일</th>
      <td><span id="f-createdDate"></span></td>
    </tr>
  </tbody>
</table>
<button id="update-btn" type="button">변경</button>
<button id="delete-btn" type="button">삭제</button>
<button id="list-btn" type="button">목록</button>
</form>

<script>

var values = location.href.split('?');
if (values.length != 2) {
  alert("옳바른 페이지 주소가 아닙니다.");
  throw "no 파라미터 값이 누락되었습니다.";
} 

var values2 = values[1].split("=");
if (values2.length != 2 || values2[0] != "no") {
  alert("옳바른 페이지 주소가 아닙니다.");
  throw "no 파라미터 값이 누락되었습니다.";
}

var no = parseInt(values2[1]);
if (isNaN(no)) {
  alert("강사 번호가 옳지 않습니다.");
  throw "no 파라미터 값이 숫자가 아닙니다.";
}

fetch(`http://localhost:8080/teachers/${no}`)
  .then((response) => response.json())
  .then((obj) => {
    if (obj.status == "failure") {
      alert("서버 요청 오류!");
      console.log(obj.data);
      return;
    }

    document.querySelector("#f-no").value = obj.data.no;
    document.querySelector("#f-name").value = obj.data.name;
    document.querySelector("#f-tel").value = obj.data.tel;
    document.querySelector("#f-email").value = obj.data.email;
    document.querySelector("#f-degree").value = obj.data.degree;
    document.querySelector("#f-school").value = obj.data.school;
    document.querySelector("#f-major").value = obj.data.major;
    document.querySelector("#f-wage").value = obj.data.wage;
    document.querySelector("#f-createdDate").innerHTML = obj.data.createdDate;
  })
  .catch((err) => {
    alert("서버 요청 오류!");
    console.log(err)
  });

document.querySelector('#update-btn').onclick = (e) => {
  var name = encodeURIComponent(document.querySelector('#f-name').value);
  var tel = document.querySelector('#f-tel').value;
  var email = document.querySelector('#f-email').value;
  var degree = document.querySelector('#f-degree').value;
  var school = encodeURIComponent(document.querySelector('#f-school').value);
  var major = encodeURIComponent(document.querySelector('#f-major').value);;
  var wage = document.querySelector('#f-wage').value;

  fetch(`http://localhost:8080/teachers/${no}`, {
    method: 'PUT',
    headers: {
      'Content-type': 'application/x-www-form-urlencoded'
    },
    body: `name=${name}&tel=${tel}&email=${email}&degree=${degree}&school=${school}` +
      `&major=${major}&wage=${wage}`
  })
  .then((response) => response.json())
  .then((obj) => {
    if (obj.status == "failure") {
      alert("강사 변경 오류!\n" + obj.data);
      return;
    }
    location.href = "list.html";
  })
  .catch((err) => {
    alert("서버 요청 오류!");
    console.log(err);
  });


};

document.querySelector('#delete-btn').onclick = (e) => {
  fetch(`http://localhost:8080/teachers/${no}`, {
    method: 'DELETE'
  })
  .then((response) => response.json())
  .then((obj) => {
    if (obj.status == "failure") {
      alert("강사 삭제 오류!\n" + obj.data);
      return;
    }
    location.href = "list.html";
  })
  .catch((err) => {
    alert("서버 요청 오류!");
    console.log(err);
  });
};

document.querySelector('#list-btn').onclick = (e) => {
  location.href = "list.html";
};

</script>
</body>
</html>

 

 

 


 

 

조언

 

*100가지 기능을 다 알아야 취업하는 건 아니다. 자주 쓰는 기능을 잘 알아야한다.

 

 

 


 

과제

 

/