JAVA/Java

[servlet/jsp/jstl] 개행문자를 기준으로 나눠 반복 처리를 하는 방법

sihyeong 2023. 9. 13. 01:10

개요

  • servlet/jsp로 게시판 프로젝트를 진행하던 도중 게시글의 줄바꿈을 어떻게 처리해야하는가에 대한 궁금증이 생겨 가장 기본적인 방안인 <br>태그를 사용하는 것을 생각해 보았으나 개행문자를 <br>문자로 바꾸고 이런 저런 작업을 하게되면 XSS에 대한 보안 위험이 생길 수 있어 다른 방법을 찾아봤다.
  • 먼저 여러 사이트에서 게시글을 어떻게 처리하는지 알면 이 문제를 해결하는것에 도움이 될까 싶어서 티스토리의 게시글 처리 방법을 분석해 보니 개행문자를 기준으로 문자를 나누고 <p>태그로 감싸 처리했다. 스타일 처리도 가능하면서  <c:out value-" " />를 통해 XSS 위험도 막을 수 있어 이 방법을 사용하여 처리하기로 했다.

발생한 문제

첫번째 시도

<c:set var="boardData" value="${boardDTO.boardcontent}" />
<c:set var="contentWords" value="${fn:split(boardData, '\n')}" />
<c:forEach items="${contentWords}" var="word">
	<p style="white-space: pre-wrap"><c:out value="${word}" /></p>
</c:forEach>
  • 가장 처음 작성한 방법이다. 개행문자인 '\n'으로 나눈 뒤 반복하여 출력하려 했으나 이클립스에서 사용할 수 없는 코드라고 다음과 같은에러 메시지를 출력한다.
  • \를 사용할 수 없다는 메시지이다.

  • 당연하게도 위의 에러를 무시하고 실행하면 아래의 에러가 출력된다.
java.lang.IllegalArgumentException: 표현식 [${fn:split(boardData, '\n')}]은(는) 유효하지 않습니다. 인용되는 문자열 내에서는, 오직 [], ['] 그리고 ["] 만이 [] 을 사용하여 escape될 수 있습니다.

 


두번째 시도

  • \는 각종 특수문자를 출력하기 위해 사용하는 문자라서 사용을 못하는 것으로 판단하고 \를 출력하기 위해 c언어에서는 \\를 사용하기에 \\n과 같은 방식으로 테스트 해봤다.
<c:set var="contentWords" value="${fn:split(boardData, '\\n')}" />
  • 이클립스의 빨간줄만 없어졌지 \만을 사용한 것과 다를바 없다.
java.lang.IllegalArgumentException: 표현식 [${fn:split(boardData, '\n')}]은(는) 유효하지 않습니다. 인용되는 문자열 내에서는, 오직 [], ['] 그리고 ["] 만이 [] 을 사용하여 escape될 수 있습니다.

 


 

세번째 시도

  • EL 구문( ${ } )에서 " \ "문자를 제대로 처리하지 못하니 컨텐츠 값을 변수로 지정한 것 처럼 \n또한 변수로 지정하여 대입하여 사용했다.
<c:set var="CRLF" value="\n" />
<c:set var="boardData" value="${boardDTO.boardcontent}" />
<c:set var="contentWords" value="${fn:split(boardData, CRLF)}" />
<c:forEach items="${contentWords}" var="word">
    <p style="white-space: pre-wrap"><c:out value="${word}" /></p>
</c:forEach>
  • 이번에는 에러 없이 실행이 된다.
  • 하지만 원하던 실행 결과인 개행문자를 기준으로 <p>태그가 사용되지 않고, <p>태그 안에 모든 입력값들이 한번에 들어가 있다. 역시나 이번에도 \n 문자에서 문제가 생겼다.
  • <c:set var="CRLF" value="\\n" /> 또한 같은 결과가 출력되었다.

1개의 p태그가 모든 값을 가지고 있다.

 


해결

  • <c:set>태그는 JSTL의 태그에서 변수의 값을 처리할 때 사용하지만 \n와 같은 문자에 대해서는 처리하지 못한다. <c:set>과 비슷한 기능을 생각하다 JSP태그인 <% pageContext.setAttribute("newLineChar", "\n"); %>를 통해 처리하는 방법을 사용하게 되었다.
<% pageContext.setAttribute("newLineChar", "\n"); %>
<c:set var="boardData" value="${boardDTO.boardcontent}" />
<c:set var="contentWords" value="${fn:split(boardData, newLineChar)}" />
<c:forEach items="${contentWords}" var="word">
    <p style="white-space: pre-wrap"><c:out value="${word}" /></p>
</c:forEach>

  • 결과는 대 성공이다.

EL과 jstl의 \ 문자 리터럴 처리는 사용하기 꽤나 복잡하다.

우회 방법을 통해 \ 문자를 받아서 처리하자.


지금은 많이 쓰지 않는 기술이라 글로 남기는게 의미가 있나 싶지만, 성장 과정을 남김과 동시에, 누군가는 이 글을 보고 도움을 받았으면 하는 마음으로 글을 작성했다.