프로그래밍/Project

[Spring] ToyProject 2단계(2) - 역할 분배, 기본 구조

코딩중독 2024. 1. 29. 22:54

월요일이 되어 팀에 호출(?)되어 역할 분배와 프로젝트 기본 구조를 만들었다.

영광스럽게도 혼자 끄적인 설계를 따라 진행하게 되었다.

사용자, 여행, 여정 크게 3개의 도메인으로 나눠놨을 때 여정 부분을 맡게 되었다.

물론 혼자 다 해보는 프로젝트도 진행 중이고 그 내용으로 포스팅을 진행한다.

 

여행의 종류(이동, 숙소, 체류)에 대해서는 enum 클래스를 사용하려고 했으나 1차적으로 String으로 처리한 후 시간여유가 있다면 enum클래스로 변경 예정이다.

예습하면서 미리 찾아보는게 좋겠다.

 

[여행 데이터베이스]

trip
컬럼명 데이터 타입 조건 설명 자바 변수명 자바 타입
id BIGINT(32) PK, AI 여행 아이디 id Long
user_id BIGINT(32) FK, NOT NULL 사용자 아이디 userId Long
name VARCHAR(50) NOT NULL 여행 이름 name String
start_date DATETIME NOT NULL 여행 출발 날짜 startDate LocalDateTime
end_date DATETIME NOT NULL 여행 도착 날짜 endDate LocalDateTime
status VARCHAR(20) NOT NULL 국내/외 여부 status enum

 

사용자별로 여러개의 여행을 저장할 수 있기 때문에 user_id를 외래키로 넣어뒀는데 이것 또한 1차적으로 진행하는 동안에는 user_id를 1로 고정해 두고 진행 예정이다.

 

[여행 API]

trip (/api/trip)
  Method URL return page
여행 전체 조회 GET / List<TripResponse>  
여행 정보 등록 POST /register void or TripResponse 등록 후 /api/trip 이동
여행 정보 조회(여정 포함) GET /{tripId} TripResponse  
여행 정보 수정 PUT /{tripId} void or TripResponse  
여행 정보 삭제 DELETE /{tripId} void 삭제 후 /api/trip 이동

 

[코드 진행]

Controller : 클라이언트로부터 입력을 받는 클래스 (Service 주입)

Service : POJO 역할을 하는 순수한 비즈니스 로직을 담당하는 클래스 (Repository, Converter 주입)

Converter : Entity -> DTO, DTO -> Entity 변환을 담당하는 클래스

Mapper(Repository) : MyBatis의 추상메서드 인터페이스

 

Request : Controller -> Service(Converter) -> Mapper

Response : Service -> Controller

[모델 생성]

UserEntity, UserRegisterRequest, UserLoginRequest, UserResponse

TripEntity, TripRequest, TripResponse

 

코드 생략

[Converter 생성]

사용자에게 입력을 받는 DTO(Request)클래스와 데이터베이스(Mapper)를 주입받는 Entity클래스, 그리고 클라이언트에 반환하는 DTO(Response) 클래스를 상황에 따라 변경하는 Converter클래스를 생성했다.

 

UserConverter, TripConverter

@Component
public class UserConverter {

    public UserEntity toEntity(UserRegisterRequest userRegisterRequest) {
        return UserEntity.builder()
            .name(userRegisterRequest.getName())
            .email(userRegisterRequest.getEmail())
            .password(userRegisterRequest.getPassword())
            .registeredAt(LocalDateTime.now())
            .build();
    }

    public UserResponse toResponse(UserEntity userEntity) {
        return UserResponse.builder()
            .id(userEntity.getId())
            .name(userEntity.getName())
            .email(userEntity.getEmail())
            .registeredAt(userEntity.getRegisteredAt())
            .build();
    }

    public List<UserResponse> toResponse(List<UserEntity> userEntityList) {
        return userEntityList.stream()
            .map(this::toResponse)
            .collect(Collectors.toList());
    }

}

 

모든 사용자의 정보를 전달하기 위해서 데이터베이스로부터 UserEntity를 List로 받게 되면, 단일 사용자의 toResponse메서드를 오버로딩 해서 만들었다.

@Component
public class TripConverter {


    public TripEntity toEntity(TripRequest tripRequest) {
        return TripEntity.builder()
            .userId(1L)
            .name(tripRequest.getName())
            .startDate(tripRequest.getStartDate())
            .endDate(tripRequest.getEndDate())
            .status(tripRequest.getStatus())
            .build();
    }


    public TripEntity toEntity(Long tripId, TripRequest tripRequest) {
        return TripEntity.builder()
            .id(tripId)
            .userId(1L)
            .name(tripRequest.getName())
            .startDate(tripRequest.getStartDate())
            .endDate(tripRequest.getEndDate())
            .status(tripRequest.getStatus())
            .build();
    }

    public TripResponse toResponse(TripEntity tripEntity) {
        return TripResponse.builder()
            .id(tripEntity.getId())
            .name(tripEntity.getName())
            .startDate(tripEntity.getStartDate())
            .endDate(tripEntity.getEndDate())
            .status(tripEntity.getStatus())
            .build();
    }

    public List<TripResponse> toResponse(List<TripEntity> tripEntityList) {
        return tripEntityList.stream()
            .map(this::toResponse)
            .collect(Collectors.toList());
    }

}

 

UserConverter와 동일하지만 특정 아이디를 전달받아서 여행 정보를 수정해야 할 때에 사용하기 위해 아이디 매개변수를 추가하고 toEntity메서드를 오버로딩 해서 만들었다.

 

사용자와 여행정보에 대한 CRUD를 완성했다.