본문 바로가기
클론코딩

LMS Web 클론코딩 13 (이미지 업로드)

by zho 2024. 2. 7.

2024/02/04

이제 게시글에 이미지를 업로드하는 기능을 추가할 것이다. 이미지 업로드는 db에 이미지 원본을 넣어 저장을 하는 것이 아니라 이미지 데이터의 정보를 저장하고, 프로젝트에서 이미지를 필요로 할 때 DB에 저장된 이미지 데이터 정보(path, name, size 등)를 통해 가져온다. local서버에 이미지를 저장하는 방법도 있고, 다른 서버를 대여하여 올리는 방법도 있다. 대표적으로는 aws의 s3를 많이 사용한다.

 

 

일단 나는 이미지 업로드 기능 자체를 구현하는것이 목표였기에, 내 local에 이미지를 저장하는 방법으로 진행했다.

 

1. PostFile 도메인 생성, db table 생성하기

package com.example.myapp.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.persistence.*;

@Getter
@Setter
@Entity
@Table(name = "qna_files")
@NoArgsConstructor
public class PostFile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String fileName;
    private String filePath;
    private long fileSize;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id")
    private Post post;

    public PostFile(String fileName, String filePath, long fileSize) {
        this.fileName = fileName;
        this.filePath = filePath;
        this.fileSize = fileSize;
    }
}

 

다음과 같이 생성해 줬다. db에서는 qna_files라는 이름의 테이블에서 위 내용들을 관리한다.

 

2. JdbcTemplate 기능 구현

public void saveFile(PostFile file) {
    String sql = "INSERT INTO qna_files (fileName, filePath, fileSize) VALUES (?, ?, ?)";
    jdbcTemplate.update(sql, file.getFileName(), file.getFilePath(), file.getFileSize());
}

 

3.  PostService 구현

public void join(Post post, MultipartFile file, Long courseId) throws IOException {
    if (!file.isEmpty()) {
        String filePath = "/Users/choejiho/Downloads/LMS_Spring/src/main/resources/static/uploads";
        UUID uuid = UUID.randomUUID();
        String fileName = uuid + "_" + file.getOriginalFilename();
        File saveFile = new File(filePath,fileName);

        file.transferTo(saveFile);

        PostFile postFile = new PostFile();
        postFile.setFileName(fileName);
        postFile.setFilePath("static/uploads/" + fileName);
        postFile.setFileSize(file.getSize());
        post.setFile(postFile);
        postRepository.saveFile(postFile);
    }
    postRepository.savePost(post, courseId);
}

 

현재는 project내의 경로로 이미지가 저장이 되도록 설정했는데, 이 방식은 프로젝트 개발 시에만 이용하는 것이 좋고, 배포할땐 프로젝트 외부로 저장이 되도록 하는것이 올바르다.

 

4. PostController 구현

@PostMapping("savePost/{id}")
public String savePost(@RequestParam String title, @RequestParam String content, @RequestParam("file") MultipartFile file,@PathVariable String id, Model model) throws IOException {
    LocalDateTime now = LocalDateTime.now();
    Timestamp timestamp = Timestamp.valueOf(now);
    Post post = new Post();
    post.setTitle(title);
    post.setContent(content);
    post.setDate(timestamp);
    model.addAttribute("currentCourseId",id);
    postService.join(post, file, Long.valueOf(id));
    return "redirect:/course/" + id;
}

 

위 기능들을 구현했으니 구현된 기능들을 호출하여 실행시키고 다시 coures로 돌아오도록 구현했다.

 


기능들이 추가되면서 일단 기능을 얼른 구현해야지라는 마음이 앞서서 깔끔한 코드를 작성하지 못하고, 어떠한 방법으로 구현할 수 있는지 그리고 각각의 장단점이 무엇인지에 대해서 생각을 많이 못했던 것 같아 아쉽다. 

728x90