프로젝트 이해하기

김태성·2024년 7월 28일

개인 프로젝트-1

목록 보기
12/53
post-thumbnail

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

하지만 혼자하는 프로젝트이다 보니 확실한 이해가 필요했다.

어떻게 실행되나


(역시 코딩도 장비빨이다. 32인치 모니터 쓰니까 역체감이 심하다.)

이번에 살펴볼 코드이다.
프로젝트를 만든 뒤 webflux를 활용한 간단한 예제를 작성해봤다.
그럼 실행 과정부터 알아보자.


스프링을 실행하면 위와 같은 실행과정들이 주루룩 뜬다.
이를 읽어보자.

  1. Java 21.0.3을 내 PID와 함께 실행한다.
  2. profile set이 없어서 default를 사용
  3. Devtools property가 default로 활성화
  4. 웹 로깅을 할꺼면 logging.level.web을 DEBUG로 바꿔라
  5. JPA를 기본 모드로 Bootstrapping한다.(부팅한다는뜻)
  6. Spring Data 리포지토리를 스캔. 발견된 interface 없음

위는 기본적인 설정인거 같다. 건드린게 없으니 다 default 가 뜬다.
JPA 또한 건드린게 없어서 interface가 발견되지 않는다.

  1. 톰켓이 8080으로 초기화된다(http)
  2. 톰켓 서비스 실행
  3. 아파치 톰켓 10.1.25버전 서블릿 엔진 실행

아파치/톰켓 관련 설정이다.
https는 나중에 배포할때 설정할 예정이고, 포트 또한 기본값인 8080

  1. WebApplicationContext 초기화 시작
  2. Root WebApplicationContext 초기화 완료. 118ms 걸림

WebApplicationContext가 초기화 되었다는 것이다.
root web/web 각각 존재하며 둘다 완료되었다는 것.

  1. Hibernate 코드 HHH000204
  2. Hibernate 코드 HHH000026
  3. No LoadTimeWeaver setup: ignoring JPA class transformer
  4. HikariPool 시작
  5. HikariPool에 postgresql.jdbc 연결을 추가
  6. HikariPool 실행 완료
  7. Hibernate코드 HHH90000025
  8. Hibernate코드 HHH000489
  9. 영속성 유닛을 위한 JPA entitymanagerfactory가 default로 초기화

하이버네이트 코드이다.
봐도 뭐라는지 모르겠다.
레퍼런스 : https://docs.jboss.org/hibernate/orm/current/logging/logging.html

하지만 자세한건 몰라도 JPA와 ORM 관련 주제라는건 알 수 있다.
하이버네이트 ORM(Hibernate ORM)은 자바 언어를 위한 객체 관계 매핑 프레임워크이다 - wiki

따라서, 데이터베이스에 영속성 객체를 매핑하는 중이라고 보면 될것같다.

  1. Welcome page 추가(static/index.html)
  2. LiveReload server가 ~~포트에 동작중
  3. Tomcat이 8080에 path'/'로 실행되었다
  4. Application이 0.254초만에 실행되었다.
  5. 컨디션 평가(condition evaluation)이 바뀌지 않았다.
  6. 영속성 유닛을 위한 JPA EntityManagerFactory(default)가 종료된다.
  7. HikariPool-3 종료가 시작된다.
  8. HikariPool-3 종료가 완료되었다.

보아하니 static에 있는 페이지들을 추가하고, 상태를 점검하는거 같다.
특히 25번을 보니 이전의 상황과 비교하여 달라진 곳이 있나 재확인 하고,
확인이 되었다면 이전에 사용되었던 도구들도 종료하는것 같다.

로딩이 시작될때 주루루룩 뜨고 이게 뭔가싶어서 봐도 눈아파서 포기했었는데,
한번 읽어보니까 생각보다는 어려운 내용이 아니었다.

정리를 해보자면

  1. 기본 설정 확인
  2. TomCat 실행
  3. WebApplicationContext 초기화
  4. Hibernate로 DB 관련 작업
  5. 잘 실행되었나 확인 후, 실행에 사용되었던 도구들 종료

가 되겠다.

MVC 패턴 실행

실행 코드는 총 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의 로직을 받아와서 실행하는 부분이 구현되었다.

  • Service에서는 로직의 처리를
  • Controller 에서는 Service를 사용
  • 다른 파일에서는 이러한 로직을 구현하는데 필요한 코드를 제공

와 같은 구조를 가지는 것을 알 수 있다.
왜 Config가 아닌 다른 파일이라고 말을 적어놨냐면
DTO , Domain 등등 여러 기능을 구현하기 위한 파일들이 있다.


어렵게 생각할것 없다.

  • config, dto, domain 등의 재료를 가지고
  • service로 로직을 구현하고
  • controller로 로직을 작동 시킨다는 것이다.

어떻게 구현해야 할지 감이 안왔었는데, 어느정도 감이 잡힌것 같다.

폴더 구조

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

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

도메인형은 위와 같다.
모듈마다 Controller, Service.... 등 필요한 파일을 배치하는 것이다.

지난 프로젝트를 하며 느꼈던 장단점을 적어보자면

계층형

장점

  • 같은 기능을 하는 파일끼리 모여있어서 기능 검토할때 편함(controller만 읽기등)
  • 하나의 파일(java에서는 클래스/객체 등)을 여러곳에서 DI할수있음

단점

  • 프로그램 전체적인 기능을 파악하기 힘듬
  • 특정 기능을 하는 코드끼리 관리할수가 없음(로그인 관련 기능만 모아놓기 ...)

도메인형

장점

  • 프로그램 기능을 모듈별로 파악하는게 편함
  • 특정 기능을 하는 코드끼리 모아놓기 편함(모듈로 관리)

단점

  • 기능 중복이 발생함 (public으로 만들어도 관리가 힘듬)
  • 폴더가 많아짐

그래서 나는 도메인형으로 폴더를 관리할 것 같다.
기능 중복/폴더 관리의 오버헤드가 발생할 수 있지만
개인프로젝트 특성상 아키텍처의 크기가 커질 수 없고,
기능의 갯수도 많지않아 중복의 걱정이 적다고 판단했다.

profile
닭이 되고싶은 병아리

0개의 댓글