728x90
formData에 속한 input, select, textarea를 서버로 보내기 전에 빈 문자열이 서버로 들어갈 경우 500 에러가 발생한다.
물론 사용자가 올바른 값을 작성하면 문제가 없지만 이에 대한 예외처리가 없으면 ux가 안좋아지므로 이를 방지하는 예외 메서드를 만들어보자.
요구사항 정리
서버로 formData를 전송하는데 사용자가 정상적으로 입력하지 않은 경우를 고려해서 예외처리를 해주어야한다.
단순히 몇 개만 체크하는건 어렵지 않은데 조건부로 많은 양의 input을 검사해야하는 경우에는 이를 깔끔하게 관리하려면 어느정도 로직이 필요하다.
function checkDetailForm(formData) {
let isValid = true;
const isIconCheck = $("#icon_no").val() === "0" ? false : true;
console.log("isIconCheck", isIconCheck);
if (fileSize === 0) {
alert("업로드할 파일을 선택하세요.");
$('#file_name_text').focus();
return false;
}
// 예외처리할 부분
// 매핑 관련 필드들
const mappingFields = ["addr", "addr_detail", "lat", "lon", "mapping_field"];
// 주요 매핑필드(장소명 제외), 정보제공필드는 필수 아님
const nameFields = ['tel_field', 'open_time']
// 정보 제공 필드
const infoFields = ['file_head_field', 'file_head_name'];
//예외 처리할 배열
const excludeNames = [...mappingFields, ...nameFields, ...infoFields];
formData.find("input, select, textarea").each(function () {
const $field = $(this);
const type = $field.attr("type");
const name = $field.attr("name");
if (!$field.is(":visible") || type === "hidden") return; // 표시되지 않는 부분은 검사x
if (type === "search") return; // 검색 버튼은 검사x
if (excludeNames.includes(name)) return; // 예외처리할 필드들은 검사x
if ($.trim($field.val()) === "") {
const fieldName = name || "알 수 없음";
alert(`'${fieldName}' 항목을 입력해주세요.`);
$field.focus();
isValid = false;
return false; // break
}
});
if (!isValid) return false;
// const isIconCheck = $("#icon_no").val() === "0" ? false : true;
// console.log("isIconCheck", isIconCheck);
//아이콘 파일 별도 검사
if (!isIconCheck) {
alert("아이콘을 선택하세요.");
$("#icon_no").focus();
return false;
}
// mapping_field 값(체크박스 값)에 따라 추가 검사
const mappingValue = $('input[name="mapping_field"]:checked').val();
if (mappingValue === "addr") {
const addr = $("#addr").val();
if (!addr) {
alert("주소 필드를 선택해주세요.");
$("#addr").focus();
return false;
}
} else if (mappingValue === "latlon") {
const lat = $("#lat").val();
const lon = $("#lon").val();
if (!lat) {
alert("위도 필드를 선택해주세요.");
$("#lat").focus();
return false;
}
if (!lon) {
alert("경도 필드를 선택해주세요.");
$("#lon").focus();
return false;
}
}
return true;
}
일반적으로 모든 값을 검사에 포함시키고 검사하지 않는 부분은 따로 빼준다.
이때 검사하지 않는 부분이 유동적으로 바뀔 수 있으므로 관리하기 편하게 작성하는게 핵심이다.
예를들어 예외처리할 부분들을 도메인 별로 묶어주고 이를 하나의 예외처리 배열에 합쳐주면 나중에 도메인별로 관리하기가 편하다.
// 등록 처리
function insertDetail() {
let form = $("#detailform");
console.log(form);
const is_valid = checkDetailForm(form);
console.log("is_valid", is_valid);
if (is_valid) {
$.LoadingOverlay("show");
const name = $(".text_admin").text().trim();
if (name !== "") {
console.log("담당자 변경 처리", name);
$('#user_id').val(name);
}
const formData = form.serializeArray();
$.ajax({
type: "POST",
url: "./item_insert_process.do",
data: $.param(formData),
async: true,
cache: false,
success: function (result) {
console.log(JSON.stringify(result));
if (result) {
$.LoadingOverlay("hide");
alert("등록 되었습니다.");
document.location.href = "./item_list.do";
}
return;
},
});
return;
}
return;
}
새로운 문제…조건에 따라 검사해야하는 항목이 분기됨
처음에 위와 같이 작성했는데 문제가 발생했다.
데이터 유형에 따라서 검사해야하는 항목들이 많이 다르다…기본적인 틀은 비슷한데 검사해야하는 항목들에 차이가 있다.
아까 작성한 코드를 수정하여 모든 경우를 만족시키도록 해야한다.
따라서 아래와 같이 작업하기로했다
- 공통 검사함수 만들기
- 공통 검사함수를 호출하고 거기에 item_kind별로 예외사항 추가하기
구현한 코드
function checkDetailForm(formData) {
let isValid = true;
let item_kind = $("input:radio[name=item_kind]:checked").val();
// 검사를 제외할 필드 목록
const excludeNames = [];
switch (item_kind) {
case "mark":
console.log("mark");
// 아이콘 체크
const isIconCheck = $("#icon_no").val() === "0" ? false : true;
if (!isIconCheck) {
alert("아이콘을 선택하세요.");
$("#icon_no").focus();
return false;
}
if (fileSize === 0) {
alert("업로드할 파일을 선택하세요.");
$('#file_name_text').focus();
return false;
} else {
// 매핑 관련 필드들
const mappingFields = ["addr", "addr_detail", "lat", "lon", "mapping_field"];
// 주요 매핑필드(장소명 제외), 정보제공필드는 필수 아님
const nameFields = ['tel_field', 'open_time']
// 정보 제공 필드
const infoFields = ['file_head_field', 'file_head_name'];
excludeNames.push(...mappingFields, ...nameFields, ...infoFields);
isValid = commonCheckDetailForm(formData, excludeNames);
const mappingValue = $('input[name="mapping_field"]:checked').val();
if (mappingValue === "addr") {
const addr = $("#addr").val();
if (!addr) {
alert("주소 필드를 선택해주세요.");
$("#addr").focus();
return false;
}
} else if (mappingValue === "latlon") {
const lat = $("#lat").val();
const lon = $("#lon").val();
if (!lat) {
alert("위도 필드를 선택해주세요.");
$("#lat").focus();
return false;
}
if (!lon) {
alert("경도 필드를 선택해주세요.");
$("#lon").focus();
return false;
}
}
}
break;
case "graph":
console.log("graph");
if (fileSize === 0) {
alert("업로드할 파일을 선택하세요.");
$('#file_name_text').focus();
return false;
} else {
isValid = commonCheckDetailForm(formData, excludeNames);
}
break;
case "table":
console.log("table");
isValid = commonCheckDetailForm(formData, excludeNames);
// 아이콘은 form에서 제거
// TODO - 통계일때 아이콘을 삭제하는게 맞는지 백엔드 확인 필요
$("#icon_no").remove();
const attachFileLengthCount = $('.data-file-item').length;
console.log("attachFileLength", attachFileLengthCount);
if (attachFileLengthCount === 0) {
alert("첨부파일을 선택하세요.");
$('#file_name_text').focus();
return false;
}
break;
}
// const isIconCheck = $("#icon_no").val() === "0" ? false : true;
// console.log("isIconCheck", isIconCheck);
//아이콘 파일 별도 검사
// mapping_field 값(체크박스 값)에 따라 추가 검사
return isValid;
}
// 공통으로 체크되는 부분
function commonCheckDetailForm(formData, excludeNames) {
let isValid = true;
formData.find("input, select, textarea").each(function () {
const $field = $(this);
const type = $field.attr("type");
const name = $field.attr("name");
if (!$field.is(":visible") || type === "hidden") return; // 표시되지 않는 부분은 검사x
if (type === "search") return; // 검색 버튼은 검사x
if (excludeNames.includes(name)) return; // 예외처리할 필드들은 검사x
if ($.trim($field.val()) === "") {
const fieldName = name || "알 수 없음";
alert(`'${fieldName}' 항목을 입력해주세요.`);
$field.focus();
isValid = false;
return false; // break
}
});
return isValid;
}
백엔드 확인이 필요한 부분은 추후 다시 수정하는 것으로 하고 일단 위와 같이 구성하였다.
3가지 경우의 수에 따라 다르게 처리되도록 구현하고 공통적으로는 모든 input, select, textarea를 체크하되 제외해야하는 부분은 유동적으로 컨트롤할 수 있도록 하였다.
'트러블 슈팅 > 트러블 슈팅' 카테고리의 다른 글
canvas에서 echart의 pie 차트가 흐리게 보이는 현상 해결 (0) | 2025.06.17 |
---|---|
class별 필터링 검색 기능 구현 (0) | 2025.06.17 |
브라우저에서 페이지 로드 시 받아온 대용량 데이터를 특정 이벤트에서 사용하는 로직 (0) | 2025.06.17 |
Flash of Unstyled Content(FOUC) 현상 해결 (0) | 2025.06.17 |
Next.js에서 유니티 빌드 파일 접근 수정 (2) | 2024.12.09 |