코딩항해기

[Error/Spring] 특정 검색 시 가게 검색 페이지 로딩 실패 본문

Error solution

[Error/Spring] 특정 검색 시 가게 검색 페이지 로딩 실패

miniBcake 2024. 10. 31. 11:12

 

종단으로 가게 검색 기능이 정상작동할 수 있게 연결하던 중 특정 검색어 검색 시 페이지가 로드되지 않으며 브라우저 콘솔에 인코딩 에러만 뜨는 문제가 발생했다.

Failed to load resource: net::ERR_INCOMPLETE_CHUNKED_ENCODING

 

콘솔창을 확인했을 때 데이터가 정상적으로 전달되고 있어 문제를 파악하기 어려웠다.

 

 

에러 발생 원인 특정

먼저 문제를 파악하기 위해 여러 검색을 시도하며 문제가 되는 상황을 정확하게 특정하고자 했다.

인코딩 에러가 발생하기 때문에 데이터를 의심했고, 데이터 자체가 인코딩이 불가능하거나 양이 많아 에러가 발생하는 경우일 가능성을 두고 검색을 시도했다.

 

1. 데이터가 2개 있는 '달' 검색 => 정상 검색

2. 데이터가 1개 있는 '행복' 검색 => 정상 검색

3. 데이터가 13개 있는 '붕', '붕어', '붕어빵' 검색 => error

 

여기까지 테스트 했을 때는 데이터의 양이 많아서 로드 실패가 걸리는게 아닐까 의심이 들었지만 첫 페이지 로드 때 4페이지까지 로드 되고 페이지네이션까지 다 진행되는데다가 이미 Model에서 데이터를 잘라서 주기 때문에 해당 부분이 원인이라기엔 여전히 애매한 상태였다. 

 

그래서 정상검색되는 '달'의 데이터를 늘려보기로 했다.

 

달을 포함하는 가게가 5개를 넘어가는 순간 검색 실패로 넘어가는 것을 확인했다. 

페이지가 2장 이상이 될 때 문제가 발생하는 것이다.

 

문제 원인 찾기

페이지가 여러 장 됐을 때 문제가 발생하기 때문에 먼저 페이지네이션 부분의 코드를 전부 주석처리하고 실행했다.

그러자 모든 검색이 정상적으로 로드되는 것을 확인할 수 있었다. (페이지 변경은 url로 직접 지정)

 

문제 원인이 페이지네이션 코드에 있다는 것을 확인할 수 있었다. 그렇다면 대체 왜....

 

정확한 문제 원인 찾기

<!-- 페이지네이션 -->
<section id="pagination">
	<div class="pagination">
		<!-- 이전 페이지 버튼 -->
		<c:if test="${page > 1}">
			<a
					href="?page=${page - 1}${keyword != null ? '&keyword='+keyword : ''}"
					id="pagenationPreValue">&laquo; 이전</a>
		</c:if>

		<c:set var="startPage" value="${page - 5}" />
		<c:set var="endPage" value="${page + 4}" />
		<c:out value="startPage: ${startPage}, endPage: ${endPage}, totalPage: ${totalPage}" />

		<c:if test="${startPage < 1}">
			<c:set var="startPage" value="1" />
		</c:if>
		<c:if test="${endPage > totalPage}">
			<c:set var="endPage" value="${totalPage}" />
		</c:if>
		<c:out value="startPage: ${startPage}, endPage: ${endPage}, totalPage: ${totalPage}" />
		<c:forEach var="i" begin="${startPage}" end="${endPage}">
			<c:choose>
				<c:when test="${i == page}">
					<strong>${i}</strong>
				</c:when>
				<c:otherwise>
					<a
							href="?page=${i}${keyword != null ? '&keyword='+keyword : ''}"
							class="pagenationValue">${i}</a>
				</c:otherwise>
			</c:choose>
		</c:forEach>

		<c:if test="${page < totalPage}">
			<a
					href="?page=${page + 1}${keyword != null ? '&keyword='+keyword : ''}"
					id="pagenationNextValue">다음 &raquo;</a>
		</c:if>
	</div>
</section>
<!-- 페이지네이션 종료 -->

 

인코딩 에러라는 말에 낚여 startPage와 endPage를 의심하게 됐다. 해당 값이 정상적으로 반영되고 있는지 확인하기 위해 c:out으로 해당 값을 전부 찍어보기로 했다.

 

다행히 이때부터 이유는 정확히 알 수 없지만 '붕어'가 비 정상적으로라도 검색이 되기 시작해서 c:out으로 확인한 것이다.

 

 

총 3번 c:out을 찍어 확인하는데 정상적으로 값이 완성되는 것을 확인할 수 있었다. 그런데 총 페이지가 4까지 로드되어야하는데, 1에서 멈추는 것을 확인할 수 있었다. 다음 버튼로 로딩되지 않는다.

 

<c:forEach var="i" begin="${startPage}" end="${endPage}">
	<c:choose>
		<c:when test="${i == page}">
			<strong>${i}</strong>
		</c:when>
		<c:otherwise>
			<a href="?page=${i}${keyword != null ? '&keyword='+keyword : ''}"
					class="pagenationValue">${i}</a>
		</c:otherwise>
	</c:choose>
</c:forEach>

 

이 부분이 버튼을 출력하는 로직인데 EL식이 의심되어 keyword EL식을 한 번 지워보고 실행해보았다. 그러자... 정상 작동되는 것을 알 수 있었다. 범인은 keyword EL식이었다....... 

 

문제 원인 파악 해결하기

해당 문제가 일어난 이유를 알기 위해 여러 검색을 해보니 url에 바로 raw 한글 데이터를 넣으면 인코딩 에러가 발생한다고 한다. url에 담아서 보내는 방식 변경해거나 인코딩을 진행해 해결해야한다. 더 찾아보니 JSTL을 사용해 url을 완성하는 방식이 있어 해당 방식을 적용하니 정상적으로 키워드가 유지되며 검색이 진행되는 것을 확인할 수 있었다.

<c:forEach var="i" begin="${startPage}" end="${endPage}">
	<c:choose>
		<c:when test="${i == page}">
			<strong>${i}</strong>
		</c:when>
		<c:otherwise>
			<c:url var="pageLink" value="">
				<c:param name="page" value="${i}"/>
				<c:if test="${keyword != null}">
					<c:param name="keyword" value="${keyword}"/>
				</c:if>
			</c:url>
			<a href="${pageLink}" class="pagenationValue">${i}</a>
		</c:otherwise>
	</c:choose>
</c:forEach>

 

또는 현재 쿼리스트링을 받아와서 사용하는 방법도 있다.

<c:set var="queryString" value="${pageContext.request.queryString}" />
<c:set var="queryWithNewPage" value="${fn:replace(queryString, 'page='+=page, 'page='+=i)}" />
<a href="?${queryWithNewPage}" class="pagenationValue">${i}</a>