개발/[Spring] 블로그 만들기

[코드로 배우는 스프링 웹 프로젝트] 26강. 게시물의 조회와 첨부파일

ee2ee2 2022. 10. 2. 00:48
728x90
반응형

해당 프로젝트는 코드로 배우는 스프링 웹 프로젝트(개정판)을 기반으로 진행됩니다.


게시물의 조회에서는 첨부파일을 다운로드하거나 원본 이미지의 파일을 볼 수 있는 기능을 구현할 것이다. 게시물을 조회하는 방법에서는 아래 두 가지 방법 중 결정이 필요하다.

게시물의 정보는 tbl_board, 첨부파일의 정보는 tbl_attach 에 기록되어있다.

  • BoardVO 객체를 가져올 때 join을 처리해서 한꺼번에 게시물과 첨부파일의 정보를 같이 처리하는 방식 (데이터베이스를 한 번만 호출하게 되므로 효율적이지만, MyBatis 쪽에서 처리해야하는 일이 많아짐)
  • JSP에서 첨부파일 정보를 Ajax를 이용해서 처리하는 방식 (다시 쿼리해야하는 불편함이 있지만, 난이도가 낮고 화면에서 처리는 JavaScript 처리가 복잡해짐)

먼저 Ajax를 이용하는 방식을 사용해서 구현해 볼 것이다. 앞서 개발해둔 예제를 활용할 수 있을 뿐더러, 댓글의 처리 역시 Ajax를 이용했으므로 일관성을 유지하기 위해서다.


26.1 BoardService와 BoardServiceImpl 수정

BoardService.java

BoardAttachMapper에서 이미 게시물의 번호를 이용해서 BoardAttachVO 타입으로 변환하는 메소드 findByBno()를 구현해놨으므로, BoardService와 BoardServiceImpl에서도 사용할 수 있도록 추가한다.

import org.zerock.domain.BoardAttachVO;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;

public interface BoardService {
	
...생략
	
	public List<BoardAttachVO> getAttachList(Long bno);
}

BoardServiceImpl.java

	@Override
	public List<BoardAttachVO> getAttachList(Long bno) {
		log.info("get Attach list by bno : " + bno);
		return attachMapper.findByBno(bno);
	}

26.2  BoardController의 변경과 화면 처리

BoardController는 특정한 게시물 번호를 이용해서 첨부파일과 관련된 데이터를 JSON 으로 반환라도록 처리한다.

BoardController.java

	//특정한 게시물 번호의 첨부파일과 관련된 데이터를 JSON으로 반환하는 메소드
	@GetMapping(value="/getAttachList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	@ResponseBody
	public ResponseEntity<List<BoardAttachVO>> getAttachList(Long bno) {
		log.info("getAttachList : " + bno);
		
		return new ResponseEntity<>(service.getAttachList(bno), HttpStatus.OK);
	}

26.2.1 게시물 조회 화면의 처리

get.jsp 내에 <script>태그를 추가하고, $(document).ready()를 이용해서 첨부파일의 데이터를 가져오는 부분을 즉시 실행 함수를 이용해서 처리한다.

get.jsp

<script>
$(document).ready(function(){
	(function(){
		var bno = '<c:out value="${board.bno}"/>';
		
		$.getJSON("/board/getAttachList", {bno:bno}, function(arr) {
			console.log(arr);
		}); //end getJSON
	})(); //end function
});
</script>

실행 결과

해당 게시글에 등록된 첨부파일 리스트를 갖고 오는 것을 확인할 수 있음.

 

첨부파일을 위와 같이 갖고왔다면 파일들을 보여줄 수 있는 <div>를 생성한다. 기존의 게시물이 보여지는 <div class='row'>의 아래쪽에 별도의 <div calss='row'>를 생성해서 처리한다.

get.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%@include file="../includes/header.jsp" %>
<style><%@ include file="/WEB-INF/views/includes/uploadAjax.css" %></style>

            <div class='bigPictureWrapper'>
                <div class='bigPicture'>
                </div>
            </div>
            <div class="row">
                <div class="col-lg-12">
                    <h1 class="page-header">Board Register</h1>
                </div>
                <!-- /.col-lg-12 -->
            </div>

..생략

                <!-- 첨부파일 목록 -->
                <div class="row">
                	<div class="col-lg-12">
                		<div class="panel panel-default">
	                		<div class="panel-heading">Files</div>
	                		<!-- /.panel-heading -->
	                		<div class="panel-body">
	                			<div class='uploadResult'>
	                				<ul>
	                				</ul>
	                			</div>
	                		</div>
	                		<!-- end panel body -->
	                	</div>
	                	<!-- end panel body -->
	                </div>
	                <!-- end panel -->
                </div>
                <!-- end row -->

실행 결과

첨부파일을 확인할 수 있는 칸이 생김을 확인.


26.2.2 첨부파일 보여주기

첨부파일 칸이 생겼으니 이제 보여줘보자! JSON으로 가져온 첨부파일 데이터는 작성된 <div>안에서 보이도록 처리해줘야 한다. 전달된 JSON 데이터는 BoardAttachVO 객체이다.

get.jsp

<script>
$(document).ready(function(){
	(function(){
		var bno = '<c:out value="${board.bno}"/>';
		
		$.getJSON("/board/getAttachList", {bno:bno}, function(arr) {
			console.log(arr);
			
			var str ="";
			
			$(arr).each(function(i, attach){
				//image Type
				if(attach.fileType) {
					var fileCallPath = encodeURIComponent(attach.uploadPath+"/s_"+attach.uuid+"_"+attach.fileName);
					
					str += "<li data-path='" + attach.uploadPath + "'";
					str += " data-uuid='" + attach.uuid + "' data-filename='" + attach.fileName + "' data-type='" + attach.fileType + "' ><div>";
					str += "<img src='/display?fileName=" + fileCallPath + "'>";
					str += "</div>";
					str + "</li>";
				} else {
					str += "<li data-path='" + attach.uploadPath + "'";
					str += " data-uuid='" + attach.uuid + "' data-filename='" + attach.fileName + "' data-type='" + attach.fileType + "' ><div>";
					str += "<span>" + attach.fileName + "</span><br/>";
					str += "<img src='/resources/img/attach.png'>";
					str += "</div>";
					str + "</li>";
				}
			});
			
			$(".uploadResult ul").html(str);
		}); //end getJSON
	})(); //end function
});
</script>

실행 결과

현재 게시글에 등록된 첨부파일이 보임.

get.jsp 내에 추가되는 <div>는 크게 첨부파일의 목록을 보여주는 <div class='uploadResult'>와 원본 이미지를 보여주는 <div class='bigPicture'> 부분이다.


26.2.3 첨부파일 클릭 시 이벤트 처리

첨부파일 목록이 보인다면 이미지 파일의 경우 화면에서 원본 이미지, 일반 파일의 경우에는 다운로드 처리가 필요하다.

get.jsp

첨부파일과 관련된 정보는 모두 <li> 태그 내에 존재하므로 이를 이용해서 이미지 파일과 일반 파일을 구분한다.

..생략

			$(".uploadResult ul").html(str);
		}); //end getJSON
	})(); //end function
	
	
	$(".uploadResult").on("click", "li", function(e){
		console.log("view Image");
		
		var liObj = $(this);
		
		var path = encodeURIComponent(liObj.data("path")+"/"+liObj.data("uuid")+"_"+liObj.data("filename"));
		
		if(liObj.data("type")) {
			showImage(path.replace(new RegExp(/\\/g), "/")); //파일 경로의 경우 함수로 전달 될 때 문제가 생기므로 replace()를 이용해서 변환한 뒤에 전달한다.
		} else {
			self.location = "/download?fileName="+path;
		}
	});
	
	function showImage(fileCallPath){
		alert(fileCallPath);
		
		$(".bigPictureWrapper").css("display","flex").show();
		
		$(".bigPicture").html("<img src='/display?fileName="+fileCallPath+"'>").animate({width:'100%', height:'100%'}, 1000);
	}
});
</script>

실행 결과

showImage()는 해당 경로의 이미지를 보여주는 역할을 한다.

화면에서 첨부파일 이미지를 클릭했을 때 크게 보이게 된다.

이미지가 아닌 일반 파일의 경우 다운로드가 된다.


26.2.4 원본 이미지 창 닫기

게시물의 조회에서 마지막 처리는 원본 이미지가 보이는 창을 닫는 작업이다. 위의 예제에서 클릭시 show()를 통해 보였다면, 다시 클릭 시 hide()를 통해 <div>를 감추어 처리한다.

get.jsp

	
	$(".bigPictureWrapper").on("click", function(e){
		$(".bigPicture").animate({width:'0%', height:'0%'}, 1000);
		
		setTimeout(function(){
			$(".bigPictureWrapper").hide();
		}, 1000);
	});
반응형

다음 게시글은 게시물의 삭제에 대한 처리다! 늦지않게 얼른 게시글을 올려야짓 :)