일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- netty
- Repository
- 배열
- JWT
- 백엔드 설정
- MySQL
- 네티 클라이언트
- 클래스
- 프로젝트
- 네티 서버
- react
- 자료형
- Security
- 자바
- axios
- Spring Boot
- springboot
- 도커
- Java
- service
- recoil
- 기초설정
- 코틀린
- 채팅
- Kotlin
- Spring
- 팀프로젝트
- controller
- 스프링부트
- toyproject
- Today
- Total
hyuko
여행일정 생성 본문
여행 일정 생성에 대한 주요 도메인을 설명합니다.
우리의 목표는 다음과 같습니다.
- 여행 일정을 저장할 수 있어야 한다.
- 원하는 날짜를 선택할 수 있어야 합니다.
- 여행에 함께 할 인원을 선택하고 이를 공유 할 수 있어야 합니다.
이 세 가지를 중심으로 코드를 구현하려 했습니다. 하나씩 저장하면 간편하게 진행될 것이라 생각했습니다.
하지만 두 가지 주요 문제가 발생했습니다.
첫번째 문제는 여행 일정이란 것이 여러 날짜의 정보를 포함하고, 각 날짜마다 다른 장소들이 할당되어야 하는
상황이었습니다. 즉, 하나의 여행이 등록될 때, 여러 개의 날짜 정보가 해당 여행의 ID 값과 매칭되어 생성되어야 했습니다.
이와 더불어 , 해당 날짜 정보의 ID 값을 기준으로 location 정보들이 각각 생성되어야 했습니다.
두번째 문제는 클라이언트에서 서버로 데이터를 전송할 때 ,
하나의 여행 정보 안에 스케줄 데이터와 해당 스케줄에 맞는 위치 정보들이 한 번에 전달되는 상황이었습니다.
따라서, 이 정보들을 한 번에 등록해야 했습니다. 이 문제를 해결하기 위해 프로시저를 사용하기로 결정했습니다.
백엔드에서는 Spring Boot를 사용하여 서버를 구현했습니다. 클라이언트에서 데이터를 가져오는
DTO와 컨트롤러의 모습은 다음과 같습니다.
// TravelPlanReqDto.java
@Getter @Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TravelPlanReqDto {
private int id;
private LocalDate date;
private List<LocationReqDto> location;
private List<PartyDataReqDto> partyData;
public void forEachLocation(Consumer<LocationReqDto> action) {
for (LocationReqDto locationReqDto : location) {
if (locationReqDto != null) {
action.accept(locationReqDto);
}
}
}
}
// TravelPlanController.java
@RestController
@RequestMapping("/api/v1/travel/plan")
@RequiredArgsConstructor
public class TravelPlanController {
private final TravelService travelService;
@PostMapping("/save")
public ResponseEntity<?> plan(@RequestBody List<TravelPlanReqDto> travels) {
travelService.travelSave(travels);
return ResponseEntity.ok(DataRespDto.ofDefault());
}
}
// TravelService.java
@Service
@RequiredArgsConstructor
public class TravelService {
private static final String IMAGE_URL = "http://localhost:8080/image/region/";
private final TravelRepository travelRepository;
public void travelSave(List<TravelPlanReqDto> travels) {
String travelName = UUID.randomUUID().toString();
Integer travelId = null;
for (TravelPlanReqDto dto : travels) {
if (dto == null || dto.getLocation() == null || dto.getPartyData().isEmpty()) continue;
travelId = saveTravelData(travelName, travelId, dto);
}
}
private Integer saveTravelData(String travelName, Integer travelId, TravelPlanReqDto dto){
for (LocationReqDto location : dto.getLocation()) {
for (PartyDataReqDto party : dto.getPartyData()) {
travelId = travelRepository.callInsertTravelData(
(travelId == null) ? travelName : null,
location.getAddr(),
location.getLat(),
location.getLng(),
party.getUserId(),
dto.getDate()
);
}
}
return travelId;
}
}
TravelPlanReqDto에서는 여행에 필요한 날짜 정보와 함께갈 인원, 장소 정보를 리스트 형식으로 받아옵니다.
이를 서비스 계층에서 처리하여 저장합니다.
package com.korea.triplocation.service;
import com.korea.triplocation.api.dto.request.travel.LocationReqDto;
import com.korea.triplocation.api.dto.request.travel.PartyDataReqDto;
import com.korea.triplocation.api.dto.request.travel.TravelPlanReqDto;
import com.korea.triplocation.api.dto.request.travel.TravelUpdateReqDto;
import com.korea.triplocation.api.dto.response.MyTravelInfoRespDto;
import com.korea.triplocation.domain.travel.entity.*;
import com.korea.triplocation.repository.TravelRepository;
import com.korea.triplocation.security.PrincipalUser;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
@RequiredArgsConstructor
public class TravelService {
private static final String IMAGE_URL = "http://localhost:8080/image/region/";
private final TravelRepository travelRepository;
public void travelSave(List<TravelPlanReqDto> travels) {
String travelName = UUID.randomUUID().toString();
Integer travelId = null;
for (TravelPlanReqDto dto : travels) {
if (dto == null || dto.getLocation() == null || dto.getPartyData().isEmpty()) continue;
travelId = saveTravelData(travelName, travelId, dto);
}
}
private Integer saveTravelData(String travelName, Integer travelId, TravelPlanReqDto dto){
for (LocationReqDto location : dto.getLocation()) {
for (PartyDataReqDto party : dto.getPartyData()) {
travelId = travelRepository.callInsertTravelData(
(travelId == null) ? travelName : null,
location.getAddr(),
location.getLat(),
location.getLng(),
party.getUserId(),
dto.getDate()
);
}
}
return travelId;
}
CREATE DEFINER=`admin`@`%` PROCEDURE `InsertTravelData`(IN travelName VARCHAR(255), IN addr VARCHAR(255), IN lat decimal(18,10), IN lng decimal(18,10), IN userId integer, IN scheduleDate date)
BEGIN
DECLARE v_travelId INT DEFAULT (SELECT MAX(travel_id) FROM travels_tb);
DECLARE v_locationId INT;
DECLARE v_scheduleId INT;
-- Check if the travel name is NULL
IF travelName IS NOT NULL THEN
-- Insert into travels_tb and get the generated ID
INSERT INTO travels_tb(travel_name) VALUES (travelName);
SET v_travelId = LAST_INSERT_ID();
END IF;
-- Check if the same dateId and visitDate already exist in schedule_tb
IF NOT EXISTS (SELECT 1 FROM schedule_tb WHERE travel_id = v_travelId AND schedule_date = scheduleDate) THEN
-- Insert into schedule_tb and get the generated ID
INSERT INTO schedule_tb(travel_id, schedule_date) VALUES (v_travelId, scheduleDate);
SET v_scheduleId = LAST_INSERT_ID();
ELSE
-- If record already exists, get the schedule_id
SET v_scheduleId = (SELECT schedule_id FROM schedule_tb WHERE travel_id = v_travelId AND schedule_date = scheduleDate);
END IF;
-- Insert into location_tb and get the generated ID
IF NOT EXISTS (SELECT 1 FROM location_tb WHERE address = addr) THEN
INSERT INTO location_tb(address, location_x, location_y) VALUES (addr, lat, lng);
SET v_locationId = LAST_INSERT_ID();
ELSE
SET v_locationId = (SELECT location_id FROM location_tb WHERE address = addr);
END IF;
-- Insert into travel_participants_tb, ignore if the pair (travel_id, user_id) already exists
IF NOT EXISTS (SELECT 1 FROM travel_participants_tb WHERE travel_id = v_travelId AND user_id = userId) THEN
INSERT INTO travel_participants_tb(travel_id, user_id) VALUES (v_travelId, userId);
END IF;
-- Insert into travel_routes_tb
IF NOT EXISTS (SELECT 1 FROM travel_routes_tb WHERE schedule_id = v_scheduleId AND location_id = v_locationId) THEN
INSERT INTO travel_routes_tb(schedule_id, location_id) VALUES (v_scheduleId, v_locationId);
END IF;
SELECT v_travelId, v_locationId, v_scheduleId;
END
여행 이름은 사용자에게서 받지 않고, 랜덤으로 생성된 UUID를 사용하여 저장합니다.
그리고 이 저장된 여행 이름에 따라 여행을 저장하고,
저장된 여행에 따라 위치 정보를 추출하여 저장하는 로직을 구현하였습니다.
이 서비스를 거쳐 프로시저를 호출하여 일관성을 유지합니다.
이렇게 하여 여행 일정 생성 도메인의 핵심적인 부분을 다루었습니다.
'토이프로젝트 > 팀 프로젝트' 카테고리의 다른 글
비밀번호 변경 (0) | 2023.05.21 |
---|---|
회원 정보 수정 (0) | 2023.05.21 |
Spring Boot를 사용한 여행 계획 API 개발 (0) | 2023.05.21 |
React를 활용한 여행 일정 계획 애플리케이션 개발 (0) | 2023.05.21 |
로그인 (0) | 2023.05.10 |