2025.02.18 작성
OS : Window
개발환경: IntelliJ IDEA
개발언어: Java
프레임워크: Spring Boot
package org.zerock.board.entity;
import jakarta.persistence.*;
import lombok.*;
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString(exclude = "writer")
public class Board extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String bno;
private String title;
private String content;
@ManyToOne
private Member writer; // 연관관계 지정
}
즉, "게시글(Board)이 회원(Member)와 어떤 관계인지"를 정의하는 역할을 함.
회원 (Member) = 한 명
게시글 (Board) = 여러 개
한 명의 회원이 여러 개의 게시글을 작성할 수 있음 → @ManyToOne 사용!
즉, System.out.println(board); 같은 코드를 실행하면 toString()이 자동으로 호출되어 객체 내용을 출력할 수 있음.
ToString(exclude = "writer")를 왜 사용하는가?
✔️ 1. 무한 재귀 호출을 방지하기 위해!
✔️ 2. @ManyToOne 관계에서 성능 최적화를 위해!
✔️ 3. writer 정보가 필요하면 board.getWriter()를 통해 직접 조회하면 됨!
<input name="uploadFiles" type="file" multiple>
<button class="uploadBtn">Upload</button>
<script>
$(".uploadBtn").click(function() {
var formData = new FormData();
var inputFile = $("input[type='file']");
var files = inputFile[0].files;
for (var i = 0; i < files.length; i++) {
console.log(files[i]);
formData.append("uploadFiles", files[i]);
}
$.ajax({
url: '/uploadAjax',
processData: false,
contentType: false,
data: formData,
type: 'post',
dataType: 'json',
success: function(result) {
console.log(result);
},
error: function(xhr, status, error) {
console.log(status);
}
});
});
</script>
📌 여러 개의 파일을 한 번에 업로드할 수 있도록 multiple 속성이 적용됨.
@RestController
@Log4j2
public class UploadController {
@Value("${org.zerock.upload.path}")
private String uploadPath;
@PostMapping("/uploadAjax")
public void uploadFile(MultipartFile[] uploadFiles) {
for (MultipartFile f : uploadFiles) {
// 1️⃣ 이미지만 허용
if (f.getContentType().startsWith("image") == false) {
log.warn("this file is not image type");
return;
}
String originalFilename = f.getOriginalFilename();
String fileName = originalFilename.substring(originalFilename.lastIndexOf("\\") + 1);
log.info("fileName:" + fileName);
// 2️⃣ 날짜별 폴더 생성
String folderPath = makeFolder();
// 3️⃣ UUID 적용하여 저장 (파일명 중복 방지)
String uuid = UUID.randomUUID().toString();
String saveName = uploadPath + File.separator + folderPath + File.separator + uuid + "_" + fileName;
Path savePath = Paths.get(saveName);
try {
// 4️⃣ 파일 저장
f.transferTo(savePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String makeFolder() {
String str = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
String folderPath = str.replace("/", File.separator);
File uploadPathFolder = new File(uploadPath, folderPath);
if (!uploadPathFolder.exists()) {
uploadPathFolder.mkdirs();
}
return folderPath;
}
}
private String makeFolder() {
String str = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
String folderPath = str.replace("/", File.separator);
File uploadPathFolder = new File(uploadPath, folderPath);
if (!uploadPathFolder.exists()) {
uploadPathFolder.mkdirs();
}
return folderPath;
}
폴더 생성 과정
- 현재 날짜(yyyy/MM/dd)로 폴더명 생성
- /을 OS에 맞는 경로 구분자(File.separator)로 변환
- 해당 폴더가 존재하지 않으면 mkdirs()로 생성
📌 결과 예시
오늘 날짜가 2025-02-15라면 → /uploadPath/2025/02/15/ 폴더가 생성됨.
--> 현재 파일 업로드 기능을 구현할 때 AJAX를 사용하여 비동기 처리하고 있음.
즉, 페이지를 새로고침하지 않고 파일을 서버에 업로드하는 방식.
Thumbnailator는 Java에서 이미지 리사이징(크기 조정), 포맷 변환, 품질 조절 등을 간편하게 수행할 수 있는 라이브러리.
Java에서 기본적으로 제공하는 ImageIO나 Graphics2D 같은 클래스를 직접 사용해서 이미지를 다루려면 코드가 복잡하고 성능도 좋지 않음.
Thumbnailator를 쓰면 몇 줄의 코드만으로 고품질의 썸네일을 만들 수 있음.
크기 조절, 포맷 변환, 품질 조절, 회전, 워터마크 추가 등이 가능.