JSFiddle - React, Tailwind, and code Playground

HTML

<form id="search-form">
  <label for="search-option"></label>
  <select name="" id="search-option">
    <option value="id" selected>아이디</option>
    <option value="name">이름</option>
    <option value="phone_number">핸드폰번호</option>
  </select>
  <label for="q"></label>
  <input type="text" id="q" placeholder="검색어를 입력해주세요">

  <select name="" id="sex-type">
    <option value="ALL" selected>전체</option>
    <option value="M">남자</option>
    <option value="W">여자</option>
  </select>
  <select name="" id="department-type">
    <option value="ALL" selected>전체</option>
    <option value="development">개발부서</option>
    <option value="marketing">마케팅부서</option>
    <option value="operation">운영부서</option>
  </select>
</form>
<table id="user-table">
  <thead>
  <tr>
    <th>아이디</th>
    <th>이름</th>
    <th>핸드폰번호</th>
    <th>성별</th>
    <th>부서</th>
  </tr>
  </thead>
  <tbody>
  </tbody>
</table>

JavaScript

class SearchAction {
    constructor({searchBar, tbody, cacheDB}) {
        this.searchBar = searchBar;
        this.tbody = tbody;
        this.cacheDB = cacheDB;
    }

    search() {
        this.tbody.setItems(
            this.searchBar.presentData(
                this.cacheDB.getItems()));

        this.tbody.renderTbody();
    }
}

class TbodyAction {
    constructor({tbody, requester, cacheDB}) {
        this.tbody = tbody;
        this.requester = requester;
        this.cacheDB = cacheDB;
    }


    create() {
        let item = {};
        this.requester.create(item)
            .then((res) => {
                let item = res.item;

                this.cacheDB.create(item);
                this.tbody.create(item);
                this.tbody.renderTbody();

                alert("생성이 완료되었습니다.");
            })
    }
}

class TheadAction {
    constructor({tbody, thead}) {
        this.tbody = tbody;
        this.thead = thead;
    }

    sort(th) {
        let column = this.thead.getColumnByTh(th);
        this.tbody.sort(column);

        this.tbody.renderTbody();
    }
}

class CacheDB {
    constructor(items) {
        this.items = items;
    }

    getItems() {
        return this.items.map(item => ({...item}));
    }

    create(item) {
        this.items = [item].concat(this.items);
    }
}

class Requester {
    //db data와 서버의 싱크를 맞춰야 하므로 의존성을 강제한다.,, 예측할 수 없게 되네. 지워!
    constructor(url) {
        this.url = url;
    }

    async create(item, url = this.url) {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(item)
        });
        return response.json();
    }
}

class SearchBar {
    constructor({searchOption, q, conditionInfos}) {
        this.searchOption = searchOption;
        this.q = q;
        this.conditionInfos = conditionInfos; // [{condition :element, column :string}]
    }

   ...