목차
지난 편에서 드디어 MyLog가 앱다운 모습을 갖추기 시작했습니다.
기록을 작성하고,
저장 버튼을 누르고,
목록에서 확인하고,
기록을 눌러 상세 내용까지 볼 수 있었습니다.
제법 그럴듯했습니다.
그래서 기분 좋게 앱을 종료했습니다.
잠시 뒤 다시 실행했습니다.
그리고 MyLog가 아주 태연하게 우리를 맞이합니다.
아직 작성한 기록이 없습니다.
...
분명 방금 썼는데요? 😐
앱 입장에서는 거짓말을 한 것이 아닙니다.
지난 편에서 우리가 만든 기록은 스마트폰에 저장된 것이 아니라 메모리에 잠시 존재하고 있었기 때문입니다.
오늘은 MyLog에게 드디어 제대로 된 기억을 만들어주겠습니다.
1. 저장했다고 했는데 왜 사라졌을까?
지난 편에서는 이런 목록을 사용했습니다.
final List<Record> records = [];그리고 새 기록을 만들면 이 목록에 추가했습니다.
records.add(newRecord)화면에는 정상적으로 표시됩니다.
문제는 records가 존재하는 곳입니다.
현재 실행 중인 앱의 메모리에 있습니다.
흐름을 보면 이렇습니다.
앱 실행
↓
메모리에 records 생성
↓
기록 작성
↓
records에 저장
↓
앱 종료
↓
메모리 사라짐
↓
기록도 사라짐그래서 지난 편에서 사용한 "저장"은 엄밀하게 말하면
현재 앱 상태에 추가했다
에 가까웠습니다.
오늘부터는 데이터를 실제 기기의 저장 공간에 남겨보겠습니다.
2. 메모리와 저장소는 무엇이 다를까?
컴퓨터를 잘 모르는 사람도 RAM과 SSD라는 말은 한번쯤 들어봤을 겁니다.
아주 단순하게 비유하면 비슷합니다.
메모리
지금 작업 중인 내용을 올려두는 책상
영구 저장소
작업이 끝난 뒤에도 보관하는 서랍
이라고 생각할 수 있습니다.
책상 위에만 올려놓은 메모는 퇴근하면서 치워지지만,
서랍에 넣은 문서는 내일 다시 꺼낼 수 있습니다.
MyLog에도 이제 서랍이 필요합니다. 🗄️
3. Flutter에서 데이터를 저장하는 방법은 하나가 아니다
여기서 바로
SQLite를 설치하세요.
라고 넘어가지는 않겠습니다.
Flutter에서 로컬 데이터를 저장하는 방법은 여러 가지입니다.
Flutter 공식 문서에서도 영속 데이터 저장 방식으로 대표적으로 Key-Value 저장, 파일 읽기·쓰기, SQLite를 각각 안내하고 있습니다.
각각 성격이 조금 다릅니다.
4. SharedPreferences, 작은 설정값을 저장할 때
가장 간단한 형태부터 보겠습니다.
예를 들어 사용자가 앱에서 다크모드를 선택했다고 해보겠습니다.
우리가 저장해야 하는 것은 사실상 이것뿐입니다.
darkMode = true또는
language = ko이런 단순한 값을 저장할 때 Key-Value 방식이 편합니다.
Flutter에서는 shared_preferences 패키지를 이용할 수 있습니다.
Key Value
darkMode true
fontSize 16
nickname hongFlutter 공식 문서에서도 shared_preferences는 비교적 작은 Key-Value 데이터 저장에 적합하며 int, double, bool, String, List<String> 같은 기본 값을 지원한다고 설명합니다. 반대로 많은 데이터를 저장하는 용도로 설계된 방식은 아닙니다.
그래서 MyLog의 기록 전체를 여기에 억지로 넣지는 않겠습니다.
5. 파일에 직접 저장하는 방법도 있다
두 번째는 파일입니다.
예를 들어 기록을 JSON으로 변환한 뒤
records.json이라는 파일에 저장할 수도 있습니다.
개념적으로는
List<Record>
↓
JSON 변환
↓
records.json 저장입니다.
앱을 다시 실행하면 반대로 읽습니다.
records.json
↓
JSON 읽기
↓
List<Record>Flutter에서는 dart:io와 path_provider 등을 이용해 기기의 앱 전용 디렉터리에 파일을 읽고 쓰는 방법을 제공합니다. 공식 문서에서도 이런 방식으로 앱 실행 사이에 데이터를 유지하거나 오프라인 사용을 위한 데이터를 저장할 수 있다고 안내합니다.
간단한 앱이라면 충분히 사용할 수 있습니다.
하지만 기록이 점점 많아지고
검색하고,
수정하고,
삭제하고,
정렬하게 된다면
파일 하나를 매번 통째로 읽고 다시 저장하는 구조는 관리하기 불편해질 수 있습니다.
6. SQLite, 구조가 있는 데이터를 저장할 때
그리고 세 번째가 오늘 사용할 SQLite입니다.
SQLite는 스마트폰이나 PC 안에서 동작하는 작은 관계형 데이터베이스입니다.
서버를 별도로 설치할 필요가 없습니다.
앱 내부에 DB 파일 하나가 생긴다고 생각하면 쉽습니다.
MyLog App
↓
SQLite
↓
records 테이블그리고 그 안에 데이터가 쌓입니다.
id title content createdAt
001 바이브 코딩 시작 오늘 처음... 2026-08-23
002 오늘의 기록 앱을 만들어... 2026-08-23
003 개발 메모 SQLite를... 2026-08-24Flutter 공식 SQLite 가이드에서도 기기에 많은 데이터를 지속적으로 저장하고 조회해야 한다면 로컬 파일이나 단순 Key-Value 저장보다 데이터베이스 사용을 고려하도록 설명하고 있습니다. SQLite를 이용하면 삽입, 조회, 수정, 삭제 같은 작업을 구조적으로 처리할 수 있습니다.
7. MyLog에는 왜 SQLite를 선택할까?
현재 기록이 몇 개밖에 없다면 JSON 파일로 저장해도 됩니다.
그런데 MyLog의 다음 모습을 생각해보면 조금 달라집니다.
앞으로 우리는
기록 수정
기록 삭제
검색
날짜 정렬
등을 추가할 가능성이 있습니다.
그렇다면 데이터는 단순한 설정값보다 작은 데이터베이스에 가까운 성격을 갖습니다.
그래서 이번 연재에서는 SQLite를 선택하겠습니다.
중요한 것은
SQLite가 항상 최고다.
가 아닙니다.
데이터 성격에 맞는 저장 방식을 고르는 것입니다.
대략 이런 기준이면 충분합니다.
다크모드 설정
사용자 환경설정
→ Key-Value
간단한 문서
캐시 파일
→ File
여러 개의 구조화된 데이터
검색·수정·삭제가 필요한 데이터
→ SQLite도구보다 데이터의 성격을 먼저 봅니다.
8. AI에게 저장 기술부터 고르게 하지 않는 이유
AI에게 이렇게 말할 수도 있습니다.
기록을 저장할 수 있게 만들어줘.
그러면 AI가 알아서 저장 기술을 선택할 겁니다.
문제는 AI가 무엇을 선택했는지 우리가 모를 수 있다는 것입니다.
예를 들어 shared_preferences에 전체 기록을 JSON 문자열로 넣을 수도 있습니다.
작동은 합니다.
MVP도 됩니다.
하지만 데이터가 커지면 구조가 점점 불편해질 수 있습니다.
그래서 제품 수준의 바이브 코딩에서는 한 단계 더 질문해보는 것이 좋습니다.
현재 MyLog의 Record 데이터를
로컬에 영구 저장하려고 한다.
후보 저장 방식을 비교해줘.
- SharedPreferences
- JSON File
- SQLite
각 방식의
1. 장점
2. 단점
3. 현재 데이터 구조와의 적합성
4. 이후 검색·수정·삭제 확장성
을 비교하고 아직 코드는 수정하지 마.AI에게 선택을 맡길 수는 있습니다.
다만 선택 이유까지 설명하게 하는 것입니다.
9. 이번에도 작업 전에 Git부터 확인한다
이제 저장 구조를 바꿀 겁니다.
지난 편보다 변경 범위가 큽니다.
따라서 먼저 확인합니다.
git status현재 MyLog가 정상적으로 동작하는지도 확인합니다.
그리고 이전 편 작업이 커밋되어 있어야 합니다.
feat: 기록 작성 목록 상세 흐름 구현이 상태가 우리의 탈출구입니다.
SQLite 붙이다가 앱이 갑자기 말을 듣지 않아도 돌아올 수 있습니다.
10. SQLite 사용에 필요한 패키지를 추가한다
Flutter 공식 SQLite 가이드에서는 sqflite와 path 패키지를 사용하는 예제를 제공합니다. 현재 공식 레시피 기준 sqflite는 Android, iOS, macOS 앱에서 SQLite를 사용하는 데 활용할 수 있습니다.
터미널에서 다음과 같이 추가할 수 있습니다.
flutter pub add sqflite path지난 #08에서 우리는 새 패키지를 무조건 추가하지 말자고 했습니다.
이번에는 이유가 명확합니다.
sqflite
→ SQLite DB 접근
path
→ 운영체제에 맞는 DB 파일 경로 구성승인.
이제 추가해도 됩니다.
11. Record 모델도 저장할 수 있는 형태가 필요하다
현재 Record는 Dart 객체입니다.
대략 이런 구조였습니다.
Record
id
title
content
createdAt그런데 SQLite는 Dart의 Record 객체 자체를 그대로 저장하지 않습니다.
DB가 이해할 수 있는 형태로 바꿔줘야 합니다.
흔히 Map 형태로 변환합니다.
Map<String, Object?> toMap() {
return {
'id': id,
'title': title,
'content': content,
'createdAt': createdAt.toIso8601String(),
};
}이 코드도 외울 필요 없습니다.
우리가 이해해야 하는 흐름은 이것입니다.
Record 객체
↓
Map
↓
SQLite 저장반대로 DB에서 읽어왔을 때는 다시 Record로 돌려놓습니다.
SQLite 데이터
↓
Map
↓
Record 객체일종의 통역 과정입니다.
12. 날짜는 왜 문자열로 바꾸나요?
Record에는
createdAt이라는 날짜 정보가 있습니다.
Dart에서는 DateTime으로 다룰 수 있지만 SQLite에 그대로 Dart 객체를 집어넣지는 않습니다.
그래서 예를 들어
createdAt.toIso8601String()처럼 문자열로 변환해서 저장할 수 있습니다.
예를 들면
2026-08-23T14:30:00.000같은 형태입니다.
읽어올 때는 다시 날짜로 바꿉니다.
DateTime.parse(map['createdAt'] as String)이것도 결국
앱에서 사용하는 데이터
↕
저장소에서 사용하는 데이터가 항상 똑같지는 않다는 이야기입니다.
앞으로 API를 다룰 때도 이 개념을 다시 만나게 됩니다.
13. DB 테이블을 만든다
이제 SQLite 안에 기록을 넣을 자리를 만듭니다.
테이블 이름은 단순하게
records로 하겠습니다.
구조는 우리가 이미 설계한 Record와 맞춥니다.
CREATE TABLE records(
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
content TEXT NOT NULL,
createdAt TEXT NOT NULL
)처음 SQL을 보면 또 새로운 언어가 나타난 것처럼 느껴집니다.
하지만 읽어보면 단순합니다.
records라는 표를 만든다.
id
title
content
createdAt
네 칸이 있다.그리고
PRIMARY KEY는 각 기록을 구분하는 핵심 키,
NOT NULL은 값이 반드시 존재해야 한다는 의미 정도로 이해하면 됩니다.
14. DB 코드를 화면 안에 전부 넣지는 말자
기록 목록 화면에서 DB를 열고,
작성 화면에서 SQL을 직접 실행하고,
상세 화면에서도 DB 코드를 작성할 수는 있습니다.
하지만 금방 코드가 뒤섞입니다.
그래서 이번에는 작은 파일 하나를 추가하겠습니다.
lib/
│
├── models/
│ └── record.dart
│
├── services/
│ └── local_database.dart
│
└── screens/
├── record_list_screen.dart
├── record_create_screen.dart
└── record_detail_screen.dartlocal_database.dart의 역할은 단순합니다.
DB 열기
기록 저장
기록 읽기아직 수정과 삭제 기능은 만들지 않습니다.
필요한 것만 넣습니다.
15. 처음 필요한 DB 기능은 두 개뿐이다
현재 MyLog에서 필요한 데이터 작업은 사실 두 가지입니다.
기록 저장
insertRecord()전체 기록 불러오기
getRecords()끝입니다.
SQL의 세계에는 수많은 기능이 있지만 오늘은 문 앞에서 신발만 벗겠습니다.
수정과 삭제는 실제 기능을 추가할 때 구현하면 됩니다.
16. 저장 흐름은 이렇게 바뀐다
지난 편까지는 저장 버튼을 누르면
Record 생성
↓
메모리 records에 추가였습니다.
이제는 중간에 SQLite가 들어갑니다.
제목 + 내용 입력
↓
Record 생성
↓
SQLite 저장
↓
목록 화면 복귀
↓
목록 다시 불러오기여기서 중요한 변화가 하나 있습니다.
데이터의 원본이 메모리에서 DB로 이동합니다.
17. 앱을 실행할 때도 DB에서 읽어야 한다
저장만 하면 끝이 아닙니다.
앱을 다시 실행했을 때 DB에 있는 데이터를 읽어야 합니다.
그래서 목록 화면이 시작될 때
SQLite
↓
기록 조회
↓
List<Record>
↓
화면 표시과정을 거칩니다.
이제 전체 구조가 이렇게 됩니다.
앱 실행
↓
SQLite 열기
↓
저장된 Records 조회
↓
화면에 목록 표시바로 우리가 원했던 기억입니다.
18. 여기서 async와 await가 등장한다
SQLite에 데이터를 읽고 쓰는 작업은 즉시 끝난다고 가정하지 않습니다.
그래서 Flutter 코드에서 이런 형태를 자주 만나게 됩니다.
final records = await database.getRecords();await라는 말은 지금 아주 단순하게 이해해도 됩니다.
이 작업 결과가 올 때까지 기다렸다가 다음으로 가자.
입니다.
흐름을 보면
DB에게 기록 요청
↓
기다림
↓
데이터 도착
↓
화면 표시입니다.
앞으로 서버 API를 호출할 때도 async, await를 굉장히 자주 만나게 됩니다.
오늘 첫 인사만 해두겠습니다.
19. 로딩 상태가 하나 추가됐다
지난 편의 기록 목록 화면에는 두 상태가 있었습니다.
기록 없음
기록 있음그런데 이제 DB에서 데이터를 읽는 시간이 생겼습니다.
따라서 한 가지 상태가 추가됩니다.
로딩 중이제 목록 화면의 상태는
로딩 중
↓
기록 있음
또는
기록 없음이 됩니다.
아주 작은 변화처럼 보이지만 중요합니다.
저장 기술 하나를 추가하자 UI 상태도 늘어났습니다.
#09에서 이야기했던
기술 하나를 추가하면 화면 상태도 함께 늘어난다.
가 실제로 나타나기 시작했습니다.
20. AI에게 이번 작업 범위를 정확하게 전달한다
이제 실제 구현 요청을 해보겠습니다.
PRD, PROJECT_RULES, APP_FLOW을 확인해줘.
현재 Record는 앱 메모리에만 저장되어
앱을 종료하면 사라진다.
이번 작업에서는 SQLite를 사용해
Record를 로컬에 영구 저장하도록 변경한다.
사용 패키지:
- sqflite
- path
구현 범위:
1. SQLite DB 초기화
2. records 테이블 생성
3. Record를 DB 저장 형태로 변환
4. 새 Record 저장
5. 저장된 Record 전체 조회
6. 앱 시작 시 저장된 기록 로딩
7. 저장 후 목록 갱신
이번 작업에서 구현하지 않을 것:
- 기록 수정
- 기록 삭제
- 검색
- 클라우드 동기화
- 서버
- 로그인
기존 작성 → 목록 → 상세 흐름은 유지한다.
아직 코드를 수정하지 말고
먼저 수정할 파일과 구현 계획을 설명해줘.또 계획부터 봅니다.
이제는 이 습관이 제법 자연스러워졌습니다.
21. AI가 이상한 구조를 제안하면 질문한다
예를 들어 AI가 갑자기
Repository
DAO
DataSource
Domain Entity
UseCase
Dependency Injection까지 만들자고 할 수도 있습니다.
틀린 설계는 아닙니다.
규모가 큰 프로젝트에서는 유용할 수 있습니다.
하지만 지금 MyLog는 기록 저장 하나를 붙이는 단계입니다.
우리는 물어봅니다.
현재 MVP 규모에서 이 구조가 모두 필요한가?LocalDatabase정도로 단순화했을 때 생기는 실제 문제를 설명해줘.
AI에게 복잡한 구조를 제안받았다고 무조건 받아들일 필요는 없습니다.
좋은 아키텍처는 복잡한 아키텍처와 같은 말이 아닙니다.
22. 저장 후에는 메모리에 그냥 추가할까, 다시 읽을까?
두 방법 모두 가능합니다.
첫 번째는 DB에 저장하고 현재 목록에도 바로 추가하는 방법입니다.
DB 저장
↓
records.add(record)
↓
화면 갱신두 번째는 저장 후 DB에서 목록을 다시 불러오는 방법입니다.
DB 저장
↓
DB 전체 조회
↓
records 교체
↓
화면 갱신현재 규모에서는 둘 다 가능합니다.
이번 연재에서는 처음에는 두 번째처럼 저장소의 데이터를 다시 읽어 화면과 맞추는 단순한 흐름으로 가도 좋습니다.
중요한 것은 어느 방법을 골랐는지 우리가 알고 있는 것입니다.
23. 구현이 끝나면 바로 앱 종료 테스트부터 한다
AI가 말합니다.
SQLite 저장 구현을 완료했습니다.
이번에는 기다릴 필요도 없습니다.
우리가 가장 먼저 해볼 테스트가 정해져 있습니다.
테스트 1
앱 실행
새 기록 작성
저장
목록 확인
테스트 2
앱 완전 종료
다시 실행
기록이 그대로 있는가?
여기서 기록이 보이면 작은 감동이 옵니다.
지난 편까지만 해도 앱이
누구세요?
하던 녀석이 이제 우리 기록을 기억합니다. 🧠
24. 한 개만 저장해보면 안 된다
조금 더 짓궂게 사용해봅니다.
테스트 3
기록 세 개 작성
앱 종료
다시 실행
→ 세 개 모두 존재하는가?
테스트 4
내용 없이 제목만 작성
저장
앱 재실행
→ 정상적으로 남아 있는가?
테스트 5
한글과 영어, 특수문자가 섞인 내용 저장
오늘 Flutter 공부! 🚀
SQLite 테스트 #1앱 재실행
→ 내용이 그대로 있는가?
제품 테스트는 항상
잘될 만한 상황만 확인하지 않는 것
이 중요합니다.
25. 앱을 삭제하면 데이터도 남아 있을까?
여기서 재미있는 질문이 하나 있습니다.
앱을 삭제하고 다시 설치하면 기록도 남나요?
현재처럼 앱의 로컬 DB에 저장했다면 일반적으로 앱 데이터와 함께 사라지는 것으로 생각해야 합니다.
이게 로컬 저장의 중요한 특징입니다.
앱 종료
→ 데이터 유지
스마트폰 재부팅
→ 데이터 유지
앱 삭제
→ 로컬 앱 데이터도 제거즉 로컬 저장은
앱이 꺼져도 남는 것
이지
어떤 상황에서도 영원히 보존되는 것
은 아닙니다.
나중에 여러 기기에서 같은 데이터를 보거나 앱을 다시 설치해도 복구하려면 클라우드 저장이 필요합니다.
#13에서 바로 그 단계로 갑니다.
26. 로컬 저장과 클라우드 저장은 경쟁 관계가 아니다
가끔 이런 질문도 생깁니다.
나중에 Supabase 같은 클라우드 DB를 쓸 거라면 SQLite는 필요 없는 것 아닌가요?
꼭 그렇지는 않습니다.
실제 제품에서는 두 가지를 함께 사용하는 경우도 많습니다.
로컬 DB
빠른 화면 표시
오프라인 사용
+
클라우드 DB
백업
여러 기기 동기화
사용자별 데이터물론 그렇게 되면 동기화라는 새로운 난도가 등장합니다.
데이터가 로컬에서도 수정되고 서버에서도 수정되면 누가 최신인지 결정해야 합니다.
그 문제는 지금 열지 않겠습니다.
문 하나 열었더니 복도가 40개 나오는 분야입니다. 🚪
현재 MyLog에서는
로컬이 유일한 저장소
입니다.
단순하게 갑니다.
27. 중요한 데이터는 SharedPreferences에 넣지 말라는 이유
이 부분은 다시 한번 짚고 넘어갈 가치가 있습니다.
shared_preferences는 간편합니다.
그래서 기록 목록 전체를 문자열로 변환해 저장하고 싶어질 수도 있습니다.
하지만 Flutter 공식 문서에서는 이 방식이 작은 Key-Value 저장을 위한 것이며 대량 데이터를 위한 저장소가 아니라고 설명합니다. 현재 공식 문서에는 모든 쓰기 작업이 디스크에 영구적으로 남는다고 보장하는 용도로 설계된 것도 아니라는 주의가 포함되어 있습니다.
따라서
다크모드 여부
첫 실행 여부
간단한 설정과
사용자가 작성한 수백 개의 기록은 성격이 다릅니다.
저장할 수 있느냐보다
무엇을 저장하는 데 적합한가
를 보는 습관을 들이겠습니다.
28. 그리고 비밀번호는 SQLite에 그냥 저장하면 안 된다
로컬 DB 이야기를 하면 여기서 꼭 하나 짚어야 합니다.
나중에 로그인을 만들 때
email
password를 SQLite에 평문으로 저장하면 될까요?
아닙니다.
비밀번호,
인증 토큰,
API Key 같은 민감정보는 일반 기록 데이터와 같은 방식으로 생각하면 안 됩니다.
다음 편부터 인증이 등장하기 때문에 이 구분이 중요합니다.
일반 앱 데이터
→ 일반 로컬 저장소
민감한 인증정보
→ 보안 저장 방식 검토지금은 이 정도만 기억해두겠습니다.
보안은 #16에서 더 제대로 다룹니다.
29. 오늘의 삽질 방지 팁 🛠️
AI에게 이런 식으로 요청하지 마세요.
앱 데이터가 안 사라지게 해줘.
기술 선택 범위가 너무 넓습니다.
대신 최소한 다음 질문은 포함해보세요.
현재 데이터 구조와 앞으로의 기능을 기준으로
어떤 로컬 저장 방식이 적합한지 먼저 설명해줘.
작동한다는 이유만으로
가장 간단한 저장 방식을 선택하지 말고
데이터 양,
조회,
수정,
삭제,
향후 검색 기능
까지 고려해줘.이건 꽤 중요한 바이브 코딩 습관입니다.
AI에게 구현 방법만 묻지 말고 선택 근거도 묻는 것.
좋은 제품은 코드보다 이런 작은 결정들이 쌓여서 만들어집니다.
30. 구현 후 AI에게 이것까지 물어보자
저장이 정상적으로 되었다면 다음 질문을 해보는 것도 좋습니다.
현재 구현된 로컬 저장 흐름을
비개발자가 이해할 수 있게 설명해줘.
다음 순서로 설명해줘.
1. 앱 최초 실행 시 DB가 어떻게 만들어지는지
2. records 테이블은 언제 생성되는지
3. 사용자가 저장 버튼을 누르면 Record가 어떻게 DB에 들어가는지
4. 앱 재실행 시 DB에서 Record를 어떻게 읽는지
5. DB 데이터를 Flutter 화면이 어떻게 표시하는지
6. 현재 구조에서 데이터가 손실될 수 있는 상황이렇게 해두면 우리가 작성하지 않은 코드도 어느 정도 구조를 파악할 수 있습니다.
31. 정상이라면 다시 Git에 저장한다
테스트까지 완료했다면
git status를 확인합니다.
새 패키지가 들어갔기 때문에 pubspec.yaml과 관련 lock 파일 변경도 있을 수 있습니다.
그리고 코드 변경 내용을 확인합니다.
정상이라면 커밋합니다.
예를 들어
feat: SQLite 기반 로컬 기록 저장 구현이제 우리 Git 기록에는 중요한 이정표가 하나 더 생겼습니다.
Flutter 프로젝트 생성
↓
기록 작성·목록·상세
↓
SQLite 로컬 저장 ← SAVE이제 앱을 종료하는 것이 무섭지 않습니다.
32. 오늘 MyLog에 생긴 진짜 변화
겉으로 보면 지난 편과 화면은 거의 똑같을 수 있습니다.
새로운 화려한 버튼도 없습니다.
디자인도 그대로입니다.
하지만 앱 내부에서는 굉장히 큰 변화가 생겼습니다.
지난 편:
화면
↓
Memory
↓
화면이번 편:
화면
↓
Record
↓
SQLite
↓
앱 종료
↓
앱 재실행
↓
SQLite
↓
Record
↓
화면데이터에 생명주기가 생겼습니다.
앱이 종료되어도 데이터가 살아남습니다.
MVP에서 제품으로 가는 데 이런 변화가 훨씬 중요합니다.
눈에 보이는 버튼 하나보다 말이죠.
33. 오늘의 완료 조건
이번 편도 체크해보겠습니다.
[ ] 메모리와 영구 저장소의 차이를 이해했다.
[ ] Key-Value, File, SQLite의 용도를 대략 구분할 수 있다.
[ ] MyLog에서 SQLite를 선택한 이유를 이해했다.
[ ] sqflite와 path 패키지의 역할을 확인했다.
[ ] Record를 DB에 저장 가능한 형태로 변환했다.
[ ] records 테이블이 만들어졌다.
[ ] 새로운 Record를 SQLite에 저장할 수 있다.
[ ] 저장된 기록 전체를 읽을 수 있다.
[ ] 앱 실행 시 DB에서 기록을 불러온다.
[ ] 앱을 완전히 종료해도 기록이 유지된다.
[ ] 제목 필수 입력 규칙이 그대로 유지된다.
[ ] 기존 작성 → 목록 → 상세 흐름이 깨지지 않았다.
[ ] 직접 재실행 테스트를 수행했다.
[ ] 정상 상태를 Git Commit으로 남겼다.여기까지 됐다면 MyLog는 이제 최소한의 진짜 기록 앱이 됐습니다.
작성하고,
읽고,
껐다 켜도 기억합니다.
생각보다 큰 단계입니다.
34. 그런데 스마트폰을 바꾸면?
이제 새로운 문제가 보이기 시작합니다.
현재 MyLog의 기록은
내 스마트폰 안에만 있습니다.
스마트폰을 바꾸면?
기록이 없습니다.
Android에서 작성한 내용을 iPhone에서 보고 싶다면?
볼 수 없습니다.
그리고 아직 사용자가 누구인지도 모릅니다.
모든 데이터가 그냥 현재 기기의 데이터입니다.
이 문제를 해결하려면 앱이 먼저
지금 사용하고 있는 사람이 누구인가?
를 알아야 합니다.
그래서 다음 단계에서는 인증(Authentication) 이 등장합니다.
회원가입과 로그인입니다.
그런데 로그인 화면 하나 추가한다고 끝나는 문제가 아닙니다.
세션은 무엇인지,
로그인 상태는 어떻게 유지하는지,
비밀번호를 앱에서 어떻게 다뤄야 하는지,
AI에게 인증을 맡길 때 어떤 실수를 조심해야 하는지
살펴볼 것이 꽤 많습니다.
다음 편
[바이브 코딩 실전 #12] 회원가입과 로그인을 붙여보자 | 인증을 AI에게 맡길 때 주의할 점
이제 MyLog는 기록을 기억합니다.
다음에는
누가 기록을 작성했는지
알게 만들어보겠습니다.
앱도 이제 슬슬 사람 얼굴을 구분하기 시작합니다. 👤📱
연재 기준: 2026년 8월Flutter의 패키지와 로컬 저장 권장 방식은 업데이트될 수 있습니다. 이번 글은 Flutter 3.44.x 공식 문서에서 안내하는 Key-Value, 파일 저장, SQLite 영속성 가이드를 기준으로 구성했습니다. 실제 프로젝트에서는 사용하는 플랫폼과 데이터 특성에 따라 저장 기술을 다시 검토하는 것이 좋습니다.
#바이브코딩 #VibeCoding #AI코딩 #Flutter #FlutterSQLite #SQLite #로컬저장소 #데이터저장 #sqflite #Flutter앱개발 #비개발자앱개발 #MVP개발 #앱개발 #AI에이전트 #MyLog #바이브코딩실전
