diff --git a/flutter/assets/svg/common/add_card.svg b/flutter/assets/svg/common/add_card.svg
new file mode 100644
index 0000000..23180d0
--- /dev/null
+++ b/flutter/assets/svg/common/add_card.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/common/add_photo.svg b/flutter/assets/svg/common/add_photo.svg
new file mode 100644
index 0000000..d0657f1
--- /dev/null
+++ b/flutter/assets/svg/common/add_photo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/common/person_default.svg b/flutter/assets/svg/common/person_default.svg
new file mode 100644
index 0000000..0837ef8
--- /dev/null
+++ b/flutter/assets/svg/common/person_default.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/common/pet_default.svg b/flutter/assets/svg/common/pet_default.svg
new file mode 100644
index 0000000..8d278ad
--- /dev/null
+++ b/flutter/assets/svg/common/pet_default.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/bird.svg b/flutter/assets/svg/species/bird.svg
new file mode 100644
index 0000000..0a24b1e
--- /dev/null
+++ b/flutter/assets/svg/species/bird.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/cat.svg b/flutter/assets/svg/species/cat.svg
new file mode 100644
index 0000000..789f399
--- /dev/null
+++ b/flutter/assets/svg/species/cat.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/dog.svg b/flutter/assets/svg/species/dog.svg
new file mode 100644
index 0000000..ac8d742
--- /dev/null
+++ b/flutter/assets/svg/species/dog.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/ferret.svg b/flutter/assets/svg/species/ferret.svg
new file mode 100644
index 0000000..450f731
--- /dev/null
+++ b/flutter/assets/svg/species/ferret.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/fish.svg b/flutter/assets/svg/species/fish.svg
new file mode 100644
index 0000000..32cca27
--- /dev/null
+++ b/flutter/assets/svg/species/fish.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/guineapig.svg b/flutter/assets/svg/species/guineapig.svg
new file mode 100644
index 0000000..6bf9c04
--- /dev/null
+++ b/flutter/assets/svg/species/guineapig.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/hamster.svg b/flutter/assets/svg/species/hamster.svg
new file mode 100644
index 0000000..5814a33
--- /dev/null
+++ b/flutter/assets/svg/species/hamster.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/hedgehog.svg b/flutter/assets/svg/species/hedgehog.svg
new file mode 100644
index 0000000..39f7dbb
--- /dev/null
+++ b/flutter/assets/svg/species/hedgehog.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/lizard.svg b/flutter/assets/svg/species/lizard.svg
new file mode 100644
index 0000000..c6692b4
--- /dev/null
+++ b/flutter/assets/svg/species/lizard.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/other.svg b/flutter/assets/svg/species/other.svg
new file mode 100644
index 0000000..36fff5d
--- /dev/null
+++ b/flutter/assets/svg/species/other.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/rabbit.svg b/flutter/assets/svg/species/rabbit.svg
new file mode 100644
index 0000000..cc602b8
--- /dev/null
+++ b/flutter/assets/svg/species/rabbit.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/snake.svg b/flutter/assets/svg/species/snake.svg
new file mode 100644
index 0000000..81826d9
--- /dev/null
+++ b/flutter/assets/svg/species/snake.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/assets/svg/species/turtle.svg b/flutter/assets/svg/species/turtle.svg
new file mode 100644
index 0000000..312f6be
--- /dev/null
+++ b/flutter/assets/svg/species/turtle.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/flutter/ios/Runner/Info.plist b/flutter/ios/Runner/Info.plist
index a58c4ae..333ac90 100644
--- a/flutter/ios/Runner/Info.plist
+++ b/flutter/ios/Runner/Info.plist
@@ -8,6 +8,8 @@
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
Tma App
+ NSPhotoLibraryUsageDescription
+ 우리 아이 프로필 사진을 등록하기 위해 사진 보관함에 접근합니다.
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
diff --git a/flutter/lib/core/constants/app_assets.dart b/flutter/lib/core/constants/app_assets.dart
index e6ac336..2e2e1e3 100644
--- a/flutter/lib/core/constants/app_assets.dart
+++ b/flutter/lib/core/constants/app_assets.dart
@@ -33,4 +33,14 @@ abstract final class AppAssets {
static const String onb3Sparkle3 = 'assets/images/onboarding/onb3_sp3.png';
static const String onb4Base = 'assets/images/onboarding/onb4_base.png';
static const String onb4Heart = 'assets/images/onboarding/onb4_ch.png';
+
+ // 공통
+ static const String petDefault = 'assets/svg/common/pet_default.svg';
+ static const String personDefault = 'assets/svg/common/person_default.svg';
+ static const String addPhoto = 'assets/svg/common/add_photo.svg';
+ static const String addCard = 'assets/svg/common/add_card.svg';
+
+ /// 종 실루엣 아이콘 — [speciesIconKey] 는 dog·cat·… (없으면 other)
+ static String speciesIcon(String speciesIconKey) =>
+ 'assets/svg/species/$speciesIconKey.svg';
}
diff --git a/flutter/lib/features/pet/data/pet_photo_store.dart b/flutter/lib/features/pet/data/pet_photo_store.dart
new file mode 100644
index 0000000..b2be49c
--- /dev/null
+++ b/flutter/lib/features/pet/data/pet_photo_store.dart
@@ -0,0 +1,32 @@
+import 'dart:io';
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:image_picker/image_picker.dart';
+import 'package:path_provider/path_provider.dart';
+
+const String _kPhotoDir = 'pet_photos';
+
+/// 앨범에서 고른 사진을 앱 전용 폴더로 복사해 경로를 돌려준다.
+/// (앨범 원본이 지워져도 아이 사진이 남도록) — 서버 업로드가 생기면 그쪽으로 바꾼다.
+class PetPhotoStore {
+ const PetPhotoStore();
+
+ Future persist(XFile file) async {
+ // 웹은 미리보기용 — 브라우저가 준 임시 주소를 그대로 쓴다
+ if (kIsWeb) return file.path;
+
+ final docs = await getApplicationDocumentsDirectory();
+ final dir = Directory('${docs.path}/$_kPhotoDir');
+ if (!dir.existsSync()) await dir.create(recursive: true);
+
+ final dot = file.name.lastIndexOf('.');
+ final ext = dot >= 0 ? file.name.substring(dot) : '.jpg';
+ // 저장 파일명은 앱이 만든다 — 원본 이름을 경로에 쓰지 않는다
+ final target = '${dir.path}/${DateTime.now().microsecondsSinceEpoch}$ext';
+ await file.saveTo(target);
+ return target;
+ }
+}
+
+final petPhotoStoreProvider = Provider((ref) => const PetPhotoStore());
diff --git a/flutter/lib/features/pet/data/repositories/allergen_menu_repository.dart b/flutter/lib/features/pet/data/repositories/allergen_menu_repository.dart
new file mode 100644
index 0000000..189e3ed
--- /dev/null
+++ b/flutter/lib/features/pet/data/repositories/allergen_menu_repository.dart
@@ -0,0 +1,28 @@
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:tma_app/core/storage/preferences_provider.dart';
+
+/// 기본 알레르기 항목 (시안 ALLERGENS)
+const List kDefaultAllergens = [
+ '닭고기', '소고기', '돼지고기', '유제품', '밀', '옥수수', '계란', '생선', '콩',
+];
+
+const String _kCustomAllergensKey = 'pet.customAllergens';
+
+/// 사용자가 "직접 추가" 한 알레르기 항목 — 다음 등록 때도 메뉴에 남는다.
+class AllergenMenuRepository {
+ AllergenMenuRepository(this._prefs);
+
+ final SharedPreferences _prefs;
+
+ List load() => _prefs.getStringList(_kCustomAllergensKey) ?? const [];
+
+ Future save(List items) => _prefs.setStringList(
+ _kCustomAllergensKey,
+ items.where((a) => !kDefaultAllergens.contains(a)).toList(),
+ );
+}
+
+final allergenMenuRepositoryProvider = Provider((ref) {
+ return AllergenMenuRepository(ref.watch(sharedPreferencesProvider));
+});
diff --git a/flutter/lib/features/pet/data/repositories/pet_repository.dart b/flutter/lib/features/pet/data/repositories/pet_repository.dart
new file mode 100644
index 0000000..3d14b0b
--- /dev/null
+++ b/flutter/lib/features/pet/data/repositories/pet_repository.dart
@@ -0,0 +1,65 @@
+import 'dart:convert';
+
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import 'package:tma_app/core/storage/preferences_provider.dart';
+import 'package:tma_app/features/pet/domain/pet.dart';
+
+/// 반려동물 저장소 계약 — 백엔드 API(/api/pets)가 생기면 Dio 구현으로 바꾼다.
+abstract interface class PetRepository {
+ /// 사용자가 정한 순서대로
+ Future> fetchPets();
+
+ Future create(PetInput input);
+
+ Future update(String id, PetInput input);
+
+ Future delete(String id);
+}
+
+const String _kPetsKey = 'pets.v1';
+
+/// 임시 구현 — 기기(SharedPreferences)에 JSON 으로 저장한다.
+/// 서버 연동 전까지 앱을 다시 켜도 등록한 아이가 남도록 하기 위한 것이다.
+class LocalPetRepository implements PetRepository {
+ LocalPetRepository(this._prefs, {DateTime Function()? clock}) : _clock = clock ?? DateTime.now;
+
+ final SharedPreferences _prefs;
+ final DateTime Function() _clock;
+
+ List _read() {
+ final raw = _prefs.getString(_kPetsKey);
+ if (raw == null) return [];
+ final list = jsonDecode(raw) as List