신입 면접에서 자주 묻는 질문 정리 - 데이터베이스(DB)편
2025. 10. 4. 18:19

1. 인덱스 (Index)

인덱스란?

데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조. 책의 목차처럼 특정 컬럼의 값과 해당 레코드의 물리적 위치를 매핑하여 빠른 검색을 가능하게 함.

인덱스를 사용하는 이유

  • 검색 성능 향상: WHERE, JOIN, ORDER BY 절의 실행 속도 개선
  • 정렬 비용 감소: 이미 정렬된 상태로 유지
  • 전체 테이블 스캔 회피: 필요한 데이터만 빠르게 접근

인덱스의 장단점

장점:

  • 검색 속도 대폭 향상 (O(log n))
  • WHERE, ORDER BY, GROUP BY 절의 성능 개선
  • MIN/MAX 값을 빠르게 조회

단점:

  • 추가 저장 공간 필요 (테이블 크기의 약 10%)
  • INSERT, UPDATE, DELETE 성능 저하 (인덱스도 함께 수정 필요)
  • 잘못 설계된 인덱스는 오히려 성능 저하 유발
  • 인덱스 유지보수 비용 발생

B-Tree 인덱스와 Hash 인덱스

구분B-Tree 인덱스Hash 인덱스

구조 균형 이진 트리 구조 해시 테이블 구조
검색 속도 O(log n) O(1)
범위 검색 가능 (>, <, BETWEEN) 불가능 (= 만 가능)
정렬 자동 정렬 유지 정렬 불가
적합한 경우 범위 검색, 정렬이 필요한 경우 정확한 일치 검색만 필요한 경우
사용 MySQL의 기본 인덱스 Memory 엔진 등 특수한 경우

복합 인덱스 (Composite Index)

두 개 이상의 컬럼을 결합하여 만든 인덱스.

특징:

  • 인덱스 컬럼 순서가 중요 (WHERE 절에서 앞쪽 컬럼부터 사용해야 효과적)
  • 첫 번째 컬럼 기준으로 정렬 후, 두 번째 컬럼 정렬
  • 예: INDEX(name, age) → WHERE name='김철수' ✅, WHERE age=30 ❌

사용 시점: 여러 컬럼을 함께 조회하는 쿼리가 빈번한 경우


2. 트랜잭션 (Transaction)

트랜잭션의 정의

데이터베이스의 상태를 변경하는 하나의 논리적 작업 단위. 여러 연산을 하나로 묶어 모두 성공하거나 모두 실패하도록 보장.

ACID 속성

A - Atomicity (원자성)

  • 트랜잭션의 모든 연산이 완전히 수행되거나 전혀 수행되지 않아야 함
  • All or Nothing 원칙
  • 예: 계좌 이체 시 출금과 입금이 모두 성공하거나 모두 취소

C - Consistency (일관성)

  • 트랜잭션 완료 후 DB는 일관된 상태를 유지해야 함
  • 무결성 제약조건을 항상 만족
  • 예: 잔액은 항상 0 이상이어야 함

I - Isolation (격리성)

  • 동시에 실행되는 트랜잭션들이 서로 영향을 주지 않아야 함
  • 트랜잭션 실행 중에는 다른 트랜잭션의 중간 결과를 볼 수 없음

D - Durability (지속성)

  • 성공적으로 완료된 트랜잭션의 결과는 영구적으로 반영됨
  • 시스템 장애가 발생해도 커밋된 데이터는 보존

트랜잭션 격리 수준 (Isolation Level)

격리 수준Dirty ReadNon-Repeatable ReadPhantom Read설명

READ UNCOMMITTED O O O 커밋되지 않은 데이터 읽기 가능
READ COMMITTED X O O 커밋된 데이터만 읽기 가능
REPEATABLE READ X X O 같은 데이터는 항상 동일하게 읽힘
SERIALIZABLE X X X 완전한 격리, 성능 저하

용어 설명:

  • Dirty Read: 커밋되지 않은 데이터를 읽는 현상
  • Non-Repeatable Read: 같은 데이터를 다시 읽었을 때 값이 변경된 현상
  • Phantom Read: 같은 조건으로 조회 시 없던 레코드가 나타나는 현상

커밋(Commit)과 롤백(Rollback)

커밋 (Commit):

  • 트랜잭션의 모든 작업을 확정하여 DB에 영구 반영
  • 커밋 후에는 되돌릴 수 없음

롤백 (Rollback):

  • 트랜잭션의 모든 작업을 취소하고 이전 상태로 복구
  • 오류 발생 시 자동 또는 수동으로 실행

데드락 (Deadlock)

정의: 두 개 이상의 트랜잭션이 서로가 점유한 리소스를 기다리며 무한 대기 상태에 빠지는 현상.

발생 예시:

  • 트랜잭션 A: X 잠금 → Y 대기
  • 트랜잭션 B: Y 잠금 → X 대기
  • 서로 상대방이 점유한 자원을 기다림

해결 방법:

  • 트랜잭션 순서 일관성 유지
  • 트랜잭션 처리 시간 최소화
  • 락 타임아웃 설정
  • DBMS의 자동 데드락 감지 및 희생 트랜잭션 선택

3. JOIN

JOIN의 정의

두 개 이상의 테이블을 연결하여 데이터를 조회하는 연산. 관계형 데이터베이스에서 분산된 데이터를 결합하여 의미 있는 정보를 추출.

JOIN을 사용하는 이유

  • 정규화된 테이블 결합: 중복을 제거한 여러 테이블의 데이터를 조합
  • 데이터 통합 조회: 필요한 정보를 한 번에 조회
  • 저장 공간 효율성: 중복 데이터 저장 없이 필요 시 결합

JOIN 종류와 특징

INNER JOIN

  • 두 테이블에서 조건이 일치하는 행만 반환
  • 교집합 개념
 
 
sql
SELECT * FROM A INNER JOIN B ON A.id = B.id;

LEFT (OUTER) JOIN

  • 왼쪽 테이블의 모든 행 반환, 오른쪽 테이블은 일치하는 행만 반환
  • 일치하지 않으면 NULL 반환
 
 
sql
SELECT * FROM A LEFT JOIN B ON A.id = B.id;

RIGHT (OUTER) JOIN

  • 오른쪽 테이블의 모든 행 반환, 왼쪽 테이블은 일치하는 행만 반환
  • LEFT JOIN의 반대
 
 
sql
SELECT * FROM A RIGHT JOIN B ON A.id = B.id;

FULL (OUTER) JOIN

  • 양쪽 테이블의 모든 행 반환
  • 일치하지 않는 부분은 NULL 반환
  • MySQL은 미지원 (UNION으로 구현)

CROSS JOIN

  • 두 테이블의 모든 조합(카테시안 곱) 반환
  • A 테이블 n개 행 × B 테이블 m개 행 = n×m개 결과
 
 
sql
SELECT * FROM A CROSS JOIN B;

SELF JOIN

  • 같은 테이블을 두 번 사용하여 JOIN
  • 계층 구조 데이터 조회 시 유용
 
 
sql
SELECT e.name, m.name AS manager
FROM Employee e JOIN Employee m ON e.manager_id = m.id;

4. 정규화 (Normalization)

정규화란?

데이터의 중복을 최소화하고 무결성을 유지하기 위해 테이블을 분해하는 과정.

목적:

  • 데이터 중복 제거
  • 이상 현상 방지 (삽입, 수정, 삭제 이상)
  • 데이터 무결성 유지
  • 저장 공간 효율화

정규화의 종류

제1정규형 (1NF)

  • 모든 속성 값이 **원자값(Atomic Value)**을 가져야 함
  • 반복 그룹 제거
  • 예: 취미: 독서, 운동 ❌ → 별도 행으로 분리 ✅

제2정규형 (2NF)

  • 1NF 만족 + 부분 함수 종속 제거
  • 기본키가 아닌 모든 속성이 기본키에 완전 함수 종속
  • 복합키의 일부에만 종속되는 속성 분리

제3정규형 (3NF)

  • 2NF 만족 + 이행 함수 종속 제거
  • 기본키가 아닌 속성들 간의 종속 관계 제거
  • 예: 학생ID → 학과 → 학과위치 (학과위치를 별도 테이블로 분리)

BCNF (Boyce-Codd Normal Form)

  • 3NF 만족 + 모든 결정자가 후보키
  • 3NF보다 엄격한 조건

제4정규형 (4NF)

  • BCNF 만족 + 다치 종속 제거

제5정규형 (5NF)

  • 4NF 만족 + 조인 종속성 제거

실무: 대부분 3NF까지 정규화

역정규화 (Denormalization)

언제 진행하나?

  • 조회 성능이 중요한 경우: 여러 테이블 JOIN으로 성능 저하 발생
  • 읽기 작업이 압도적으로 많은 경우: 쓰기보다 읽기가 훨씬 빈번
  • 집계/통계 조회가 빈번한 경우: 미리 계산된 값 저장
  • 실시간 응답이 중요한 경우: JOIN 비용 감소 필요

방법:

  • 테이블 통합
  • 중복 컬럼 추가
  • 파생 컬럼 추가 (계산된 값 저장)
  • 요약 테이블 생성

주의: 데이터 일관성 유지 부담 증가


5. SQL문

DDL (Data Definition Language) - 데이터 정의어

정의: 데이터베이스 구조를 정의하고 변경하는 명령어

예시:

  • CREATE: 테이블, 인덱스, 뷰 생성
  • ALTER: 테이블 구조 변경
  • DROP: 테이블, 인덱스, 뷰 삭제
  • TRUNCATE: 테이블 데이터 전체 삭제 (구조 유지)

DML (Data Manipulation Language) - 데이터 조작어

정의: 데이터를 조회, 삽입, 수정, 삭제하는 명령어

예시:

  • SELECT: 데이터 조회
  • INSERT: 데이터 삽입
  • UPDATE: 데이터 수정
  • DELETE: 데이터 삭제

DCL (Data Control Language) - 데이터 제어어

정의: 데이터 접근 권한을 제어하는 명령어

예시:

  • GRANT: 권한 부여
  • REVOKE: 권한 회수

기본 SQL문 작성 예시

 
 
sql
-- INSERT: 데이터 삽입
INSERT INTO users (name, age, email)
VALUES ('김철수', 30, 'kim@example.com');

-- DELETE: 데이터 삭제
DELETE FROM users WHERE age < 20;

-- ALTER: 테이블 구조 변경
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

-- DROP: 테이블 삭제
DROP TABLE old_users;

-- SELECT 종합 쿼리
SELECT 
    u.name,
    u.age,
    COUNT(o.id) AS order_count,
    SUM(o.amount) AS total_amount
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE u.age >= 20
GROUP BY u.id, u.name, u.age
HAVING COUNT(o.id) > 0
ORDER BY total_amount DESC;

절 실행 순서: FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY


6. SQL 인젝션 (SQL Injection)

SQL 인젝션이란?

악의적인 사용자가 입력값을 조작하여 의도하지 않은 SQL 쿼리를 실행시키는 보안 취약점 공격 기법.

발생 상황

취약한 코드 예시:

 
 
java
String query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'";

공격 시나리오:

  • 입력값: username = "admin' --", password = "anything"
  • 실행 쿼리: SELECT * FROM users WHERE username = 'admin' --' AND password = 'anything'
  • 결과: 비밀번호 확인 없이 admin 계정 로그인 성공

해결 방법

1. Prepared Statement (권장)

  • 쿼리와 데이터를 분리하여 전송
  • 자동으로 특수문자 이스케이프 처리
 
 
java
PreparedStatement pstmt = conn.prepareStatement(
    "SELECT * FROM users WHERE username = ? AND password = ?"
);
pstmt.setString(1, username);
pstmt.setString(2, password);

2. ORM 사용

  • JPA, Hibernate 등 ORM 프레임워크 사용
  • 내부적으로 Prepared Statement 사용

3. 입력값 검증

  • 화이트리스트 방식으로 허용된 문자만 입력 허용
  • 특수문자, SQL 키워드 필터링

4. 저장 프로시저 사용

  • 미리 컴파일된 쿼리 사용

5. 최소 권한 원칙

  • DB 사용자에게 필요한 최소 권한만 부여
  • DROP, ALTER 등 위험한 권한 제한

7. 쿼리 성능 최적화

최적화 작업 방법

1. 인덱스 최적화

  • WHERE, JOIN, ORDER BY에 사용되는 컬럼에 인덱스 생성
  • 복합 인덱스 순서 최적화
  • 불필요한 인덱스 제거

2. 쿼리 재작성

  • SELECT * 대신 필요한 컬럼만 조회
  • 서브쿼리보다 JOIN 사용 (경우에 따라)
  • UNION ALL 사용 (중복 제거 불필요 시)
  • EXISTS 사용 (IN보다 효율적인 경우 많음)

3. 실행 계획 분석

  • EXPLAIN 명령어로 쿼리 실행 계획 확인
  • Full Table Scan 확인 및 개선
  • 인덱스 사용 여부 확인

4. 정규화/역정규화

  • 읽기 성능을 위한 역정규화 고려
  • 계산된 값을 미리 저장

5. 페이징 처리

  • LIMIT, OFFSET 사용으로 필요한 데이터만 조회
  • 커서 기반 페이징 사용

6. 캐싱 활용

  • Redis 등을 이용한 쿼리 결과 캐싱
  • 자주 조회되는 데이터는 애플리케이션 레벨에서 캐싱

7. 파티셔닝

  • 대용량 테이블을 논리적/물리적으로 분할
  • 범위, 리스트, 해시 파티셔닝

8. 배치 처리

  • 대량 INSERT/UPDATE는 배치로 처리
  • 트랜잭션 크기 조절

9. 통계 정보 업데이트

  • 옵티마이저가 올바른 실행 계획을 세우도록 통계 정보 최신화

10. N+1 문제 해결

  • Fetch Join, Batch Size 설정 등