Skip to content

최신 인기 장소 목록 UI#30

Merged
Cassiiopeia merged 4 commits intomainfrom
20260209_#18_최신_인기_장소_목록_UI
Feb 23, 2026

Hidden character warning

The head ref may contain hidden characters: "20260209_#18_\ucd5c\uc2e0_\uc778\uae30_\uc7a5\uc18c_\ubaa9\ub85d_UI"
Merged

최신 인기 장소 목록 UI#30
Cassiiopeia merged 4 commits intomainfrom
20260209_#18_최신_인기_장소_목록_UI

Conversation

@Cassiiopeia
Copy link
Copy Markdown
Contributor

@Cassiiopeia Cassiiopeia commented Feb 10, 2026

Summary by CodeRabbit

출시 노트

  • 새로운 기능

    • 홈 화면 대폭 개편 - 최신 장소와 인기 장소를 별도 섹션으로 표시
    • 무한 스크롤을 통한 최신 장소 목록 조회 기능
    • 3열 그리드 레이아웃으로 인기 장소 표시
    • 장소 카드에 이미지, 주소, 태그 정보 표시
  • 사용성 개선

    • 로딩 중 스켈레톤 UI 표시
    • 빈 상태와 오류 상태에 대한 명확한 메시지
    • 오류 발생 시 재시도 버튼 제공

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 10, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

홈 피드 기능을 새로 구현하면서 콘텐츠 모델, 데이터 소스, 레포지토리, 상태 관리를 추가했습니다. 다양한 페이지와 서비스의 import 경로를 재구성하고, 생성된 Freezed/Riverpod 파일들을 정리했습니다.

Changes

Cohort / File(s) Summary
홈 기능 - 데이터 모델
lib/features/home/data/models/content_response.dart, lib/features/home/data/models/cursor_model.dart, lib/features/home/data/models/place_model.dart
Freezed 기반 불변 데이터 모델 추가: ContentItem, ContentListResponse, CursorModel, PlaceModel. JSON 직렬화 지원 포함.
홈 기능 - 데이터 레이어
lib/features/home/data/home_remote_datasource.dart, lib/features/home/data/home_repository.dart, lib/features/home/data/home_repository_impl.dart, lib/features/home/data/content_status.dart
원격 데이터 소스, 추상 저장소, 구현체 추가. 최신 및 인기 콘텐츠 fetch API 정의 및 구현. ContentStatus enum으로 상태 관리.
홈 기능 - 상태 관리 및 UI
lib/features/home/presentation/home_provider.dart, lib/features/home/presentation/pages/home_page.dart
HomeNotifier와 HomeState로 상태 관리 구현. HomePage를 ConsumerStatefulWidget으로 변환하고 무한 스크롤, 새로고침 기능 추가.
홈 기능 - UI 위젯
lib/features/home/presentation/widgets/place_card.dart, lib/features/home/presentation/widgets/popular_place_tile.dart, lib/features/home/presentation/widgets/home_loading_shimmer.dart, lib/features/home/presentation/widgets/home_empty_state.dart, lib/features/home/presentation/widgets/home_error_state.dart
장소 카드, 인기 타일, 로딩 스켈레톤, 빈 상태, 에러 상태 위젯 신규 추가.
색상 상수
lib/common/constants/home_colors.dart
홈 화면용 다크 테마 색상 팔레트 정의.
Auth 기능 - Import 경로 업데이트
lib/features/auth/data/auth_remote_datasource.dart, lib/features/auth/data/auth_repository.dart, lib/features/auth/data/auth_repository_impl.dart, lib/features/auth/data/firebase_auth_error_handler.dart, lib/features/auth/presentation/auth_provider.dart, lib/features/auth/presentation/pages/login_page.dart, lib/features/auth/presentation/pages/splash_page.dart
core 경로를 common으로, 상대 import 정규화.
Onboarding 기능 - Import 경로 업데이트
lib/features/onboarding/data/onboarding_remote_datasource.dart, lib/features/onboarding/data/onboarding_repository.dart, lib/features/onboarding/data/onboarding_repository_impl.dart, lib/features/onboarding/presentation/onboarding_provider.dart, lib/features/onboarding/presentation/pages/*
core/domain 경로를 common으로, 상대 import 정규화.
생성된 Freezed 파일 제거
lib/features/auth/data/models/reissue_request.freezed.dart, lib/features/auth/data/models/reissue_response.freezed.dart, lib/features/auth/data/models/sign_in_request.freezed.dart, lib/features/auth/data/models/sign_in_response.freezed.dart, lib/features/onboarding/data/models/birth_date_request.freezed.dart, lib/features/onboarding/data/models/gender_request.freezed.dart, lib/features/onboarding/data/models/profile_request.freezed.dart, lib/features/onboarding/data/models/terms_request.freezed.dart, lib/features/onboarding/presentation/providers/onboarding_provider.freezed.dart
Freezed 생성 보일러플레이트 제거. JSON 직렬화, copyWith, 동등성 구현 삭제.
생성된 JSON 직렬화 파일 제거
lib/features/auth/data/models/*.g.dart, lib/features/onboarding/data/models/*.g.dart
JsonSerializable 생성 파일 정리.
생성된 Riverpod 파일 제거
lib/core/network/api_client.g.dart, lib/core/network/token_storage.g.dart, lib/core/services/device/device_info_service.g.dart, lib/core/services/fcm/firebase_messaging_service.g.dart, lib/features/auth/data/datasources/auth_remote_datasource.g.dart, lib/features/auth/data/repositories/auth_repository_impl.g.dart, lib/features/auth/presentation/providers/auth_provider.g.dart, lib/features/onboarding/data/datasources/onboarding_remote_datasource.g.dart, lib/features/onboarding/data/repositories/onboarding_repository_impl.g.dart, lib/features/onboarding/presentation/providers/onboarding_provider.g.dart
Riverpod 자동 생성 provider 정의 제거.
플레이스홀더 파일 제거
lib/core/utils/_placeholder.dart, lib/core/utils/extensions/_placeholder.dart, lib/core/widgets/_placeholder.dart, lib/features/auth/data/models/_placeholder.dart, lib/features/auth/data/repositories/_placeholder.dart, lib/features/auth/domain/entities/_placeholder.dart, lib/features/auth/domain/repositories/_placeholder.dart, lib/features/auth/domain/usecases/_placeholder.dart, lib/features/auth/presentation/widgets/_placeholder.dart, lib/features/onboarding/data/models/_placeholder.dart
구조 가이드용 플레이스홀더 파일 정리.
기타 Import 업데이트
lib/common/services/error_interceptor.dart, lib/common/services/firebase_messaging_service.dart, lib/main.dart, lib/routing/app_router.dart
core 모듈 경로를 common으로 통일.
문서 제거
SUH-DEVOPS-TEMPLATE-SETUP-GUIDE.md
개발환경 설정 가이드 문서 제거.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant HomePage
    participant ScrollController as ScrollController
    participant HomeNotifier
    participant HomeRepository
    participant HomeRemoteDataSource
    participant API as API Server

    User->>HomePage: 페이지 진입
    HomePage->>HomeNotifier: fetchRecentPlaces() 초기화
    HomeNotifier->>HomeRepository: getRecentContent()
    HomeRepository->>HomeRemoteDataSource: fetchRecentContent()
    HomeRemoteDataSource->>API: GET /api/content/recent
    API-->>HomeRemoteDataSource: ContentListResponse
    HomeRemoteDataSource-->>HomeRepository: ContentListResponse
    HomeRepository-->>HomeNotifier: ContentListResponse
    HomeNotifier->>HomeNotifier: state.copyWith(recentPlaces, cursor 업데이트)
    HomeNotifier-->>HomePage: 상태 업데이트

    User->>ScrollController: 스크롤 (바닥 도달)
    ScrollController->>HomePage: onScroll 콜백
    HomePage->>HomeNotifier: fetchMoreRecentPlaces()
    HomeNotifier->>HomeRepository: getRecentContent(cursor=nextCursor)
    HomeRepository->>HomeRemoteDataSource: fetchRecentContent(cursor)
    HomeRemoteDataSource->>API: GET /api/content/recent?cursor=...
    API-->>HomeRemoteDataSource: ContentListResponse
    HomeRemoteDataSource-->>HomeRepository: ContentListResponse
    HomeRepository-->>HomeNotifier: ContentListResponse
    HomeNotifier->>HomeNotifier: state.copyWith(기존 리스트 + 새 항목)
    HomeNotifier-->>HomePage: 상태 업데이트 (페이지네이션)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50분

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 변경사항의 주요 내용을 명확하게 반영하고 있습니다. '최신 인기 장소 목록 UI'는 홈 화면 UI 구현의 핵심을 간결하게 표현하며, 추가된 파일들(홈페이지, 위젯, 상태관리 등)이 모두 이 주제와 일관성있게 연결되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 20260209_#18_최신_인기_장소_목록_UI

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@lib/features/home/data/datasources/home_remote_datasource.dart`:
- Around line 36-48: The code unsafely casts response.data to Map<String,
dynamic> causing TypeError on null or unexpected responses; update the logic in
the method that calls ContentListResponse.fromJson (and likewise in
fetchMemberContent) to first verify response.data is non-null and is a
Map<String, dynamic> (e.g., check response.data is Map or use a safe cast), and
handle the failure path by logging the response/error and either throwing a
descriptive exception or returning an appropriate fallback (empty
ContentListResponse or error result) before calling ContentListResponse.fromJson
so deserialization is never invoked with an invalid type.

In `@lib/features/home/data/models/cursor_model.dart`:
- Around line 1-22: The CI is failing because the Freezed-generated files for
CursorModel (cursor_model.freezed.dart and cursor_model.g.dart) are missing; run
the Dart build runner to generate them (dart run build_runner build
--delete-conflicting-outputs), then either commit the generated files or update
CI to run build_runner before tests/builds so models like CursorModel (and
others mentioned such as ContentResponse, HomeRemoteDatasource,
HomeRepositoryImpl) have their corresponding *.freezed.dart and *.g.dart
artifacts available at runtime.

In `@lib/features/home/data/models/place_model.dart`:
- Around line 1-39: The build artifacts for the Freezed/JsonSerializable parts
referenced by PlaceModel (place_model.freezed.dart, place_model.g.dart providing
_$PlaceModel mixin and _$PlaceModelFromJson) are missing; fix by either running
code generation locally with `dart run build_runner build
--delete-conflicting-outputs` and committing the generated files, or update the
CI workflow to run a build step (after flutter pub get) that executes `dart run
build_runner build` so the part files are generated during CI. Ensure generated
files for PlaceModel are present in the repo or produced in CI so _$PlaceModel
and _$PlaceModelFromJson resolve.

In `@lib/features/home/presentation/providers/home_provider.dart`:
- Around line 47-51: The `@override` warning means the generated Riverpod
signature doesn't match this method; first run the generator (dart run
build_runner build) to ensure the provider code is up-to-date and that the
method signature (build / HomeState) matches the generated code; if generation
is intentionally not used, remove the `@override` annotation so it stops reporting
as not overriding. Also avoid silent fire-and-forget for initialization: change
Future.microtask(() => _initialize()) to a form that surface errors (either
await the call in an async build or attach error handling like
Future.microtask(() => _initialize()).catchError(...)) so exceptions from
_initialize (not just fetchRecentPlaces/fetchPopularPlaces) are handled;
references: HomeState, build(), _initialize(), fetchRecentPlaces(),
fetchPopularPlaces().
🧹 Nitpick comments (11)
lib/features/home/domain/entities/content_status.dart (1)

16-21: 알 수 없는 상태값에 대한 무조건적 pending 폴백은 데이터 문제를 숨길 수 있습니다.

서버에서 예상치 못한 상태값이 내려올 경우, 오류 없이 pending으로 처리되어 디버깅이 어려워질 수 있습니다. 최소한 로그를 남기거나, assert를 추가하는 것을 권장합니다.

💡 로그 추가 제안
  static ContentStatus fromString(String value) {
    return ContentStatus.values.firstWhere(
      (e) => e.name.toUpperCase() == value.toUpperCase(),
-     orElse: () => ContentStatus.pending,
+     orElse: () {
+       debugPrint('Unknown ContentStatus: $value, defaulting to pending');
+       return ContentStatus.pending;
+     },
    );
  }
lib/features/home/presentation/widgets/home_loading_shimmer.dart (1)

7-25: "Shimmer"라고 명명되었지만 실제 애니메이션이 없는 정적 스켈레톤입니다.

현재 구현은 색상 블록만 표시하고 있어 로딩 중이라는 시각적 피드백이 부족합니다. shimmer 패키지를 활용하거나 AnimationController로 그라데이션 애니메이션을 추가하면 사용자 경험이 개선됩니다. 지금 당장 필요하지 않다면 클래스 이름을 HomeLoadingSkeleton으로 변경하는 것도 방법입니다.

lib/features/home/presentation/widgets/place_card.dart (2)

103-112: 네트워크 이미지 로딩 시 사용자 피드백 및 캐싱이 없습니다.

Image.network는 로딩 중 빈 영역을 표시하며, 이미지 캐싱도 지원하지 않습니다. cached_network_image 패키지를 사용하면 로딩 플레이스홀더와 캐싱을 모두 처리할 수 있습니다.

💡 CachedNetworkImage 적용 제안
+import 'package:cached_network_image/cached_network_image.dart';
...
  Widget _buildThumbnail() {
    if (place.imageUrl != null && place.imageUrl!.isNotEmpty) {
-     return Image.network(
-       place.imageUrl!,
+     return CachedNetworkImage(
+       imageUrl: place.imageUrl!,
        fit: BoxFit.cover,
-       errorBuilder: (_, __, ___) => _buildPlaceholder(),
+       placeholder: (_, __) => _buildPlaceholder(),
+       errorWidget: (_, __, ___) => _buildPlaceholder(),
      );
    }
    return _buildPlaceholder();
  }

20-21: GestureDetector 대신 InkWell을 사용하면 탭 시 시각적 피드백(리플 효과)을 제공할 수 있습니다.

현재 탭 시 사용자에게 아무런 시각적 반응이 없어 터치가 인식되었는지 알기 어렵습니다. Material + InkWell 조합으로 변경하면 리플 이펙트를 통해 UX가 개선됩니다.

lib/features/home/presentation/widgets/popular_place_tile.dart (1)

68-77: 네트워크 이미지 캐싱 및 로딩 상태 고려

Image.network는 이미지 캐싱을 제공하지 않아 스크롤 시마다 재다운로드가 발생할 수 있습니다. 그리드에서 다수의 이미지를 동시에 표시하는 경우 성능 및 사용자 경험에 영향을 줄 수 있습니다.

cached_network_image 패키지 사용을 권장합니다. 또한 loadingBuilderframeBuilder가 없어 이미지 로딩 중 빈 영역이 표시됩니다.

♻️ CachedNetworkImage 적용 제안
+import 'package:cached_network_image/cached_network_image.dart';
+
 Widget _buildThumbnail() {
   if (place.imageUrl != null && place.imageUrl!.isNotEmpty) {
-    return Image.network(
-      place.imageUrl!,
+    return CachedNetworkImage(
+      imageUrl: place.imageUrl!,
       fit: BoxFit.cover,
-      errorBuilder: (_, __, ___) => _buildPlaceholder(),
+      errorWidget: (_, __, ___) => _buildPlaceholder(),
+      placeholder: (_, __) => _buildPlaceholder(),
     );
   }
   return _buildPlaceholder();
 }
lib/features/home/domain/repositories/home_repository.dart (1)

1-10: Domain 레이어에서 Data 레이어 모델을 직접 참조하고 있습니다.

HomeRepository는 domain 레이어에 위치하지만 ContentListResponse를 data 레이어(../../data/models/content_response.dart)에서 import하고 있습니다. Clean Architecture 원칙에 따르면 의존성 방향은 외부 → 내부(data → domain)여야 합니다.

프로젝트 규모와 팀 컨벤션에 따라 허용될 수 있지만, 향후 확장성을 고려한다면 domain 레이어에 별도의 entity를 정의하고 repository impl에서 매핑하는 구조를 권장합니다.

lib/features/home/data/datasources/home_remote_datasource.dart (1)

30-73: API 호출에 에러 핸들링이 없습니다.

fetchRecentContentfetchMemberContent 모두 try-catch 없이 Dio 호출을 수행합니다. 네트워크 오류, 타임아웃, 서버 에러(4xx/5xx) 시 DioException이 그대로 상위 레이어로 전파됩니다.

데이터소스 또는 리포지토리 레이어에서 DioException을 캐치하여 앱 내부의 도메인 예외로 변환하면, 상위 레이어의 에러 처리가 일관되고 명확해집니다.

lib/features/home/presentation/pages/home_page.dart (1)

178-180: 인기 장소 표시 개수가 30개로 하드코딩되어 있습니다.

childCountmin(30, state.popularPlaces.length)로 제한하고 있습니다. getMemberContent의 기본 size도 30이므로 현재는 동작하지만, 향후 페이지 크기가 변경되면 동기화가 깨질 수 있습니다. 상수로 추출하여 데이터소스와 UI에서 공유하는 것을 권장합니다.

♻️ 상수 추출 제안
+// home_constants.dart 또는 적절한 위치에 정의
+const int kPopularPlacesMaxCount = 30;
 childCount: state.popularPlaces.length > 30
-    ? 30
+    ? kPopularPlacesMaxCount
     : state.popularPlaces.length,
lib/features/home/data/models/content_response.dart (1)

19-23: status 필드에 ContentStatus enum 사용을 권장합니다.

ContentStatus enum이 명확히 정의되어 있으며, fromString()toJson() 메서드를 통해 JSON 변환을 지원합니다. 이를 사용하면 타입 안전성을 개선할 수 있습니다.

반면, createdAtDateTime?으로 변경하는 제안은 현재 코드베이스에서 데이터 모델의 JSON 역직렬화 시 날짜 변환을 위한 인프라가 명확히 보이지 않아, 추가 설정(예: @JsonKey(fromJson: ...)와 같은 커스텀 변환기) 없이는 구현이 복잡할 수 있습니다. API 응답 형식이 문자열이므로 현재의 String? 타입이 의도적일 가능성이 있습니다.

♻️ status 필드 타입 강화 제안
+import '../../domain/entities/content_status.dart';
+
 const factory ContentItem({
   required int contentId,
   String? sourceUrl,
-  String? status,
+  ContentStatus? status,
   String? createdAt,
   `@Default`([]) List<PlaceModel> places,
 }) = _ContentItem;
lib/features/home/presentation/providers/home_provider.dart (2)

53-59: 동시 fetch 시 errorMessage 경쟁 상태 가능성.

Future.wait으로 fetchRecentPlaces()fetchPopularPlaces()를 동시에 실행하는데, 두 메서드 모두 시작 시 errorMessage: null로 초기화하고 실패 시 단일 errorMessage 필드에 쓰기합니다. 한쪽만 실패하면 문제없지만, 양쪽 모두 실패할 경우 마지막에 완료된 쪽의 에러 메시지만 남게 됩니다.

현재로서는 큰 문제는 아니지만, 향후 에러 메시지를 recentErrorMessage/popularErrorMessage로 분리하면 각 섹션별 에러를 독립적으로 표시할 수 있습니다.


108-111: 페이지네이션 실패 시 사용자에게 피드백이 없습니다.

fetchMoreRecentPlaces catch 블록에서 isLoadingMorefalse로 설정하고 에러 메시지를 표시하지 않습니다. 네트워크 오류 시 사용자가 더 이상 데이터가 없는 것으로 오해할 수 있습니다. 스낵바 표시나 재시도 버튼 노출 등 최소한의 피드백을 고려해주세요.

Comment on lines +36 to +48
final response = await _dio.get(
ApiEndpoints.recentContent,
queryParameters: {
if (cursor != null) 'cursor': cursor,
'size': size,
},
);

final result = ContentListResponse.fromJson(
response.data as Map<String, dynamic>,
);
debugPrint('✅ Recent content fetched: ${result.content.length} items');
return result;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

response.data의 안전하지 않은 타입 캐스팅

response.data as Map<String, dynamic> 캐스팅은 응답이 null이거나 예상과 다른 타입일 경우 TypeError를 발생시킵니다. 서버 오류나 비정상 응답 시 디버깅이 어려운 런타임 예외로 이어질 수 있습니다.

🛡️ 안전한 캐스팅 제안
   final response = await _dio.get(
     ApiEndpoints.recentContent,
     queryParameters: {
       if (cursor != null) 'cursor': cursor,
       'size': size,
     },
   );

+  final data = response.data;
+  if (data is! Map<String, dynamic>) {
+    throw FormatException('Unexpected response format: ${data.runtimeType}');
+  }
   final result = ContentListResponse.fromJson(
-    response.data as Map<String, dynamic>,
+    data,
   );

동일한 패턴이 fetchMemberContent (Line 68-69)에도 적용되어야 합니다.

🧰 Tools
🪛 GitHub Actions: Project Flutter CI

[error] 44-44: The getter 'content' isn't defined for the type 'ContentListResponse'

🤖 Prompt for AI Agents
In `@lib/features/home/data/datasources/home_remote_datasource.dart` around lines
36 - 48, The code unsafely casts response.data to Map<String, dynamic> causing
TypeError on null or unexpected responses; update the logic in the method that
calls ContentListResponse.fromJson (and likewise in fetchMemberContent) to first
verify response.data is non-null and is a Map<String, dynamic> (e.g., check
response.data is Map or use a safe cast), and handle the failure path by logging
the response/error and either throwing a descriptive exception or returning an
appropriate fallback (empty ContentListResponse or error result) before calling
ContentListResponse.fromJson so deserialization is never invoked with an invalid
type.

Comment on lines +1 to +22
import 'package:freezed_annotation/freezed_annotation.dart';

part 'cursor_model.freezed.dart';
part 'cursor_model.g.dart';

/// 커서 기반 페이지네이션 모델
@freezed
class CursorModel with _$CursorModel {
const factory CursorModel({
/// 다음 페이지 존재 여부
@Default(false) bool hasNext,

/// 다음 커서 값 (다음 페이지 요청 시 사용)
int? nextCursor,

/// 현재 페이지 아이템 수
@Default(0) int size,
}) = _CursorModel;

factory CursorModel.fromJson(Map<String, dynamic> json) =>
_$CursorModelFromJson(json);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

코드 생성(build_runner) 실행이 필요합니다.

파이프라인에서 cursor_model.freezed.dartcursor_model.g.dart가 존재하지 않는다는 에러가 발생하고 있습니다. Freezed 모델을 추가한 후 반드시 코드 생성을 실행해야 합니다:

dart run build_runner build --delete-conflicting-outputs

생성된 *.freezed.dart*.g.dart 파일을 커밋에 포함시키거나, CI 파이프라인에서 build_runner가 자동 실행되도록 설정해 주세요. 현재 이 파일뿐 아니라 content_response.dart, home_remote_datasource.dart, home_repository_impl.dart 등 다른 파일의 파이프라인 에러도 모두 동일한 원인입니다.

🧰 Tools
🪛 GitHub Actions: Project Flutter CI

[error] 3-3: Target of URI doesn't exist: 'package:mapsy/features/home/data/models/cursor_model.freezed.dart'


[error] 4-4: Target of URI hasn't been generated: 'package:mapsy/features/home/data/models/cursor_model.g.dart'

🤖 Prompt for AI Agents
In `@lib/features/home/data/models/cursor_model.dart` around lines 1 - 22, The CI
is failing because the Freezed-generated files for CursorModel
(cursor_model.freezed.dart and cursor_model.g.dart) are missing; run the Dart
build runner to generate them (dart run build_runner build
--delete-conflicting-outputs), then either commit the generated files or update
CI to run build_runner before tests/builds so models like CursorModel (and
others mentioned such as ContentResponse, HomeRemoteDatasource,
HomeRepositoryImpl) have their corresponding *.freezed.dart and *.g.dart
artifacts available at runtime.

Comment on lines +1 to +39
import 'package:freezed_annotation/freezed_annotation.dart';

part 'place_model.freezed.dart';
part 'place_model.g.dart';

/// 장소 모델
@freezed
class PlaceModel with _$PlaceModel {
const factory PlaceModel({
/// 장소 ID
required int placeId,

/// 장소명
required String placeName,

/// 주소
String? address,

/// 위도
double? latitude,

/// 경도
double? longitude,

/// 카테고리
String? category,

/// 태그 목록
@Default([]) List<String> tags,

/// 대표 이미지 URL
String? imageUrl,

/// 콘텐츠 ID (상위 콘텐츠)
int? contentId,
}) = _PlaceModel;

factory PlaceModel.fromJson(Map<String, dynamic> json) =>
_$PlaceModelFromJson(json);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check for CI configuration files
find .github -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -20

Repository: MapSee-Lab/MapSy-FE

Length of output: 1159


🏁 Script executed:

# Look for pubspec.yaml to check dependencies
find . -name "pubspec.yaml" -type f | head -5

Repository: MapSee-Lab/MapSy-FE

Length of output: 77


🏁 Script executed:

# Check if generated files exist
find . -name "place_model.freezed.dart" -o -name "place_model.g.dart" 2>/dev/null

Repository: MapSee-Lab/MapSy-FE

Length of output: 45


🏁 Script executed:

# Check for build_runner references in the codebase
rg "build_runner" --type yaml --type toml --type json

Repository: MapSee-Lab/MapSy-FE

Length of output: 112


🏁 Script executed:

# Check the Flutter CI workflow configuration
cat .github/workflows/PROJECT-FLUTTER-CI.yaml

Repository: MapSee-Lab/MapSy-FE

Length of output: 5899


🏁 Script executed:

# Also check if there are any generated file references in place_model.dart
cat -n lib/features/home/data/models/place_model.dart

Repository: MapSee-Lab/MapSy-FE

Length of output: 1027


🏁 Script executed:

# Check pubspec.yaml to see the full freezed configuration
cat pubspec.yaml | grep -A 10 -B 5 "freezed"

Repository: MapSee-Lab/MapSy-FE

Length of output: 1148


CI 실패: Freezed 코드 생성 파일이 누락되었습니다.

파일 시스템에서 place_model.freezed.dartplace_model.g.dart가 존재하지 않습니다. place_model.dart는 이 파일들을 part 지시문으로 참조하고 있으며 (_$PlaceModel mixin, _$PlaceModelFromJson 함수), 이들 파일이 없으면 코드가 컴파일되지 않습니다.

현재 CI 파이프라인에는 build_runner build 단계가 없으므로 자동 생성도 이루어지지 않습니다.

다음 중 하나를 선택해 주세요:

  • 로컬에서 dart run build_runner build --delete-conflicting-outputs 실행 후 생성된 파일을 커밋하거나
  • CI 파이프라인 .github/workflows/PROJECT-FLUTTER-CI.yaml에서 flutter pub get 이후 dart run build_runner build 단계를 추가해 주세요.
🧰 Tools
🪛 GitHub Actions: Project Flutter CI

[error] 3-3: Target of URI doesn't exist: 'package:mapsy/features/home/data/models/place_model.freezed.dart'


[error] 4-4: Target of URI hasn't been generated: 'package:mapsy/features/home/data/models/place_model.g.dart'

🤖 Prompt for AI Agents
In `@lib/features/home/data/models/place_model.dart` around lines 1 - 39, The
build artifacts for the Freezed/JsonSerializable parts referenced by PlaceModel
(place_model.freezed.dart, place_model.g.dart providing _$PlaceModel mixin and
_$PlaceModelFromJson) are missing; fix by either running code generation locally
with `dart run build_runner build --delete-conflicting-outputs` and committing
the generated files, or update the CI workflow to run a build step (after
flutter pub get) that executes `dart run build_runner build` so the part files
are generated during CI. Ensure generated files for PlaceModel are present in
the repo or produced in CI so _$PlaceModel and _$PlaceModelFromJson resolve.

Comment on lines +47 to +51
@override
HomeState build() {
Future.microtask(() => _initialize());
return const HomeState();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd 'home_provider' -e 'dart' | head -20

Repository: MapSee-Lab/MapSy-FE

Length of output: 122


🏁 Script executed:

ls -la lib/features/home/presentation/providers/ | grep -E "home_provider|\.g\.dart|\.freezed"

Repository: MapSee-Lab/MapSy-FE

Length of output: 130


🏁 Script executed:

cat -n lib/features/home/presentation/providers/home_provider.dart

Repository: MapSee-Lab/MapSy-FE

Length of output: 4836


파이프라인 경고: @override가 상속된 메서드를 오버라이드하지 않습니다.

CI에서 Line 48에 The method doesn't override an inherited method 경고가 발생하는 것으로 확인됩니다. @riverpod 코드 생성이 올바르게 실행되었는지 확인하고, dart run build_runner build를 다시 실행해주세요.

또한, Future.microtask(() => _initialize())는 fire-and-forget 방식입니다. 현재는 fetchRecentPlaces()fetchPopularPlaces() 모두 try-catch로 보호되어 있어 괜찮지만, _initialize() 자체에서 발생하는 예외는 상위에서 포착되지 않습니다. 향후 _initialize()에 보호되지 않은 로직이 추가될 경우 주의가 필요합니다.

🧰 Tools
🪛 GitHub Actions: Project Flutter CI

[warning] 48-48: The method doesn't override an inherited method

🤖 Prompt for AI Agents
In `@lib/features/home/presentation/providers/home_provider.dart` around lines 47
- 51, The `@override` warning means the generated Riverpod signature doesn't match
this method; first run the generator (dart run build_runner build) to ensure the
provider code is up-to-date and that the method signature (build / HomeState)
matches the generated code; if generation is intentionally not used, remove the
`@override` annotation so it stops reporting as not overriding. Also avoid silent
fire-and-forget for initialization: change Future.microtask(() => _initialize())
to a form that surface errors (either await the call in an async build or attach
error handling like Future.microtask(() => _initialize()).catchError(...)) so
exceptions from _initialize (not just fetchRecentPlaces/fetchPopularPlaces) are
handled; references: HomeState, build(), _initialize(), fetchRecentPlaces(),
fetchPopularPlaces().

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 11, 2026

❌ Flutter CI 실패

검사 항목 상태 소요 시간
🔍 Analyze ❌ 실패 42초
🤖 Android 빌드 ❌ 실패 5분 27초
🍎 iOS 빌드 ❌ 실패 3분 9초
항목
브랜치 20260209_#18_최신_인기_장소_목록_UI
커밋 78fb2ad
총 소요 시간 5분 45초

💡 확인 사항

Analyze 실패 시:

  • flutter analyze 로컬에서 실행하여 lint 오류 확인
  • 코드 스타일 및 타입 오류 수정

Android 빌드 실패 시:

  • Gradle 빌드 로그에서 에러 확인
  • 의존성 버전 호환성 확인

iOS 빌드 실패 시:

  • Xcode 빌드 로그에서 에러 확인
  • CocoaPods 의존성 확인

📋 워크플로우 로그

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Feb 23, 2026

❌ Flutter CI 실패

검사 항목 상태 소요 시간
🔍 Analyze ❌ 실패 43초
🤖 Android 빌드 ❌ 실패 5분 16초
🍎 iOS 빌드 ❌ 실패 5분 40초
항목
브랜치 20260209_#18_최신_인기_장소_목록_UI
커밋 877811b
총 소요 시간 6분 3초

💡 확인 사항

Analyze 실패 시:

  • flutter analyze 로컬에서 실행하여 lint 오류 확인
  • 코드 스타일 및 타입 오류 수정

Android 빌드 실패 시:

  • Gradle 빌드 로그에서 에러 확인
  • 의존성 버전 호환성 확인

iOS 빌드 실패 시:

  • Xcode 빌드 로그에서 에러 확인
  • CocoaPods 의존성 확인

📋 워크플로우 로그

@Cassiiopeia Cassiiopeia merged commit d8b6d9f into main Feb 23, 2026
1 of 5 checks passed
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.

1 participant