ZeroBase/CS

TEXT와 BLOB - 대용량 데이터 저장 타입

Red_Horse 2025. 9. 11. 08:57

데이터베이스에서 대용량 문자열이진 데이터를 저장할 때 사용하는 TEXT와 BLOB 타입에 대해 알아보겠습니다. 이들은 일반적인 VARCHAR, CHAR와는 다른 저장 방식과 성능 특성을 가지고 있어 적절한 사용법을 이해하는 것이 중요합니다.

 

TEXT 타입 - 대용량 문자열 저장

TEXT는 CHAR, VARCHAR와 다르게 행 내부가 아닌 디스크에 저장됩니다.

일반적인 저장 방식 (VARCHAR):
┌──────────────────────────────────────┐
│ Row Data                             │
├─────┬─────┬─────────────────────────┤
│ ID  │Name │ Description(VARCHAR)     │
│ 1   │김철수│ 짧은 설명 텍스트         │
└─────┴─────┴─────────────────────────┘
모든 데이터가 행 내부에 저장 (메모리)

TEXT 저장 방식:
┌──────────────────────────┐    ┌─────────────────────┐
│ Row Data                 │    │ Disk Storage        │
├─────┬─────┬─────────────┤     ├─────────────────────┤
│ ID  │Name │ TEXT Pointer │───→│ 매우 긴 텍스트 내용     │
│ 1   │김철수 │ 8byte 주소   │    │ 저장...               │
└─────┴─────┴─────────────┘    └─────────────────────┘
행에는 8바이트 포인터만, 실제 데이터는 디스크에
 
 

TEXT 타입 종류 (MySQL 기준)

타입 최대 길이 저장 공간 용도
TINYTEXT 255자 L + 1바이트 짧은 메모
TEXT 65,535자 L + 2바이트 일반적인 긴 텍스트
MEDIUMTEXT 16,777,215자 L + 3바이트 중간 크기 문서
LONGTEXT 4,294,967,295자 L + 4바이트 대용량 문서

 

L = 실제 데이터 길이

 

 

VARCHAR vs TEXT 성능 비교

성능 테스트 시나리오: 1만 개 레코드에서 검색

VARCHAR(1000) - 평균 500자 저장:
┌─────────────────┬──────────────┐
│ 저장 위치         │ 메모리 (행내부)  │
│ 읽기 속도         │ 0.1초         │
│ 검색 속도         │ 0.05초        │
│ 메모리 사용량      │ 높음           │
│ 인덱스 효율성      │ 높음           │
└─────────────────┴──────────────┘

TEXT - 평균 500자 저장:
┌─────────────────┬──────────────┐
│ 저장 위치         │ 디스크         │
│ 읽기 속도         │ 0.3초         │
│ 검색 속도         │ 0.15초        │
│ 메모리 사용량      │ 낮음           │
│ 인덱스 효율성      │ 낮음 (제한적)   │
└─────────────────┴──────────────┘
 
 

TEXT 사용 권장 상황

 

1. 매우 큰 문자열 데이터

-- 블로그 포스트 내용
post_content LONGTEXT

-- 상품 상세 설명
product_description TEXT

-- 로그 메시지
error_log MEDIUMTEXT

-- 사용자 약관
terms_of_service LONGTEXT
 
 

2. 검색과 수정이 빈번하지 않은 데이터

-- 게시글 내용 (작성 후 수정 빈도 낮음)
article_body TEXT

-- 이메일 내용 (보관용)
email_content TEXT

-- 백업 데이터
backup_data LONGTEXT
 
 
 

TEXT 사용 비권장 상황

 

1. 자주 검색되는 데이터

-- 자주 검색되는 사용자명
username TEXT  

-- VARCHAR 사용 권장
username VARCHAR(50)
 
 
 

2. WHERE 절에 자주 사용되는 컬럼

-- 상태값을 TEXT로
status TEXT

-- 효율적인 검색을 위해
status VARCHAR(20)
 

 

BLOB 타입 - 이진 데이터 저장

BLOB(Binary Large Object)은 이진 데이터를 저장하는 데이터 타입입니다.

 

BLOB 타입 종류

타입 최대 크기 용도 예시
TINYBLOB 255바이트 작은 아이콘
BLOB 65KB 썸네일 이미지
MEDIUMBLOB 16MB 일반 이미지, 문서
LONGBLOB 4GB 비디오, 대용량 파일

 

BLOB 사용 예시

-- 이미지 저장 테이블
CREATE TABLE user_profiles (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    profile_image MEDIUMBLOB,    -- 프로필 사진
    signature BLOB               -- 서명 이미지
);

-- 문서 저장 테이블  
CREATE TABLE documents (
    doc_id INT PRIMARY KEY,
    title VARCHAR(200),
    file_data LONGBLOB,          -- PDF, Word 파일
    file_type VARCHAR(50)        -- MIME 타입
);
 
 

BLOB의 문제점

 

1. 성능 저하

시나리오: 사용자 목록 조회

BLOB 포함 쿼리:
SELECT user_id, username, profile_image FROM users;

문제점:
- 각 행마다 MB 단위 이미지 데이터 전송
- 네트워크 대역폭 과도한 사용
- 메모리 사용량 급증
- 쿼리 응답 시간 지연
 
 

2. 백업 및 복제 문제

데이터베이스 크기 비교:

BLOB 사용:
- 테이블 크기: 10GB (이미지 포함)
- 백업 시간: 2시간
- 복제 지연: 심각

URL 방식:
- 테이블 크기: 100MB (URL만 저장)  
- 백업 시간: 5분
- 복제 지연: 최소
 
 

3. 확장성 문제

  • 데이터베이스 서버 저장 공간 부족
  • 캐싱 효율성 저하
  • 수평 확장의 어려움

 

현대적 해결책: 이미지 호스팅 서비스

 

권장 아키텍처

기존 방식 (BLOB 사용):
[클라이언트] ──→ [웹서버] ──→ [데이터베이스(BLOB)]
                              ↑
                         이미지도 함께 저장

현대 방식 (호스팅 서비스):
[클라이언트] ──→ [웹서버] ──→ [데이터베이스(URL)]
     │                            ↑
     └──────→ [S3/CDN] ─────────────┘
              (실제 파일 저장)
 
 

호스팅 서비스 사용 시 데이터베이스 설계

-- 사용자 프로필 테이블
CREATE TABLE user_profiles (
    user_id INT PRIMARY KEY,
    username VARCHAR(50),
    profile_image_url VARCHAR(500),  -- S3 URL 저장
    cover_image_url VARCHAR(500),    -- 커버 이미지 URL
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 상품 이미지 테이블
CREATE TABLE product_images (
    image_id INT PRIMARY KEY AUTO_INCREMENT,
    product_id INT,
    image_url VARCHAR(500),          -- 원본 이미지 URL
    thumbnail_url VARCHAR(500),      -- 썸네일 URL
    alt_text VARCHAR(200),           -- 접근성을 위한 대체 텍스트
    sort_order INT DEFAULT 0
);
 
 

성능 최적화 전략

 

TEXT 최적화

1. 적절한 타입 선택

-- 과도한 크기 X
short_description LONGTEXT    -- 실제로는 200자 내외

-- 적절한 크기 O 
short_description VARCHAR(500)
long_description TEXT
 
 

2. 분할 테이블 설계

-- 기본 정보 테이블 (자주 조회)
CREATE TABLE articles (
    article_id INT PRIMARY KEY,
    title VARCHAR(200),
    author VARCHAR(100),
    created_at TIMESTAMP,
    view_count INT
);

-- 내용 테이블 (필요시에만 조회)
CREATE TABLE article_contents (
    article_id INT PRIMARY KEY,
    content LONGTEXT,
    FOREIGN KEY (article_id) REFERENCES articles(article_id)
);
 
 
 

BLOB 대체 전략

1. 하이브리드 접근

-- 작은 이미지는 BLOB, 큰 이미지는 URL
CREATE TABLE user_avatars (
    user_id INT PRIMARY KEY,
    small_avatar BLOB,           -- 64x64 썸네일 (< 10KB)
    large_avatar_url VARCHAR(500) -- 고해상도는 S3 URL
);
 
 
 

2. 지연 로딩

// 목록 조회 시에는 URL만
const users = await db.query(
    'SELECT user_id, username, avatar_url FROM users'
);

// 상세 조회 시에만 이미지 로드
const userDetail = await db.query(
    'SELECT * FROM users WHERE user_id = ?', [userId]
);

'ZeroBase > CS' 카테고리의 다른 글

Map과 Set  (0) 2025.09.13
Apache Kafka - 분산 스트리밍 플랫폼  (0) 2025.09.11
CHAR vs VARCHAR - 문자열 타입  (0) 2025.09.11
데이터베이스 기초 - 엔터티, 릴레이션, 속성  (0) 2025.09.11
Convoy Effect, Starvation, Busy Wait  (0) 2025.09.08