이 영역을 누르면 첫 페이지로 이동
codesche's blog 블로그의 첫 페이지로 이동

codesche's blog

페이지 맨 위로 올라가기

codesche's blog

데이터베이스 + JPA

  • 2023.03.27 13:41
  • Study Cafe/기술면접

 

1. 데이터베이스에서 인덱스를 사용하는 이유 및 장단점

데이터베이스에서 인덱스를 사용하는 이유는 검색 성능을 향상시키기 위함입니다. 검색 성능을 향상시키기 위해서는 해당 쿼리가 index를 사용하는지, 카디널리티 또는 selectivity와 같은 요소들이 고려된 인덱스가 생성되어야 합니다.

인덱스를 사용하여 얻을 수 있는 장점으로는 빠른 검색 속도 향상입니다. 단점으로는 추가 저장공간이 필요합니다. 그리고 insert, update, delete 등의 변동 사항이 있는 경우 성능이 저하됩니다. 

 

* 인덱스를 어느 컬럼에 사용하는 게 좋을까?

인덱스는 where 절에서 '자주 조회'하고 '수정 빈도'가 낮으며 '데이터 중복'이 적은 컬럼을 선택하는 것이 좋습니다.

join 조건으로 자주 사용되는 컬럼도 인덱스로 사용하면 좋습니다. 데이터의 양이 많을수록 인덱스의 성능 향싱이 커집니다.

 

단, 한 테이블에 인덱스가 너무 많을 경우 데이터 수정시 소요시간이 늘어납니다. 또한 성별처럼 데이터 중복이 높은 값은 인덱스를 생성하지 않는 것이 크게 의미가 없습니다. 왜냐하면 인덱스의 이점보다 추가 저장공간이나 데이터 수정에 대한 성능 저하가 더 크기 때문입니다.


2. 트랜잭션

트랜잭션이란 데이터베이스의 상태를 변화시키는 하나의 논리적인 작업 단위라고 할 수 있으며, 트랜잭션에는 여러개의 연산이 수행될 수 있습니다. 트랜잭션은 수행 중에 한 작업이라도 실패하면 전부 실패하고, 모두 성공해야 성공이라고 할 수 있습니다.


3. ACID

1) 원자성(Atomicity)

: 트랜잭션의 연산은 모든 연산이 완벽히 수행되어야 하며, 한 연산이라도 실패하면 트랜잭션은 실패해야 합니다.

 

2) 일관성(Consistency)

: 트랜잭션은 유효한 상태로만 변경될 수 있습니다.

 

3) 고립성(Isolation)

: 트랜잭션은 동시에 실행될 경우 다른 트랜잭션에 의해 영향을 받지 않고 독립적으로 실행되어야 합니다.

 

4) 내구성(Durability)

: 트랜잭션이 커밋된 이후에는 시스템 오류가 발생하더라도 커밋된 상태로 유지되는 것을 보장해야 합니다.


4. 트랜잭션 격리수준

1) READ UNCOMMITTED

: 다른 트랜잭션에서 커밋되지 않은 내용도 참조할 수 있다.

 

2) READ COMMITTED

: 다른 트랜잭션에서 커밋된 내용만 참조할 수 있다.

 

3) REPEATABLE READ

: 트랜잭션에 진입하기 이전에 커밋된 내용만 참조할 수 있다.

 

4) SERIALIZABLE

: 트랜잭션에 진입하면 락을 걸어 다른 트랜잭션이 접근하지 못하게 한다.


5. 정규화

하나의 릴레이션에 하나의 의미만 존재하도록 릴레이션을 분해하는 과정이며, 데이터의 일관성, 최소한의 데이터 중복, 최대한의 데이터 유연성을 위한 방법입니다.

 

제1 정규형 : 테이블의 컬럼이 하나의 값을 갖도록 분해합니다.

제2 정규형 : 제1 정규형을 만족하고, 기본키가 아닌 속성이 기본키에 완전 함수 종속되도록  분해합니다.

(※ 완전 함수 종속 - 기본키의 부분집합이 다른 값을 결정하지 않는 다는 것을 의미)

제3 정규형 : 제2 정규형을 만족하고, 이행적 함수 종속을 없애도록 분해합니다.

(※ 이행적 종속 : A -> B, B -> C가 성립할 때 A -> C가 성립되는 것을 의미

BCNF 정규형 : 제3 정규형을 만족하고, 함수 종속성 X -> Y가 성립할 때 모든 결정자 X가 후보키가 되도록 분해합니다.

 

# 정규화의 장단점

○ 장점

1. 데이터베이스 변경시 이상현상이 발생하는 문제점을 해결할 수 있습니다.

2. 데이터베이스 구조 확장시 정규화된 데이터베이스는 그 구조를 변경하지 않아도 되거나 일부만 변경해도 됩니다.

 

○ 단점

1. 릴레이션의 분해로 인해 릴레이션 간의 연산, 즉 JOIN 연산이 많아집니다. 이로 인해 질의에 대한 응답 시간이 느려질 수 있습니다.

 

# 역정규화를 하는 이유

정규화를 거치면 릴레이션 간의 연산이 많아지는데, 이로 인해 성능이 저하될 우려가 있습니다. 역정규화를 하는 가장 큰 이유는 성능 문제가 있는 DB의 전반적인 성능을 향상시키기 위함입니다.

 

# 이상 현상

1. 삽입 이상 : 자료를 삽입할 때 특정 속성에 해당하는 값이 없어 NULL을 입력해야 하는 현상

2. 갱신 이상 : 중복된 데이터 중 일부만 수정되어 데이터 모순이 일어나는 현상

3. 삭제 이상 : 어떤 정보를 삭제하면, 의도하지 않은 다른 정보까지 삭제되어버리는 현상

=> 이러한 이상 현상을 예방하고 효과적인 연산을 하기 위해 데이터 정규화를 합니다.


6. JOIN

JOIN은 한 데이터베이스 내의 여러 테이블을 조합하여 하나의 열로 표현한 것을 말합니다. 

서로 관계있는 데이터가 여러 테이블로 나누어 저장되는 경우, 각 테이블에 저장된 데이터를 효과적으로 검색하기 위해 조인이 필요합니다.

 

○ 조인의 종류

1. INNER JOIN

- 여러 애플리케이션에서 사용되는 가장 흔한 결합 방식이며, 기본 조인으로 간주됩니다.

- 내부 조인은 조인 구문에 기반한 2개의 테이블(A, B)의 컬럼 값을 결합함으로써 새로운 결과 테이블을 생성합니다.

- 명시적 조인 표현(explicit)과 암시적 조인 표현(implicit) 2개의 다른 조인식 구문이 있습니다.

 

2. OUTER JOIN

- 조인 대상 테이블에서 특정 테이블의 데이터가 모두 필요한 상황인 경우 외부 조인을 활용하여 효과적으로 결과 집합을 생성할 수 있습니다.

- 방향(LEFT, RIGHT)을 통해 특정 테이블을 지정하여 특정 테이블의 데이터를 모두 포함시킬지 결정합니다.

 

a. 왼쪽 외부 조인 (LEFT OUTER JOIN = LEFT JOIN)

- 우측 테이블에 조인할 컬럼의 값이 없는 경우 사용합니다.

- 즉, 좌측 테이블의 모든 데이터를 포함하는 결과 집합을 생성합니다.

 

b. 오른쪽 외부 조인 (RIGHT OUTER JOIN)

- 좌측 테이블에 조인할 컬럼의 값이 없는 경우 사용합니다.

- 즉, 우측 테이블의 모든 데이터를 포함하는 결과 집합을 생성합니다.

 

c. 완전 외부 조인 (FULL OUTER JOIN)

- 양쪽 테이블 모두 OUTER JOIN이 필요할 때 사용합니다.

 

3. 셀프 조인 (SELF JOIN)

- 한 테이블에서 자기 자신에 조인을 시키는 것입니다.

- 계층형 구조에서 사용됩니다.

(ex. 현재 선택된 행의 상사가 누구인지 출력하는 경우)

 

○ 조인 사용시 고려사항

- 조인할 대상의 집합을 최소화

(집합을 최소화할 방법이 있으면, 조건을 먼저 적용하여 관계 맺을 집합을 최소화한 후, 조인을 맺는 것이 효율적)

 

- 효과적인 인덱스 활용

(인덱스 활용시, 조인 연산 비용을 낮출 수 있음)



7. RDBMS vs NoSQL

# RDBMS

RDBMS는 모든 데이터를 2차원 테이블 형태로 표현합니다. 데이터베이스를 이루는 객체들의 릴레이션을 통해 데이터를 저장하는 데이터베이스입니다. SQL을 사용해 데이터의 저장, 질의, 수정, 삭제를 할 수 있으며 데이터를 효율적으로 보관하는 것을 목적으로 하고 구조화가 굉장히 중요합니다.

 

○ 장점 : 스키마에 맞춰 데이터를 관리하기 때문에 데이터의 정합성을 보장할 수 있습니다.

○ 단점 : 시스템이 커질수록 쿼리가 복잡해지고 성능이 저하되며 Scale-out이 어렵습니다. (Scale-up만 가능)

 

# NoSQL

NoSQL은 RDBMS와 반대로 데이터간의 관계를 정의하지 않고, 스키마가 없어 좀 더 자유롭게 데이터를 관리할 수 있으며, 컬렉션이라는 형태로 데이터를 관리합니다. 

 

○ 장점

- 스키마 없이 Key-Value 형태로 데이터를 관리해 자유롭게 데이터를 관리할 수 있습니다.

- 데이터 분산이 용이하여 성능 향상을 위한 Scale-up, Scale-out이 가능합니다.

 

○ 단점 : 

- 데이터 중복이 발생할 수 있고, 중복된 데이터가 변경될 경우 모든 컬렉션에서 수정해야 합니다.

- 스키마가 존재하지 않기에 명확한 데이터 구조를 보장하지 않아 데이터 구조 결정이 어려울 수 있습니다.

 

# RDBMS와 NoSQL은 어느 경우에 적합한가?

*RDBMS는 데이터 구조가 명확하고, 변경될 여지가 없으며 스키마가 중요한 경우 사용하는 것이 좋습니다.

또한 중복된 데이터가 없어(데이터 무결성) 변경이 용이하기 때문에 관계를 맺고 있는 데이터가 자주 변경이 이루어지는 시스템에 적합합니다.

 

*NoSQL은 정확한 데이터 구조를 알 수 없고 데이터가 변경/확장 될 수 있는 경우 사용하는 것이 좋습니다.

또한 단점에서도 명확하듯 데이터 중복이 발생할 수 있으며 중복된 데이터가 변경될 시 모든 컬렉션에서 수정해야 하기 때문에 Update가 많이 이루어지지 않는 시스템에 좋으며, Scale-out이 가능하다는 장점을 활용해 막대한 데이터를 저장해야 해서 DB를 Scale-out 해야 되는 시스템에 적합합니다.


8. Redis

Redis는 Key-Value Store NoSQL DB입니다. 싱글스레드로 동작하며 자료구조를 지원합니다. 데이터의 스냅샷 혹은 AOF 로그를 통해 복구가 가능해서 어느정도의 영속성도 보장됩니다. 스프링에서는 세션을 관리하거나, 캐싱을 하는데 자주 사용되는 것으로 알고 있습니다.


9. Redis와 Memcached의 차이

1. Redis는 다양한 자료구조를 지원하고, Memcached는 문자열 형태로만 저장합니다.

2. Redis는 싱글 스레드 기반으로 동작하고, Memcached는 멀티 스레드를 지원해서 멀티 프로세싱이 가능합니다.

3. Redis는 트랜잭션을 지원하지만, Memcached는 트랜잭션을 지원하지 않습니다.

4. Redis는 데이터를 저장할 수 있지만, Memcached는 들고 있는 데이터를 저장할 수 있는 기능이 없습니다.


10. Elastic Search

Elastic Search는 자바로 개발된 오픈소스 검색엔진입니다. 보통 단독으로 사용하기 보다는 ELK 스택이라고 부르는Logstash, Kibana, Beats를 추가적으로 사용합니다. Inverted Index 구조로 데이터를 저장해서, 전문(Full-text) 검색시에 RDBMS에 비해 뛰어난 성능을 보장합니다. 데이터 저장, 문서 검색, 위치 검색, 머신 러닝 기반 검색 등 다양한 용도로 사용할 수 있습니다.


11. Elastic Search의 키워드 검색과 RDBMS

- RDBMS는 단순 텍스트매칭에 대한 검색만을 제공해 동의어나 유의어 같은 검색은 불가능합니다.

- Elastic Search는 동의어나 유의어를 활용한 검색이 가능하며, 비정형 데이터의 색인과 검색이 가능하고,

역색인 지원으로 매우 빠른 검색이 가능합니다.

 

※ Full-Text : 이미지, CSS, 글 등의 복합적으로 이뤄진 컨텐츠에서 순수하게 텍스트만 추출한 데이터를 의미. 이 과정을 보통 크롤링으로 구현함 ( 엘라스틱 서치의 검색엔진엔 크롤러가 빠져있어 별도로 구축해야함)


12. MongoDB

MongoDB는 C++로 제작된 문서지향 오픈소스 NoSQL 데이터베이스를 말합니다. 비정형 데이터를 JSON방식으로 데이터를 저장합니다. DB에서 데이터를 검색하기 위해 필드, 범위기반, 문자열 패턴 일치 등 쿼리를 지원하며, 확장, 축소가 쉽고 데이터 파티셔닝 지원기능이 내장되어 있습니다.

 

# MongoDB의 기능

인덱싱 : 일반적인 보조 인덱스 지원. 고유, 복합, 텍스트 인덱싱 등의 기능도 제공

샤딩 : 데이터를 머신간에 분할하는 프로세스

파일 스토리지 : 대용량 파일 및 파일 메타데이터를 저장하기 위해 사용하는 프로토콜 지원

집계 : 데이터처리 파이프라인 개념을 기반으로 집계 프레임워크 제공

 

# MongoDB의 장점 및 단점

○ 장점

- 위치 기반 데이터에 적합합니다.

- JSON으로 바로 넣을 수 있습니다.

- 데이터의 유연한 변화를 기대할 수 있습니다.

 

○ 단점

- Document 자체 용량이 row보다 큽니다.

- RDBMS보다 안정성이 떨어집니다.

 


13. CAP이론, Eventual Consistency에 대한 설명

CAP 이론은 분산 환경에서 모두를 만족하는 시스템은 없다는 이론입니다.

○ 일관성(Consistency)

: 모든 노드가 같은 시간에 같은 데이터를 보여줘야 합니다.

 

○ 가용성(Availability)

: 모든 동작에 대한 응답이 리턴되어야 합니다.

 

○ 분할 내성(Partition Tolerance)

: 시스템 일부가 네트워크에서 연결이 끊기더라도 동작해야 합니다.

 

Eventual Consistency는 일관성을 보장하지 못하기에 나온 개념으로, 일관성을 완전히 보장하지는 않지만 결과적으로는 언젠가 일관성이 보장된다는 것을 의미합니다.

 


14. JPA 영속성 컨텍스트의 이점

영속성 컨텍스트는 엔티티를 영구 저장하는 환경을 의미합니다.

영속성 컨텍스트를 쓰는 이유는 1차 캐시, 동일성 보장, 쓰기 지연, 변경감지(Dirty checking), 지연로딩이 있습니다.

  • 1차 캐시: 조회가 가능하며 1차 캐시에 없으면 DB에서 조회하여 1차 캐시에 올려 놓습니다.
  • 동일성 보장: 동일성 비교가 가능합니다.(==)
  • 쓰기 지연: 트랜잭션을 지원하는 쓰기 지연이 가능하며 트랜잭션 커밋하기 전까지 SQL을 바로 보내지 않고 모아서 보낼 수 있습니다.
  • 변경 감지(Dirty checking): 스냅샷을 1차 캐시에 들어온 데이터를 찍습니다. commit 되는 시점에 Entity와 스냅샷과 비교하여 update SQL을 생성합니다.
  • 지연 로딩: 엔티티에서 해당 엔티티를 불러올 때 그 때 SQL을 날려 해당 데이터를 가져옵니다.

15. JPA를 사용하는 이유

JPA를 사용하는 이유는 객체지향 프레임워크이기 때문입니다. JPA를 사용하면 비즈니스 로직이 RDBMS에 의존하는 것이 아니라, 자바 코드로 표현될 수 있기 때문입니다. 그로 인해서 생산성이 높아진다고 볼 수 있습니다.

또한 JPA는 JPQL로 SQL을 추상화하기 때문에 RDBMS Vendor에 관계없이 동일한 쿼리를 작성해서 같은 동작을 기대할 수 있다는 장점도 가지고 있습니다. 이는 database dialect를 지원하기 때문에 가지는 장점입니다.


16. N + 1 문제는 무엇이고 이것이 발생하는 이유, N + 1 문제해결방법

N + 1 쿼리 문제는 즉시 로딩과 지연 로딩 전략 각각의 상황에서 발생할 수 있습니다. 하위 엔티티들이 존재하는 경우 한 쿼리에서 모두 가져오는 것이 아닌, 필요한 곳에서 각각 쿼리가 발생하는 경우를 말합니다.

 

즉시 로딩에서 발생하는 이유는 JPQL을 사용하는 경우 전체 조회를 했을 때, 영속성 컨텍스트가 아닌 데이터베이스에서 직접 데이터를 조회한 다음 즉시로딩 전략이 동작하기 때문입니다.


지연 로딩에서 발생하는 이유는 지연로딩 전략을 사용한 하위 엔티티를 로드할 때, JPA에서 프록시 엔티티를 unproxy 할 때 해당 엔티티를 조회하기 위한 추가적인 쿼리가 실행되어 발생합니다.

 

해결 방법으로는 Fetch Join이라고 불리는 JPQL의 join fetch를 사용하는 방법이 있으며, 또 다른 방법으로는 @EntityGraph를 사용하는 방법, @Fetch(FetchMode.SUBSELECT)를 사용하는 방법, @BatchSize를 사용해 조절하거나 전역적인 batch-size를 설정하는 방법이 있습니다.

 

*참고
https://theheydaze.tistory.com/584
https://dev-coco.tistory.com/158
https://luran.me/359
https://github.com/ksundong/backend-interview-question#CS-%EA%B4%80%EB%A0%A8-%EC%A7%80%EC%8B%9D
https://velog.io/@emer/MongoDB-%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91
https://colinch4.github.io/2020-12-03/database/

'Study Cafe > 기술면접' 카테고리의 다른 글

자료구조/알고리즘, 컴파일러  (1) 2023.04.17
Spring  (0) 2023.04.09
네트워크  (0) 2023.03.16
백엔드 개발 면접 질문 주요 리스트(1)  (0) 2023.01.30
기술 면접 주요 질문 답변 정리(5문항)  (0) 2022.12.25

댓글

이 글 공유하기

  • 구독하기

    구독하기

  • 카카오톡

    카카오톡

  • 라인

    라인

  • 트위터

    트위터

  • Facebook

    Facebook

  • 카카오스토리

    카카오스토리

  • 밴드

    밴드

  • 네이버 블로그

    네이버 블로그

  • Pocket

    Pocket

  • Evernote

    Evernote

다른 글

  • 자료구조/알고리즘, 컴파일러

    자료구조/알고리즘, 컴파일러

    2023.04.17
  • Spring

    Spring

    2023.04.09
  • 네트워크

    네트워크

    2023.03.16
  • 백엔드 개발 면접 질문 주요 리스트(1)

    백엔드 개발 면접 질문 주요 리스트(1)

    2023.01.30
다른 글 더 둘러보기

정보

codesche's blog 블로그의 첫 페이지로 이동

codesche's blog

  • codesche's blog의 첫 페이지로 이동

검색

메뉴

  • 홈
  • 태그
  • 방명록

카테고리

  • 분류 전체보기 (76)
    • Algorithm (15)
      • 백준 (3)
      • 프로그래머스 (10)
      • inflearn 알고리즘(Java) (2)
    • 블로그소개 (1)
    • Back-End (11)
      • Java (10)
      • SpringBoot (1)
    • Database (2)
      • MySQL (0)
      • MariaDB (1)
      • Redis (0)
      • 개념, 이론 (1)
    • Front-End (0)
      • html, css, javascript (0)
    • Git (2)
    • 알고리즘 지식 (11)
      • 자료구조 (11)
    • Study Cafe (21)
      • 기술면접 (6)
      • Clean Code 스터디 (14)
      • CS 스터디 (0)
      • 개발용어 (1)
    • 주간 에세이 (10)
    • DevOps (3)
      • 배포, Front&Back 연동 (1)
      • AWS (0)
      • Docker (1)
      • 이론 (1)

최근 글

인기 글

댓글

공지사항

아카이브

태그

  • 주간에세이
  • java
  • 자바 기초
  • 자바 변수
  • 자료구조
  • 개발자 현실
  • 클린코드
  • git commit

나의 외부 링크

정보

The Code의 codesche's blog

codesche's blog

The Code

블로그 구독하기

  • 구독하기
  • RSS 피드

방문자

  • 전체 방문자
  • 오늘
  • 어제

티스토리

  • 티스토리 홈
  • 이 블로그 관리하기
  • 글쓰기
Powered by Tistory / Kakao. © The Code. Designed by Fraccino.

티스토리툴바