프로젝트 이해하기 라고 적긴 했지만 사실 프레임워크가 어떻게 흘러가고, 어떻게 코딩해야 하는지 감을잡는 단계라고 생각하면 되겠다. 앞서 말했다시피 이전 프로젝트에서 Nest.JS 코드를 처음 봤을때 팀원이 '이렇게 하면 되요'라고 하는걸 듣고 무작정 따라하다가 DI 패턴을 여러번 접하고 이런건가? 하는 감만 잡았었다.
하지만 혼자하는 프로젝트이다 보니 확실한 이해가 필요했다.

(역시 코딩도 장비빨이다. 32인치 모니터 쓰니까 역체감이 심하다.)
이번에 살펴볼 코드이다.
프로젝트를 만든 뒤 webflux를 활용한 간단한 예제를 작성해봤다.
그럼 실행 과정부터 알아보자.

스프링을 실행하면 위와 같은 실행과정들이 주루룩 뜬다.
이를 읽어보자.
위는 기본적인 설정인거 같다. 건드린게 없으니 다 default 가 뜬다.
JPA 또한 건드린게 없어서 interface가 발견되지 않는다.
아파치/톰켓 관련 설정이다.
https는 나중에 배포할때 설정할 예정이고, 포트 또한 기본값인 8080
WebApplicationContext가 초기화 되었다는 것이다.
root web/web 각각 존재하며 둘다 완료되었다는 것.
하이버네이트 코드이다.
봐도 뭐라는지 모르겠다.
레퍼런스 : https://docs.jboss.org/hibernate/orm/current/logging/logging.html
하지만 자세한건 몰라도 JPA와 ORM 관련 주제라는건 알 수 있다.
하이버네이트 ORM(Hibernate ORM)은 자바 언어를 위한 객체 관계 매핑 프레임워크이다 - wiki
따라서, 데이터베이스에 영속성 객체를 매핑하는 중이라고 보면 될것같다.
보아하니 static에 있는 페이지들을 추가하고, 상태를 점검하는거 같다.
특히 25번을 보니 이전의 상황과 비교하여 달라진 곳이 있나 재확인 하고,
확인이 되었다면 이전에 사용되었던 도구들도 종료하는것 같다.
로딩이 시작될때 주루루룩 뜨고 이게 뭔가싶어서 봐도 눈아파서 포기했었는데,
한번 읽어보니까 생각보다는 어려운 내용이 아니었다.
정리를 해보자면
가 되겠다.

실행 코드는 총 3가지 부분으로 나뉜다.
Model , View , Controller로 나눠지는게 아닌가? 라고 한다면
어느정도는 맞는 말이긴 하지만 코드상에서는 틀린 말이 된다.
또 코드에서 틀렸다고 하면 MVC 실행 코드를 뜯어와서 맞다고 할 수 있지만,
내가 말하려는거는 개발자가 직접 타이핑 하는 코드에 한정해서 말하는 것이다.
// config.java
@Configuration
public class AppConfig {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
//service.java
@Service
public class FileUploadService {
private final WebClient.Builder webClientBuilder;
public FileUploadService(WebClient.Builder webClientBuilder) {
this.webClientBuilder = webClientBuilder;
}
public Mono<String> uploadFile() {
String url = "https://api.example.com/upload"; // 실제 API URL로 변경
Resource resource = new ClassPathResource("path/to/your/file.txt");
return webClientBuilder.build()
.post()
.uri(url)
.contentType(MediaType.MULTIPART_FORM_DATA)
.body(BodyInserters.fromMultipartData("file", resource))
.retrieve()
.bodyToMono(String.class);
}
}
// controller.java
@RestController
public class FileUploadController {
private final FileUploadService fileUploadService;
public FileUploadController(FileUploadService fileUploadService) {
this.fileUploadService = fileUploadService;
}
@GetMapping("/upload-file")
public Mono<String> upload() {
return fileUploadService.uploadFile();
}
}
이번에 내가 사용한 예제의 코드이다.
Config 에서는 WebClient를 Bean에 등록하여 사용할 수 있게 하였고
Service 에서는 WebClient의 의존성을 받아와 기능을 구현하였다.
Controller 에서는 Service의 로직을 받아와서 실행하는 부분이 구현되었다.
즉
와 같은 구조를 가지는 것을 알 수 있다.
왜 Config가 아닌 다른 파일이라고 말을 적어놨냐면
DTO , Domain 등등 여러 기능을 구현하기 위한 파일들이 있다.
어렵게 생각할것 없다.
어떻게 구현해야 할지 감이 안왔었는데, 어느정도 감이 잡힌것 같다.

현재 사용하고 있는 폴더의 구조는 위과 같다.
위와 같이 controller , service , config 등의 폴더에 파일을 배치하는 것을 계층형 구조라고 한다.

계층형은 위와 같은 폴더 구조를 가지고 있다고 보면 된다.
하나의 폴더에 Controller가 모여있는 형태다.
또 다른 형태는 도메인형 구조가 있다.

도메인형은 위와 같다.
모듈마다 Controller, Service.... 등 필요한 파일을 배치하는 것이다.
지난 프로젝트를 하며 느꼈던 장단점을 적어보자면
계층형
장점
단점
도메인형
장점
단점
그래서 나는 도메인형으로 폴더를 관리할 것 같다.
기능 중복/폴더 관리의 오버헤드가 발생할 수 있지만
개인프로젝트 특성상 아키텍처의 크기가 커질 수 없고,
기능의 갯수도 많지않아 중복의 걱정이 적다고 판단했다.