IT 일기장
[JSP] 공통 폼 태그 자동 생성기 유틸 만들기 본문
시작 계기
개발을 하다 보면 select, radio, checkbox 같은 폼 태그를 반복해서 작성해야 할 때가 많다.
특히 데이터베이스(DB) 값이나 공통 코드(CMMN)로 옵션을 불러오는 경우, HTML을 매번 직접 작성하는 것은 굉장히 비효율적이라 생각하여 공통 유틸을 만들고자 생각했다.
"태그 유형별로 적절히 생성해 주고, 필요한 옵션만 넘기면 알아서 만들어주는 유틸리티가 있으면 좋지 않을까?"
하는 생각에서 HtmlObjUtil을 만들게 되었다.
HtmlObjUtil은 JSP에서 <cfn:HtmlObjUtil /> 태그 하나로 select, radio, checkbox, toggle 형태를 자동으로 출력해 주는 공통 모듈이다. 기본 입력 폼을 깔끔하고 일관성 있게 관리하고자 설계했다. CSS는 bootStrap5를 사용했다.
구조
속성명 | 설명 |
objType | 생성할 태그 유형 (select, radio, checkbox, toggle) |
objName | 태그의 id, name 속성 값 (DB 컬럼명) |
objItemMode | 데이터 모드 설정 (DB, KEYIN, CMMN) |
objItemDepth | DB 조회 시 코드 depth 지정 (선택) |
objItemOptions | KEYIN 입력값 설정 (M:Male,F:Female 형식) |
selectedValue | 선택된 값 (select, radio용) |
checkedValues | 체크된 값들 (checkbox용, ,로 구분) |
objCommonKey | CMMN 모드일 때 공통 옵션 키 |
objOnChange | onchange 이벤트 함수명 |
objOnClick | onclick 이벤트 함수명 |
동작 흐름
- objItemMode를 기준으로 옵션 데이터를 가져온다.
- objType에 맞게 HTML 태그를 만들어 출력한다.
- 필요한 경우 onchange, onclick 이벤트도 자동으로 삽입한다.
사용 예시
- DB
<%@ taglib prefix="cfn" uri="/WEB-INF/tld/custom.tld" %>
<!--
objItemOptions 값은 DB의 SEQ값으로 설계했다. (앞으로 어떻게 하면 좋을지 고민..)
1depth의 SEQ 값이 "1573"인 2depth 목록 출력
-->
<cfn:HtmlObjUtil objItemMode="DB" objType="radio" objName="paaaClss" objItemDepth="2" objItemOptions="1573" />
- KEYIN
<%@ taglib prefix="cfn" uri="/WEB-INF/tld/custom.tld" %>
<!--
DB에 들어갈 값 : 1,2,3 ... ,7
화면에 보일 값 : 매니저,선임 ... , 대표
-->
<cfn:HtmlObjUtil objItemMode="KEYIN" objType="select" objName="ppuPstn" objItemOptions="1:매니저,2:선임,3:책임,4:이사,5:전무,6:상무이사,7:대표" selectedValue="1" />
- CMMN
<%@ taglib prefix="cfn" uri="/WEB-INF/tld/custom.tld" %>
<!--
사용 여부
Y:사용,N:미사용
-->
<cfn:HtmlObjUtil objItemMode="CMMN" objType="toggle" objName="pacUseYn" objCommonKey="useStatus" selectedValue="Y" />
참고로 CMMN 모드인 경우 htmlobjutil-cmmn.properties 파일을 따로 만들어줬다.
그리고 다음과 같이 설정 돼있어야 한다.
useStatus=Y:사용,N:미사용
주요 함수
- doTag()
- JSP에서 <cfn:HtmlObjUtil /> 태그가 호출되면 doTag()가 실행된다.
- objItemMode에 따라 옵션 리스트(optionList)를 준비한다.
- objType에 따라 적절한 HTML을 생성한다.
- JSP 화면에 HTML을 출력한다.
- initializeApplicationContext()
- Spring의 ApplicationContext를 JSP Tag 안에서도 사용할 수 있게 초기화하는 함수다.
- JSP 커스텀 태그는 Spring Bean이 아니라서 직접 cationContext를 가져야 한다.
- 현재 페이지 컨텍스트에서 ServletContext를 얻고, 이를 통해 WebApplicationContext를 주입한다.
- fetchOptionsFromDB()
- DB에서 옵션 목록을 불러오는 함수다.
- 내부적으로 BpsSysCodeController의 selectListBpsSysCode() 메서드를 호출한다.
- 매개변수(objItemDepth, objItemOptions)에 따라 depth별 Key값을 바꿔서 전달한다.
- 결과로 받아온 리스트를 HTML용 String[][] 포맷으로 변환한다.
- parseOptions()
- KEYIN 모드일 때, 직접 입력한 옵션 문자열을 파싱하는 함수다.
- 예시 입력값: "M:Male,F:Female"
- 처리 결과: [["M", "Male"], ["F", "Female"]]
- , 로 구분해서 각각의 : 단위로 쪼개기
- fetchCommonOptions()
- CMMN 모드일 때, 공통 속성(properties 파일)로부터 옵션을 불러오는 함수.
- htmlobjutil-cmmn.properties 파일을 읽어서, 필요한 key에 해당하는 옵션 리스트를 반환한다.
- 파일 경로: /resources/htmlobjutil-cmmn.properties
- loadCommonOptions()
- fetchCommonOptions() 내부에서 실제로 파일을 읽어오는 역할.
- UTF-8로 properties 파일을 로딩한다.
- useStatus=Y:사용,N:미사용 같은 값을 Map 형태로 변환한다.
- extractOptionList(Object result, Map<String, Object> methodArgs)
- DB 결과를 [value, label] 형태의 옵션 배열로 변환하는 함수.
- selectListBpsSysCode로 받은 Map 결과 중 rows 리스트를 꺼낸다.
- 각각 sscSeq(코드값)과 sscNm(코드이름) 필드를 사용해 옵션으로 변환한다.
- generateHTML(String objType, List<String[]> optionList)
- 최종적으로 HTML 태그를 만들어주는 메인 함수.
- objType(select, radio, checkbox, toggle)에 따라 분기 처리.
- 각각 전용 함수(generateSelect, generateRadio, generateCheckbox, generateToggle)를 호출해서 완성한다.
- generateSelect(List<String[]> optionList)
- <select> 태그를 생성하는 함수.
- 옵션 목록을 돌면서 <option>을 만든다.
- selectedValue가 현재 옵션 값과 일치하면 selected 속성 추가.
- generateRadio(List<String[]> optionList)
- <input type="radio"> 그룹을 생성하는 함수.
- 옵션마다 input과 label 세트를 만들고, selectedValue로 체크 상태를 제어한다.
- generateCheckbox(List<String[]> optionList)
- <input type="checkbox"> 그룹을 생성하는 함수.
- 다중 체크 가능
- checkedValues에 포함된 경우 checked 속성을 추가한다.
- generateToggle(List<String[]> optionList, String selectedValue)
- 토글 스위치 형태의 <input type="checkbox">를 생성하는 함수.
- ON/OFF 두 가지 상태를 가진다.
- ON 상태일 경우 checked를 추가하고, toggle 이벤트에서 label을 변경해준다.
- generateEmptyHTML(String objType)
- 옵션 데이터가 없을 경우 비어있는 기본 HTML을 생성하는 함수.
- select, radio, checkbox 각각의 기본 형태만 출력해서 오류를 방지한다.
기대 효과
1. 반복되는 폼 작업을 90% 이상 줄일 수 있었다. 매번 select, radio, checkbox를 HTML로 직접 짜던 수고를 덜 수 있다.
2. 코드의 일관성이 높아진다. 프로젝트 전체의 폼 구조를 통일되게 유지할 수 있다. 디자인팀/기획팀 요구사항 반영에도 유리하다.
3. 속성에 대한 숙지를 하고 있다면 수정/변경이 용이해진다. 만약 모든 select 태그 스타일을 바꾸고 싶으면 HtmlObjUtil.java 안에서만 수정하면 끝난다.
4. DB, 하드코딩(KEYIN), 공통(CMMN) 옵션을 유연하게 대응할 수 있다. 개발 중, 기획 변경사항이 생겨도 거의 대부분 대응할 수 있다.
마무리
HtmlObjUtil은 "복잡한 폼 작업을 단순화하고 싶다"는 작은 생각에서 출발했지만, 개발을 진행하면서 느낀 점은 다음과 같다.
- DB 모드에 대한 고려 부족
- 현재 DB 모드에서는 코드 관리 테이블에 의존해서 옵션을 불러오게 되어 있다. 하지만 실제 프로젝트에서는 코드 구조나 요구사항이 제각각이라서 특정 테이블 조회, 특정 조건 필터링, 다국어 지원 같은 다양한 케이스가 필요할 수 있다.
- 앞으로는 DB 조회 부분을 더 유연하게 개선해서, 사용자 정의 쿼리도 쉽게 적용할 수 있도록 발전시킬 계획이다.
- 속성(attribute) 개수가 너무 많음
- 지금 HtmlObjUtil은 좋은 기능을 갖추고 있지만, 초심자 입장에서는 속성이 너무 많아서 처음 사용 시 부담이 생길 수 있다.
- 필수값/선택값을 구분, 기본값을 더 많이 잡아주기, 속성 그룹핑(단일 설정으로 여러 속성 제어) 등 더 직관적으로 사용할 수 있게 개선할 방법을 고민 중이다.
- 다른 개발자 사용성도 고려하기
- 내가 쓰는 것을 넘어서, "다른 개발자가 처음 봐도 쉽게 이해하고 사용할 수 있을까?" 라는 질문을 계속 던지고 있다.
- 예제 문서를 충분히 제공, 공통 옵션 설정을 더 명확하게 문서화, 커스텀 확장 포인트 제공 등 내 코드가 개인 유틸을 넘어서 팀, 조직에서도 쓸 수 있는 수준까지 성장시키고 싶다.
목표
- DB 구조 자유화 : 다양한 테이블/필드를 대응할 수 있게 설계 확장
- 속성 최적화 : 꼭 필요한 속성만 쓰게 하고, 나머지는 옵션화
- 사용자 배려 강화 : 문서, 주석, 사용성까지 고려한 설계
- 재사용성 향상 : 다른 프로젝트에도 쉽게 이식할 수 있도록
단순히 HTML 찍어주는 도구에 머무르지 않고 모든 폼 작업을 시스템화하는 경험을 만들고 싶다.
'프로그래밍 언어 > JSP' 카테고리의 다른 글
[JSP] JSTL 삼항 연산자 사용 시 문자열 연결 (0) | 2023.02.20 |
---|---|
[JSTL] Core Tag 활용 (0) | 2021.12.07 |
[JSP] JSTL taglib (0) | 2021.12.01 |