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 #1099

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open

Conversation

DHkimgit
Copy link
Contributor

🔥 연관 이슈

image

  • API 요구명세, 피그마
  • 캠퍼스팀 11월 버스 스프린트 - 버스 교통편 조회하기 기능을 구현한 API 입니다.

🚀 작업 내용

  • 출발지, 도착지, 날짜, 시간, 차량 종류에 대응하는 버스 스케줄을 반환하는 API를 작성했습니다.

설계

image

  • 스케줄을 조회하는 메서드에 대한 추상화가 가능하다고 생각해서 이를 적용했습니다.
  • 고속버스의 경우 스케줄 데이터를 가져오는 외부 API가 현재 KEY 만료로 동작하지 않는 상태입니다. redis에 정적으로 저장된 데이터를 가져오는 방법이 있었으나, 추후 리팩토링이 예정되어 있으므로 일단 데이터를 final class에 정적으로 정의하고 이를 이용했습니다.

DataSource

  • 셔틀버스(shuttle, commuting) : MongoDB (collection = "bus_timetable")
  • 시내버스 : MongoDB (collection = "citybus_timetable")
  • 고속버스(대성) : ExpressBusSchedule 클래스

셔틀버스 스케줄 조회 상세 구현 로직

image

  • Stream을 이용해서 데이터를 정제합니다.
public boolean filterDepartAndArriveNode(BusStation departNode, BusStation arriveNode) {
        boolean foundDepart = false;
        for (ArrivalNode node : arrivalInfos) {
            if (!foundDepart && node.getNodeName().contains(departNode.getQueryName())) {
                foundDepart = true;
            }
            else if (foundDepart && node.getNodeName().contains(arriveNode.getQueryName())) {
                return true;
            }
        }
        return false;
    }
  • ArrivalNode 를 순회하면서 depart와 arrive가 순서대로 나온다면 결과에 추가하는데, 혹시 더 좋은 방법 떠오르신다면 알려주세요...

RequestBody

{
	"date": "2024-11-05",
	"time": "00:00",
	"bus_type": "ALL",
	"depart": "KOREATECH",
	"arrival": "TERMINAL"	
}
  • date: 요청하는 날짜 (예: "2024-11-05").
  • time: 요청하는 시간 (예: "00:00").
  • bus_type: 요청할 버스 유형 (ALL, CITY, EXPRESS, SHUTTLE)
  • depart: 출발지 (KOREATECH, TERMINAL, STATION).
  • arrival: 도착지 ( KOREATECH, TERMINAL, STATION).

ResponseBody

{
  "depart": "KOREATECH",
  "arrival": "TERMINAL",
  "depart_date": "2024-11-05",
  "depart_time": "16:00",
  "schedule": [
    {
      "bus_type": "express",
      "route_name": "대성티앤이",
      "depart_time": "16:50"
    },
    {
      "bus_type": "city",
      "route_name": "400",
      "depart_time": "16:56"
    },
    {
      "bus_type": "city",
      "route_name": "402",
      "depart_time": "17:30"
    },
    {
      "bus_type": "shuttle",
      "route_name": "주중(20시 00분)",
      "depart_time": "20:00"
    }
  ]
}

💬 리뷰 중점사항

  • 설계, 구현 다 부족합니다ㅜ 한번씩 읽어보시고 조언 부탁드려요!

Copy link

github-actions bot commented Nov 28, 2024

Unit Test Results

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

Results for commit 0552b56.

♻️ This comment has been updated with latest results.

@DHkimgit DHkimgit added Team Campus 캠퍼스 팀에서 작업할 이슈입니다 기능 새로운 기능을 개발합니다. labels Nov 28, 2024
Copy link
Contributor

@kih1015 kih1015 left a comment

Choose a reason for hiding this comment

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

PR 상세히 작성해주셔서 리뷰하기 편했습니다!

고생많이하셨어요~

Comment on lines 27 to 30
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_400 = 6;
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_402 = 13;
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_405 = 7;
private static final Integer ADDITIONAL_TIME_DEPART_TO_STATION = 7;
Copy link
Contributor

Choose a reason for hiding this comment

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

A

기점에서 정류장까지 걸리는 시간(분)인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

맞습니다! 시내버스 API 에서 받아오는 출발 시간 데이터는 기점 출발 기준입니다. 예를 들어 400번의 경우 한기대 정류장이 아니라 출발지인 병천3리 정류장을 기준으로 스케줄 정보를 제공합니다. 따라서 사용자가 한기대 -> 터미널의 스케줄을 요청한 경우 시간 데이터에 병천3리 -> 한기대 사이의 이동 시간을 추가하여 시간을 보정합니다. 해당 작업을 위해 정의한 상수입니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A

해당 정보의 출처는 어디인지, 이 상수들의 용도가 무엇인지 주석으로 명시하면 좋을 것 같아요!

Comment on lines +95 to +101
if (!foundDepart && node.getNodeName().contains(departNode.getQueryName())) {
foundDepart = true;
}

else if (foundDepart && node.getNodeName().contains(arriveNode.getQueryName())) {
return true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

C

출발지를 찾는 로직과 도착지를 찾는 로직을 else로 엮지 않고 분리하면 조금 더 잘 읽힐 것 같습니다!

            if (!foundDepart && node.getNodeName().contains(departNode.getQueryName())) {
                foundDepart = true;
            }
            if (foundDepart && node.getNodeName().contains(arriveNode.getQueryName())) {
                return true;
            }

Copy link
Contributor

@kih1015 kih1015 Nov 29, 2024

Choose a reason for hiding this comment

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

else-if 블록이 실행되는 경우를 살펴보려면, 상위 if문의 조건과, else-if문의 조건을 모두 만족해야하기 때문에 조건을 두번 확인해야하는 수요가 생깁니다.

if 문을 한번만 사용한다면 분기를 한번만 확인하기 때문에 가독성이 높아진다고 생각합니다. 어떻게 생각하시나요?

참조: https://velog.io/@jiwon615/%EC%9E%90%EB%B0%94-%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C-if-else%EB%AC%B8-%EC%9A%B0%EC%95%84%ED%95%98%EA%B2%8C-%EC%A7%80%EC%9A%B0%EB%8A%94-%EB%B0%A9%EB%B2%95

@DHkimgit DHkimgit self-assigned this Nov 28, 2024
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.

리뷰 늦게남겨서 죄송합니다 😭
고생하셨습니다! 코멘트 확인 부탁드려요~

### 버스 교통편 조회
- **시간** : 00:00 인 경우 해당 날짜의 모든 스케줄을 조회합니다.
- **날짜** : 요일을 기준으로 스케줄을 출력합니다. 공휴일 처리는 구현되어 있지 않습니다.
- **출발지 & 도착지** : 출발지와 도착지가 일치하는 경우 빈 리스트를 반환합니다. (천안역 -> 터미널) & (터미널 -> 천안역) 역시 빈 리스트를 반환합니다.
Copy link
Collaborator

Choose a reason for hiding this comment

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

R

터미널, 천안역 간 교통편 조회는 빈 결과를 반환한다는 요구사항이 있었나요??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

저희 데이터 중 터미널-천안역 간 정확한 스케줄 정보를 제공할 수 있는 데이터가 없어서 빈 결과를 반환하게 했습니다. 따로 제시된 요구사항은 없습니다. 천안역 -> 천안역이 빈 리스트를 반환하는 것과 같은 맥락으로 생각했습니다. PM님과 상의해야하는 부분일까요?

Comment on lines +114 to +115
@Parameter(description = "yyyy-MM-dd") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date,
@Parameter(description = "HH:mm") @RequestParam String time,
Copy link
Collaborator

Choose a reason for hiding this comment

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

C

request와 response에서 모두 date와 time을 분리하여 전달하고 있는데, 분리해야 했던 이유가 있을까요?? 다른 곳에서는 대부분은 합쳐서 사용하고 있지 않나요??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

디자인에 '오늘 오후 10:30 출발' 이런식으로 출력하도록 되어 있길래 분리 하는 게 클라이언트 입장에서 더 편할 것 같다고 생각했습니다. 버스 도메인 다른 API(버스 검색)도 저런 형태로 정보를 받고 있어서 그대로 진행했습니다.

Comment on lines 116 to 118
@Parameter(
description = "CITY, EXPRESS, SHUTTLE, ALL"
) @RequestParam BusRouteType busRouteType,
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을 주면 swagger에서 조회 시 드롭다운으로 나타날텐데 description에 예시를 제공해야 할까요??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

불필요하네요! 제거하겠습니다.

Copy link
Collaborator

@songsunkook songsunkook Dec 10, 2024

Choose a reason for hiding this comment

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

C

request dto 용도의 클래스를 만들어야 한다면 차라리 GET요청이지만 request body를 사용하는 건 어떻게 생각하시나요?? 기능에 비해 복잡도가 커지는 것 같아서 우려되네요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BusRouteCommand를 request dto처럼 만드는게 어떻냐는 말씀이신가요? command 객체가 BusRouteStrategy 추상화 메소드의 매개변수 타입으로 사용되고 있는데 이 객체를 request dto처럼 만들면 더 복잡해 질 것 같습니다.

Comment on lines 55 to 60
@JsonNaming(SnakeCaseStrategy.class)
public record ScheduleInfo(
String busType,
String busName,
LocalTime departTime
) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

A

여기도 @Schema로 부연설명을 붙일 수 있을 것 같아요. 그렇게 한다면 schedule 변수의 Schema 예시 설명을 제거할 수 있을 것 같습니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

수정했습니다.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A

주석으로 부연설명을 조금 달아두는 것도 좋을 것 같아요!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

적용했습니다.

Comment on lines 27 to 30
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_400 = 6;
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_402 = 13;
private static final Integer ADDITIONAL_TIME_DEPART_TO_KOREATECH_405 = 7;
private static final Integer ADDITIONAL_TIME_DEPART_TO_STATION = 7;
Copy link
Collaborator

Choose a reason for hiding this comment

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

A

해당 정보의 출처는 어디인지, 이 상수들의 용도가 무엇인지 주석으로 명시하면 좋을 것 같아요!

}

public ScheduleInfo getCommutingShuttleBusScheduleInfo(BusStation depart) {
String busType = "한기대".equals(depart.getQueryName()) ? "하교셔틀" : "등교셔틀";
Copy link
Collaborator

Choose a reason for hiding this comment

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

A

출발지가 한기대가 아닌데 하교셔틀이면 어떡하나요??
ex) 터미널 -> 천안역

+) 크게 치명적인 내용은 아닌 것 같습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

위 터미널 <-> 천안역 사이 빈 결과를 반환 부분과 연결되는 내용 같아요.. 셔틀버스를 터미널에서 타서 천안역에서 내리는 경우는 없다고 생각하고 배제해서 로직을 작성했습니다...

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