Repository navigation
feat: 인스타그램 장소 추출 파이프라인 유기적 연동 및 응답 구조 재설계 - #40
Conversation
평평한 GeoCandidate[] 대신 추출 장소 단위 PlaceMatch[]로 반환한다. 서로 다른 장소의 후보가 섞이지 않도록 장소별로 랭킹하고, best/candidates와 AI가 뽑은 query(relation 포함)를 함께 담는다. 부분 실패·결과 없음은 빈 후보로 유지하고 전부 실패한 경우만 GEOCODER_ALL_FAILED로 취급한다. area_type 분류 기준을 프롬프트에 명시해 지오코딩 정확도를 높인다.
외부 어댑터(스크래퍼/AI/지오코더)만 override로 대체하고 나머지 조립을 실제로 관통시켜 POST /places의 PlaceMatch[] 계약·에러 경로를 검증한다.
임시 지오코딩 확인용 엔드포인트와 관련 DTO(testGeocodeRequestSchema)를 제거하고, 컨트롤러의 GeocoderService 직접 의존도 정리한다.
POST /api/v1/place/places에 @ApiTags/@ApiOperation/@ApiBody/@apiresponse를 붙인다. 요청 스키마는 valibot(createPlaceRequestSchema)에서 생성하고, 응답·에러 스키마는 OpenAPI 스키마 상수로 문서화한다. @nestjs/swagger가 공개 export하지 않는 SchemaObject 타입은 common/swagger에 헬퍼로 둔다.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthrough장소 추출 API가 장소별 Changes장소 매칭 응답 흐름
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant PlaceController
participant PlaceService
participant ScraperService
participant AiService
participant GeocoderService
Client->>PlaceController: POST /api/v1/place/places
PlaceController->>PlaceService: extractFromUrl(url)
PlaceService->>ScraperService: fetchPost(url)
PlaceService->>AiService: extract(post)
PlaceService->>GeocoderService: searchAll(query)
GeocoderService-->>PlaceService: 후보 또는 실패
PlaceService-->>PlaceController: PlaceMatch[]
PlaceController-->>Client: 201 응답 또는 502 오류
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/modules/place/place.dto.ts`:
- Around line 19-77: 각 스키마에 실제 응답 타입과 일치하는 required 배열을 추가하세요. coordinateSchema,
geoCandidateSchema, extractedPlaceSchema, placeMatchSchema,
placeMatchListResponseApiSchema, errorResponseApiSchema의 필수 필드를 타입 정의에 맞춰 지정하고,
특히 geoCandidateSchema는 provider, providerPlaceId, placeName, address,
coordinate만 required로 설정하며 distance, mapUrl, phone, category는 제외하세요.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a8240820-44ad-4df8-97ac-ad5d95f296ff
📒 Files selected for processing (7)
e2e/place.e2e.spec.tssrc/common/swagger/schema.tssrc/modules/place/place.controller.tssrc/modules/place/place.dto.tssrc/modules/place/place.service.spec.tssrc/modules/place/place.service.tssrc/modules/place/place.type.ts
| const coordinateSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| lat: { type: "number", example: 37.5445 }, | ||
| lng: { type: "number", example: 127.0559 }, | ||
| }, | ||
| }; | ||
|
|
||
| const geoCandidateSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| provider: { type: "string", enum: ["kakao", "google"] }, | ||
| providerPlaceId: { type: "string" }, | ||
| placeName: { type: "string" }, | ||
| address: { type: "string" }, | ||
| coordinate: coordinateSchema, | ||
| distance: { type: "number", nullable: true }, | ||
| mapUrl: { type: "string", nullable: true }, | ||
| phone: { type: "string", nullable: true }, | ||
| category: { type: "string", nullable: true }, | ||
| }, | ||
| }; | ||
|
|
||
| const extractedPlaceSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| placeName: { type: "string" }, | ||
| areaName: { type: "string" }, | ||
| areaType: { type: "string", enum: [...AREA_TYPES] }, | ||
| relation: { type: "string" }, | ||
| }, | ||
| }; | ||
|
|
||
| const placeMatchSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| extracted: extractedPlaceSchema, | ||
| matches: { | ||
| type: "array", | ||
| items: geoCandidateSchema, | ||
| description: "지오코딩 결과 후보", | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export const placeMatchListResponseApiSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| data: { type: "array", items: placeMatchSchema }, | ||
| }, | ||
| }; | ||
|
|
||
| // TODO: KakaoProvider 확인용 임시 의존성으로 전체 플로우 연동 후 제거합니다. | ||
| export type TestGeocodeRequest = v.InferOutput<typeof testGeocodeRequestSchema>; | ||
| export const errorResponseApiSchema: SchemaObject = { | ||
| type: "object", | ||
| properties: { | ||
| errorCode: { type: "string", example: "GEOCODER_ALL_FAILED" }, | ||
| message: { type: "string", example: "장소 검색이 모두 실패했습니다." }, | ||
| }, | ||
| }; |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# GeoCandidate 타입 정의에서 필수/선택 필드 확인
rg -n 'interface GeoCandidate' -A 20 src/infrastructures/geocoder/geocoder.type.tsRepository: mash-up-kr/Team-MINO-Node
Length of output: 583
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== place.dto.ts =="
nl -ba src/modules/place/place.dto.ts | sed -n '1,180p'
echo
echo "== related place types =="
rg -n 'interface .*Place|type .*Place|interface .*Error|type .*Error|extractedPlace|placeMatch|errorResponse' -A 20 -B 5 src | sed -n '1,260p'Repository: mash-up-kr/Team-MINO-Node
Length of output: 222
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== place.dto.ts =="
sed -n '1,180p' src/modules/place/place.dto.ts
echo
echo "== related place types =="
rg -n 'interface .*Place|type .*Place|interface .*Error|type .*Error|extractedPlace|placeMatch|errorResponse' -A 20 -B 5 src | sed -n '1,260p'Repository: mash-up-kr/Team-MINO-Node
Length of output: 18663
required 배열을 추가해 Swagger 응답 스키마를 실제 타입과 맞춰주세요 coordinateSchema, geoCandidateSchema, extractedPlaceSchema, placeMatchSchema, placeMatchListResponseApiSchema, errorResponseApiSchema 모두 required가 없어 응답 필드가 전부 선택적으로 표시됩니다. 특히 geoCandidateSchema는 GeoCandidate에 맞춰 provider, providerPlaceId, placeName, address, coordinate만 필수로 두고 나머지는 제외하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/modules/place/place.dto.ts` around lines 19 - 77, 각 스키마에 실제 응답 타입과 일치하는
required 배열을 추가하세요. coordinateSchema, geoCandidateSchema, extractedPlaceSchema,
placeMatchSchema, placeMatchListResponseApiSchema, errorResponseApiSchema의 필수
필드를 타입 정의에 맞춰 지정하고, 특히 geoCandidateSchema는 provider, providerPlaceId, placeName,
address, coordinate만 required로 설정하며 distance, mapUrl, phone, category는 제외하세요.
|
@minsour |
…am-scrap-e2e # Conflicts: # e2e/place.e2e.spec.ts
@KKardy |
📌 Related Issue
GM-88
🚀 Description
Instagram URL → scrap→ AI extraction → geocoding파이프라인을 하나의 유기적 흐름으로 연동하고, 응답 구조를 재설계했습니다.PlaceMatch[](extracted+matches) 구조로 바꿨습니다._test/geocode엔드포인트를 제거했습니다.✅ Done
PlaceMatch[](extracted/matches) 장소별 그룹 구조로 재설계matches(정상), 전부 실패만GEOCODER_ALL_FAILED(502)ExtractedPlace) 매핑area_type분류 기준 프롬프트 보강_test/geocode엔드포인트 및 DTO 제거📢 Notes
Summary by CodeRabbit
extracted정보와 지오코딩 후보matches를 함께 반환합니다.matches로 처리합니다.