사이먼's 코딩노트

[SpringBoot] 사진 파일 등록 본문

카테고리 없음

[SpringBoot] 사진 파일 등록

simonpark817 2024. 5. 30. 11:03

[사진 파일 등록 적용]

  • 웹 페이지를 구현할 때 글을 작성하면서 사진을 첨부하거나, 회원가입 시 프로필 사진을 등록하는 등과 같이 프로그램에서 사진 파일을 등록하는 기능이 필요할 때가 있을 것이다.
  • 이번에는 위와 같이 게시글에 사진 파일 등록을 하는 방법을 알아봅시다.
  • 앞서 진행했던 SBB 프로그램이 아닌 임시로 만들어 둔 다른 프로젝트를 통해 구현할 예정이기 때문에 코드를 참고하고 싶으시다면 아래 깃허브 리포지터리 주소를 통해 참고 부탁드립니다.
  • 깃허브 리포지터리 주소 : https://github.com/psm817/sb_blog_2405

 

[application.yml 수정]

  • 먼저 업로드한 사진이 어느 디렉토리에 저장할 것인지 경로를 지정해줘야 한다.
  • application.yml에서 아래와 같이 코드를 추가하고 경로는 사용자가 원하는 곳을 작성해주면 된다.
custom:
  fileDirPath: C:\work\thumbnail

 

[엔티티 수정]

  • 먼저 게시글과 관련된 엔티티에 thumbnail이라는 사진 파일과 관련된 컬럼을 추가해야 한다.
  • 아래 코드는 Post.java에 해당 컬럼을 추가한 모습이다.
@Entity
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Post extends BaseEntity {
    private String title;
    private String content;
    private String thumbnailImg;
}
  • 실제 데이터베이스에서는 등록한 사진이 저장되는 것이 아니고 해당 파일이 저장될 경로를 저장한다.

 

[서비스 수정]

  • 현재 사진 파일 등록을 구현하고자 하는 부분은 게시글을 등록했을 때 첨부하는 방법이다.
  • PostService.java 클래스에서 create() 메서드에 아래와 같이 코드를 수정해야 한다.
@Service
@RequiredArgsConstructor
public class PostService {
    private final PostRepository postRepository;

    @Value("${custom.fileDirPath}")
    private String fileDirPath;

    public List<Post> getList() {
        return postRepository.findAll();
    }

    public void create(String title, String content, MultipartFile thumbnail) {
        String thumbnailRelPath = "post/" + UUID.randomUUID().toString() + ".jpg";

        File thumbnailFile = new File(fileDirPath + "/" + thumbnailRelPath);

        try {
            thumbnail.transferTo(thumbnailFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        Post post = Post.builder()
                .title(title)
                .content(content)
                .thumbnailImg(thumbnailRelPath)
                .build();
        postRepository.save(post);
    }

    public Post getPost(Long id) {
        Optional<Post> op = postRepository.findById(id);

        if ( op.isPresent() == false ) throw new DateTimeException("post not found");

        return op.get();
    }
}
  • thumbnail의 타입은 String 문자열이 아닌 MultipartFile이다.
  • thumbnailRelPath은 이제 실제 등록된 사진이 저장된 경로를 의미하는 변수로서 모든 등록된 사진은 post라는 디렉토리 밑에 UUID를 사용한 랜덤 문자를 넣어주고 확장자는 .jpg로 저장되도록 하였다.
  • 다시 thumbnailFile이라는 변수에 application.yml에서 설정한 기본 경로인 fileDirPath와 thumbnailRelPath의 문자열을 합쳐 최종 경로가 탄생한다.
  • 예를 들어 하나의 사진을 등록하게 되면 해당 사진의 경로는 이제부터 C:\work\thumbnail\post\aldfjldksj-1234j9.jpg가 된다.
  • 예외처리를 포함하여 파일 변환을 해주고, builder()에 이제 경로도 추가할 수 있도록 .thumbnailImg(thumbnailRelPath)를 추가 작성한다. 

 

[컨트롤러 수정]

  • 이제 게시글을 등록할 때 PostService에서 create() 메서드의 매개변수가 추가가 되었으니 컨트롤러에서도 해당 메서드에 맞게 인자를 추가해줘야 한다.
  • 아래 코드는 PostController.java 클래스에서 파라미터 매개변수와 인자를 추가한 모습이다.
@GetMapping("/create")
public String create() {
    return "post/create_form";
}

@PostMapping("/create")
public String postCreate(@RequestParam("title") String title, @RequestParam("content") String content, @RequestParam("thumbnail") MultipartFile thumbnail) {
    this.postService.create(title, content, thumbnail);

    return "redirect:/post/list";
}

 

[WebMvcConfig.java 생성]

  • 외부에 저장된 이미지를 사용하고자 할 때 WebMvcCongifurer 인터페이스를 구현하여 설정을 할 수 있으면, addResourceHandlers() 메서드를 오버라이딩하여 정적 리소스를 웹 애플리케이션에서 제공할 수 있도록 핸들러를 추가해야 한다.
  • 아래 코드는 WebMvcCongfig.java 클래스를 새로 생성하여 작성한 모습이다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Value("${custom.fileDirPath}")
    private String fileDirPath;

    @Override
    public void addResourceHandlers (ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/file/**")
                .addResourceLocations("file:///" + fileDirPath + "/");
    }
}
  • addResourceHandlers() 메서드는 정적 리소스(이미지, JavaScript, CSS 등)를 웹 애플리케이션에서 제공하기 위해 핸들러를 추가하려면, 웹 애플리케이션 루트의 특정 위치, 클래스 경로 및 기타 위치에 해당하는 정적 리소스 경로를 등록하는 역할을 한다.

 

[템플릿 수정]

  • 마지막으로 사진 파일 등록 기능을 구현이 마무리되고, 실제 화면에 보일 수 있도록 몇 가지 html 템플릿 수정이 필요하다.
  • 먼저 게시글 등록 시 파일을 첨부하는 버튼을 create_form.html에서 아래와 같이 코드를 추가하였다.
<h1>게시글 등록</h1>

<form th:action="@{/post/create}" method="POST" enctype="multipart/form-data">
    <h3>제목</h3>
    <input type="text" name="title">

    <h3>내용</h3>
    <textarea name="content"></textarea>

    <h3>사진</h3>
    <input type="file" name="thumbnail" accept="image/png, image/gif, image/jpeg">
    <button type="submit">등록</button>
</form>
  • input 태그 안에 type="file" 속성을 쓰게 되면 파일 첨부가 가능한 모양의 버튼이 생성된다.
  • 여기서 허용한 파일의 속성은 .png, .gif, .jpeg인 확장자만 파일 첨부가 가능하도록 하였다.
  • 추가로 아래와 같이 사진 파일 등록을 완료했을 때 게시글 리스트에서도 등록된 사진이 보일 수 있게 list.html에서 코드를 수정하였다.
<div>게시판 목록</div>
<div>
    <ul th:each="post: ${postList}">
        <li th:text="${post.title}"></li>
        <li th:text="${post.content}"></li>
        <li>
            <img th:src="@{|/file/${post.thumbnailImg}|}" alt="123456">
        </li>
    </ul>
</div>

<a href="/post/create">게시글 작성</a>

 

  • 위의 모든 작업을 마쳤다면, 로컬 서버를 재실행했을 때 사진 파일 등록이 구현된 것을 확인할 수 있다.

파일 선택을 통한 사진 파일 등록

 

사진 파일 등록 성공

 

사진 파일이 저장된 실제 경로 확인

 

반응형