유저 프로필 사진 저장 로직 개선

Regular Kim·2025년 5월 9일
0

Reelvy

목록 보기
1/11

개선 전

// UserUtil
public String saveProfileImage(MultipartFile profileImage, User user) { 
  // 기존 프로필 이미지가 있으면 삭제 
  if(!Objects.isNull(user.getProfileImagePath())) { 
      deleteImage(user.getProfileImagePath()); 
  } 
  String basePath = "myVideos/" + user.getId() + "/images/profile"; 
  String fileName = UUID.randomUUID() + "_" + profileImage.getOriginalFilename(); 
  Path filePath = Paths.get(basePath, fileName); 
  try {
    Files.createDirectories(filePath.getParent()); 
    Files.write(filePath, profileImage.getBytes()); 
  } catch (IOException e) {
    throw new RuntimeException("프로필 사진 변경에 실패했습니다.", e); 
  } return filePath.toString(); 
} 

public String saveBackgroundImage(MultipartFile backgroundImage, User user) { 
  // 기존 배경 이미지가 있으면 삭제 
  if(!Objects.isNull(user.getBackgroundImagePath())) { 
    deleteImage(user.getBackgroundImagePath()); 
  } 
  String basePath = "myVideos/" + user.getId() + "/images/background"; 
  String fileName = UUID.randomUUID() + "_" + backgroundImage.getOriginalFilename(); 
  Path filePath = Paths.get(basePath, fileName); 
  try {
    Files.createDirectories(filePath.getParent()); 
    Files.write(filePath, backgroundImage.getBytes()); 
  } catch (IOException e) {
    throw new RuntimeException("배경 사진 변경에 실패했습니다.", e); 
  } return filePath.toString(); 
}

사진을 저장하는 로직은 똑같지만 사진 종류가 다르다는 이유만으로 저장하는 메서드 2개를 정의해버렸다.

사진 종류에 따라서 위치만 다르게 저장하면 된다. 하지만 해당 문제해결 방안이 생각이 안 나서 중복되는 메서드가 하나 더 생겼다. 한층 더 복잡해진 클래스는 보너스다.

리팩토링 기획을 하던 중에 사진 종류를 상수로 만들어서 저장 위치를 동적으로 가져오자는 아이디어가 떠올랐다. 아래는 해당 아이디어 적용 후 결과이다.

개선 후

// UserUtil
public String saveImage(MultipartFile profileImage, User user, UserImageType userImageType) { 
  if (!Objects.isNull(userImageType.getImagePathOf(user))) {
    deleteImage(userImageType.getImagePathOf(user));
  }
  String basePath = "myVideos/" + user.getId() + "/images/" + userImageType.getFolderName();
  String fileName = UUID.randomUUID() + "_" + profileImage.getOriginalFilename();
  Path filePath = Paths.get(basePath, fileName);
  try {
    Files.createDirectories(filePath.getParent());
    Files.write(filePath, profileImage.getBytes());
  } catch (IOException e) {
    throw new RuntimeException("프로필 사진 변경에 실패했습니다.", e);
  }
  return filePath.toString();
}

메서드가 받는 파라미터가 하나 더 추가되었다. UserImageType 파라미터를 추가하여 저장할 이미지의 종류를 동적으로 지정할 수 있도록 하였다.

// UserImageType
public enum UserImageType {

	PROFILE("profile"){
		@Override
		public String getImagePathOf(User user) {
			return user.getProfileImagePath();
		}
	},
	BACKGROUND("background"){
		@Override
		public String getImagePathOf(User user) {
			return user.getBackgroundImagePath();
		}
	};

	private final String folderName;

	public abstract String getImagePathOf(User user);

	UserImageType(String folderName) {
		this.folderName = folderName;
	}

	public String getFolderName() {
		return folderName;
	}
}

이미지타입 상수는 위와 같다. getImagePathOf() 추상 메서드를 필드에서 필요한 대로 정의하였다.

하지만 여기서 더 개선할 수 있다면? 가능하다. 람다식을 사용하면 한 번 더 개선 할 수 있다.

최종 개선안

@RequiredArgsConstructor
public enum UserImageType {

	PROFILE("profile.jpg", User::getProfileImagePath),
	BACKGROUND("background.jpg", User::getBackgroundImagePath);

	@Getter
	private final String fileName;
	private final Function<User, String> userImagePathResolver;

	public String getImagePathOf(User user) {
		return userImagePathResolver.apply(user);
	}
}

롬복과 람다식을 사용하여 코드를 더 간결하게 개선하였다.

profile
What doesn't kill you, makes you stronger

0개의 댓글