[Springfolio] 5편 - 이미지 업로드 기능 + 썸네일 (2)

Jlee7362·2025년 8월 10일
post-thumbnail

문제 상황

JSP 게시판에서 글 작성 시 첨부한 이미지가 자동으로 저장되지 않고,
매번 직접 C:/upload 폴더에 이미지를 넣고 DB에서 UPDATE해야만 보이는 문제가 발생.


해결 과정

1. application.yml – 파일 업로드 허용

spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 20MB
      max-request-size: 20MB

용량을 2배로 늘렸다.


2. 글 작성 폼 (write.jsp)

<form action="/usr/article/write" method="post" enctype="multipart/form-data">
  <div>제목: <input type="text" name="title" required></div>
  <div>작성자 ID: <input type="number" name="memberId" required></div>
  <div>썸네일: <input type="file" name="thumbImgFile" accept="image/*"></div>
  <button type="submit">저장</button>
</form>
  • enctype="multipart/form-data" 필수
  • 파일 input의 name과 컨트롤러 파라미터 이름이 일치해야 함
    (전에 했던 세팅 그대로다)

3. 컨트롤러 (ArticleController.java)

	@GetMapping("/usr/article/write")
	public String showWriteForm() {
		return "article/write";
	}

	@PostMapping(value="/usr/article/write", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)	
	public String doWrite(@RequestParam String title, @RequestParam int memberId,
			@RequestParam(value="thumbImgFile", required = false) MultipartFile file) throws IOException {
		String savedName = null;
		
		if (file != null && !file.isEmpty()) {
			// 1) 폴더 보장
			Path uploadDir = Paths.get("C:/upload/"); // 경로를 정해준다.
			Files.createDirectories(uploadDir);
			
			// 2) 원본 확장자 유지
			String original = file.getOriginalFilename();
			String ext = "";
			if (original != null&& original.lastIndexOf('.') != -1) {
				ext = original.substring(original.lastIndexOf('.')); // .png, .jpg...
			}
			// 3) 저장 파일명 생성
			savedName = UUID.randomUUID().toString().replace("-", "")+ext;
			// 잘 돌아가는지 확인.
			System.out.println("upload file = " + original + " -> saved = " + savedName);
			
			// 4) 저장 
			Path target = uploadDir.resolve(savedName);
			Files.copy(file.getInputStream(), target, StandardCopyOption.REPLACE_EXISTING);
		}

		articleRepository.writeArticle(title, memberId, savedName);
		
		return "redirect:/usr/article/list";
	}

핵심코드이다.
폴더가 없으면 만들고, 거기에 원본 확장자 유지 + 저장 파일명을 랜덤이름으로 생성.
그리고 혹시 몰라서 sysout으로 파일명을 콘솔에 출력하게 적었다. 마지막으로 그 파일을 저장 및 writeArticle을 이용해서 내용 저장.

모든 과정 후에 list로 돌아간다.


4. Mapper & Repository

Repository

void writeArticle(@Param("title") String title,
                  @Param("memberId") int memberId,
                  @Param("thumbImg") String thumbImg);

ArticleMapper.xml

<insert id="writeArticle">
    INSERT INTO article
    SET regDate = NOW(),
        title = #{title},
        memberId = #{memberId},
        thumbImg = #{thumbImg}
</insert>

사실상 나머지는 같다.


5. list.jsp – 이미지 출력

<c:if test="${not empty article.thumbImg}">
  <img src="/upload/${article.thumbImg}" width="80" style="object-fit:cover;">
</c:if>
  • /upload/** 경로는 WebConfig에서 C:/upload로 매핑

6. WebConfig – 업로드 폴더 경로 매핑

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("file:///C:/upload/");
    }
}


체크리스트

  1. enctype="multipart/form-data" 폼 속성 확인
  2. input name과 컨트롤러 파라미터 이름 일치
  3. Mapper에 thumbImg 컬럼 INSERT/SELECT 반영
  4. C:/upload 폴더 존재 여부
  5. 업로드 후 http://localhost:8080/upload/파일명으로 직접 접근 가능 여부

결과

  • 글 작성 시 업로드한 이미지가 자동으로 C:/upload에 저장
  • DB에 파일명이 저장되고, 리스트에서 즉시 썸네일 표시
  • 수동 파일 복사 및 SQL UPDATE 불필요


0개의 댓글