Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 학교버스 시간표 관련 API #1119

Merged
merged 13 commits into from
Dec 12, 2024
Merged

Conversation

kih1015
Copy link
Contributor

@kih1015 kih1015 commented Dec 5, 2024

🔥 연관 이슈

새롭게 개선되는 학교버스 시간표 기능에서 다음과 같은 변경점이 존재합니다.

  • 노선 분류 변경(셔틀, 통학 -> 순환, 주중, 주말)
    image
  • 노선과 정류장 이름에 소제목 제공
    image
  • 단일 노선이 아니라 표 형태로 제공
    image
    • 정류장에 정차하지 않는다면 null값으로 제공해야함
    • 기존 데이터 구조로 사실상 불가능
  • 업데이트 시간이 아니라 학기 정보 제공
    image

위와 같은 변경점들로 인해 기존의 mongodb 컬렉션(bus_timetables)을 그대로 사용하기에 많은 어려움이 있습니다.

따라서 변경사항에 적합한 데이터 구조를 가진 컬렉션(shuttlebus_timetables)을 추가하려합니다.

예상되는 문제점들과 솔루션은 다음과 같습니다.

  • 학기가 전환(정규학기 -> 계절학기)될 때 배치 작업 두번 필요
    • SOL: shuttlebus_timetables컬렉션에 "정규학기, 계절학기, 방학" 데이터를 미리 삽입
    • 학기가 전환됨에 따라 기간에 맞는 데이터 자동 제공 (학기 정보는 versions 테이블의 title 속성값을 따름)
  • 학교버스 노선 및 시간표 데이터가 중복 (bus_timetables, shuttlebus_timetables) -> 이상현상 발생 가능성 존재
    • SOL: 1월 중 버스리팩토링 기간에 하나로 통합
  • 새로운 배치 구조 필요
    • SOL: 12월 중 JAVA로 배치 마이그레이션 -> 버스 리팩토링 기간 배치 구조 수정 가능

🚀 작업 내용

  1. /bus/courses/shuttle: 학교버스 노선 조회 API 구현
  2. /bus/timetable/shuttle: 학교버스 시간표 조회 API 구현

shuttlebus_timetables 스키마 예시 천안셔틀

{
  "_id": {
    "$oid": "675013f9465776d6265ddfdb"
  },
  "semester_type": "정규학기",
  "region": "천안",
  "route_type": "순환",
  "route_name": "천안 셔틀",
  "sub_name": null,
  "node_info": [
    {
      "name": "본교",
      "detail": null
    },
    {
      "name": "2캠퍼스",
      "detail": null
    },
    {
      "name": "천안터미널",
      "detail": null
    },
    {
      "name": "천안역",
      "detail": null
    },
    {
      "name": "본교",
      "detail": null
    }
  ],
  "route_info": [
    {
      "name": "1회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "11:10",
        null,
        "11:35",
        "11:40",
        "12:10"
      ]
    },
    {
      "name": "2회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "13:10",
        null,
        "13:35",
        "13:40",
        "14:10"
      ]
    },
    {
      "name": "3회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "14:10",
        null,
        "14:35",
        "14:42",
        "15:15"
      ]
    },
    {
      "name": "4회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "16:10",
        null,
        "16:35",
        "16:40",
        "17:10"
      ]
    },
    {
      "name": "5회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "20:00",
        null,
        "20:25",
        "20:30",
        "21:00"
      ]
    },
    {
      "name": "6회",
      "running_days": [
        "MON",
        "TUE",
        "WED",
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "21:00",
        null,
        "21:25",
        "21:30",
        "22:00"
      ]
    },
    {
      "name": "목, 금 추가",
      "running_days": [
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "14:10",
        null,
        "14:35",
        "14:40",
        "15:10"
      ]
    },
    {
      "name": "목, 금 추가",
      "running_days": [
        "THE",
        "FRI"
      ],
      "arrival_time": [
        "16:30",
        null,
        "16:55",
        "17:00",
        "17:30"
      ]
    }
  ]
}

💬 리뷰 중점사항

/courses/shuttle 학교버스 노선 조회 API 구현
/timetable/shuttle 학교버스 시간표 조회 API 구현
모델 객체와 DTO 분리
컨트롤러 메서드 이름 변경
정규학기, 계절학기, 방학에 따라 다른 노선 반환
@kih1015 kih1015 added 기능 새로운 기능을 개발합니다. Team Campus 캠퍼스 팀에서 작업할 이슈입니다 labels Dec 5, 2024
@kih1015 kih1015 self-assigned this Dec 5, 2024
Copy link

github-actions bot commented Dec 5, 2024

Unit Test Results

344 tests   343 ✔️  1m 27s ⏱️
  41 suites      1 💤
  41 files        0

Results for commit ff355d2.

♻️ This comment has been updated with latest results.

전체 노선 조회 response 구조 변경
@kih1015 kih1015 force-pushed the feat/shuttle-timetable-api branch from f43cb64 to c835f5f Compare December 7, 2024 09:23
지역 순서대로 반환 (천안, 서울, 청주)
노선 종류 순서대로 반환 (순환, 주중, 주말)
Copy link
Contributor

@DHkimgit DHkimgit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

늦어서 죄송합니다!!

@@ -29,6 +34,8 @@
public class BusController implements BusApi {

private final BusService busService;
private final ShuttleBusRepository shuttleBusRepository;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

db로부터 받은 데이터를 단순히 response dto에 매핑시키는 간단한 로직이라 service 단 거치지 않는 구조로 만드신 것 같습니다. 이 과정에서 contoller에 repository 의존성이 추가되었는데 확장성이나 유지보수 고려하면 간단하더라도 service단 한번 거치는게 좋지 않을까요?

Comment on lines 111 to 113
@Operation(summary = "학교버스 시간표 조회")
@GetMapping("/timetable/shuttle")
ResponseEntity<ShuttleBusRouteResponse> getShuttleBusTimetable(@RequestParam String id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id에 무슨 내용이 들어와야 하는지 @Opreation(description = "") 로 적어주시면 api 문서 안봐도 되서 편할 것 같아요

Comment on lines 45 to 53
public static List<RouteRegion> mapCategories(List<ShuttleBusRoute> shuttleBusRoutes) {
return shuttleBusRoutes.stream()
.collect(Collectors.groupingBy(ShuttleBusRoute::getRegion))
.entrySet().stream()
.map(entry -> new RouteRegion(entry.getKey(), RouteName.mapRouteNames(entry.getValue())))
.sorted()
.toList();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

데이터 전송 객체가 너무 많은 책임을 가지고 있는 것 같아요. service 사용하지 않은 이유가 궁금해요.

Copy link
Contributor Author

@kih1015 kih1015 Dec 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Service에서 특정 DTO에 의존하게 되면 여러 종류의 Controller에서 해당 Service를 이용할 수 없어 코드 재사용성이 떨어지게 된다라고 생각해서 변환의 책임을 DTO에 두었습니다.

그런데 다시 생각해보니 말씀하신대로 데이터 전송 객체에 무거운 책임을 두는 것은 좋지 않은 생각인 것 같아요. service 사용하도록 수정하겠습니다. 👍

참조

Copy link
Collaborator

@songsunkook songsunkook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굉장히 늦은 리뷰 죄송합니다 😭
고생하셨습니다!

Comment on lines 93 to 103
@GetMapping("/courses/shuttle")
public ResponseEntity<ShuttleBusRoutesResponse> getShuttleBusRoutes() {
VersionMessageResponse version = versionService.getVersionWithMessage("shuttle_bus_timetable");
return ResponseEntity.ok()
.body(ShuttleBusRoutesResponse.of(shuttleBusRepository.findBySemesterType(version.title()), version));
}

@GetMapping("/timetable/shuttle")
public ResponseEntity<ShuttleBusRouteResponse> getShuttleBusTimetable(@RequestParam String id) {
return ResponseEntity.ok().body(ShuttleBusRouteResponse.from(shuttleBusRepository.getById(id)));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A

controller에서 repository에 직접 접근하고 있군요..!
service를 반드시 껴야하는 건 아니긴 한데, 괜찮은 구조라고 생각하시는지 궁금해요
저도 잘 확신이 안서네요..

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

controller 입장에서 계층적으로 service는 가까운 친구이지만, repository는 멀리있는 친구이기 때문에 service만 알고 있는 것도 좋은 방법 같습니다. (repository에 직접 참조한다면 당장은 편하겠지만..)
우선 service에 의존하도록 하고 bus 리팩토링 기간 조금 더 고민해보도록 하겠습니다!

Comment on lines 17 to 18
@Schema(description = "지역 이름", example = "천안")
String region,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A

enum을 적용하는 건 어떻게 생각하시나요??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum 사용 시, 정렬할 때 우선순위 값으로 활용할 수 있고 확장성이 향상되는 등 객체지향 기법에 적절하다고 생각해서 말씀하신대로 수정해보겠습니다👍

import in.koreatech.koin.domain.bus.exception.BusNotFoundException;
import in.koreatech.koin.domain.bus.model.mongo.ShuttleBusRoute;

public interface ShuttleBusRepository extends Repository<ShuttleBusRoute, ObjectId> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A

ObjectId는 무슨 자료형인가요??

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ObjectId: mongodb 방식에 특화되어 기본적으로 제공하는 id 타입으로 알고있습니다.
spring data mongodb에서 자바와 맵핑 가능하도록 제공하는 것으로 보입니다.
jpa에서 string이 아닌, 해당 타입으로 설정해야 id로 검색이 가능해서 설정해두었습니다.

uri 수정: /bus/timetable/shuttle/{id}
ShuttleBusService 구현
dto 책임 분리
dto 이름 변경
지역, 노선종류 속성 enum 대체
정렬 로직 개선
노선 정보에 detail 속성 추가
노선 지역 response 이름 수정
# Conflicts:
#	src/main/java/in/koreatech/koin/domain/bus/controller/BusApi.java
#	src/main/java/in/koreatech/koin/domain/bus/controller/BusController.java
@kih1015 kih1015 merged commit 91f7692 into develop Dec 12, 2024
4 checks passed
@kih1015 kih1015 deleted the feat/shuttle-timetable-api branch December 12, 2024 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team Campus 캠퍼스 팀에서 작업할 이슈입니다 기능 새로운 기능을 개발합니다.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants