사이드 프로젝트 리펙토링(3) - 도메인 디렉토리 구조가 더 좋은 것 같다

김정훈·2024년 7월 5일
0

프로젝트의 규모가 커지면서 점점 파일이 쌓여가고 있다. 복잡한 디렉토리 구조가 거슬리때 쯤
https://cheese10yun.github.io/spring-guide-directory/ 이 글을 보게됐다.

핵심

계층형

src/
└── main/
└── java/
└── com/
└── example/
└── myapp/
├── config/
│ └── SecurityConfig.java
├── controller/
│ ├── MemberController.java
│ └── GameController.java
├── service/
│ ├── MemberService.java
│ └── GameService.java
├── repository/
│ ├── MemberRepository.java
│ └── GameRepository.java
├── model/
│ ├── Member.java
│ └── Game.java
├── dto/
│ ├── MemberDto.java
│ └── GameDto.java
└── Application.java

도메인형

src/
└── main/
└── java/
└── com/
└── example/
└── reactmapping/
├── domain/
│ ├── member/
│ │ ├── controller/
│ │ │ └── MemberController.java
│ │ ├── service/
│ │ │ └── MemberService.java
│ │ ├── repository/
│ │ │ └── MemberRepository.java
│ │ └── dto/
│ │ └── MemberDto.java
│ ├── game/
│ │ ├── controller/
│ │ │ └── GameController.java
│ │ ├── service/
│ │ │ └── GameService.java
│ │ └── repository/
│ │ └── GameRepository.java
│ └── ...
├── config/
│ └── SecurityConfig.java
├── exception/
│ └── GlobalExceptionHandler.java
└── Application.java

현재 내 구조는 계층형이다.

이렇게 보면 별 문제 없어 보이는데

Service는 service대로 쭉 나열되어 있으니까 원하는 service에 찾아가는게 힘들다.

프로젝트 규모가 작을 때는 오히려 계층형이 더 편하다. 하지만 규모가 커질 수록 파일이 많아지는데 service에 접근했더니 20개의 service가 나열된다면 굉장히 보기 싫을 것이다.

변경 후

디렉토리


훨씬 깔끔하다.

클래스

@Service
@Transactional
@RequiredArgsConstructor
public class ImageCreateService {
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;
    private final S3Config s3Config;
    private static final String EMPTY_STRING = "";

    public String createImg(MultipartFile file) throws IOException {
        if (isFilenameEmpty(file)) {
            return null;
        }
        String fileExtension = extractFileExtension(file.getOriginalFilename());
        String uuid = generateUUID();

        File localFile = createTemporaryFile(file, uuid, fileExtension);
        uploadFileToS3(uuid, fileExtension, localFile);

        return generateFileUrl(uuid, fileExtension);
    }

    private boolean isFilenameEmpty(MultipartFile file) {
        return Objects.equals(file.getOriginalFilename(), EMPTY_STRING);
    }

    private String extractFileExtension(String filename) {
        return filename.substring(filename.lastIndexOf("."));
    }

    private String generateUUID() {
        return String.valueOf(UUID.randomUUID());
    }

    private File createTemporaryFile(MultipartFile file, String uuid, String fileExtension) throws IOException {
        File localFile = File.createTempFile(uuid, fileExtension);
        try (InputStream inputStream = file.getInputStream()) {
            FileUtils.copyInputStreamToFile(inputStream, localFile);
        }
        return localFile;
    }

    private void uploadFileToS3(String uuid, String fileExtension, File file) {
        s3Config.amazonS3Client().putObject(new PutObjectRequest(bucket, uuid + fileExtension, file)
                .withCannedAcl(CannedAccessControlList.PublicRead));

    }

    private String generateFileUrl(String uuid, String fileExtension) {
        return s3Config.amazonS3Client().getUrl(bucket, uuid + fileExtension).toString();
    }

}

createImage() 하나의 메소드를 리펙토링 한건데 이렇게 많은 메서드들이 생겼다. image 관련 로직을 imageService에 모조리 담아 리펙토링 하면 몇 백줄로 늘어날 것이고, image 기능별로 service를 나누면 service 디렉토리에 무수히 많은 service들이 생길 것이다.
즉 도메인 형식으로 바꾸면

이렇게 마음놓고 늘릴 수 있다.

profile
백엔드 개발자

0개의 댓글