Kim VamPa

[Spring][쇼핑몰 프로젝트][29] 상품 이미지 수정 - 1(이미지 출력) 본문

스프링 프레임워크/쇼핑몰 프로젝트

[Spring][쇼핑몰 프로젝트][29] 상품 이미지 수정 - 1(이미지 출력)

Kim VamPa 2021. 7. 13. 16:30
728x90
반응형
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188

 

목표

이미지 수정 구현

 이미지 수정 기능 구현을 위한 전체적인 방향에 대해 생각해보고, 상품 수정 페이지에서 이미지가 출력을 목표로 합니다. 

 

 

 

순서

1. 방향

2. 수정 페이지 이미지 출력 

 

 

 

1. 방향

 우리가 구현하고자 하는 바는 사용자가 상품 수정 페이지에서 기존의 상품의 이미지가 없다면 새로운 이미지를 등록하고, 기존의 이미지가 있다면 새로운 이미지를 등록 한 뒤 '수정 버튼'을 누르면 새로 추가하거나 수정 해준 이미지가 DB와 서버에 저장되는 것입니다.

 

 이미지 수정 기능 구현은 기존 수정 구현때와 같이 데이터를 수정해주는 것과 다르게 기존의 이미지 데이터를 삭제하고 추가해주는 작업입니다. 이미지 수정을 크게 실제 '이미지'가 저장되는 서버와 '이미지 정보'가 저장되는 DB 2 가지 측면으로 생각해보겠습니다.

 


 

 먼저 DB 측면에서 생각해보겠습니다. DB측면에서는 기존의 데이터를 어떻게 삭제하고 어떻게 새로운 데이터들을 추가해줄지 생각해보아야 하는데 두 가지 방식으로 처리가 가능하다고 생각합니다. 첫 번째 방식은 일일이 vam_image 테이블에서 삭제할 이미지를 행 하나하나를 찾은 후 새로 추가할 이미지 정보가 담긴 행을 추가해주는 것입니다. 두 번째 방식은 vam_image 테이블에서 수정하고자 하는 상품과 관련된 행을 모두 지우고 새로 추가 할 이미지 정보와 기존에 존재 해야할 이미지 정보가 담긴 행을 추가 해주는 방식입니다.

 

 두 번째 방식이 좀 더 효율적이고 코드 작성하기도 간편합니다. 현재의 프로젝트에서의 상품 이미지는 한 개 만 처리할 것이기 때문에 두 가지 방식은 크게 차이가 없습니다. 하지만 만약 여러 개의 이미지를 등록을 할 수 있고 수정할 수 있는 경우 크게 차이가 나게 됩니다. 

 

 첫 번째 방식의 경우 뷰에서 삭제할 이미지 정보를 선별해서 서버로 전송 한 뒤 전송받은 이미지 정보에 근거하여 해당 행만을 일일이 찾아서 지워줍니다. 그리고 난 후 새로 추가해야 할 이미지 정보만 따로 뷰로부터 전달받아서 테이블에 행을 추가해주어야 합니다.

 

 두 번째 방식의 경우는 뷰에서 삭제할 이미지 정보를 별도로 전달받지 않고 수정할 대상 상품과 관련된 이미지 정보를 모두 지워줍니다. 그리고 기존에 존재해야 할 이미지 정보와 새로 추가한 이미지 정보를 뷰로 전달받아 테이블에 행들을 새롭게 추가해주는 것입니다. 

 

 저는 두 가지 방식 중 두 번째 방식으로 구현할 것입니다. 

 


 다음은 서버 측면입니다. 서버 측면에서 곰곰이 생각할 부분은 어떠한 타이밍에 서버에 저장된 파일을 삭제하고 추가해줄 것인가입니다.

 

 제일 단순한 방식은 수정 페이지에서 이미지 삭제 버튼을 누르면 서버의 이미지가 삭제가 되고, 이미지 추가 버튼을 누르면 서버의 이미지가 저장되는 방식입니다. 하지만 이러한 방식은 사용자가 정확히 개발자의 의도에 맞게 행동해야만 한다는 문제점이 있습니다.

 

 예를 들어서 사용자가 수정 페이지에 이미지 수정을 해주기 위해서 기존의 이미지를 지우고 새로운 이미지를 추가하여 서버에서는 기존의 이미지가 지워지고 새로운 이미지가 저장되었습니다. 여기까지는 문제가 없지만 사용자가 변심 혹은 다른 여러 사유로 인해 '수정 버튼'을 누르지 않고 해당 페이지를 벗어날 경우 문제가 생깁니다. DB에 대한 정보 수정은 '수정 버튼'을 눌렀을 때 이루어지도록 할 것인데 '수정 버튼'을 누르지 않고 페이지를 벗어나게 되면 삭제한 이미지 정보는 DB에 남겨져 있고 새로 추가한 이미지의 정보는 저장되지 않는 상태가 됩니다. 

 

 이러한 문제점을 보완할 수 있는 방식은 2가지가 있다고 생각됩니다. 첫 번째 방식은 서버에서의 이미지 삭제와 이미지 추가 작업을 '수정 버튼'이 눌렀을 때 이루어지도록 하는 것입니다. 두 번째 방식은 사용자가 수정을 하는 과정에서는 서버에 저장된 파일에 대한 삭제 작업은 전혀 하지 않고 추가 작업만 해주는 것입니다. 대신 서버 내에서 주기적으로 DB에 등록된 이미지 정보와 서버에 저장된 이미지를 비교하여 DB에 등록되지 않은 이미지가 있다면 해당 이미지들만 삭제해주는 것입니다.

 

 두 번째 방식은 배치 프로그램을 사용하여 구현이 가능한데, 해당 방식으로 구현해보도록 할 것입니다.

 


 

 

 앞서 두 측면에서 어떠한 방식으로 구현할 것인지 말하였습니다. 해당 방식으로 구현할 경우 뷰(view)와 서버에서 해주어야 할 작업들을 정리하면 다음과 같습니다.

 

뷰(viwe)(상품 수정 페이지)

 - 기존에 저장되어 있는 이미지가 있다면 사용자가 볼 수 있도록 출력한다. 더불어 기존 이미지에 대한 정보가 담긴 <input>태그가 작성되도록 한다.

 - 출력된 이미지에는 삭제 버튼이 있다.

 - 삭제 버튼을 누르면 서버에 저장된 이미지에 대한 삭제를 서버에 요청하지 않고 단순히 이미지가 출력이 되는 태그와 이미지 정보가 담긴 <input> 태그만 삭제된다.

 - 사용자가 새로운 이미지를 추가하면 서버에 이미지 저장을 요청을 한다. 서버에서는 이미지 저장 후 이미지 데이터를 뷰로 다시 반환해준다. 뷰는 반환받은 이미지 정보를 통해서 이미지 가 출력이 되도록 태그를 추가하고 반환 받은 데이터를 저장하는 <input>태그가 저장되도록 한다.

 - 수정 버튼을 누르면 수정된 상품 정보와 함께 서버에 존재해야 할(<input> 태그에 작성된) 이미지 정보를 서버로 전송한다.

 

서버(server)

 - 뷰에서 이미지 저장 요청이 있을 경우 서버에 이미지를 저장하고 해당 이미지 정보를 뷰로 반환한다.

 -  뷰에서 수정 요청이 들어오면 전달받은 수정되어야 할 상품 정보와 이미지 정보가 담긴 BookVO 객체를 통해서 수정 작업을 한다.

 - 먼저 상품 정보에 대한 수정 작업을 진행한 후 상품 이미지 정보 수정 작업을 진행한다.

 - 상품 이미지 작업은 관련 이미지 정보를 모두 삭제한 후 뷰로부터 전달받은 이미지 정보를 등록해준다.

 

 

2. 수정 페이지 이미지 출력 

 수정 페이지에 이미지 출력은 앞서 조회 페이지에서 이미지 출력을 위해 작성한 코드를 그대로 활용하면 됩니다. 단지 이미지 삭제 버튼과 출력될 이미지 정보가 담긴 <input> 태그가 추가적으로 출력돼야 한다는 점만 다릅니다.

 

새로 추가할 이미지 관련 태그의 스타일을 추가해주기 위해서 goodsModify.css 파일에 아래의 코드를 추가해줍니다.

 

	#result_card img{
		max-width: 100%;
	    height: auto;
	    display: block;
	    padding: 5px;
	    margin-top: 10px;
	    margin: auto;	
	}
	#result_card {
		position: relative;
	}
	.imgDeleteBtn{
	    position: absolute;
	    top: 0;
	    right: 5%;
	    background-color: #ef7d7d;
	    color: wheat;
	    font-weight: 900;
	    width: 30px;
	    height: 30px;
	    border-radius: 50%;
	    line-height: 26px;
	    text-align: center;
	    border: none;
	    display: block;
	    cursor: pointer;	
	}

 

그림 2-1

 

 

 jstl을 사용하기 위해서 goodsModify.jsp 파일 상단에 아래의 라이브러리 태그 코드를 추가해주었습니다.

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

 

 

 

 상품 정보 입력란 제일 하단 공간에 이미지를 추가할 수 있는 버튼과 저장된 이미지가 출력이 될 수 있도록 코드를 추가해줍니다.

 

                    		<div class="form_section">
                    			<div class="form_section_title">
                    				<label>상품 이미지</label>
                    			</div>
                    			<div class="form_section_content">
									<input type="file" id ="fileItem" name='uploadFile' style="height: 30px;">
									<div id="uploadResult">
																		
									</div>									
                    			</div>
                    		</div>

 

 

 

 기존 상품 상세 페이지에서 작성한 이미지 출력과 관련된 Javascript코드에 일부를 수정 해준 코드를 $(document).ready 함수 구현부에 추가해줍니다. 

 

			/* 기존 이미지 출력 */
			let bookId = '<c:out value="${goodsInfo.bookId}"/>';
			let uploadResult = $("#uploadResult");
			
			$.getJSON("/getAttachList", {bookId : bookId}, function(arr){
				
				console.log(arr);
				
				if(arr.length === 0){
					
					
					let str = "";
					str += "<div id='result_card'>";
					str += "<img src='/resources/img/goodsNoImage.png'>";
					str += "</div>";
					
					uploadResult.html(str);				
					return;
				}
				
				let str = "";
				let obj = arr[0];
				
				let fileCallPath = encodeURIComponent(obj.uploadPath + "/s_" + obj.uuid + "_" + obj.fileName);
				str += "<div id='result_card'";
				str += "data-path='" + obj.uploadPath + "' data-uuid='" + obj.uuid + "' data-filename='" + obj.fileName + "'";
				str += ">";
				str += "<img src='/display?fileName=" + fileCallPath +"'>";
				str += "<div class='imgDeleteBtn' data-file='" + fileCallPath + "'>x</div>";
				str += "<input type='hidden' name='imageList[0].fileName' value='"+ obj.fileName +"'>";
				str += "<input type='hidden' name='imageList[0].uuid' value='"+ obj.uuid +"'>";
				str += "<input type='hidden' name='imageList[0].uploadPath' value='"+ obj.uploadPath +"'>";				
				str += "</div>";
				
				uploadResult.html(str);			
				
			});// GetJSON

 

그림 2-4

 

 

 수정 및 추가 해준 부분은 출력되어야 할 태그 데이터들이 담긴 str 변수의 값입니다. 아래의 그림에서 보는 바와 같이 삭제 버튼과 출력된 이미지 정보가 담긴 <input> 태그가 출력이 될 수 있도록 코드가 추가된 것을 볼 수 있습니다.

 

 

 

 추가된 <input> 태그는 <form> 태그 내부에 작성되어져서 '상품 수정' 버튼을 눌렀을 때 상품 데이터와 함께 BookVO객체에 담겨 서버로 전송되게 됩니다. 기존에 저장된 데이터 조차 <input> 태그에 담겨 전송되도록 한 이유는 서버에서 작성할 이미지 수정 관련 코드가 무조건 기존 이미지 데이터를 삭제하고 뷰로부터 전달받은 이미지 정보를 새로 추가하도록 할 것이기 때문입니다.

 

 

그림 2-6

 

 

REFERENCE

  • 코드로배우는 스프링 웹 프로젝트(남가람북스)
  •  

 

 

 

DATE

  • 2020.07.13

 

 

728x90
반응형
Comments