2026년 8월 5일 수요일

Hive 써봤지만 정확히 몰랐던 것들 - 초보 개발자의 개념 정리기

Hive와 Flutter 로컬 저장소 가이드

Hive가 대체 머야.... 먼데 자꾸 쓰냐...


Developer English 앱 만들면서

오답노트 기능 저장할 때 Hive를 썼는데,

사실 그때도 "일단 하라니까 쓴다" 수준이었지

Hive가 정확히 뭔지, 

왜 다른 것들 두고 이걸 썼는지는 

제대로 몰랐어요. 

이번 기회에 제대로 정리해보려고요.





1. Hive는 한마디로 - Flutter용 로컬 저장소

Hive는

Flutter/Dart 앱 안에서

데이터를 기기에 직접 저장하는 NoSQL 데이터베이스예요. 


서버 없이, 인터넷 연결 없이

앱 안에서 데이터를 저장하고 불러올 수 있게 해주는 도구죠.


제 앱의 오답노트가 인터넷을 안 켜도 예전에 틀렸던 문제를 계속 보여주는 게 

바로 이 Hive 덕분이었어요.





2. 이름이 왜 Hive(벌집)일까?

이게 은근 개념 이해에 도움이 되는 부분인데요,

Hive의 핵심 구조가 진짜 벌집처럼 짜여있어요.


벌집 비유 Hive 용어 역할
벌집 전체 Hive 데이터베이스 라이브러리 자체
벌집 안의 한 칸 Box 실제 데이터가 저장되는 하나의 저장 공간 (테이블 느낌)
칸 안에 채워진 꿀 Key-Value 데이터 Box 안에 저장된 실제 값들


제 오답노트 기능으로 치면,

wrongNotesBox라는 Box(벌집 칸) 하나를 만들어서 

그 안에 "문제 ID → 오답 정보" 형태로

꿀(데이터)을 차곡차곡 채워넣은 거였어요.





3. 왜 SQLite 안 쓰고 Hive를 썼을까?

Flutter에서 로컬 저장소 선택지가 여러 개 있는데, 각각 쓰임새가 달라요.



저장소 방식 적합한 경우
SharedPreferences 단순 key-value 로그인 여부, 다크모드 설정처럼 작은 값 하나
SQLite (sqflite) 관계형 DB, SQL 쿼리 테이블 간 관계가 복잡하거나 SQL이 익숙할 때
Hive NoSQL key-value, Dart 객체 그대로 저장 복잡한 관계 없이 빠르게, Dart 문법 그대로 쓰고 싶을 때


제일 크게 와닿았던 차이는 이거였어요.

SQLite는 

SQL 쿼리문을 따로 배워서 써야 하는데,

Hive는

그냥 Dart 클래스 객체를 그대로 저장하고 꺼내 쓸 수 있어요.


오답노트처럼

"문제, 내 답, 정답, 틀린 날짜"를 담은 객체 하나를 통째로 저장했다가

그대로 꺼내 쓰는 구조라

SQL 없이 Dart 코드만으로 끝나는 Hive가 훨씬 편했어요.


게다가 순수 Dart로 만들어져서 네이티브 의존성이 없다 보니 속도도 꽤 빨랐고요.





4. 실제로 어떻게 쓰는지 (제 오답노트 코드 기준)


4-1. 초기화

// main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Hive.initFlutter();
  Hive.registerAdapter(WrongNoteAdapter()); // 내가 만든 모델의 어댑터 등록
  await Hive.openBox<WrongNote>('wrongNotesBox');
  runApp(MyApp());
}


4-2. 모델 클래스에 어댑터 붙이기

@HiveType(typeId: 0)
class WrongNote extends HiveObject {
  @HiveField(0)
  String question;

  @HiveField(1)
  String myAnswer;

  @HiveField(2)
  String correctAnswer;

  WrongNote({required this.question, required this.myAnswer, required this.correctAnswer});
}


@HiveType, @HiveField 어노테이션 보고 

처음엔 "이게 왜 필요하지?" 싶었는데,

Hive는 Dart 객체를 그대로 저장할 수 있게 바이너리로 변환해서 저장하거든요.


근데 Dart는

원래 리플렉션(런타임에 클래스 구조 읽는 기능)을 지원 안 해서,

어떤 필드를 몇 번째 자리에 저장할지

미리 알려주는 역할을 이 어노테이션이 해주는 거였어요.


그리고 이 어노테이션 기반으로 build_runner가 

실제 변환 코드(*.g.dart 파일)를 자동 생성해줘요.



4-3. 저장 / 조회 / 삭제

final box = Hive.box<WrongNote>('wrongNotesBox');

// 저장
box.add(WrongNote(question: "...", myAnswer: "...", correctAnswer: "..."));

// 전체 조회
List<WrongNote> allNotes = box.values.toList();

// 삭제
await box.deleteAt(0);


SQL 쿼리 한 줄 없이,

그냥 Dart 리스트 다루듯이 쓸 수 있다는 게 진짜 편했어요.





5. 헷갈렸던 부분 - Provider랑은 무슨 관계?

제 앱에서 Provider랑 Hive를 같이 쓰다 보니

처음엔 둘이 하는 일이 겹치는 줄 알았는데,

역할이 완전히 달라요.


  • Hive: 데이터를 기기에 영구 저장하는 역할 (앱을 껐다 켜도 남아있음)
  • Provider: 화면들 사이에서 상태를 실시간으로 공유·전달하는 역할 (앱이 켜져있는 동안만)


그래서 실제 흐름은

"Hive에서 데이터 불러오기 → Provider한테 그 데이터를 넘겨서

여러 화면이 실시간으로 반영하도록 관리" 순서였어요.


둘이 경쟁 관계가 아니라 저장(Hive)과 화면 반영(Provider)으로

역할 분담을 하는 거였더라고요.






오늘의 정리

  • Hive는 Flutter/Dart용 로컬 NoSQL 데이터베이스 - 서버나 인터넷 없이 기기에 데이터 저장
  • Box(벌집 칸)라는 단위로 데이터를 저장하고, 그 안에 key-value 형태로 값이 들어감
  • SQL 쿼리 없이 Dart 객체를 그대로 저장·조회할 수 있어서 편함
  • @HiveType / @HiveField는 Dart 객체를 바이너리로 변환하기 위한 설계도 역할
  • Hive(저장) + Provider(화면 공유)는 경쟁이 아니라 역할 분담 관계


이번에 정리하면서 느낀 건데,

저처럼 일단 코드 돌아가니까 계속 갖다 쓰다가

나중에서야 "이게 대체 뭐였지" 하고

되짚어보는 경우 은근 많은 것 같아요.


다음엔 Provider 자체도 한 번 제대로 파봐야겠어요 🍑

댓글 없음:

댓글 쓰기

커서(Cursor)로 바이브코딩을 처음 해본 후기|편하긴 한데 앱이 버그 덩어리가 됐다

커서(Cursor)로 바이브코딩을 처음 해본 후기 편하긴 한데 앱이 버그 덩어리가 됐다 오늘은 커서(C...