데이터베이스 그리고 인덱스

Jihye Gim·2026년 2월 26일

Codeit SB11

목록 보기
4/22

데이터 베이스란?

데이터 베이스는 컴퓨터에 체계적으로 저장되는 데이터의 모음을 말한다. 쉽게 말해서 여러가지 데이터를 잘 정리해서 보관하는 큰 저장소라고 볼수 있다.

웹 애플리케이션이나 다른 소프트웨어에서는 사용자 정보, 게시글, 주문 내역 같은 다양한 데이터가 필요한데, 이런 데이터들이 바로 데이터베이스에 저장된다. 컴퓨터 과학에서의 데이터 베이스란 시스템에 데이터로 저장되는 정보의 컬렉션으로 정의한다.

데이터베이스에서는 데이터를 보통 "테이블" 형태로 저장한다.
예를 들어 "User" 라는 테이블에는 사용자 정보, "Review"라는 테이블에는 리뷰 데이터를 저장할 수 있다.

그리고, 데이터베이스를 만들고 관리하고 사용할 때는 "DBMS(DataBase Management System)이라는 프로그램을 사용한다. 또, 이 데이터베이스에 저장된 데이터를 읽거나 수정하기 위해서 "SQL" 언어를 사용한다.

데이터베이스를 사용하는 이유에는 여러가지가 있다.
1. 데이터를 체계적으로 관리할 수 있다.
많은 데이터를 엑셀이나 텍스트 파일로만 관리하려고 하면 헷갈리기 쉽고, 불편해진다. 하지만 데이터베이스를 표(테이블) 형태로 잘 정리해서 저장하게 되면 체계적으로 관리 가능하다.

  1. 데이터 검색과 수정이 효율적이다.
    데이터베이스는 수많은 데이터 중에서 원하는 데이터를 빠르게 검색하거나, 수정, 삭제, 추가 할수 있는 기능을 제공한다.

  2. 여러 사람이 동시에 데이터를 사용할수 있다.
    여러 명이 팀으로 일할 때, 각자 다른 컴퓨터에서 동시에 데이터를 조회하거나 수정할 수 있다. DBMS를 이용해서 데이터의 일관성과 정합성을 유지할 수 있다.

  3. 대용량 데이터를 효율적으로 처리할 수 있다.
    요즘 웹서비스나 앱에서는 수백만, 수천만개의 데이터가 필요할 수 있는데, 데이터베이스는 이런 대량의 데이터를 빠르고 효율적으로 처리할 수 있게 해준다.

데이터베이스 유형

  1. 관계형 데이터베이스(Relational Database, RDBMS)
    데이터를 표(테이블) 형태로 저장한다.
    테이블들은 서로 관계(관계형)을 맺을 수 있다.
    예) MySQL, PostgreSQL, Oracle, Microsoft SQL Server, Azure SQL 등
  2. 비관계형 데이터베이스(NoSQL)
    전통적인 테이블 구조 대신 다른 방식으로 데이터를 저장한다.
    문서(Document), 키-값(Key-Value), 그래프(Graph), 컬럼(Column) 등 다양한 타입이 있다.
    - 문서형: MongoDB 등
    - 키-값형: Redis 등
    - 그래프형: Neo4j 등
    - 컬럼형: Cassandra 등
  3. 객체지향 데이터베이스(Object-Oriented Database)
    객체지향 프로그래밍의 객체 구조 그대로 데이터를 저장한다.
    객체와 객체 간의 관계도 함께 관리한다.
    예) db4o, ObjectDB 등
  4. 분산 데이터베이스(Distributed Database)
    여러 서버나 컴퓨터에 데이터를 나눠서 저장하는 방식이다.
    대용량 데이터 처리, 장애복구, 높은 접근성을 위해 사용한다.
    예) Google Spanner, Amazon DynamoDB등
  5. 클라우드 데이터베이스(Cloud Database)
    클라우드 환경에서 제공되는 데이터베이스 서비스.
    별도의 설치나 물리 서버 없이 사용할 수 있다.
    예) AWS RDS, Google Cloud SQL 등

관계형 데이터베이스가 기본/가장 많이 쓰이고,
NoSQL(비관계형)은 다양한 구조와 유연함이 필요할 때 사용된다.

다음 이미지는 자료구조(data structure)의 대표적인 예시들이다.

데이터베이스는 내부적으로 이런 자료구조들을 활용해서 데이터를 저장, 인덱싱, 검색, 관리한다.
예를 들어,
배열/연결리스트 : 테이블의 행들을 메모리나 디스크에 순서대로 저장할 때 사용.
트리(B-트리, B+트리 등): 인덱스(검색 속도 향상 용도)에 사용.
그래프: 그래프 데이터베이스, 혹은 복잡한 관계 표현
해시테이블: 키-값 저장/검색 구조에 사용(NoSQL DB, 인덱스 등)
이 외에 문서 중심 데이터베이스도 있는데, 이것은 "자료구조" 라기보다 데이터베이스의 한 종류(유형)이다.
예: MongoDB, CouchDB 등
내부적으로는 해시, 트리, 배열 등 다양한 자료구조를 조합해서 동작한다.

이미지 출처: https://azure.microsoft.com/ko-kr/resources/cloud-computing-dictionary/what-are-databases

  • "선형 구조에서는 요소가 시퀀스로 구성됨"
    시퀀스(sequence)란, 순서가 있다는 뜻이다. 요소(데이터, 값)들이 '일렬로', '정해진 순서'대로 나열 되어 있다는 것이다. (예: 배열(array)의 경우 1번, 2번, 3번.. 이렇게 인덱스대로 순서가 있다. 연결리스트(linked list) 는 각 요소가 다음 요소를 가리켜서, 차례로 이어진다. 이러한 구조에서는 "처음", "다음", "끝" 같은 순서관계가 중요하다. 즉, "선형 구조에서 요소가 시퀀스로 구성된다"라는 것은 데이터들이 앞->뒤로 순서있게 연결되어 있다는 의미로 볼수 있다.
  • 배열
    데이터를 일렬로 나열해서 저장하는 구조.
    데이터베이스 엔진 내부에서는 데이터를 효율적으로 저장하거나, 읽어올 때 배열이나 리스트 구조를 많이 쓴다.
    단순한 테이블의 레코드(행)들은 실제 메모리/디스크에 배열처럼 저장된다고 볼수 있다.
  • 이진트리
    각 노드가 두개의 자식 노드를 가질 수 있는 트리 구조.
    데이터베이스의 '검색'정렬'등의 작업을 빠르게 하기 위해 트리 기반 자료구조를 많이 사용한다.
    대표적으로 B-Tree, B+Tree 등이 인덱스(Index)로 사용된다.
  • 그래프
    여러 노드가 서로 연결(간선)되는 구조.
    일반적인 관계형 데이터베이스는 그래프처럼 '관계'를 테이블로 표현한다. 특별히, 그래프 데이터베이스(예:?Neo4j)는 데이터 간의 연결 관계를 직접적으로 그래프로 저장하고 쿼리할 수 있다.
  • 해시테이블
    키(Key)와 값(Value)을 매핑하는 자료구조
    NoSQL 데이터베이스 중 키-값 데이터베이스(예:Redis, DynamoDB 등)는 바로 해시 테이블 구조를 기반으로 작동한다.
    관계형 데이터베이스의 인덱스 구현에서도 해싱 기법을 사용할 때가 있다.(예:MySQL의 해시 인덱스)
  • DB-Engines Ranking - Trend Popularity

    이미지 출처: https://db-engines.com/en/ranking_trend

위 이미지는 DB-Engines의 링크이다. 설문조사 형식은 아니지만, 전 세계의 다양한 데이터를 바탕으로 DB별 인기 순위를 월 단위로 발표한다.
검색 트렌드, 소셜 미디어 언급, 기술 문헌 등 다양한 지표를 종합해서 점수를 매긴다.

JetBrains나 Stack Overflow 등 다양한 곳에서 매년 개발자 대상 대규모 설문조사를 해서 인기 있거나 트렌드인 데이터베이스 순위를 발표하곤 한다. 이런 설문 결과는 실제 시장에서 어떤 데이터베이스가 많이 사용되고, 최근 트렌드는 어떤지 확인할 때 참고하기 좋다.

대표적으로 JetBrains Developer Ecosystem Survey는 우리가 사용하는 IDE 프로그램 제작사에서 매년 전 세계 개발자를 대상으로 설문하고, 인기 프로그래밍 언어, 데이터베이스, 프레임워크 등 통개를 공겨한다. 그리고 설문 결과에는 "가장 많이 사용하는 DB"와 선호하는 DB", "Cloud DB 사용률"같은 항목이 포함된다.
이 외에 Stack Overflow Deeloper Survey는 전 세계에서 가장 규모가 큰 개발자 설문조사 중 하나인데, "Most popular database" 등 인기 및 성장세를 확인할 수 있는 데이터를 매년 공개한다.

인덱스

인덱스(Index)란, 데이터베이스에서 데이터를 빠르게 찾을 수 있도록 도와주는 자료구조. 책의 목차와 비슷한 역할을 한다.
인덱스가 왜 필요할까?
데이터가 많아질수록 원하는 데이터를 찾는 데 시간이 오래 걸리기 때문에 인덱스를 사용하여 검색 속도를 향상한다.
예를 들어서 데이터베이스에 데이터가 아주 많이 쌓이면( 수만~ 수백만개 레코드), 원하는 데이터를 찾으려면 처음부터 끝까지 하나씩 다 비교해야 한다.(이러한 것을 "선형 탐색"이라고 한다.) 이렇게 되면 속도가 매우 느려져서, 실시간 서비스에는 큰 문제가 생길 수 있다.
책의 목차(소제목 -> 페이지 번호)나 맨 뒤의 색인(인덱스)(용어->페이지 번호)를 보고 원하는 페이지를 찾아갈수 있는 원리이다.
데이터 베이스 인덱스도 같은 원리이다. 특정 값이 어디(어떤 행)에 있는지 알려주는 정보를 미리 정리해 두는 구조이다. 예: WHERE 조건, JOIN, ORDER BY 등에서 인덱스를 활용하면 훨씬 더 빠르게 원하는 정보를 찾아낼 수 있다.

가장 많이 사용되는 방식으로는 B-Tree인덱스, Hash 인덱스 등이 있다.
하지만, 인덱스 자체도 저장 공간이 필요하고, 데이터 삽입/수정/삭제 시 오버헤드가 생기기 때문에 중요한 컴럼에만 인덱스를 만드는 것이 좋다.

인덱스를 걸면 좋은 필드(컬럼)

  1. WHERE 조건에 자주 등장하는 필드
    예: SELECT * FROM user WHERE email = 'codei@email.com';
    -> email 컬럼에 인덱스가 있으면 빠르게 찾을 수 있다.

  2. JOIN에 자주 사용 되는 컬럼
    두 테이블을 JOIN 할때 연결하는 컬럼에 인덱스가 있으면 성능이 좋아진다.
    예: SELECT * FROM orders JOIN users ON orders.user_id = user.id;
    -> 보통 user_id, id에 인덱스를 사용한다.

  3. ORDER BY(정렬)에 자주 쓰는 컬럼
    예: SELECT * FROM articles ORDER BY created_at DESC;
    -> created_at 컬럼에 인덱스가 있으면 정렬이 빨라진다.

  4. 단일 값이 아닌, 값이 많이 나누어져 있는 컬럼(커디널리티가 높음)
    카디널리티(Cardinality): 컬럼에 서로 다른 값이 많을수록 '카디널리티"가 높다고 한다. 주민등록번호, 이메일처럼 중복이 적은 컬럼이 인덱스 성능에 유리하다.
    반대로 '성별(남/여)'처럼 값이 몇개 없는 컬럼에 인덱스는 성능에 큰 도움이 안된다.

  5. 주로 검색이나 조회, 참조에 사용되는 컬럼
    데이터를 자주 업데이트하지 않고, 읽는 빈도가 높을 때 인덱스가 특히 효과적이다.

    인덱스를 안 걸어도 되는 경우

    값이 거의 변하지 않거나, 경우의 수가 적은 컬럼(예: 성별, TRUE/FALSE만 있는 필드)
    거의 조회에 사용하지 않는 컬럼
    데이터가 너무 적어서 인덱스 효과가 없는 테이블

    *Primary Key는 자동으로 인덱스가 걸린다.

스프링 백엔드는 JAVA 언어로 만들어진 Spring 프레임워크를 사용해서 웹 서버의 뒷단(Back-end)을 개발하는 것을 말한다.

백엔드는 사용자가 직접 볼 수 없는 웹 서비스의 내부 시스템이다. 예를 들어, 회원가입, 로그인, 게시글 저장, 데이터 관리 등 눈에 보이지 않는 '진짜 처리'를 담당한다.
보통 서버, 데이터베이스, API 개발 등이 백엔드의 영역이다.

스프링(Spring) 프레임워크란, 스프링은 자바로 백엔드 서버를 쉽게, 효율적으로, 안전하게 만들 수 있게 도와주는 대표적인 프레임워크다. 웹 서버 구축, 데이터베이스 연동, 보안, REST API 등 다양한 기능을 쉽게 구현할 수 있다.

그렇게 때문에, 기본 SQL 문법(SELECT, INSERT, UPDATE, DELETE, WHERE 등), 데이터테이블 설계(테이블 구조(예: 행/열, 데이터 타입 등), 기본키(Primary Key), 외래키(Foreign Key) 개념), 그리고 앞에 언급한 데이터베이스의 구조를 알면 스프링 강의나 실습을 따라가는데 도움이 될 것으로 추측한다.

B-Tree란

데이터베이스와 파일시스템 등에서 검색, 삽입, 삭제를 빠르게 처리하기 위해 널리 사용하는 트리 기반 자료구조다.
1. B-Tree의 특징

  • 균형 잡힌(밸런스된)트리
    모든 리프 노드(마지막 가지)가 같은 깊이(레벨)을 유지한다. -> 검색할 때 항상 비슷한 단계를 거치니까 성능이 균일하다.
  • 한 노드에 여러 개의 값(키)과 자식
    일반 이진 트리는 최대 2개의 자식을 가지는데, B-Tree는 여러개(예: 3,4,5,..) 자식을 가질수 있다. -> 이렇게 하면 트리의 높이가 낮아져서, 검색할 때 디스크 접근 횟수가 줄어든다.
  1. B-Tree의 간단한 구조
  • 노드(박스하나) 가 여러 데이터(키)와 여러 자식을 가질 수 있다.
[  10  |  20  |   30  ]
   |      |        |     |
 ...     ...      ...    ...  
  • 노드 안의 값들은 크기 순서대로 정렬되어 있다.
  • 검색할 때, 내가 찾는 값이 어느 범위에 있는지 판단해서 맞는 자식 노드로 내려간다.
  1. 어디에 많이 많이 쓰이나?
  • 관계형 데이터베이스의 인덱스
    MySQL, PostgreSQL, ORACLE 등 거의 모든 DB의 기본 인덱스 구조.
  • 파일 시스템
    컴퓨터 하드디스크의 폴더/파일 관리 등에서도 사용된다.
  1. B-Tree의 장점
  • 검색, 삽입, 삭제 모두 빠름
    -> 트리 높이가 낮게 때문에, 대용량 데이터에서도 성능이 좋다.
  • 디스크(하드)에서 효율적으로 동작
    한번에 여러 데이터(키)를 읽고, 불필요한 디스크 접근을 줄여준다.

B+Tree란

B-Tree 구조를 확장한 자료구조.
대용량 데이터를 빠르고 효율적으로 검색, 삽입, 삭제 할수 있도록 설계되었다.
특히 범위 검색이 매우 효율적이다.

  1. 구조의 특징
  • 모든 데이터(값)는 리프(leaf)노드에만 저장
    내부(internal노드는 오로지 "키(key)" 값만 가지고 있다.
    실제 데이터(테이블 행 주소 등)는 맨 아래 리프 노드에만 저장되어 있다.
  • 리프 노드끼리 연결되어 있다.
    각 리프 노드는 옆 리프 노드와 포인터로 연결되어 있어서, 연속된 범위의 데이터를 빠르게 탐색할 수 있다.
    컬렉션 처럼 쫙-이어져 있는 느낌.
  • 트리의 균형(밸런스)유지
    삽입/삭제가 이루어져도 트리의 높이가 일정하게 유지되어서, 검색, 삽입, 삭제가 모두 O(log n) 시간에 처리된다.
  1. 왜 B+Tree을 쓸까
  • 빠른 검색과 효율적 범위 쿼리
    WHERE 조건이나 특정 구간의 데이터 검색 시 속도가 아주 빠르다.
  • 정렬된 형태로 데이터 순회(ORDER BY등)에 최적
  • 디스크 접근 감소
    한번에 여러 키를 읽으니, 트리의 높이가 낮고 검색 시 디스크/메모리 접근이 적다.
  1. 적용예시
    데이터베이스 인덱스(MySQL, PostgreSQL, Oracle등)
    파일시스템
    웨어러블 디바이스, 임베디드 시스템의 파일 검색 등

  2. B-Tree와의 차이

  • B-Tree는 내부 노드도 데이터(값)을 가진다. 리프끼리 연결 안됨.
  • B+Tree는 내부 노드는 "키"만, 실제 데이터(주소 등)는 리프에만 가진다. 그리고 리프끼리 연결 됨.
[   10   |   20  ]     (내부노드, 실제 데이터 없음)
\    |      |       \
... ...    ...      ...
리프 노드(데이터 있음): [1,4,7] <-> [11,15,19] <-> [21,23,30]
(연결 리스트처럼 옆으로 쭉 이어져 있음)

** 정리 하자면, B+Tree는 데이터베이스 인덱스의 표준, 빠른 검색+ 범위 검색 + 정렬 까지 효율적, 내부노드: 키만/ 리프노드: 실제 데이터 + 연결.
DB 인덱스에서는 거의 항상 B+Tree만 사용하지만, 컨셉을 설명하거나 아주 제한된 상황에서는 B-Tree도 쓰일 수 있다.

Optinal

String을 new로 선언 vs ""리터럴로 선언차이

""리터럴 선언
String s1 = "hello";

  • String Constanct Pool(상수 풀) 이라는 영역에 문자열이 저장된다.
  • 같은 값의 문자열이 이미 있으면, 새로운 객체를 만들지 않고 기존 객체의 참조값만 사용한다.
  • 메모리 효율이 좋다.

new 키워드 선언
String s2 = new String("hello");

  • 명시적으로 새로운 String 객체를 Heap 영역에 생성한다.
  • 같은 값을 가지더라도 무조건 새 객체가 생성된다.
  • 보통 특별한 이유가 없으면 리터럴방식("hello")을 쓴다.
String a = "codeit";
String b = "codeit";
String c = new String("codeit");

System.out.println(a == b); // true(같은 객체)
System.out.println(a == c); // faluse(다른 객체)
System.out.println(a.equals(c)); // true(값은 값다)

'==' : 객체 자체(주소) 비교
'.equals()' : 값(문자열 내용) 비교

String, String Builder, String Buffer 차이

String
불면(immutable) 클래스: 한번 생성하면 값을 바꿀 수 없다.
문자열을 더하거나 수정할 때마다 새로운 객체가 생성되서, 많은 문자열 연산에는 비효율적일 수 있다.

String Builder
가변(mutable)클래스: 문자열 내용 변경 가능
문자열 덧붙이기, 삭제 등 반복 작업에 효율적
싱글 스레드(단일 실행 흐름)에 적합(멀티스레드 환경에서 안전하지 않음)

StringBuffer
StringBuilder와 거의 동일하지만,
멀티스레드 환경에서 아넌하도록 동기화(synchronized)처리되어 있다. 성능은 StringBuilder보다 살짝 느릴 수 있다.

** 일반적인 문자열 작업 : "문자열" 리터럴, String 사용

** 문자열을 반복해서 수정/추가 : StringBuilder(단일 스레드)

** 여러 스레드에서 동시에 작업: StringBuffer

참고 : https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html
https://docs.oracle.com/en/database/oracle/oracle-database/19/cncpt/indexes-and-index-organized-tables.html
https://www.postgresql.org/docs/current/indexes-types.html

profile
Rookie

0개의 댓글