모의 해킹에 사용할 게시판 회원가입 주소 검색 구현
검색할 주소를 입력 후 검색 버튼을 클릭하면 fetch
함수가 컨트롤러에 전달한다.
주소가 존재하면 주소 버튼을 생성해 선택을 유도한다.
function inputHTML() {
const buttons = document.querySelectorAll("#search-contents button");
// input 태그 선택
const input = document.querySelector("#address");
// 각 버튼에 클릭 이벤트 리스너 등록
buttons.forEach((button) => {
button.addEventListener("click", () => {
// 클릭된 버튼의 innerHTML 값을 가져와 input 태그에 반영
input.value = button.innerHTML;
});
});
}
function search_form() {
// form
const form = document.getElementById("search-form");
form.addEventListener("submit", (event) => {
event.preventDefault(); // 기본 제출 동작 막기
const formData = new FormData(form);
const address = formData.get("address");
const encodedURL = encodeURIComponent(address);
const url = "/hackthebox/searchprocess?address=" + encodedURL;
fetch(url, {
method: "GET",
})
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
})
.then((result) => {
if (result.search === "success") {
const searchContents = document.getElementById("search-contents");
const dialog = document.getElementById("modal-dialog");
const count = Object.values(result.address).length; // 생성할 버튼 갯수
const button_check = document.querySelectorAll(".check-button");
if (button_check.length > 0) {
// 이미 버튼이 존재하면 기존 버튼 삭제
for (let i = 0; i < button_check.length; i++) {
button_check[i].parentNode.removeChild(button_check[i]);
}
}
for (let i = 0; i < count; i++) {
const button = document.createElement("button");
button.classList.add("btn", "btn-success", "btn-block", "mt-3", "check-button");
button.dataset.dismiss = "modal";
button.dataset.toggle = "modal";
if (i === 0) {
button.innerHTML = result.address[i];
} else if (i === count - 1) {
button.innerHTML = result.address[i];
} else if (i % 2 === 0) {
button.innerHTML = result.address[i];
} else if (i % 2 !== 0) {
button.innerHTML = result.address[i];
}
searchContents.appendChild(button);
}
if (count > 5) {
dialog.style.marginTop = "2%"; // modal 위치 조정
} else {
dialog.style.marginTop = "-11%"; // modal 위치 조정
}
inputHTML();
} else if (result.search === "fail") {
alert("검색 결과가 없습니다.");
}
})
.catch((error) => {
console.error(error);
alert('"강남구 선릉로 10길"과 같은 도로명 주소로 검색해주세요.');
});
});
}
search_form();
전달받은 주소를 dao의 searchaddress
메소드에 전달한다. 주소가 존재하면 success
를 응답하고 그렇지 않다면 fail
을 응답한다.
@WebServlet("/searchprocess")
public class SearchAddressController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
JSONObject jsonObj;
JSONArray jsonArr;
String address = req.getParameter("address");
UserDAO dao = new UserDAO();
ArrayList<AddressDTO> vo_list = dao.SearchAddress(address);
if (vo_list.size() != 0) {
jsonObj = new JSONObject();
jsonArr = new JSONArray();
HashSet<String> set = new HashSet<>();
for (int i = 0; i < vo_list.size(); i++) {
AddressDTO vo = vo_list.get(i);
String result = vo.getSido() + " " + vo.getSigungu() + " " + vo.getDoro_name() + " "
+ vo.getSigungu_building_name();
if (!set.add(result)) {
continue;
}
}
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String element = it.next();
jsonArr.put(element);
}
jsonObj.put("search", "success");
jsonObj.put("address", jsonArr);
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.print(jsonObj.toString());
out.flush();
} else {
jsonObj = new JSONObject();
jsonObj.put("search", "fail");
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
PrintWriter out = resp.getWriter();
out.print(jsonObj.toString());
out.flush();
}
}
}
시군구, 도로명, 빌딩 이름 기준으로 분할한 주소를 SQL 쿼리로 질의한다. 질의 결과를 리스트에 담아 컨트롤러에 반환한다.
public ArrayList<AddressDTO> SearchAddress(String address) {
ArrayList<AddressDTO> vo_list = new ArrayList<>();
String sido = null;
String sigungu = null;
String doro_name = null;
String sigungu_building_name = null;
String query = null;
ArrayList<String> splitAddress = SplitAddress(address); // " " 기준으로 문자열 자르기
sigungu = (String) splitAddress.get(0);
doro_name = (String) splitAddress.get(1);
if (splitAddress.size() == 3) {
sigungu_building_name = (String) splitAddress.get(2);
query = "SELECT SIDO, SIGUNGU, DORO_NAME, SIGUNGU_BUILDING_NAME FROM postcode WHERE SIGUNGU='"
+ sigungu + "' AND DORO_NAME='" + doro_name + "' AND SIGUNGU_BUILDING_NAME='"
+ sigungu_building_name + "'";
} else {
query = "SELECT SIDO, SIGUNGU, DORO_NAME, SIGUNGU_BUILDING_NAME FROM postcode WHERE SIGUNGU='"
+ sigungu + "' AND DORO_NAME='" + doro_name + "'";
}
conn = driver.getConnect();
try {
stmt = conn.createStatement();
rs = stmt.executeQuery(query);
while (rs.next()) {
AddressDTO vo = new AddressDTO();
sido = rs.getString("sido");
sigungu = rs.getString("sigungu");
doro_name = rs.getString("doro_name");
sigungu_building_name = rs.getString("sigungu_building_name");
vo.setSido(sido);
vo.setSigungu(sigungu);
vo.setDoro_name(doro_name);
if (sigungu_building_name == null) {
vo.setSigungu_building_name(" ");
} else {
vo.setSigungu_building_name(sigungu_building_name);
}
vo_list.add(vo);
}
} catch (NullPointerException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
driver.dbClose(rs, stmt, conn);
}
return vo_list;
}
입력받은 주소를 시군구, 도로명, 빌딩 이름 기준으로 분리한다.
private ArrayList<String> SplitAddress(String address) {
String tmp = null;
String[] result;
String sigungu = null;
String doro_name = null;
String sigungu_building_name = null;
ArrayList<String> list;
if (address.contains("로 ")) {
tmp = address.replace("로 ", "로");
result = tmp.split(" ");
} else {
result = address.split(" ");
}
sigungu = result[0];
doro_name = result[1];
list = new ArrayList<String>();
list.add(sigungu);
list.add(doro_name);
if (result.length == 3) {
sigungu_building_name = result[2];
list.add(sigungu_building_name);
}
return list;
}