본문 바로가기
개발노트

JSP에서 페이지별 JS 모듈을 invoke로 효율적으로 호출하는 방법

by SoonNote 2025. 4. 15.
반응형

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>

 

 

🔄 실행 흐름 정리

  1. JSP에서 JS 파일 로딩 후 invoke() 호출
  2. 객체 이름(SampleMain)으로 전역 객체 탐색
  3. userData, listData 같은 속성을 세팅
  4. 객체 내부의 init() 함수 자동 실행

 

✅ 이 구조의 장점

장점설명
🧩 JS 모듈화 각 기능별로 JS 객체 분리 가능
📦 공통 호출 test.invoker.invoke()로 구조 통일
🔗 서버 연동 용이 ${}를 통해 JSP에서 JS로 데이터 전달 가능
🛡️ 에러 방지 init 미존재 시 경고 출력

 

💡 응용 가능한 곳

  • 페이지마다 다른 JS 모듈이 필요한 프로젝트
  • JSP에 너무 많은 JS 코드를 넣기 싫을 때
  • 로그인/게시판/관리자 페이지 등 기능별 분리 설계

 

🧩 확장 아이디어

  • destroy(), reload() 같은 메서드 추가로 라이프사이클 관리
  • 모듈 자동 로딩(invokeAll) 기능으로 발전
  • async/await 패턴에 맞는 비동기 초기화 대응

✅ 마무리

이 방식은 JSP 환경에서 JS 모듈을 깔끔하게 초기화하고,
중복 없이 코드 구조를 유지하고 싶은 분들에게 매우 유용한 패턴.

반응형