반응형

JSP 기반 프로젝트에서
페이지마다 JS 파일을 독립적으로 구성하면서
공통된 방식으로 초기화하는 패턴이 필요할 때가 있다.
이 글에서는 invoker 객체를 통해
JSP → JavaScript 객체를 호출하고 데이터를 전달하는 방식을
샘플 예제와 함께 작성.
✅ 이런 구조가 필요한 이유
- ✅ JS 모듈을 기능별로 분리하고 싶을 때
- ✅ JSP에서 서버 데이터를 JS로 넘겨야 할 때
- ✅ 페이지마다 init 함수를 호출하는 반복 코드를 통일하고 싶을 때
📁 예시 구성
resources/
├── js/
│ ├── test.js ← 공통 invoker 정의
│ ├── sampleMain.js ← 메인 페이지용 모듈
│ └── sampleList.js ← 리스트 페이지용 모듈
webapp/
├── sampleMain.jsp
└── sampleList.jsp
✅ 1. test.js – 공통 invoker 정의
var test = test || {};
test.invoker = {
invoke: function(scriptName, varName, jsonStr) {
var invoker = new ScriptInvoker(scriptName);
invoker.setAttribute(varName, jsonStr);
invoker.invoke();
}
};
function ScriptInvoker(scriptName) {
this.scriptName = scriptName;
this.scriptObject = window[scriptName];
}
ScriptInvoker.prototype.setAttribute = function(varName, value) {
if (this.scriptObject && varName) {
this.scriptObject[varName] = value;
}
};
ScriptInvoker.prototype.invoke = function() {
if (this.scriptObject && typeof this.scriptObject.init === 'function') {
this.scriptObject.init();
} else {
console.warn("[invoke] '" + this.scriptName + "'의 init 함수가 존재하지 않습니다.");
}
};
✅ 2. sampleMain.js – 메인 페이지 전용 모듈
var SampleMain = {
userData: {},
init: function() {
console.log("[SampleMain] init 실행됨");
console.log("userData:", this.userData);
}
};
✅ 3. sampleList.js – 리스트 페이지 전용 모듈
var SampleList = {
listData: [],
init: function() {
console.log("[SampleList] init 실행됨");
this.listData.forEach(item => {
console.log(`ID: ${item.id}, 제목: ${item.title}`);
});
}
};
✅ 4. sampleMain.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %>
<!DOCTYPE html>
<html>
<head>
<title>SampleMain</title>
<script src="${pageContext.request.contextPath}/resources/js/test.js"></script>
<script src="${pageContext.request.contextPath}/resources/js/sampleMain.js"></script>
<script>
$(function(){
test.invoker.invoke("SampleMain", "userData", {
userId: "${sessionScope.user.id}",
userName: "${sessionScope.user.name}"
});
});
</script>
</head>
<body>
<h2>SampleMain.jsp</h2>
</body>
</html>
✅ 5. sampleList.jsp
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %>
<!DOCTYPE html>
<html>
<head>
<title>SampleList</title>
<script src="${pageContext.request.contextPath}/resources/js/test.js"></script>
<script src="${pageContext.request.contextPath}/resources/js/sampleList.js"></script>
<script>
$(function(){
test.invoker.invoke("SampleList", "listData", [
{ id: 1, title: "공지사항 1" },
{ id: 2, title: "공지사항 2" }
]);
});
</script>
</head>
<body>
<h2>SampleList.jsp</h2>
</body>
</html>
🔄 실행 흐름 정리
- JSP에서 JS 파일 로딩 후 invoke() 호출
- 객체 이름(SampleMain)으로 전역 객체 탐색
- userData, listData 같은 속성을 세팅
- 객체 내부의 init() 함수 자동 실행
✅ 이 구조의 장점
장점설명
| 🧩 JS 모듈화 | 각 기능별로 JS 객체 분리 가능 |
| 📦 공통 호출 | test.invoker.invoke()로 구조 통일 |
| 🔗 서버 연동 용이 | ${}를 통해 JSP에서 JS로 데이터 전달 가능 |
| 🛡️ 에러 방지 | init 미존재 시 경고 출력 |
💡 응용 가능한 곳
- 페이지마다 다른 JS 모듈이 필요한 프로젝트
- JSP에 너무 많은 JS 코드를 넣기 싫을 때
- 로그인/게시판/관리자 페이지 등 기능별 분리 설계
🧩 확장 아이디어
- destroy(), reload() 같은 메서드 추가로 라이프사이클 관리
- 모듈 자동 로딩(invokeAll) 기능으로 발전
- async/await 패턴에 맞는 비동기 초기화 대응
✅ 마무리
이 방식은 JSP 환경에서 JS 모듈을 깔끔하게 초기화하고,
중복 없이 코드 구조를 유지하고 싶은 분들에게 매우 유용한 패턴.
반응형
'개발노트' 카테고리의 다른 글
| JavaScript에서 옵저버 패턴을 활용한 클릭 이벤트 흐름 (1) | 2025.04.15 |
|---|---|
| JSP + Mustache.js + Ajax로 동적으로 데이터 렌더링하기 (0) | 2025.04.15 |
| [javascript] DateRangePicker 달력 라이브러리 (0) | 2024.09.27 |
| [restAPI] @restcontroller API converter 오류 (0) | 2024.07.05 |
| [Github Pages] 깃허브 페이지(github.io) 만들기 (0) | 2024.06.25 |