Nick Dev

[Outstagram] 이미지 처리 추상화 본문

Outstagram

[Outstagram] 이미지 처리 추상화

Nick99 2024. 12. 11. 12:52
반응형

현재 상황 및 이슈 포인트

현재 상황

  • 아직 로컬에서 프로젝트를 진행하고 있기에 이미지 저장도 로컬 디렉토리에 저장하기로 함

📌 이슈 포인트

  • 하지만 이미지 처리는 추후에 로컬이 아닌 S3에 저장되도록 수정할 수 있으므로 이미지 처리를 추상화할 필요가 있다고 느낌
  • 그래서 이미지 서비스 계층을 인터페이스화 해서 추후에 AWS S3에 저장하는 클래스만 구현하면 됨

이미지 서비스 추상화

ImageService

package com.outstagram.outstagram.service;

import com.outstagram.outstagram.dto.ImageDTO;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;

public interface ImageService {

    void saveImages(List<MultipartFile> imgFiles, Long postId);

    List<ImageDTO> getImages(Long postId);

    void deleteByIds(List<Long> deleteImgIds);
}

ImageServieLocal

@Slf4j
@Service
@RequiredArgsConstructor
public class ImageServiceLocal implements ImageService {

    ...

}

⭐ 추상화 진행 시, DIP & OCP 고려

DIP

  • 자신보다 변하기 쉬운 것에 의존하지 마라
  • 컨트롤러는 변하기 쉬운 로컬 저장 서비스에 의존하지 않고 인터페이스 서비스에 의존

OCP

  • 컨트롤러 입장에서는 이미지 저장 인터페이스 덕분에 하위 구현체가 바뀌어도(로컬 저장 서비스 -> S3 저장 서비스) 영향이 없다
  • 이미지 저장 인터페이스는 확장에 열려 있고, 컨트롤러 입장에서는 주변의 변화에 폐쇄되어 있음
  • 다른 서비스 계층(PostService, UserService)은 추후에 변경될 일이 없다. 그래서 따로 Service 계층을 인터페이스화 하지 않았다

추후에 S3에 저장하는 서비스 로직 적용 방법

  1. ImageService 인터페이스를 구현하는 ImageSeviceAwsS3 클래스를 구현
    @Service
    @RequiredArgsConstructor
    public class ImageSeviceAwsS3 implements ImageService {
    

...

}

2. Config 파일을 통해 `ImageService` 인터페이스의 구현체로 `ImageSeviceAwsS3` 클래스를 사용하겠다고 설정

```java
@Configuration
public class ServiceConfig {
    @Bean
    @Profile("local")
    public ImageService imageServiceLocal() {
        return new ImageServiceLocal();
    }

    @Bean
    @Profile("prod")
    public ImageService imageServiceS3(AmazonS3 amazonS3) {
        return new ImageServiceS3(amazonS3);
    }
}
  • 이 코드는 로컬에서는 ImageServiceLocal 구현체를 사용하고
  • 실제 prod 환경에서는 ImageServiceAwsS3 구현체를 사용하겠다고 설정한 코드

➡ 따로 코드를 수정할 것 없이, S3에 저장하는 로직 구현하고 이를 @Bean으로 등록하면 된다


📌 정리

  • 추후에 S3가 아니더라도 다른 위치에 저장하게 되더라도 해당 로직 구현하고 config에 설정만 해주면 된다
  • 컨트롤러의 이미지 저장 코드는 전혀 수정하지 않고 로직을 변경할 수 있다
  • 이를 통해, 유지보수성이 상당히 올라감

최근에 이론적으로 DIP, OCP 등 객체지향의 5대원칙을 공부했었다.
실제로 내 프로젝트에 해당 원칙을 적용해보니 제대로 이해가 간다.
역시 코드로 느껴야 돼...

추후에 해당 구조에서도 겹치는 코드가 많아서 템플릿 메서드 패턴 도입함... ㅎㅎ
[여기서 더 발전된 패턴 볼 수 있음!] (https://velog.io/@nick9999/Outstagram-%ED%85%9C%ED%94%8C%EB%A6%BF-%EB%A9%94%EC%84%9C%EB%93%9C-%ED%8C%A8%ED%84%B4%EC%9D%84-%EC%8B%A4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0)

반응형