콘텐츠로 건너뛰기

5-1. 기억 저장소 (데이터베이스): 식재료 창고와 장부

  • 기준

창고 역할을 한다고 이야기 했던 데이터베이스(DB)는 단순한 데이터 저장소가 아닙니다. 서비스의 모든 기록을 관리하는 철저한 ‘장부’ 이자 ‘거대한 창고’입니다. 바이브 코딩에서 우리가 어떤 창고를 선택하느냐에 따라 서비스의 확장성이 결정됩니다.

사실 프로젝트의 목적과 툴등을 이미 정하고 환경설정을 마쳤으므로 DB 설정과 스키마 설계부터 ‘바이브 코딩’을 적용하면 됩니다.

다만, AI에게 상세하게 지시하지 않으면 의도와 다른 결과가 나올 수 있으며 그중 데이터베이스는 가장 중요하며 계속 데이터가 늘어나고 중간에 테이블 설계가 잘못되었다는 것을 인식해 변경하려 하면 수정하는데 어려움이 크게 다가옵니다.

상상해 보세요 엑셀 몇십 을 변경하려면 할 수 있지만 그게 몇만 가 된다면 사람이 할 짓이 못 됩니다. 따라서 데이터베이스의 초기 설계와 꼼꼼한 가이드가 무엇보다 중요합니다.

흔히 “AI는 뭐든지 알아서 코드를 잘 작성해 줄 것”이라고 오해합니다. 하지만 AI에게 정확하고 명확하게 지시하지 않으면 엉뚱한 결과가 나올 수 있습니다. 만약 AI가 뱉어낸 코드를 검증할 최소한의 지식조차 없다면, 나중에 에러가 쌓여 프로젝트를 처음부터 다시 시작해야 할 수도 있습니다.

그중 데이터 저장이 가장 중요합니다. 예를 들어 1Day OHLCV(오픈, 클로즈 가격등으로 일반적인 캔들차트)에 저장되는 티커가 5개이면 하루에 5개이고 1년이면 365*5=1825, 30년이면54,750데이터가 쌓입니다. 분봉(Minute), 시봉(Hour)등을 생각하면 몇백만 데이터가 있을수 있습니다.

때문에 이 책에서 제공하는 테이블(가이드)을 참고하는 것이 시행착오를 줄이는 지름길입니다.

🗂️ 데이터베이스의 종류와 특징

현재까지 많은 종류의 디비가 나와 있으며 유료에서 무료까지 다양하게 있습니다. 우린 이런 디비중 수치에 최적화된 PostgreSQL을 사용하겠습니다.

정가제 규격 상품: RDBMS (관계형 데이터베이스)

이 상품들은 ‘계산대 점원’이 아주 까다롭습니다. 바코드가 찍히지 않거나, 잔돈이 1원이라도 안 맞으면 결제 자체를 취소해 버리죠.

  • 구조(Schema): 엑셀 시트처럼 미리 정의된 열(Column)에 맞춰 데이터를 넣어야 합니다. 중간에 갑자기 “유통기한” 칸이 없는데 유통기한을 넣으려 하면 입고 거부됩니다.

  • 관계(Relation): ‘구매자 명부’와 ‘상품 목록’을 연결(Join)해서 누가 무엇을 샀는지 정교하게 추적합니다.

  • 대표주자:

  • PostgreSQL: 기능이 아주 많은 고급 백화점 느낌. 복잡한 계산도 척척 해냅니다.

  • MySQL: 가장 대중적인 편의점. 속도가 빠르고 관리가 편해 전 세계 어디서나 쓰입니다.

종합 선물 세트: NoSQL (문서형 데이터베이스)

여기는 ‘창고형 할인마트’와 비슷합니다. 상품이 규격화되어 있지 않아도 일단 박스(JSON 형태)에 담아 쌓아둡니다.

  • 구조: 데이터마다 속성이 달라도 괜찮습니다. A 상품은 [이름, 가격]만 있고, B 상품은 [이름, 가격, 색상, 무게, 리뷰]가 있어도 한 박스에 담습니다.

  • 확장: 손님이 갑자기 몰리면 옆에 창고 건물을 하나 더 지어서(샤딩, Sharding) 물건을 분산해 쌓기 좋습니다.

  • 대표주자: MongoDB. “일단 서비스부터 런칭하고, 데이터 구조는 나중에 고민하자!” 할 때 최고의 선택입니다.

타임 세일 상품: In-Memory DB (인메모리 데이터베이스)

일반적인 DB가 ‘지하 창고(HDD/SSD)’에서 물건을 꺼내온다면, 여기는 ‘카운터 바로 위 선반(RAM)’에 물건을 둡니다.

  • 속도: 창고까지 가는 시간을 아끼기 때문에 응답 속도가 마이크로초($mu s$) 단위로 측정될 만큼 압도적으로 빠릅니다.

  • 리스크: 전원이 꺼지면 선반 위의 물건이 증발할 수 있습니다. 그래서 ‘영구 저장’보다는 ‘잠시 보관하는 장바구니’나 ‘인기 순위(Ranking)’ 저장용으로 씁니다.

  • 대표주자: Redis. 웹사이트 로그인 세션이나 게임 서버의 실시간 랭킹 시스템에 필수입니다.

전문가 추천 도서: Vector DB (벡터 데이터베이스)

단순히 “사과”라는 글자를 찾는 게 아니라, “빨갛고 아삭하며 비타민이 풍부한 과일”이라는 ‘의미’를 찾아내는 고도화된 시스템입니다.

  • 동작 방식: 모든 상품 정보를 수천 개의 숫자로 이루어진 좌표(벡터)로 변환합니다.

  • 검색: “이 고양이 사진이랑 비슷한 거 찾아줘”라고 하면, 좌표상에서 가장 가까운 거리에 있는 데이터를 집어옵니다.

  • AI와의 만남: ChatGPT 같은 생성형 AI가 “내 회사 내부 문서를 참고해서 답변해줘”라고 할 때(RAG 기술), 그 문서들을 저장하고 찾아주는 핵심 창고 역할을 합니다.

  • 대표주자: Pinecone, Milvus, Weaviate.

🎯 왜 반드시 PostgreSQL이어야 하는가?

앞으로 실습할 웹서비스는 야후 파이낸스, 인베스팅닷컴과 제가 만든 “firemarkets.net”같은 투자 분석 플랫폼입니다. 단순히 데이터를 저장하는 것을 넘어, ‘분석’과 ‘신뢰’가 핵심입니다. PostgreSQL은 다음 3가지 이유로 우리의 유일한 선택지가 됩니다.

하나, 돈과 관련된 데이터의 신뢰성 (ACID 준수)

투자 데이터에서 ‘1원’ 혹은 ‘0.00001 BTC’의 오차는 치명적입니다. PostgreSQL은 업계에서 가장 엄격하게 데이터 무결성을 지키는 것으로 유명합니다. “기록되었다면 반드시 존재한다”는 확신을 주는 가장 신뢰할 수 있는 장부입니다.

둘, 하이브리드 전략: SQL의 안정성 + NoSQL의 유연성

바이브 코딩을 하다 보면 AI가 가져오는 시황 뉴스나 소셜 데이터처럼 형식이 제각각인 데이터를 다뤄야 할 때가 있습니다. PostgreSQL은 JSONB라는 기능을 통해 NoSQL처럼 자유로운 형식의 데이터도 초고속으로 처리할 수 있습니다. 즉, ‘하나의 DB로 두 마리 토끼’를 잡을 수 있습니다.

셋, AI 시대의 준비: 벡터 데이터 처리 (pgvector)

우리는 나중에 AI에게 수만 개의 뉴스를 읽히고 유사한 패턴을 찾게 할 것입니다. 이때 필요한 것이 ‘벡터 검색’입니다. PostgreSQL은 pgvector라는 확장을 통해 AI 데이터를 처리하는 벡터 데이터베이스로 즉시 변신할 수 있습니다. 미래를 위한 최고의 투자입니다.

넷, 강력한 오픈소스 생태계와 무료 이용

Vultr 같은 리얼 서버에 올릴 때, 오라클처럼 비싼 라이선스 비용 걱정 없이 기업용 수준의 성능을 무료로 마음껏 쓸 수 있습니다.

이제 우리는 이 강력한 냉장고(PostgreSQL)를 도커(Docker)라는 상자에 담아 우리 주방에 들여놓을 것입니다.

🗄️ 프로젝트 DB 구조 잡기

데이터 베이스를 어렵게 생각할 필요는 없습니다. 엑셀을 생각하시면 거의 똑같습니다.-사실 디비의 테이블을 보여주는 툴로 보면 차이가 없습니다.-

여기에 엑셀과 가장 큰 차이는 서비스(service)라는 개념으로 데이터베이스는 항상 컴퓨터의 메모리에 상주하고 있어(이러한 프로그램은 서비스 프로그램이라 합니다.) 언제나 내가 요청을하면(SQL) 바로바로 답을 줍니다. 또한 유저 정보도 갖고 있어 보안에 더+ 강력합니다.

바로 여기에 디비 초기 설정의 힌트가 있습니다. 어느 곳(localhost)에서 어떤 형식(invest)의 디비를 누가(testUser@test@1234) 사용할 것인지를 정해주면 됩니다.

접속정보
DB_HOSTNAME=localhostDB_DATABASE=invest //본인이 원하는 DB이름DB_USERNAME=testUser DB_PASSWORD=test@1234

이 접속정보는 직관적으로 어떤 내용인지 알수 있습니다.

“아니 그런데 왜 DB_DATABASE라는 설정의 이름이 있는 것이지 PostgreSQL 이란 디비를 사용한다고 하지 않았나”

라고 생각할수 있습니다.

먼저 언급하였듯이 데이터베이스 는 하나의 거대한 서비스(service) 이고 디비는 저장되는 형식의 종류에 따라 각각 디비명을 따로 만들고 서비스하는 것이 합리적입니다.

예를 들어 우리같이 파이낸싱 디비를 만들고 전용으로 사용하는 중 분야가 완전다른 게임이나 SNS등의 디비를 만들어 서비스 해야 된다면 다른 디비를 만들어 사용하는 것이 직관적이겠죠! 굳이 파이낸싱 디비에 게임에서 사용하는 테이블을 사용할수도 있지만 권하지는 않습니다.

-- -- 데이터베이스: `markets` -- -- -------------------------------------------------------- -- db/init.sql -- 데이터베이스: `markets`  -- 데이터베이스 `markets` 생성 (이미 있다면 스킵) CREATE DATABASE IF NOT EXISTS `invest` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE `markets`;
스키마(테이블)

디비를 가장 먼저 생성하고 실제 데이터를 저장하고 사용하는 것을 테이블 이라 하고 각 테이블의 목적어 즉 실제 데이터를 지정할 이름을 컬럼이라합니다.

👍컬럼명이 id이면 순번, ticker이면 주식 티커이름 등등

자 이제 바이브 코딩으로 프로젝트를 만들고 그 데이터를 저장할 공간을 계획해 봅시다. 가장 기본적인 테이블인 ‘assets’(//자산 테이블), `asset_types`(//자산타입 테이블)이고 가격을 수집하고 참조하는 `ohlcv_data`(실제 주식이나 코인 가격 데이터)을 만들겠습니다.

1. ‘assets’(자산 테이블)
-- PostgreSQL 기준 자산 마스터 테이블 CREATE TABLE assets (     asset_id SERIAL PRIMARY KEY,'자산의 고유 심볼/티커 (예: BTCUSDT, AAPL, EURUSD)'     ticker VARCHAR(50) UNIQUE NOT NULL,'자산의 고유 심볼/티커 (예: BTCUSDT, AAPL, EURUSD)',     asset_type_id INTEGER NOT NULL,'asset_types 테이블의 ID 참조'     name VARCHAR(255) NOT NULL, '자산의 이름 (예: Bitcoin, Apple Inc.)',     exchange VARCHAR(100),'거래소 (예: Binance, NASDAQ, NYSE)'     currency VARCHAR(10), '기준 통화 (예: USD, KRW)'     is_active BOOLEAN DEFAULT TRUE,     description TEXT,     created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,     updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP );
2.`asset_types`(자산타입 테이블)
---- 테이블 구조 `asset_types`--CREATE TABLE `asset_types` (  `asset_type_id` int NOT NULL AUTO_INCREMENT,  `type_name` varchar(100) NOT NULL COMMENT '예: Cryptocurrency, Stock, Forex, Bond, Commodity',  `description` text DEFAULT NULL,  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),  PRIMARY KEY (`asset_type_id`),  UNIQUE KEY `type_name` (`type_name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='자산 유형 마스터 테이블';
`3.ohlcv_data`(실제 주식이나 코인 가격 데이터)
---- 테이블 구조 `ohlcv_data`--CREATE TABLE `ohlcv_data` (  `ohlcv_id` bigint NOT NULL AUTO_INCREMENT,  `asset_id` int NOT NULL COMMENT 'assets 테이블의 ID 참조',  `timestamp_utc` datetime NOT NULL COMMENT '데이터의 시간 (UTC 기준)',  `data_interval` varchar(10) NOT NULL DEFAULT '1d' COMMENT '데이터 간격 (예: 1m, 5m, 1h, 1d, 1w, 1M)',  `open_price` decimal(24,10) NOT NULL,  `high_price` decimal(24,10) NOT NULL,  `low_price` decimal(24,10) NOT NULL,  `close_price` decimal(24,10) NOT NULL COMMENT '기존 Price 필드',  `volume` decimal(30,10) NOT NULL COMMENT '거래량 (정수 또는 소수 가능)',  `change_percent` decimal(10,4) DEFAULT NULL COMMENT '종가 기준 변화율',  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),  `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),  PRIMARY KEY (`ohlcv_id`), -- 'PRIMARY_KEY'를 'PRIMARY KEY'로 수정  UNIQUE KEY `asset_interval_timestamp` (`asset_id`,`data_interval`,`timestamp_utc`),  FOREIGN KEY (`asset_id`) REFERENCES `assets` (`asset_id`) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='OHLCV 시계열 데이터';

💡 혹시나 각 테이블의 컬럼이 왜 이렇게 구성되었는지 궁금하면 AI에 물어 보시면 됩니다.

🤖 실전! 프로젝트 DB 만들기

✨ 사용자의 의도(Vibe)

“이 설정(위의 SQL 구문)으로 PostgreSQL 도커 컨테이너를 만들어줘”

💻 AI가 생성한 코드 (Syntax)

docker-compose.yml

version: '3.8'services:  postgres:    image: postgres:15    container_name: postgres-markets    environment:      POSTGRES_USER: root      POSTGRES_PASSWORD: rootpassword      POSTGRES_DB: markets      TZ: "Asia/Seoul" # 한국 시간대 설정    ports:      - "5432:5432"    volumes:      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql      - postgres_data:/var/lib/postgresql/data    restart: unless-stoppedvolumes:  postgres_data:
  1. docker-compose.yml 란 파일을 만들고(만약 없으면 =>”yml파일을 만들어줘”)

  2. docker compose up -d 라고 AI가 명령을하고

  1. Antigravity의 Terminal을 선택하면 아래에 터미널 창이 나옵니다.

  1. 터머닐(Terminal)창에 docker ps라고 쓰고 엔터를 누르면
CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS         PORTS                                         NAMES1674d640dae2   postgres:15          "docker-entrypoint.s..."   9 minutes ago   Up 9 minutes   0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp   postgres-markets48d5870f550f   frontend-dashboard   "docker-entrypoint.s..."   22 hours ago    Up 22 hours    0.0.0.0:3000->3000/tcp, [::]:3000->3000/tcp   my-dashboard

docker-compose.yml파일에 있는 “container_name: postgres-markets“이란 컨테이너가 보일것입니다. 여기에 우리가 만든 디비와 각 테이블이 들어가 있습니다.

💡 Antigravity기준으로 db폴더가 만들어지고 그 내부에 init.sql이 있을것입니다. 여기에 우리가 지시한 SQL스크립트가 있습니다. 혹시 없더라도 큰 문제는 없으니까 걱정 마세요!

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다