배경 및 문제 정의
Spring MVC 프로젝트에서 JSP 화면의 JavaScript에 서버 데이터를 전달해야 하는 상황이 생겼다.

Controller에서 Model에 Java 객체를 담아 넘겼는데,
JavaScript에서 이 데이터를 인식하지 못하는 문제가 발생했다.
Java 객체를 그대로 Model에 담으면
JavaScript는 [MemberDto@abc123] 같은 toString() 결과만 볼 수 있었고,
이를 JSON 형태로 변환해야 정상적으로 사용할 수 있다는 걸 알게 됐다.
결국 Jackson 라이브러리의 ObjectMapper를 활용해
Java 객체를 JSON 문자열로 변환하는 방식으로 해결했다.
최종 해결 요약
Jackson 라이브러리의
ObjectMapper.writeValueAsString() 메서드를 사용해
Java 객체를 JSON 문자열로 변환한 뒤
Model에 담아 JSP로 전달했다.
JavaScript에서는 이 JSON 문자열을
JSON.parse()로 파싱해 객체로 활용했다.
핵심 코드 흐름은 다음과 같다:
[Controller]
List<MemberDto> → ObjectMapper.writeValueAsString() → JSON 문자열 → Model에 담기
[JSP]
${memberListJson} → JSON.parse() → JavaScript 객체로 활용
시도한 방법들
시도 1: Java 객체를 그대로 Model에 담기 (실패)

시도한 이유
처음에는 단순하게 생각했다.
Controller에서 Java 객체를 Model에 담으면
JSP에서 바로 쓸 수 있지 않을까?
적용 방법
@Controller
public class MemberController {
@GetMapping("/members")
public String getMembers(Model model) {
List<MemberDto> memberList = memberService.findAllMembers();
model.addAttribute("memberList", memberList);
return "member/list";
}
}
JSP에서 JavaScript로 직접 사용하려고 했다:
<script>
var members = ${memberList}; // 여기서 문제 발생
console.log(members);
</script>
문제점/한계
브라우저 콘솔에 구문 오류가 발생했다.
${memberList}가 [MemberDto@abc123, MemberDto@def456]처럼
Java 객체의 toString() 결과로 렌더링됐기 때문이다.
JavaScript는 이런 형식을 이해하지 못한다.
참고로 JSP의 JSTL/EL에서는 Java 객체를 직접 다룰 수 있다.
<c:forEach> 같은 태그로 반복 처리가 가능하다.
하지만 <script> 태그 안의 JavaScript는 Java 객체를 인식할 수 없다.
배운 점
JSP 서버 사이드 렌더링(JSTL/EL)과 클라이언트 사이드(JavaScript)는 데이터 처리 방식이 다르다
JavaScript에서 사용하려면 JSON 형식으로 변환이 필요하다
시도 2: ObjectMapper로 JSON 문자열 변환 후 전달 (성공)

시도한 이유
JavaScript가 이해할 수 있는 형식은 JSON이다.
Java 객체를 JSON 문자열로 변환하면
JavaScript에서 파싱해서 쓸 수 있을 거라 판단했다.
적용 방법
먼저 DTO 클래스를 준비했다.
Jackson이 직렬화/역직렬화를 수행하려면 기본 생성자와 getter/setter가 필요하다:
package com.example.dto;
public class MemberDto {
private String memberId;
private String memberName;
private int age;
// 기본 생성자 (Jackson 역직렬화에 필요)
public MemberDto() {
}
// 모든 필드를 받는 생성자
public MemberDto(String memberId, String memberName, int age) {
this.memberId = memberId;
this.memberName = memberName;
this.age = age;
}
// Getters
public String getMemberId() {
return memberId;
}
public String getMemberName() {
return memberName;
}
public int getAge() {
return age;
}
// Setters
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public void setMemberName(String memberName) {
this.memberName = memberName;
}
public void setAge(int age) {
this.age = age;
}
}
Controller에서 ObjectMapper를 사용해 JSON 문자열로 변환했다:
package com.example.controller;
import com.example.dto.MemberDto;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.ArrayList;
import java.util.List;
@Controller
public class MemberController {
private final ObjectMapper objectMapper;
// 생성자 주입 (ObjectMapper는 Spring Boot에서 자동으로 빈 등록됨)
public MemberController(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@GetMapping("/members")
public String getMembers(Model model) throws JsonProcessingException {
// 테스트용 데이터 생성
List<MemberDto> memberList = new ArrayList<>();
memberList.add(new MemberDto("M001", "홍길동", 28));
memberList.add(new MemberDto("M002", "김철수", 32));
memberList.add(new MemberDto("M003", "이영희", 25));
// Java 객체 → JSON 문자열 변환
String memberListJson = objectMapper.writeValueAsString(memberList);
// Model에 JSON 문자열 담기
model.addAttribute("memberListJson", memberListJson);
return "member/list";
}
}
JSP에서 JSON 문자열을 JavaScript 객체로 파싱해서 사용했다:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<title>회원 목록</title>
</head>
<body>
<h1>회원 목록</h1>
<div id="memberContainer"></div>
<script>
// JSON 문자열을 JavaScript 객체로 파싱
var memberList = JSON.parse('${memberListJson}');
console.log(memberList);
// 출력: [{memberId: "M001", memberName: "홍길동", age: 28}, ...]
// 데이터 활용 예시
var container = document.getElementById('memberContainer');
memberList.forEach(function(member) {
var div = document.createElement('div');
div.textContent = member.memberName + ' (' + member.age + '세)';
container.appendChild(div);
});
</script>
</body>
</html>
결과
브라우저 콘솔에 JavaScript 배열 객체가 정상 출력됐다.
memberList[0].memberName으로 각 속성에 접근할 수 있게 됐다.
배운 점
ObjectMapper는 Jackson 라이브러리의 핵심 클래스로, JSON 직렬화/역직렬화를 담당한다writeValueAsString()메서드로 Java 객체를 JSON 문자열로 변환할 수 있다
Spring Boot 환경에서는ObjectMapper가 자동으로 빈 등록되므로 주입받아 사용하면 된다
실행 가능한 테스트 코드
아래 테스트 코드로 ObjectMapper의 동작을 직접 확인할 수 있다:
package com.example.blog;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class ObjectMapperTest {
/**
* 테스트용 DTO 클래스
*/
static class MemberDto {
private String memberId;
private String memberName;
private int age;
public MemberDto() {
}
public MemberDto(String memberId, String memberName, int age) {
this.memberId = memberId;
this.memberName = memberName;
this.age = age;
}
public String getMemberId() { return memberId; }
public String getMemberName() { return memberName; }
public int getAge() { return age; }
public void setMemberId(String memberId) { this.memberId = memberId; }
public void setMemberName(String memberName) { this.memberName = memberName; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "MemberDto{memberId='" + memberId + "', memberName='" + memberName + "', age=" + age + "}";
}
}
@Test
@DisplayName("Java 객체를 JSON 문자열로 변환 (직렬화)")
void testSerializeObjectToJson() throws JsonProcessingException {
// given
ObjectMapper mapper = new ObjectMapper();
MemberDto member = new MemberDto("M001", "홍길동", 28);
// when
String jsonString = mapper.writeValueAsString(member);
// then
System.out.println("=== 단일 객체 직렬화 결과 ===");
System.out.println(jsonString);
// 출력: {"memberId":"M001","memberName":"홍길동","age":28}
assertNotNull(jsonString);
assertTrue(jsonString.contains("\"memberId\":\"M001\""));
}
@Test
@DisplayName("Java List를 JSON 배열 문자열로 변환")
void testSerializeListToJson() throws JsonProcessingException {
// given
ObjectMapper mapper = new ObjectMapper();
List<MemberDto> memberList = new ArrayList<>();
memberList.add(new MemberDto("M001", "홍길동", 28));
memberList.add(new MemberDto("M002", "김철수", 32));
// when
String jsonArrayString = mapper.writeValueAsString(memberList);
// then
System.out.println("=== List 직렬화 결과 ===");
System.out.println(jsonArrayString);
// 출력: [{"memberId":"M001","memberName":"홍길동","age":28},{"memberId":"M002","memberName":"김철수","age":32}]
assertTrue(jsonArrayString.startsWith("["));
assertTrue(jsonArrayString.endsWith("]"));
}
@Test
@DisplayName("JSON 문자열을 Java 객체로 변환 (역직렬화)")
void testDeserializeJsonToObject() throws JsonProcessingException {
// given
ObjectMapper mapper = new ObjectMapper();
String jsonString = "{\"memberId\":\"M001\",\"memberName\":\"홍길동\",\"age\":28}";
// when
MemberDto member = mapper.readValue(jsonString, MemberDto.class);
// then
System.out.println("=== 역직렬화 결과 ===");
System.out.println(member);
assertEquals("M001", member.getMemberId());
assertEquals("홍길동", member.getMemberName());
assertEquals(28, member.getAge());
}
@Test
@DisplayName("JSON 배열을 Java List로 변환")
void testDeserializeJsonArrayToList() throws JsonProcessingException {
// given
ObjectMapper mapper = new ObjectMapper();
String jsonArray = "[{\"memberId\":\"M001\",\"memberName\":\"홍길동\",\"age\":28}," +
"{\"memberId\":\"M002\",\"memberName\":\"김철수\",\"age\":32}]";
// when
List<MemberDto> memberList = mapper.readValue(
jsonArray,
mapper.getTypeFactory().constructCollectionType(List.class, MemberDto.class)
);
// then
System.out.println("=== List 역직렬화 결과 ===");
memberList.forEach(System.out::println);
assertEquals(2, memberList.size());
assertEquals("홍길동", memberList.get(0).getMemberName());
}
}
@Controller vs @RestController 비교
참고로, REST API를 개발할 때는
ObjectMapper를 직접 쓸 필요가 없다.
@RestController를 사용하면 Spring이 자동으로 JSON 변환을 처리해준다.
| 구분 | @Controller + Model | @RestController |
|---|---|---|
| 용도 | JSP 등 View 렌더링 | REST API 응답 |
| JSON 변환 | ObjectMapper 직접 사용 | Spring이 자동 처리 |
| 응답 형태 | HTML 페이지 | JSON 데이터 |
// REST API 방식 - Java 객체를 그대로 반환하면 Spring이 자동으로 JSON 변환
@RestController
public class MemberApiController {
@GetMapping("/api/members")
public List<MemberDto> getMembers() {
List<MemberDto> memberList = new ArrayList<>();
memberList.add(new MemberDto("M001", "홍길동", 28));
memberList.add(new MemberDto("M002", "김철수", 32));
return memberList; // 자동으로 JSON 변환됨
}
}

정리 및 배운 점
- JSP 서버 사이드(JSTL)에서 사용할 데이터: Java 객체 그대로
Model에 담는다 - JavaScript에서 사용할 데이터:
ObjectMapper.writeValueAsString()으로 JSON 문자열로 변환 후Model에 담는다 - REST API 개발 시:
@RestController를 사용하면 Spring이 자동으로 JSON 변환을 처리한다
ObjectMapper는 성능상 인스턴스를 재사용하는 게 좋다.
Spring Boot 환경에서는 자동으로 빈 등록되므로 주입받아 사용하면 된다.