# localStorage에서 MongoDB까지: 초보자를 위한 데이터베이스 구조 완전 정복

---

# # 📌 서론 – “데이터는 어디에 저장해야 할까?”

웹 애플리케이션을 만들다 보면 **데이터를 어디에 보관할지** 고민하게 됩니다.

초기 개발 단계에서는 브라우저에 내장된 `localStorage`를 이용해 간단히 데이터를 저장합니다.

하지만 사용자가 늘어나고, 데이터가 영구적이어야 하며, 여러 디바이스에서 동기화가 필요해지면 **데이터베이스**가 필수입니다.

특히 **MongoDB**와 같은 NoSQL 데이터베이스는 스키마가 자유롭고 확장성이 뛰어나서 현대 웹·모바일 서비스에 많이 선택됩니다.

이번 포스트에서는 `localStorage`와 `MongoDB` 사이의 차이를 짚어보고, **MongoDB 구조**를 초보자도 이해하기 쉽도록 단계별로 설명합니다.

> **키워드**: `MongoDB 구조`, `localStorage`, `데이터베이스 연동`

---

# # 1️⃣ localStorage – 브라우저에 “잠깐” 저장하기

## # 1-1. localStorage란?

- 브라우저가 제공하는 **키‑값(key‑value) 형태**의 저장소

- 문자열만 저장 가능 → 객체는 `JSON.stringify` 로 변환 필요

- 도메인 별로 격리돼 있어 같은 사이트 내에서만 접근 가능

## # 1-2. 장점 & 단점

| 장점 | 단점 |

|------|------|

| 구현이 간단 → `localStorage.setItem('key', value)` 한 줄 | 용량 제한 (≈ 5 MB) |

| 비동기 호출이 없어 즉시 저장/읽기 | 영구적이지 않음 (브라우저 캐시 삭제 시 사라짐) |

| 서버와 통신 불필요 → 네트워크 비용 절감 | 보안 취약 (XSS 공격 시 노출 가능) |

## # 1-3. 언제 쓰나요?

- 사용자의 UI 설정(테마, 언어) 저장

- 로그인 상태 유지(토큰) (단, 보안 고려 필요)

- 작은 임시 데이터(폼 입력값) 보관

하지만 **비즈니스 로직에 중요한 데이터**를 `localStorage`에만 의존하면 안 됩니다. 여기서 **데이터베이스 연동**이 필요합니다.

---

# # 2️⃣ MongoDB – “문서형” 데이터베이스의 기본 구조

## # 2-1. MongoDB란?

- **NoSQL** 계열 중 하나로, JSON 형태의 **문서(Document)**를 저장

- 스키마가 자유롭고, 컬렉션(Collection) 단위로 데이터를 관리

## # 2-2. 핵심 개념

| 용어 | 설명 |

|------|------|

| **Database** | 여러 컬렉션을 포함하는 논리적 단위 |

| **Collection** | 같은 종류의 문서를 모아둔 집합 (예: `users`, `posts`) |

| **Document** | `{ field: value, ... }` 형태의 JSON-like 객체 |

| **ObjectId** | 각 문서를 고유히 식별하는 12바이트 ID (자동 생성) |

## # 2-3. MongoDB 구조 예시

```
json

{
  '_id': ObjectId('65f9c2a5b1e4c8d6f9a0b123'),

  'username': 'johndoe',

  'email': 'john@example.com',

  'profile': {

    'age': 28,

    'city': 'Seoul'

  },

  'createdAt': ISODate('2024-10-01T12:34:56Z')

}

```

- **중첩 문서(Nested Document)** 로 관계형 DB의 JOIN을 대체

- **배열(Array)** 로 여러 값을 하나의 필드에 저장 가능

## # 2-4. 왜 MongoDB인가?

1. **스키마 유연성** – 초기 설계가 미완성돼도 바로 데이터 삽입 가능

2. **수평 확장성** – 샤딩(Sharding)으로 트래픽 급증에 대응

3. **빠른 개발 속도** – JSON 형태라 프론트엔드와 데이터 포맷이 일치

---

# # 3️⃣ localStorage와 MongoDB 연동 흐름 – 전체 아키텍처

## # 3-1. 기본 흐름도

```
mermaid

flowchart TD

    A[브라우저] -->|입력 데이터| B[localStorage]

    B -->|동기화 트리거| C[프론트엔드 JS]

    C -->|REST API 호출| D[Node.js/Express 서버]

    D -->|MongoDB 드라이버| E[MongoDB]

    E -->|응답| D

    D -->|결과 반환| C

    C -->|업데이트| B

```

1. **사용자 입력** → 일시적으로 `localStorage`에 저장 (빠른 UI 반응)

2. **동기화 시점**(예: 페이지 언로드, 일정 주기, 버튼 클릭) → 프론트엔드에서 **API 호출**

3. **서버**는 요청을 받아 **MongoDB**에 데이터를 삽입/수정

4. **응답**을 받아 프론트엔드가 `localStorage`를 최신 상태로 업데이트

## # 3-2. 언제 동기화할까?

| 상황 | 권장 동기화 방법 |

|------|----------------|

| 사용자가 **저장** 버튼을 클릭 | 즉시 `POST /api/items` 호출 |

| 페이지를 **떠날 때** | `window.onbeforeunload` 이벤트에 API 호출 |

| 일정 **주기**마다 (예: 5분) | `setInterval` 로 백그라운드 동기화 |

| 네트워크가 **복구**될 때 | 오프라인 모드 → 온라인 전환 감지 후 전송 |

---

# # 4️⃣ 실전 예제 – React + Express + MongoDB 연동하기

## # 4-1. 프로젝트 구조 (간단히)

```

my-app/

├─ client/          # React 프로젝트

│   └─ src/

│       └─ utils/

│           └─ storage.js   # localStorage 헬퍼

├─ server/          # Express + MongoDB

│   └─ routes/

│       └─ items.js

│   └─ models/

│       └─ Item.js

└─ README.md

```

## # 4-2. 프론트엔드 – localStorage 헬퍼 (`storage.js`)

```
javascript

// storage.js

export const saveToLocal = (key, data) => {

  localStorage.setItem(key, JSON.stringify(data));

};

export const loadFromLocal = (key) => {

  const raw = localStorage.getItem(key);

  return raw ? JSON.parse(raw) : null;

};

export const clearLocal = (key) => {

  localStorage.removeItem(key);

};

```

## # 4-3. 데이터 저장 & 동기화 로직 (React 컴포넌트)

```
javascript

import { useState, useEffect } from 'react';

import axios from 'axios';

import { saveToLocal, loadFromLocal } from './utils/storage';

function TodoApp() {

  const [todos, setTodos] = useState(() => loadFromLocal('todos') || []);

  // 입력 → localStorage에 즉시 저장

  const addTodo = (text) => {

    const newTodo = { id: Date.now(), text };

    const updated = [...todos, newTodo];

    setTodos(updated);

    saveToLocal('todos', updated);

  };

  // 5분마다 서버와 동기화

  useEffect(() => {

    const timer = setInterval(() => {

      axios.post('/api/todos/sync', { todos })

        .then(res => console.log('Sync success:', res.data))

        .catch(err => console.error('Sync error:', err));

    }, 5 * 60 * 1000);

    return () => clearInterval(timer);

  }, [todos]);

  return (/* UI 생략 */);

}

```

## # 4-4. 서버 – Express 라우터 (`items.js`)

```
javascript

const express = require('express');

const router = express.Router();

const Item = require('../models/Item');

// 클라이언트에서 전송한 전체 배열을 MongoDB에 upsert

router.post('/todos/sync', async (req, res) => {

  const { todos } = req.body;

  try {

    // 기존 데이터 모두 삭제 후 새로 삽입 (간단 예시)

    await Item.deleteMany({});

    await Item.insertMany(todos.map(t => ({ text: t.text, createdAt: new Date() })));

    res.json({ status: 'ok', synced: todos.length });

  } catch (e) {

    console.error(e);

    res.status(500).json({ error: 'Sync failed' });

  }

});

module.exports = router;

```

## # 4-5. MongoDB 모델 (`Item.js`)

```
javascript

const mongoose = require('mongoose');

const ItemSchema = new mongoose.Schema({

  text: { type: String, required: true },

  createdAt: { type: Date, default: Date.now }

});

module.exports = mongoose.model('Item', ItemSchema);

```

> **핵심 포인트**

> - **JSON 형태**가 그대로 `MongoDB`에 저장돼 `localStorage`와 구조가 유사 → 변환 로직이 최소화됩니다.

> - `ObjectId` 대신 클라이언트에서 만든 `id`(예: 타임스탬프)를 임시 키로 사용해도 무방합니다.

---

# # 5️⃣ 베스트 프랙티스 & 주의사항

| 항목 | 권장 방법 |

|------|-----------|

| **데이터 검증** | 서버에서 `Joi`·`zod` 등으로 스키마 검증 후 DB에 삽입 |

| **보안** | 토큰 기반 인증(JWT) → API 호출 시 `Authorization` 헤더에 포함 |

| **오프라인 지원** | Service Worker + IndexedDB 로 `localStorage`를 보완 (용량·복구) |

| **에러 처리** | 동기화 실패 시 재시도 로직(`exponential backoff`) 구현 |

| **성능 최적화** | 대량 삽입 시 `insertMany` 사용, 인덱스는 필요한 필드에만 생성 |

특히 **민감 정보(예: 비밀번호, 토큰)**는 절대로 `localStorage`에 저장하지 말고, **HttpOnly 쿠키** 혹은 **Secure Storage** 를 활용하세요.

---

# # 📌 결론 – 지금 바로 “localStorage → MongoDB” 여정을 시작해보세요!

- **문제**: `localStorage`는 편리하지만 영구성·보안·확장성이 부족합니다.

- **해결**: 프론트엔드에서 데이터를 잠시 저장하고, 적절한 시점에 **MongoDB**와 연동하면 사용자 경험과 데이터 무결성을 동시에 확보할 수 있습니다.

- **행동**: 오늘 만든 작은 프로젝트에 위 예시 코드를 적용해 보세요.

  1. `storage.js` 로 `localStorage` 헬퍼 만들기

  2. Express + Mongoose 로 간단한 API 구축

  3. 주기적 동기화 로직을 추가하고, 콘솔에 성공·실패 로그 확인

**당신의 첫 번째 “데이터베이스 연동”이 성공하면, 다음 단계는 인증·권한 관리, 그리고 클라우드 배포입니다.**

궁금한 점이 있으면 댓글로 남겨 주세요! 🙌

---

*키워드 재노출* : **MongoDB 구조**, **localStorage**, **데이터베이스 연동**

---
