본문 바로가기

Study/개발일지

[백엔드스터디WIL]8주차 학습일지

제이쿼리(jQuery)는 자바스크립트 라이브러리(Javascript library)로, Html 문서 조작, 이벤트 처리, 애니메이션 등 다양한 기능을 쉽게 구현할 수 있도록 도와주는 라이브러리입니다. 이번 포스팅에서는 jQuery의 기본 개념과 사용법을 코드 예제를 곁들여서 자세히 살펴보도록 하겠습니다.

 

jQuery란? 기본 개념과 사용법, 코드 예제로 알아보기


jQuery의 라이브러리 로딩

jQuery 라이브러리를 사용하기 위해서는 먼저 jQuery 라이브러리 파일을 HTML 문서에 로딩해야 합니다. jQuery 라이브러리 파일은 jQuery 공식 웹사이트에서 다운로드하거나, CDN(Content Delivery Network)에서 제공하는 파일을 사용할 수 있습니다.

 

HTML 예시

<!-- 로컬 파일 로딩 예시 -->
<script src="jquery.js"></script>

<!-- CDN 파일 로딩 예시 -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

 

선택자(Selector)

Query를 사용하여 HTML 요소를 선택하기 위해서는 선택자(selector)를 사용합니다. 선택자는 CSS 선택자와 동일한 문법을 사용합니다.

 

Javasript 예시

// id가 "myDiv"인 요소 선택 예시
$("#myDiv")

// 클래스가 "myClass"인 요소 선택 예시
$(".myClass")

// 태그 이름이 "p"인 요소 선택 예시
$("p")

 

 

 

이벤트 처리

jQuery를 사용하게 되면, HTML 요소에 이벤트 처리를 쉽게 할 수 있습니다. 이벤트 처리를 위해서는 on() 메서드를 사용하게 됩니다.

 

Javascript 예시

// 클릭 이벤트 처리 예시
$("button").on("click", function() {
  alert("클릭 이벤트 발생");
});

// 마우스 오버 이벤트 처리 예시
$("p").on("mouseover", function() {
  $(this).css("background-color", "yellow");
});

 

HTML  문서 조작

jQuery를 사용하여 HTML 요소를 쉽게 조작할 수 있습니다. 예를 들어 아래와 같이 HTML 요소의 텍스트를 빠르게 변경할 수 있습니다.

 

// HTML 요소의 텍스트 변경 예시
$("p").text("변경할 텍스트");

 

HTML 요소의 속성값도 쉽게 변경할 수 있습니다.

// HTML 요소의 속성 변경 예시
$("img").attr("src", "change-image.jpg");

 

애니메이션

jQuery를 사용하여 애니메이션 효과를 적용할 수 있습니다. 예를 들어, 다음과 같이 HTML 요소를 서서히 사라지게 할 수 있습니다.

 

// HTML 요소를 서서히 사라지게 하는 예시
$("p").fadeOut("slow");

 

 

multipart 이미지 업로드 관련 기능 학습

 

※ 개발 환경:

Back-end

Project: Gradle Project, Language: Java 11, Spring Boot: 2.6.7

Dependencies: SpringWeb, Thymeleaf, Lombok ,Validation, H2 Database, MySQL Driver, Spring Data JPA

Front-end

JavaScript, Thymeleaf, HTML5

 

 

파일은 문자와 다르게 바이너리 데이터를 전송해야 한다.

그리고 보통 폼을 전송할 때 문자와 바이너리를 동시에 전송해야하는 경우가 대부분일 것이다.

이 문제를 해결하기 위해 스프링이 제공하는 multipart/form-data 라는 전송 방식을 사용한다.

 

바이너리 파일(binart file)
바이너리 파일은 데이터의 저장과 처리를 목적으로 
0과 1의 이진 형식으로 인코딩된 파일을 가리킵니다. (텍스트 파일이 아닌 컴퓨터 파일)
프로그램이 이 파일의 데이터를 읽거나 쓸 때는 데이터의 어떠한 변환도 일어나지 않습니다.

 

html

 
<form action="/save" method="post" enctype="multipart/form-data">
‌<input type="text" name="name">
‌<input type="file" name="image">
​​​​<button type="submit">전송</button>
</form>

 

데이터를 전송하게 되면 아래와 같은 내용으로 HTTP Body에 담긴다.

HTTP Message Body

 
------WebKitFormBoundaryMVA4MPoFDDjKPJl2
Content-Disposition: form-data; name="name"

kim!
------WebKitFormBoundaryMVA4MPoFDDjKPJl2
Content-Disposition: form-data; name="image"; filename="사진.jpg"
Content-Type: image/jpeg

... ÿØÿà·'j©?AGÙ'ìÿÙ ...
------WebKitFormBoundaryMVA4MPoFDDjKPJl2--
  • "---xxx"로 영역 구분
  • "Content-Disposition:form-data; data="data" ~ → 영역의 시작(해당 영역에 대한 정보)
  • "---xxx--" 끝 명시

위와 같은 식으로 각각의 항목을 구분해서 한번에 형식이 다른 여러 항목들을 전송할 수 있다.

 

 

 

multipart/form-data 방식

 

1. HTML <form></form>

 
<form th:action="@{/product/new}" th:object="${form}" method="post" enctype="multipart/form-data">
‌<div class="form-group">
​​​​<label th:for="name">대표 이미지</label>
​​​​<input type="file" th:field="*{thumbnail}" class="form-control"
​​​​​​​​​​​th:class="${#fields.hasErrors('thumbnail')}? 'form-control fieldError' : 'form-control'"><!--에러 테두리 붉은색으로-->
​​​​<p th:if="${#fields.hasErrors('thumbnail')}" th:errors="*{thumbnail}">Incorrect date</p><!--에러 메시지-->
​​​​</div>
​​​​<button type="submit" class="btn btn-primary">Submit</button>
</form>

우선 이 방식을 사용하려면 Form 태크에 enctype="multipart/form-data"를 추가로 지정해야 한다.

 

2. 파일 저장과 관련된 업무를 처리할 수 있는 Class (컨트롤러에서 넣어줘도 상관없다.)

package project.toyproject.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

@Component
public class FileUpload {
​​​​/**
     * @param filename: 서버에 업로드되는 파일명
​​​​​* @param fileDir: 파일이 저장되는 경로
​​​​​*/
​​​​public String getFullPath(String filename, String fileDir) {
​​​​​​​​return fileDir + filename;
​​​​}

​​​​public String serverUploadFile(MultipartFile multipartFile, String fileDir) throws IOException {
​​​​​​​​if (multipartFile.isEmpty()) { //파일 없으면 null 반환
​​​​​​​​​​​​return null;
​​​​​​​​}
​​​​​​​​String originalFilename = multipartFile.getOriginalFilename(); //원래 파일명

​​​​​​​​String serverUploadFileName = createServerFileName(originalFilename); //uuid 생성해서 뒤에 원래파일명의 확장자명 붙이기
​​​​​​​​multipartFile.transferTo(new File(getFullPath(serverUploadFileName, fileDir)));//저장: (서버에 업로드되는 파일명, 업로드 되는 경로)

​​​​​​​​return serverUploadFileName;
​​​​}

​​​​//uuid 생성해서 뒤에 원래파일명의 확장자명 붙이기
​​​​private String createServerFileName(String originalFilename) {
​​​​​​​​String uuid = UUID.randomUUID().toString();
​​​​​​​​String ext = extractExt(originalFilename);
​​​​​​​​return uuid + "." + ext;
​​​​}

​​​​//원래 파일명에서 확장자 뽑기(.jpg, .png ...)
​​​​private String extractExt(String originalFilename) {
​​​​​​​​int pos = originalFilename.lastIndexOf(".");
​​​​​​​​return originalFilename.substring(pos + 1);
​​​​}
}

extractExt(): 원래 파일명에서 확장자를 뽑는다. (.jpg, .pnp ...)

createServerFileName(): 서버 내부에서 관리하는 파일명으로 UUID를 생성한 후 원래 파일명 확장자를 붙인다. (ex: UUID.jpg)

서버에 업로드되는 파일명은 UUID 외에도 "업로드날짜 + 원래파일명" 식으로 해도 상관없다.

하지만 중복된 파일명으로 저장될 아주 작은 가능성을 생각해서는 UUID를 사용하는 것이 좋다. (개인적인 생각)

serverUploadFile(): 파일을 저장한다.

file.transferTo(new File("PATH") 을 이용해 파일을 저장할 수 있다.

사용자가 업로드한 파일명은 file.getOriginalFilename() 으로 받을 수 있다.

 

 

3. Cotroller (파일이 저장되는 경로 구하기)

@PostMapping("/new")
public String create(@Valid @ModelAttribute("form") CreateProductForm form, BindingResult result,
​​​​​​​​​​​​​​​​​​​​​@LoginCheck SessionMemberData loginMember,
​​​​​​​​​​​​​​​​​​​​​RedirectAttributes redirectAttributes,
​​​​​​​​​​​​​​​​​​​​​HttpServletRequest request
) throws IOException {
​​​​if (result.hasErrors()) { //만약에 result 안에 에러가 있으면
​​​​​​​​return "product/createProductForm"; //다시 폼으로 이동
​​​​}

​​​​String realPath = request.getSession().getServletContext().getRealPath("/upload/");// 저장 경로
​​​​String uploadFile = fileUpload.serverUploadFile(form.getThumbnail(), realPath);

​​​​//데이터 베이스에 저장
​​​​Long productId = productService.saveProduct(uploadFile);

​​​​redirectAttributes.addAttribute("productId", productId);

​​​​return "redirect:/product/detail/{productId}"; // 상품디테일 페이지로 넘어가게
}

realPath: 파일이 저장되는 경로이다.

 

request.getSession().getServletContext().getRealPath("/"): 내 프로젝트/src/main/webapp 파일 경로이다.

즉, 저 경로에 webapp 파일이 없다면 에러가 나거나 톰캣의 임시폴더에 저장되게 된다.

즉, 이러한 오류를 방지하려면 webapp 파일을 꼭 만들어줘야한다.

728x90