Skip to content
woowa-busPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

65 Commits

Folders and files

Repository files navigation

버스 알리미

우테코 크루가 자주 이용하는 정류장과 버스를 Slack 명령어로 조회하고, 설정한 시간대에 버스가 곧 도착하면 Slack DM으로 알려주는 퇴근 보조 서비스입니다.

핵심 기능

  • /조회 [정류장]
  • /조회 [정류장] [버스번호]
  • /알림 [정류장] [버스번호] [몇 분 전] [시작시간] [종료시간]
  • /알림 초기화
  • /알림목록
  • /알림삭제 [정류장] [버스번호]
  • 정류장 별칭 허용
  • 조회 결과는 도착 시간 순으로 정렬
  • /도움말
  • /상태
  • /조회 결과는 Block Kit으로 렌더링
  • /알림목록은 Block Kit으로 렌더링
  • /알림목록에서 삭제 버튼 제공
  • 삭제 버튼을 누르면 기존 목록 메시지를 삭제 완료 메시지와 갱신된 알림목록으로 교체
  • /알림을 인자 없이 입력하면 Modal로 등록 (정류장 선택, 시간 선택)
  • Modal 등록 성공 시 사용자에게 등록 완료 DM 발송
  • 알림 DM에는 현재 시각과 "탑승 완료" 버튼 표시
  • 알림 DM의 "탑승 완료" 버튼을 누르면 오늘 더 이상 모든 알림 발송 안 함
  • /알림 초기화로 탑승 완료 이후 오늘 중지된 알림을 다시 울리도록 초기화
  • 1분 주기 알림 스케줄링
  • 같은 알림 10분 내 중복 발송 방지
  • 같은 사용자, 정류장, 버스번호 조합의 중복 등록 시 기존 알림 업데이트

기술 스택

  • Java 21
  • Spring Boot 4
  • Spring Web MVC
  • Spring Data JPA
  • H2 file mode
  • Slack Slash Command
  • Slack chat.postMessage
  • Slack views.open
  • Slack Block Kit Interactivity
  • 경기버스 API
  • Gradle

실행 준비

필수 환경변수:

export SLACK_BOT_TOKEN="<slack-bot-token>"
export SLACK_SIGNING_SECRET="..."
export GBIS_SERVICE_KEY="..."

주의:

  • Slack bot token, signing secret, 경기버스 API key는 커밋하지 않습니다.
  • 노출된 Slack token은 Slack App 설정에서 즉시 폐기하고 새로 발급합니다.
  • 로컬 데모에서는 ngrok URL을 Slack Slash Command Request URL로 연결합니다.

실행

로컬 설정 파일을 생성합니다.

cp src/main/resources/application-example.properties src/main/resources/application.properties

src/main/resources/application.properties에는 로컬 실행용 기본값이 들어 있습니다. Slack token, signing secret, 경기버스 API key는 환경변수로만 주입합니다.

./gradlew bootRun

기본 설정:

  • 서버 timezone: Asia/Seoul
  • DB: jdbc:h2:file:./data/bus-alert
  • H2 Console: /h2-console
  • 알림 쿨타임: 10분
  • 알림 체크 주기: 60초

테스트

./gradlew test

테스트는 src/test/resources/application.properties의 H2 in-memory 설정을 사용합니다. 실행 중 생성되는 file mode DB와 분리되어 있습니다.

Slack App 설정

Slack App에서 아래 Slash Command를 생성하고, Request URL을 ngrok 또는 배포 주소와 연결합니다.

Slack 명령어 Request URL
/조회 POST /slack/commands/search
/알림 POST /slack/commands/alert
/알림목록 POST /slack/commands/alert-list
/알림삭제 POST /slack/commands/alert-delete
/도움말 POST /slack/commands/help
/상태 POST /slack/commands/status

예시:

https://{ngrok-domain}/slack/commands/search
https://{ngrok-domain}/slack/commands/alert
https://{ngrok-domain}/slack/commands/alert-list
https://{ngrok-domain}/slack/commands/alert-delete
https://{ngrok-domain}/slack/commands/help
https://{ngrok-domain}/slack/commands/status

Interactivity & Shortcuts 설정에서 Interactivity를 켜고, Request URL을 아래처럼 연결합니다.

https://{ngrok-domain}/slack/actions

/slack/actions는 아래 Slack 인터랙션을 처리합니다.

  • /알림 Modal 제출
  • /알림목록의 삭제 버튼
  • 알림 DM의 탑승 완료 버튼

현재 Modal의 정류장 선택은 static_select를 사용하므로 Options Load URL은 비워둡니다.

Bot Token Scopes에는 최소한 아래 권한이 필요합니다.

  • chat:write
  • commands

/조회, /알림목록, /알림 초기화, 명령어 기반 알림 등록 응답은 본인에게만 보이는 ephemeral 응답으로 반환됩니다. 알림 발송과 Modal 등록 성공 메시지는 chat.postMessage로 사용자 DM에 전송됩니다.

명령어 예시

정류장 도착 정보 조회:

/조회 텔레칩스

특정 버스 도착 정보 조회:

/조회 텔레칩스 310

알림 등록:

/알림 텔레칩스 310 5 17:45 23:30

Modal로 알림 등록:

/알림

오늘 중지된 알림 다시 울리기:

/알림 초기화

알림 목록 조회:

/알림목록

알림 삭제:

/알림삭제 텔레칩스 310

도움말:

/도움말

시스템 상태 (GBIS API 호출 통계):

/상태

지원 정류장과 버스

MVP에서는 정류장 이름 중복을 피하기 위해 아래 정류장만 지원합니다.

  • 텔레칩스
  • 벤처타운(북문)

벤처타워(북문), 벤처타워 북문 같은 별칭도 벤처타운(북문)으로 해석합니다.

지원 정류장과 노선 매핑은 DB에서 관리합니다. 앱 시작 시 정류장 기본 데이터와 해당 정류장의 경유 노선을 경기버스 API에서 읽어 자동으로 저장합니다.

정류장 stationId mobileNo 지역
텔레칩스 204000158 05341 성남
벤처타운(북문) 204000159 05342 성남
실행 후 bus_routes 테이블에 경유 노선이 채워집니다.

알림 정책

알림은 아래 조건을 모두 만족할 때 발송됩니다.

  • 현재 시간이 알림 시작 시간 이상입니다.
  • 현재 시간이 알림 종료 시간 이하입니다.
  • 등록된 정류장과 버스번호 매핑이 존재합니다.
  • 첫 번째 버스 도착 예정 시간이 notifyBeforeMinutes 이하입니다.
  • 같은 사용자, 정류장, 버스번호 조합의 알림이 최근 10분 이내 발송되지 않았습니다.

MVP에서는 자정을 넘기는 알림 시간을 지원하지 않습니다. 예를 들어 23:00 01:00은 등록할 수 없습니다.

알림 DM의 탑승 완료 버튼을 누르면 해당 사용자의 모든 알림이 오늘은 더 이상 울리지 않습니다. 다음 날에는 다시 알림이 울립니다. 당일에 다시 알림을 받고 싶으면 /알림 초기화를 입력합니다.

입력 검증

정류장:

  • 지원 정류장만 허용합니다.

버스번호:

  • 정류장별로 설정된 버스번호만 허용합니다.

알림 기준 시간:

  • 1분 이상 30분 이하만 허용합니다.

시간:

  • HH:mm 형식만 허용합니다.
  • 예: 09:05, 17:45, 23:30
  • 비허용: 5:45, 17, 24:00

시작/종료 시간:

  • 종료 시간은 시작 시간보다 늦어야 합니다.
  • 자정을 넘기는 시간대는 지원하지 않습니다.

패키지 구조

도메인 우선 패키지 구조를 사용합니다.

com.woowa.bus
├── alert
│   ├── application
│   ├── domain
│   └── infrastructure
├── arrival
│   ├── domain
│   └── infrastructure
├── route
│   ├── domain
│   └── infrastructure
├── search
│   └── application
├── slack
│   ├── application
│   ├── infrastructure
│   └── presentation
└── global
    └── config

레이어 책임:

  • presentation: HTTP 요청/응답과 Slack command text 변환
  • application: 유스케이스 흐름 조율
  • domain: 핵심 규칙과 저장소 포트
  • infrastructure: JPA, 경기버스 API, Slack API 구현

주요 설정 파일

  • src/main/resources/application-example.properties: 로컬 실행 설정 예시
  • src/main/resources/application.properties: 로컬 실행 설정
  • src/test/resources/application.properties: 테스트 실행 설정
  • build.gradle: 의존성과 Java 버전

데모 체크리스트

  • Slack App 생성
  • Slash Command 6개 생성
  • 각 Slash Command Request URL을 ngrok 또는 배포 URL로 연결
  • Interactivity & Shortcuts 켜기
  • Interactivity Request URL을 /slack/actions로 연결
  • SLACK_BOT_TOKEN 설정
  • SLACK_SIGNING_SECRET 설정
  • GBIS_SERVICE_KEY 설정
  • 텔레칩스 stationId 확보
  • 벤처타운(북문) stationId 확보
  • bus_routes 테이블 자동 동기화 확인
  • /조회 텔레칩스 응답 확인
  • /조회 텔레칩스 310 Block Kit 응답 확인
  • /알림 텔레칩스 310 5 17:45 23:30 등록 확인
  • /알림 Modal 등록 확인
  • /알림목록 확인
  • /알림목록 삭제 버튼 확인
  • Slack DM 알림 발송 확인
  • 알림 DM의 탑승 완료 버튼 확인
  • /알림 초기화 후 알림 재발송 가능 여부 확인

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages