// DataController.java
@RestController
@RequestMapping("/api")
public class DataController {
@GetMapping("/products/{id}")
public ResponseEntity<Product> getProduct(@PathVariable String id) {
Product product = productService.findById(id);
return ResponseEntity.ok(product);
}
@GetMapping("/users")
public ResponseEntity<List<User>> getUsers(
@RequestParam(required = false) String department) {
List<User> users = userService.getUsersByDepartment(department);
return ResponseEntity.ok(users);
}
}
<%-- parentComponent.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" %>
<div id="parentContainer">
<h2>제품 정보 조회</h2>
<input type="text" id="productIdInput" placeholder="제품 ID 입력">
<button id="loadBtn">조회</button>
<div id="productDetailContainer"></div>
<div id="relatedProductsContainer"></div>
</div>
<script>
$(function() {
// API 호출 함수
function fetchProductData(productId) {
return $.ajax({
url: '/api/products/' + productId,
method: 'GET',
dataType: 'json'
});
}
// 자식 컴포넌트 로드 함수
function loadChildComponents(productData) {
// 제품 상세 정보 컴포넌트 로드
$('#productDetailContainer').load('/components/productDetail.jsp',
{ productJson: JSON.stringify(productData) },
function() {
console.log('제품 상세 컴포넌트 로드 완료');
}
);
// 연관 제품 컴포넌트 로드
if (productData.relatedProducts && productData.relatedProducts.length > 0) {
$('#relatedProductsContainer').load('/components/relatedProducts.jsp',
{ productsJson: JSON.stringify(productData.relatedProducts) }
);
}
}
// 조회 버튼 클릭 이벤트
$('#loadBtn').click(function() {
const productId = $('#productIdInput').val().trim();
if (!productId) return;
fetchProductData(productId)
.done(function(productData) {
loadChildComponents(productData);
})
.fail(function(xhr) {
alert('제품 조회 실패: ' + xhr.responseJSON?.message || xhr.statusText);
});
});
});
</script>
<%-- productDetail.jsp --%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<script>
// JSON 파싱 유틸리티 (XSS 방지)
function safeJsonParse(jsonStr) {
try {
const decoded = jsonStr.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/</g, '<')
.replace(/>/g, '>');
return JSON.parse(decoded);
} catch (e) {
console.error('JSON 파싱 오류', e);
return null;
}
}
// 제품 데이터 파싱
const product = safeJsonParse('${fn:escapeXml(param.productJson)}');
</script>
<div class="product-detail" data-product-id="${product.id}">
<h3>${product.name}</h3>
<div class="price-section">
<span class="price">${product.price.toLocaleString()}원</span>
<c:if test="${product.discountRate > 0}">
<span class="discount">${product.discountRate}% 할인</span>
</c:if>
</div>
<div class="description">
${product.description}
</div>
<div class="actions">
<button class="btn-cart" data-product-id="${product.id}">장바구니</button>
<button class="btn-buy" data-product-id="${product.id}">구매하기</button>
</div>
</div>
<script>
$(function() {
// 이벤트 핸들러 등록
$('.btn-cart').click(function() {
const productId = $(this).data('product-id');
addToCart(productId);
});
$('.btn-buy').click(function() {
const productId = $(this).data('product-id');
startPurchase(productId);
});
// 부모 컴포넌트와 통신
$(document).on('productUpdated', function(event, updatedProduct) {
if (updatedProduct.id === product.id) {
$('.price').text(updatedProduct.price.toLocaleString() + '원');
// 기타 UI 업데이트
}
});
});
// 장바구니 추가 함수
function addToCart(productId) {
$.post('/api/cart', { productId: productId })
.done(function() {
alert('장바구니에 추가되었습니다');
})
.fail(function(xhr) {
alert('오류: ' + xhr.responseJSON?.message);
});
}
</script>
<%-- relatedProducts.jsp --%>
<script>
const relatedProducts = JSON.parse('${fn:escapeXml(param.productsJson)}'
.replace(/"/g, '"')
.replace(/'/g, "'")
);
</script>
<div class="related-products">
<h4>함께 보면 좋은 상품</h4>
<div class="product-list">
<c:forEach items="${relatedProducts}" var="product">
<div class="product-item" data-product-id="${product.id}">
<img src="${product.thumbnailUrl}" alt="${product.name}">
<div class="info">
<h5>${product.name}</h5>
<p>${product.price.toLocaleString()}원</p>
</div>
</div>
</c:forEach>
</div>
</div>
<script>
$(function() {
$('.product-item').click(function() {
const productId = $(this).data('product-id');
// 부모 컴포넌트에 이벤트 전달
$(document).trigger('relatedProductSelected', {
productId: productId,
source: 'relatedProducts'
});
});
});
</script>
- 부모/자식 컴포넌트 통신
// 부모 컴포넌트에서 이벤트 리스너 등록
$(document).on('relatedProductSelected', function(event, data) {
// 연관 제품 선택 시 해당 제품 다시 로드
fetchProductData(data.productId)
.done(loadChildComponents);
});
// 자식 컴포넌트에서 이벤트 발생 예시
$(document).trigger('productUpdated', {
id: "P1001",
price: 120000,
// 기타 업데이트 필드
});