Skip to content

feat: 디트릭스 예술영화관 상영시간표·잔여 좌석 조회 추가 - #178

Closed
bgmbgm94 wants to merge 4 commits into
hmmhmmhm:mainfrom
bgmbgm94:feat/dtryx-arthouse-cinema
Closed

bgmbgm94 wants to merge 4 commits into
hmmhmmhm:mainfrom
bgmbgm94:feat/dtryx-arthouse-cinema

Conversation

@bgmbgm94

@bgmbgm94 bgmbgm94 commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

변경 요약

  • 국내 독립·예술영화관 다수가 공용으로 쓰는 디트릭스(Dtryx) 예매 플랫폼 어댑터를 추가했습니다. 기존 3사로는 조회되지 않던 예술영화 전용관 22곳의 상영 정보를 조회할 수 있습니다.
  • MCP 도구 3종(dtryx_list_cinemas / dtryx_list_now_showing / dtryx_get_remaining_seats)과 GET API 3종(/api/dtryx/cinemas, /api/dtryx/movies, /api/dtryx/seats)을 추가했습니다.
  • 극장 목록에 광역 지역명과 도로명 주소를 담고, region 파라미터로 조회 범위를 좁힐 수 있게 했습니다. 전국 22곳을 모두 훑지 않고 서울·경기만 조회하는 경로가 생깁니다.
  • src/index.ts 가 이미 449줄이어서 서비스를 추가하면 450줄 제한을 넘기므로, 도메인 라우트 등록을 src/api/routes/registerServiceRoutes.ts 로 분리했습니다.

관련 이슈

체크리스트

  • npm run format:check 통과
  • npm run lint 통과
  • npm run typecheck 통과
  • npm test 통과
  • 필요 시 문서(README/CONTRIBUTING) 업데이트
  • 민감 정보(API 키/토큰/개인정보) 미포함 확인

문서는 서비스 목록 표기 방식에 맞춰 수정하는 편이 좋을 것 같아 아직 손대지 않았습니다. 원하시는 위치를 알려주시면 반영하겠습니다.

테스트 방법

npm run check

테스트는 49개를 추가했습니다(1644 → 1693). 모두 mock 기반이라 네트워크에 의존하지 않습니다.

  • tests/services/dtryx/client.test.ts — 날짜 변환, 좌석 계산, HTTP 오류, 타임아웃
  • tests/services/dtryx/location.test.ts — 코드 중복, 브랜드 유효성, 키워드·지역 검색, 주소와 지역 표기 정합성
  • tests/services/dtryx/index.test.ts — 프로바이더 메타데이터, 도구 등록
  • tests/services/dtryx/tools/dtryxTools.test.ts — 도구 3종 정상·에러 경로
  • tests/api/dtryx-handlers.test.ts — GET API 3종, 404/500 처리

실제 응답으로 확인한 결과입니다.

① dtryx_list_cinemas                          → 22곳
② dtryx_list_now_showing (모모, 상영일 포함)   → 14편 / 12일
③ dtryx_get_remaining_seats (모모, 20260820)   → 9회차
     10:30-12:11 어떻게 해야 했을까? 1관 잔여 117/138
     11:00-12:47 산양들            2관 잔여 127/138
④ 전체 22개관 스윕 + 영화명 '경멸'             → 4회차 / 실패 0
     에무시네마      09:50 잔여  37/51
     더숲아트시네마   14:20 잔여  33/42
     아트하우스모모   17:40 잔여 125/138
     라이카시네마     19:20 잔여   4/26
⑤ region='서울' 로 좁힌 뒤 영화명 필터          → 7개관 중 2회차
     에무시네마      15:15 잔여  30/51
     더숲아트시네마   18:20 잔여   1/42

참고 사항

리뷰에서 봐주시면 좋을 지점들입니다.

1. 폴더명을 브랜드명이 아니라 플랫폼명(dtryx)으로 두었습니다.
BrandCd 3종이 모두 공개 브랜드가 아니어서입니다. etc 는 미분류 버킷이고, spacedog 는 라이카시네마의 사업자명이며, indieart 는 극장 페이지에 노출되지 않는 내부 분류 코드로 보입니다. 브랜드 단위로 나누면 etc/ 폴더가 생기고 클라이언트가 3중 중복됩니다. 다른 배치를 원하시면 맞추겠습니다.

2. findNearbyTheaters 는 넣지 않았습니다.
디트릭스 응답에 극장 좌표가 없어서 위치 기반 검색을 만들 수 없었습니다. 좌표를 임의로 채우는 것은 피하고, 대신 극장명 키워드로 찾는 dtryx_list_cinemas 를 두었습니다. 좌표 테이블을 하드코딩하는 방향을 원하시면 알려주세요.

3. 극장 목록을 location.ts 상수로 관리합니다.
브랜드/극장 목록을 반환하는 공개 엔드포인트를 찾지 못했습니다. 상영시간표 응답의 CinemaNm 으로 확인된 22곳만 담았고, indieart/000068 과 etc/000086 은 상영 가능 날짜는 있으나 편성 회차가 없어 극장명을 확인하지 못해 제외했습니다. 카탈로그에 없는 극장도 brandCode 와 함께 지정하면 조회됩니다. 다른 영화관 서비스와 파일명을 맞추려고 location.ts 에 두었지만, 좌표가 없어 근접 검색 대신 극장명·지역 매칭만 담당한다는 점을 헤더 주석에 적어두었습니다. 지역과 주소는 디트릭스 극장 페이지의 안내 정보를 기준으로 채웠고, 낭만극장과 허리우드클래식은 같은 건물이라 주소가 동일합니다.

4. PlaySDT 날짜 형식이 함정입니다.
YYYY-MM-DD 로만 동작하고 YYYYMMDD 는 오류 없이 RecordCount: 0 을 반환합니다. 클라이언트에서 항상 변환하고 테스트로 고정했습니다.

5. 운영 비용에는 영향이 없습니다.
src/services/lottecinema/client.ts 처럼 fetch 로 직접 호출하므로 Zyte 를 경유하지 않고 API 키 발급·관리도 없습니다.

6. CLI 명령은 포함하지 않았습니다.
메가박스도 서버 측만 제공하고 있어 같은 범위로 맞췄습니다. 필요하시면 후속 PR 로 dtryx-* 명령을 추가하겠습니다.

7. Windows 환경 참고사항 (이 PR 과 무관)
tests/app/cli.test.ts 의 직접 실행 여부를 올바르게 판별한다 는 Windows 에서 실패합니다. fileURLToPath('file:///tmp/test.js') 가 드라이브 문자가 없어 File URL path must be absolute 를 던지기 때문입니다. 이 브랜치 이전 커밋에서도 동일하게 재현되어 별도 사안으로 두었습니다. 위 1686 집계는 이 1건을 제외한 수치입니다.

국내 독립·예술영화관 다수가 공용으로 사용하는 디트릭스(Dtryx) 예매 플랫폼
어댑터를 추가합니다. 기존 CGV·롯데시네마·메가박스로는 조회되지 않던
예술영화 전용관 22곳의 상영 정보를 조회할 수 있습니다.

- MCP 도구 3종: dtryx_list_cinemas / dtryx_list_now_showing /
  dtryx_get_remaining_seats
- GET API 3종: /api/dtryx/cinemas, /api/dtryx/movies, /api/dtryx/seats
- 공개 엔드포인트로 직접 호출하므로 Zyte 를 경유하지 않고 API 키도 필요 없습니다.
- PlaySDT 는 YYYY-MM-DD 로만 동작하고 YYYYMMDD 는 조용히 0건을 반환하므로
  클라이언트에서 항상 변환합니다.
- 극장 목록 반환 엔드포인트가 없어 확인된 극장을 catalog.ts 상수로 관리합니다.
- src/index.ts 가 이미 449줄이어서 서비스 추가 시 450줄 제한을 넘기므로
  도메인 라우트 등록을 registerServiceRoutes.ts 로 분리했습니다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bgmbgm94
bgmbgm94 requested a review from hmmhmmhm as a code owner August 19, 2026 11:21
CGV·롯데시네마·메가박스가 모두 location.ts 를 쓰고 있어 파일명을 맞췄습니다.
디트릭스 응답에는 극장 좌표가 없어 좌표 기반 근접 검색 대신 극장명 매칭만
제공한다는 점을 헤더 주석에 남겼습니다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bgmbgm94

Copy link
Copy Markdown
Contributor Author

극장 좌표가 없어 근접 검색을 넣지 못한다고 적었는데, 주소는 확인이 가능해서 정리해 둡니다. 나중에 좌표 테이블을 붙이거나 지역 필터를 넣을 때 참고가 될 것 같습니다.

출처는 디트릭스 극장 페이지(https://www.dtryx.com/cinema/main.do?BrandCd={brand}&CinemaCd={code})의 "오시는 길" 항목입니다. 씨네인디U 만 해당 페이지에 주소가 없어 공개 자료로 확인했습니다.

BrandCd CinemaCd 극장 지역 주소
indieart 000065 더숲아트시네마 서울 노원 서울특별시 노원구 노해로 480, 지하1층 (상계동, 조광빌딩)
indieart 000067 아트하우스모모 서울 서대문 서울특별시 서대문구 이화여대길 52 지하4층 (대현동, 이화여대 ECC)
indieart 000069 에무시네마 서울 종로 서울특별시 종로구 경희궁1가길 7, 1~3층·지하1층 (신문로2가)
spacedog 000072 라이카시네마 서울 서대문 서울특별시 서대문구 연희로8길 18 (연희동)
etc 000088 아리랑시네센터 서울 성북 서울특별시 성북구 아리랑로12길 4
etc 000113 낭만극장 서울 종로 서울특별시 종로구 삼일대로 428, 4층
etc 000115 허리우드클래식 서울 종로 서울특별시 종로구 삼일대로 428, 4층
indieart 000071 헤이리시네마 경기 파주 경기도 파주시 탄현면 헤이리마을길 93-119, 지상3층
etc 000117 자유로자동차극장 경기 파주 경기도 파주시 탄현면 필승로 432
etc 000116 명화극장 경기 안산 경기도 안산시 단원구 중앙대로 921 (고잔동, 동서코아빌딩 지하2층)
etc 000100 애관극장 인천 중구 인천광역시 중구 경동 238
etc 000098 씨네인디U 대전 중구 대전광역시 중구 계백로 1712 (문화동, 기독교연합봉사회관 1층)
etc 000083 천안인생극장 충남 천안 충청남도 천안시 동남구 버들로 41
etc 000107 금성시네마 충남 부여 충청남도 부여군 부여읍 사비로100번길 12
indieart 000059 오오극장 대구 중구 대구광역시 중구 국채보상로 537 (수동)
indieart 000066 광주극장 광주 동구 광주광역시 동구 충장로46번길 10 (충장로5가)
etc 000084 광주자동차극장 광주 북구 광주광역시 북구 우치로 649
indieart 000061 전주디지털독립영화관 전북 전주 전라북도 전주시 완산구 전주객사3길 22, 2층 (고사동, 전주영화제작소)
etc 000097 모퉁이극장 부산 중구 부산광역시 중구 광복중앙로 13, 4층
indieart 000053 씨네아트 리좀 경남 창원 경상남도 창원시 마산합포구 동서북14길 24 (동성동)
etc 000092 밀양시네마 경남 밀양 경상남도 밀양시 백민로 75-1
indieart 000057 인디플러스포항 경북 포항 경상북도 포항시 남구 희망대로 850, 1층 (대도동, 포항문화예술회관)

지역 분포는 서울 7, 경기 3, 인천 1, 충청 3, 영남 5, 호남 3 입니다.

한 가지 참고로, 낭만극장과 허리우드클래식은 주소가 같습니다(종로 낙원상가 건물). 좌표 기반 근접 검색을 넣게 되면 두 극장이 같은 지점으로 나오는 점을 고려해야 할 것 같습니다.

주소를 location.ts 에 함께 넣어둘지, 아니면 좌표까지 확보한 뒤에 한 번에 넣을지는 의견 주시면 맞추겠습니다. 지금 PR 에는 포함하지 않았습니다.

극장 목록에 광역 지역명과 도로명 주소를 담고, 지역으로 조회 범위를 좁히는
필터를 추가했습니다. 전국 22개 극장을 모두 조회하지 않고 서울·경기 등
특정 지역만 훑을 수 있습니다.

- DtryxCinema 에 region, address 필드 추가 (극장 22곳)
- findCinemasByRegion() 추가
- dtryx_list_cinemas, dtryx_get_remaining_seats 에 region 파라미터 추가
- GET /api/dtryx/cinemas, /api/dtryx/seats 에 region 쿼리 추가

주소는 디트릭스 극장 페이지의 안내 정보를 기준으로 정리했습니다.
좌표는 제공되지 않아 포함하지 않았고, 근접 검색도 그대로 제외되어 있습니다.
낭만극장과 허리우드클래식은 같은 건물이라 주소가 동일합니다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@bgmbgm94

Copy link
Copy Markdown
Contributor Author

위 주소 표를 location.ts 에 반영했습니다(커밋 3494067). 좌표는 여전히 제공되지 않아 넣지 않았고 근접 검색도 그대로 제외되어 있습니다.

  • DtryxCinema 에 region, address 를 추가하고 극장 22곳을 채웠습니다.
  • findCinemasByRegion() 과 region 파라미터를 추가해 조회 범위를 좁힐 수 있게 했습니다. 극장을 지정하지 않으면 전국 22곳을 모두 호출하던 부분이 지역 단위로 줄어듭니다.
  • 주소가 지역 표기와 어긋나지 않는지 확인하는 테스트를 넣어 두어, 나중에 극장을 추가할 때 오타를 잡을 수 있게 했습니다.

실제 동작입니다.

dtryx_list_cinemas { region: '서울' } → 7곳
dtryx_list_cinemas { region: '경기' } → 3곳

dtryx_get_remaining_seats { region: '서울', playDate: '20260820', movieName: '어떻게' }
  → 7개관 조회, 2회차
     에무시네마      15:15  잔여 30/51
     더숲아트시네마   18:20  잔여  1/42

주소를 코드에 두는 것이 부담스러우시면 되돌리고 지역 필드만 남기는 것도 가능합니다.

@hmmhmmhm

Copy link
Copy Markdown
Owner

오...디트릭스 예술영화관..!! 감사합니다 퇴근하면 바로 볼게요

Coverage 게이트(100%)를 통과하지 못해 보완했습니다.

- 앱 통합 테스트(tests/app/app-api-dtryx.test.ts)를 추가해 라우트 등록을
  검증합니다. 기존 메가박스·롯데시네마와 같은 방식입니다.
- 기본값 대입, 정렬 동률, 극장 해석 분기 등 남은 경로를 tests/services/dtryx/
  coverage.test.ts 로 채웠습니다.
- 좌석 조회 핸들러의 try/catch 를 제거했습니다. Promise.allSettled 로 극장별
  실패를 흡수하므로 예외가 전파되지 않아 도달할 수 없는 코드였습니다.
  개별 실패는 기존대로 failedCinemas 로 보고합니다.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] 디트릭스(Dtryx) 예술영화관 상영시간표·좌석 조회 서비스 추가

2 participants