JSP를 사용하는 SpringMVC 프로젝트에서, Controller에서 넘긴 객체를 JSP에 바인딩해 HTML input, JavaScript 코드 등에 사용하려고 할 때 다음과 같은 질문들이 자연스럽게 생깁니다.
EL 표현식으로 JS에서 값을 비교하려 했는데 왜 에러가 날까??
title, content처럼 긴 텍스트나 ", \n, <script> 등이 섞인 데이터는 어떻게 넘겨야 안전할까??
이 글에서는 Controller에서 객체를 JSP로 안전하게 전달하고,
JavaScript에서도 문제 없이 활용할 수 있는 안정적인 방식을 제시합니다.
아래와 같이 Controller에서 model에 담아서 JSP로 전달했을 경우,
model.addAttribute("title", "나의 포트폴리오");
<input type="text" value="${title}" />
위와 같이 단순하게 사용하면 됩니다.
이 방식은 단순 출력용으로는 충분하지만,
JS에서 아래처럼 사용하면 문제가 생길 수 있습니다:
<script>
let title = ${title}; // 큰따옴표 없으면 JS 에러 발생 가능
</script>
아래와 같이 따옴표를 꼭 감싸야 합니다.
"${title}"
title, content가 긴 문자열일 경우
", <, >, \n 등이 포함되면 JS 파싱 에러 발생
JSON처럼 구조화된 데이터를 JS에서 쓰고 싶을 때
EL 표현식으로 하나씩 바인딩하는 건 번거롭고 유지보수도 힘듦
<script type="application/json">!본 글에서 설명하고 싶은 핵심입니다!
컨트롤러에서의 반환에서부터 시작하겠습니다!
먼저 Controller에서부터 그냥 반환하면 안됩니다.
ObjectMapper mapper = new ObjectMapper();
String portfolioJson = mapper.writeValueAsString(portfolioDTO);
model.addAttribute("portfolioJson", portfolioJson);
위와 같이 바로 반환하는 것이 아니라, ObjectMapper로 JSON으로 변환하여 반환합니다.
controller에서 JSON으로 전달한 객체를 일단 저장해야 합니다.
<script id="portfolio-data" type="application/json">
<c:out value="${portfolioJson}" escapeXml="false" />
</script>
type="application/json" - 데이터를 JS가 아니라 단순한 JSON으로 사용하기 위해 설정하였습니다.
id="..." - 자바스크립트에서 접근하기 위한 DOM id 를 지정해 주었습니다.
<c:out value="..." /> - null 값에 대한 예외가 생기지 않게 하기 위해서 사용했습니다.
escapeXml="false" -
JSP에서는 기본적으로 <, >, " 등의 문자가 HTML로 인식되는 걸 막기 위해 자동 이스케이프하기 때문에,
JSON 문자열의 따옴표 등을 이스케이프하지 않도록 하기 위해 사용했습니다.
저장된 객체는 아직 JSON 문자열에 불과합니다.
객체로 파싱을 해 주어야 합니다.
let portfolioDTO = null;
const portfolioDataElement = document.getElementById("portfolio-data");
if (portfolioDataElement) {
try {
portfolioDTO = JSON.parse(portfolioDataElement.textContent);
} catch (e) {
console.error("JSON 파싱 실패:", e);
}
}
위의 예시는 파싱에 실패했을 경우, error 로그가 나오도록 되어 있지만,
각자의 상황에 알맞는 조취를 취하시면 될 것 같습니다.
( catch문 안에 )
SpringMVC + JSP 환경에서 복잡한 데이터를 안정적으로 넘기고 싶다면,
JSON.stringify + JSON.parse 방식으로 넘기는 것이 안정적입니다!
특히 입력 폼, 수정 폼, 에디터처럼 사용자 입력이 많고 구조도 복잡한 경우에는
이 패턴을 활용해보세요!!