2026년 02월 09일

🗄️ 데이터베이스와 DBMS

Java Spring Boot
Cover Image

🗄️ 데이터베이스와 DBMS

모든 애플리케이션의 심장 - 데이터를 저장하고 관리하는 시스템

💡 핵심 개념

데이터베이스(Database, DB)

정의: 구조화된 데이터의 집합

실생활 예시:

DBMS (Database Management System)

정의: 데이터베이스를 관리하고 운영하는 소프트웨어

DB (데이터)  +  MS (관리 시스템)  =  DBMS

🆚 파일 시스템 vs DBMS

파일 시스템의 한계

Excel 예시

[판매_오전.xlsx]  [판매_오후.xlsx]  [판매_야간.xlsx]
     A 직원            B 직원            C 직원

문제점:

시나리오:

오전 판매: A 직원이 노트북 판매 기록
오후 반품: B 직원이 노트북 반품 접수
❓ 누가 기록해야 할까?
→ 두 명 모두 기록 → 중복
→ 아무도 기록 안 함 → 누락
→ 월말 합계 불일치!

DBMS의 해결책

// 모든 직원이 동일한 DB 사용
@Service
@Transactional
public class SalesService {

    private final SalesRepository salesRepository;

    // 판매 기록 (동시성 보장)
    public void recordSale(SaleRequest request) {
        Sale sale = Sale.builder()
            .product(request.getProduct())
            .amount(request.getAmount())
            .employee(getCurrentEmployee())
            .saleTime(LocalDateTime.now())
            .build();

        salesRepository.save(sale);
    }

    // 반품 처리 (트랜잭션으로 무결성 보장)
    public void processReturn(Long saleId) {
        Sale sale = salesRepository.findById(saleId)
            .orElseThrow(() -> new SaleNotFoundException(saleId));

        sale.markAsReturned();
        // 자동으로 업데이트, 중복/누락 없음
    }

    // 실시간 집계 (모든 데이터 통합 조회)
    public DailySalesReport getDailySales(LocalDate date) {
        return salesRepository.findDailySales(date);
    }
}

비교 테이블

특성파일 시스템 (Excel)DBMS (MySQL)
동시 접근❌ 불가능✅ 다중 사용자 동시 접근
데이터 무결성❌ 보장 안 됨✅ 제약 조건으로 보장
트랜잭션❌ 지원 안 함✅ ACID 보장
중복 방지❌ 수동 관리✅ UNIQUE 제약
백업/복구❌ 수동 복사✅ 자동 백업
보안❌ 파일 권한만✅ 세밀한 권한 관리
확장성❌ 느려짐✅ 대용량 최적화
적합 용도개인, 소규모프로덕션 서비스

🏗️ DBMS의 종류

1️⃣ 관계형 DBMS (RDBMS)

가장 많이 사용되는 DBMS

주요 제품

DBMS특징주요 사용처가격
MySQL오픈소스, 빠름, 웹 친화적스타트업, 웹 서비스무료
PostgreSQL강력한 기능, 표준 준수엔터프라이즈, 복잡한 쿼리무료
Oracle고성능, 기업용대기업, 금융권유료
MariaDBMySQL 호환, 오픈소스MySQL 대체무료
MS SQL ServerWindows 친화적.NET 생태계유료

관계형 DBMS의 특징

데이터를 테이블(Table) 형태로 저장
테이블 간 관계(Relation)를 통해 데이터 연결

2️⃣ NoSQL

관계형이 아닌 다양한 형태의 데이터 저장

DBMS타입특징사용처
MongoDBDocumentJSON 형태유연한 스키마
RedisKey-Value초고속캐싱, 세션
CassandraWide-Column분산 처리대용량 데이터
Neo4jGraph관계 중심소셜 네트워크

📊 관계형 DBMS의 구조

테이블(Table)

정의: 데이터를 저장하는 기본 단위

테이블 예시: 회원(Member)

회원 테이블
┌────┬─────────────┬────────┬─────────────────┐
│ ID │    이름      │  나이   │     이메일       │
├────┼─────────────┼────────┼─────────────────┤
│ 1  │   홍길동     │   25   │ hong@example.com │
│ 2  │   김철수     │   30   │ kim@example.com  │
│ 3  │   이영희     │   28   │ lee@example.com  │
│ 4  │   박민수     │   35   │ park@example.com │˿ 행(Row)
└────┴─────────────┴────────┴─────────────────┘
   ↑        ↑          ↑            ↑
  열(Column)
         

용어 정리

용어설명별칭
테이블(Table)데이터를 저장하는 구조릴레이션(Relation), 엔티티(Entity)
행(Row)하나의 데이터레코드(Record), 튜플(Tuple)
열(Column)데이터 항목필드(Field), 속성(Attribute)
기본 키(Primary Key)행을 고유하게 식별PK
외래 키(Foreign Key)다른 테이블 참조FK

💻 Spring Boot에서의 RDBMS

1️⃣ 테이블 구조 설계

-- 회원 테이블
CREATE TABLE members (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    age INT NOT NULL,
    created_at DATETIME NOT NULL,
    updated_at DATETIME NOT NULL
);

-- 주문 테이블
CREATE TABLE orders (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    member_id BIGINT NOT NULL,
    total_amount INT NOT NULL,
    status VARCHAR(20) NOT NULL,
    created_at DATETIME NOT NULL,
    FOREIGN KEY (member_id) REFERENCES members(id)
);

-- 주문 상품 테이블
CREATE TABLE order_items (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT NOT NULL,
    product_name VARCHAR(200) NOT NULL,
    quantity INT NOT NULL,
    price INT NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id)
);

2️⃣ JPA 엔티티로 매핑

// 회원 엔티티 = members 테이블
@Entity
@Table(name = "members")
@Getter
@NoArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;  // id 컬럼

    @Column(nullable = false, length = 100)
    private String name;  // name 컬럼

    @Column(nullable = false, unique = true, length = 100)
    private String email;  // email 컬럼

    @Column(nullable = false)
    private int age;  // age 컬럼

    @CreatedDate
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;  // created_at 컬럼

    @LastModifiedDate
    @Column(nullable = false)
    private LocalDateTime updatedAt;  // updated_at 컬럼

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();  // 1:N 관계
}

// 주문 엔티티 = orders 테이블
@Entity
@Table(name = "orders")
@Getter
@NoArgsConstructor
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")  // 외래 키
    private Member member;

    @Column(nullable = false)
    private int totalAmount;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private OrderStatus status;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    @CreatedDate
    @Column(nullable = false, updatable = false)
    private LocalDateTime createdAt;
}

3️⃣ DB 연결 설정

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver

  jpa:
    hibernate:
      ddl-auto: update # create, update, validate, none
    show-sql: true
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.MySQLDialect

📝 SQL (Structured Query Language)

SQL이란?

정의: RDBMS와 소통하는 언어

개발자 (Java) → SQL → DBMS (MySQL) → Database

SQL의 종류

분류역할주요 명령어예시
DDL구조 정의CREATE, ALTER, DROP테이블 생성
DML데이터 조작SELECT, INSERT, UPDATE, DELETE데이터 CRUD
DCL권한 제어GRANT, REVOKE사용자 권한
TCL트랜잭션COMMIT, ROLLBACK작업 확정/취소

기본 SQL 문법

-- 조회 (SELECT)
SELECT id, name, email
FROM members
WHERE age >= 20
ORDER BY name ASC;

-- 삽입 (INSERT)
INSERT INTO members (name, email, age, created_at, updated_at)
VALUES ('홍길동', 'hong@example.com', 25, NOW(), NOW());

-- 수정 (UPDATE)
UPDATE members
SET age = 26, updated_at = NOW()
WHERE id = 1;

-- 삭제 (DELETE)
DELETE FROM members
WHERE id = 1;

-- 조인 (JOIN)
SELECT m.name, o.total_amount
FROM members m
JOIN orders o ON m.id = o.member_id
WHERE o.status = 'COMPLETED';

🔧 Spring Boot에서 SQL 사용

1️⃣ Spring Data JPA (Repository)

public interface MemberRepository extends JpaRepository<Member, Long> {

    // 메서드 이름으로 쿼리 자동 생성
    Optional<Member> findByEmail(String email);

    List<Member> findByAgeGreaterThanEqual(int age);

    // JPQL
    @Query("SELECT m FROM Member m WHERE m.name LIKE %:keyword%")
    List<Member> searchByName(@Param("keyword") String keyword);

    // Native SQL
    @Query(value = "SELECT * FROM members WHERE age BETWEEN :min AND :max",
           nativeQuery = true)
    List<Member> findByAgeRange(@Param("min") int min, @Param("max") int max);
}

2️⃣ JdbcTemplate (순수 SQL)

@Repository
@RequiredArgsConstructor
public class MemberJdbcRepository {

    private final JdbcTemplate jdbcTemplate;

    public Member findById(Long id) {
        String sql = "SELECT * FROM members WHERE id = ?";
        return jdbcTemplate.queryForObject(sql,
            (rs, rowNum) -> Member.builder()
                .id(rs.getLong("id"))
                .name(rs.getString("name"))
                .email(rs.getString("email"))
                .age(rs.getInt("age"))
                .build(),
            id
        );
    }

    public void save(Member member) {
        String sql = """
            INSERT INTO members (name, email, age, created_at, updated_at)
            VALUES (?, ?, ?, ?, ?)
            """;
        jdbcTemplate.update(sql,
            member.getName(),
            member.getEmail(),
            member.getAge(),
            LocalDateTime.now(),
            LocalDateTime.now()
        );
    }
}

3️⃣ MyBatis (XML 매핑)

<!-- MemberMapper.xml -->
<mapper namespace="com.example.mapper.MemberMapper">
    <select id="findById" resultType="Member">
        SELECT id, name, email, age
        FROM members
        WHERE id = #{id}
    </select>

    <insert id="save">
        INSERT INTO members (name, email, age, created_at, updated_at)
        VALUES (#{name}, #{email}, #{age}, NOW(), NOW())
    </insert>
</mapper>
@Mapper
public interface MemberMapper {
    Member findById(Long id);
    void save(Member member);
}

📌 SQL 표준

표준 SQL

정의: 국제표준화기구(ISO)에서 정한 SQL 규격

표준 SQL (공통)
├─ Oracle (PL/SQL) ← 표준 + Oracle 전용
├─ MySQL (SQL) ← 표준 + MySQL 전용
└─ MS SQL Server (T-SQL) ← 표준 + MSSQL 전용

DBMS별 차이점 예시

기능MySQLPostgreSQLOracle
자동 증가AUTO_INCREMENTSERIALSEQUENCE
문자열 결합CONCAT()\|\|\|\|
LIMITLIMIT 10LIMIT 10ROWNUM <= 10
날짜 형식DATE_FORMAT()TO_CHAR()TO_CHAR()
-- MySQL
SELECT * FROM members LIMIT 10;

-- PostgreSQL
SELECT * FROM members LIMIT 10;

-- Oracle
SELECT * FROM members WHERE ROWNUM <= 10;

-- SQL Server
SELECT TOP 10 * FROM members;

🎯 실무 예제: 주문 시스템

테이블 설계

-- 회원
CREATE TABLE members (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    created_at DATETIME NOT NULL
);

-- 상품
CREATE TABLE products (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(200) NOT NULL,
    price INT NOT NULL,
    stock INT NOT NULL
);

-- 주문
CREATE TABLE orders (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    member_id BIGINT NOT NULL,
    total_amount INT NOT NULL,
    status VARCHAR(20) NOT NULL,
    created_at DATETIME NOT NULL,
    FOREIGN KEY (member_id) REFERENCES members(id)
);

-- 주문 상품
CREATE TABLE order_items (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    quantity INT NOT NULL,
    price INT NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

Service 구현

@Service
@RequiredArgsConstructor
@Transactional
public class OrderService {

    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;

    public Order createOrder(Long memberId, List<OrderItemRequest> items) {
        // 1. 재고 확인 및 차감
        for (OrderItemRequest item : items) {
            Product product = productRepository.findById(item.getProductId())
                .orElseThrow(() -> new ProductNotFoundException());

            if (product.getStock() < item.getQuantity()) {
                throw new InsufficientStockException();
            }

            product.decreaseStock(item.getQuantity());
        }

        // 2. 주문 생성
        Order order = Order.create(memberId);

        // 3. 주문 상품 추가
        for (OrderItemRequest item : items) {
            Product product = productRepository.findById(item.getProductId())
                .orElseThrow();
            order.addItem(product, item.getQuantity());
        }

        // 4. 저장
        return orderRepository.save(order);

        // 트랜잭션 성공 → COMMIT
        // 예외 발생 → ROLLBACK (재고 차감 취소)
    }
}

💡 핵심 요약

DBMS의 3대 특징

1️⃣ 동시성: 여러 사용자 동시 접근
2️⃣ 무결성: 데이터 일관성 보장
3️⃣ 트랜잭션: ACID 속성으로 안정성

관계형 DBMS 구조

데이터베이스 (Database)
└─ 테이블 (Table)
   ├─ 열 (Column) ← 데이터 항목
   └─ 행 (Row) ← 데이터 레코드

SQL의 역할

Java 코드 → JPA/JDBC → SQL → MySQL → 데이터

📚 학습 로드맵

1단계: RDBMS 개념 이해
├─ 테이블, 행, 열
├─ 기본 키, 외래 키
└─ 관계(1:1, 1:N, N:M)

2단계: SQL 기초 문법
├─ SELECT, WHERE, JOIN
├─ INSERT, UPDATE, DELETE
└─ GROUP BY, ORDER BY

3단계: JPA/Hibernate
├─ 엔티티 매핑
├─ 연관관계
└─ 영속성 컨텍스트

4단계: 실무 최적화
├─ 인덱스
├─ 쿼리 튜닝
└─ 트랜잭션 관리

🚀 마무리

"DBMS는 애플리케이션의 심장이며, SQL은 DBMS와 소통하는 언어입니다"

Backend 개발자라면:

데이터베이스를 제대로 이해하면 안정적이고 확장 가능한 시스템을 만들 수 있습니다! 💪

← 목록으로 돌아가기