본문 바로가기
CS/기술 면접 대비

[백엔드 기술 면접] #9 DB심화

by 경험의 가치 2024. 11. 24.

#9 DB심화

 

Q. 데이터베이스 파티셔닝의 필요성과 파티셔닝 방식에는 어떤 것들이 있나요?

A. 데이터베이스 파티셔닝은 대용량 데이터베이스의 관리를 용이하게 하고 성능을 향상시키기 위해 사용됩니다. 주요 파티셔닝 방식으로는 수평 파티셔닝(Horizontal Partitioning)과 수직 파티셔닝(Vertical Partitioning)이 있습니다. 수평 파티셔닝은 데이터 행을 여러 테이블로 나누고, 수직 파티셔닝은 열을 기준으로 데이터를 분할합니다. 각 방식은 특정 쿼리 유형에 최적화되어 성능을 개선할 수 있습니다.

 

Q. MySQL에서 파티션 테이블에 외래키 제약조건을 설정할 수 있나요? 없다 실제 사용 시 어떻게 대응하는 것이 좋을까요?

A. MySQL에서 파티션 테이블은 외래키 제약조건을 지원하지 않습니다. 이는 파티션 간의 데이터 무결성을 자동으로 관리하는 데 한계가 있기 때문입니다. 따라서, 파티션은 실제 외래키가 없는 테이블에만 적용을 해야 하거나 아니면 파티션이 필요하다 생각되는 테이블이면 외래키 제약조건을 제거하고 비즈니스 로직으로 검증하는 식으로 구현해야 합니다.

 

Q. 데이터베이스 스케일-아웃(Sharding) 시 기본 키의 유일성을 보장하기 위해 어떤 기술을 사용할 수 있나요?

A. 데이터베이스를 스케일-아웃 할 때는 여러 데이터베이스 서버에 걸쳐 데이터가 분산되므로 기본 키의 유일성 보장이 중요한 문제가 됩니다. 이를 해결하기 위해 티켓 서버, UUID, 스노우플레이크(Snowflake) 같은 기술을 사용할 수 있습니다. 티켓 서버는 중앙에서 일련번호를 발급하여 기본 키로 사용하며, UUID는 전역적으로 유일한 식별자를 제공합니다. 스노우플레이크 알고리즘은 시간 기반의 접근 방식으로 고유한 ID를 생성하며, 여러 서버에서 동시에 발생하는 충돌을 방지할 수 있습니다. 이 기술들은 기본 키의 유일성뿐만 아니라 확장성 및 성능 최적화에도 기여합니다.

 

Q. 트랜잭션이 무엇이고, 트랜잭션 특성에 대해서 설명해보세요.

A. 트랜잭션은 데이터베이스에서 실행되는 일련의 작업들을 하나의 논리적 단위로 묶은 것으로, 모든 작업이 완벽하게 수행되거나 아예 실행되지 않는 방식으로 처리되어야 합니다. 이를 통해 데이터의 일관성과 무결성을 보장합니다. 트랜잭션의 주요 특성은 ACID(원자성, 일관성, 독립성, 지속성)로 알려져 있습니다. 원자성은 트랜잭션의 모든 작업이 완전히 실행되거나 전혀 실행되지 않아야 함을 의미합니다. 일관성은 트랜잭션이 성공적으로 완료되면 데이터베이스가 일관된 상태를 유지해야 함을 의미하며, 독립성은 여러 트랜잭션이 동시에 실행될 때 각 트랜잭션이 서로의 중간 결과를 볼 수 없도록 보장하는 것을 말합니다. 마지막으로 지속성은 트랜잭션이 완료된 후 그 결과가 영구적으로 데이터베이스에 반영되어야 함을 의미합니다. 이러한 ACID 속성은 데이터베이스의 안정성과 신뢰성을 보장하는 데 핵심적인 역할을 합니다.

 

Q. Stored Procedure란 무엇이며, 사용하는 이유는 무엇인가요?

A. 스토어드 프로시저는 SQL 문과 선택적으로 제어문을 포함하는 데이터베이스 내에 저장된 프로그램입니다. 사용자가 정의한 연산을 수행하고, 필요에 따라 입력 파라미터를 받고 결과를 반환할 수 있습니다. 스토어드 프로시저를 사용하는 주요 이유는 코드의 재사용성을 높이고, 네트워크 트래픽을 줄이며, 데이터베이스 서버의 성능을 향상시키기 위함입니다.

 

Q. 데이터베이스에서 슬로우 쿼리를 발견했을 때 문제를 진단하고 해결할 수 있는 방법에는 어떤 것들이 있나요?

A. 슬로우 쿼리 문제를 해결하기 위해 먼저 데이터베이스의 슬로우 쿼리 로그를 활용하여 문제가 되는 쿼리를 식별합니다. 이후 쿼리의 실행 계획을 분석하여 인덱스 활용 여부와 조인 방식 등을 검토합니다. 적절한 인덱스 추가나 쿼리 리팩토링을 통해 성능을 개선할 수 있습니다. 또한, 데이터베이스 서버의 설정을 조정하여 리소스 할당을 최적화하거나 하드웨어 업그레이드를 고려할 수도 있습니다. 자주 사용되는 결과는 캐시에 저장하여 빠르게 접근할 수 있도록 하여 성능을 개선할 수 있습니다. 필요한 경우, 데이터베이스 파티셔닝을 통해 쿼리 성능을 향상시키는 방법도 있습니다.

 

Q. 데이터베이스 정규화란 무엇이며, 왜 중요한가요?

A. 데이터베이스 정규화는 데이터베이스 설계 과정에서 데이터 중복을 최소화하고, 데이터 무결성을 향상시키기 위해 데이터를 구조화하는 과정입니다. 정규화는 여러 단계의 정규 형태(Normal Forms)로 구성되며, 각 단계는 데이터의 중복을 점진적으로 제거하고, 데이터베이스의 효율성을 높입니다. 정규화를 통해 데이터의 삽입, 삭제, 갱신 이상(Anomaly)을 방지할 수 있고, 데이터 무결성을 유지할 수 있습니다. 이는 데이터베이스 시스템의 유지 관리를 용이하게 하고, 데이터의 일관성과 정확성을 보장하는 데 중요한 역할을 합니다.

 

Q. 데이터베이스에서 반정규화(Denormalization)란 무엇이며, 어떤 상황에서 반정규화를 고려해야 하나요?

A. 반정규화는 데이터베이스 설계에서 의도적으로 정규화 원칙을 완화하여 데이터의 중복을 허용하고, 그 결과로 조회 성능을 향상시키는 과정입니다. 이는 일반적으로 데이터 쓰기 작업보다 읽기 작업이 훨씬 빈번하거나, 시스템의 응답 시간이 매우 중요한 고성능 애플리케이션에서 사용됩니다. 반정규화의 주의점으로는 데이터 중복으로 인해 데이터의 무결성이 저하될 수 있으며, 데이터 갱신, 삽입, 삭제 작업이 복잡해질 수 있다는 것입니다. 따라서 반정규화를 결정할 때는 성능 이점과 데이터 관리의 복잡성 사이에서 신중한 균형을 고려해야 합니다.

 

Q. MySQL에서의 레코드 락, 갭 락, 넥스트 키 락, 자동 증가 락의 차이점은 무엇인가요?

A. MySQL에서는 여러 종류의 락을 사용하여 데이터 무결성과 동시성을 관리합니다. 레코드 락은 개별 레코드를 대상으로 잠금을 걸어 다른 트랜잭션이 해당 레코드를 수정하지 못하도록 합니다. 갭 락은 인덱스 레코드 사이의 간격에 잠금을 걸어 삽입 이상을 방지합니다. 넥스트 키 락은 레코드 락과 갭 락을 결합한 형태로, 레코드와 그 앞의 간격에 대해 잠금을 걸어 동시성과 일관성을 높입니다. 자동 증가 락은 AUTO_INCREMENT 속성을 가진 컬럼에 대한 값을 생성할 때, 동시에 여러 트랜잭션에서 중복 없이 값을 생성하도록 도와주는 테이블 레벨의 잠금입니다.

 

Q. MySQL의 Storage 엔진이 무엇이며, 그 동작 원리에 대해 설명해주세요.

A. MySQL의 Storage 엔진은 데이터를 저장, 검색, 수정 및 삭제하는 방식을 정의하는 데이터베이스 구성 요소입니다. 여러 종류의 Storage 엔진이 있으며, 각각은 특정 유형의 데이터베이스 작업에 최적화되어 있습니다. 가장 일반적으로 사용되는 Storage 엔진은 InnoDB입니다.

InnoDB는 트랜잭션을 지원하며, 데이터의 무결성과 일관성을 유지하기 위해 ACID(Atomicity, Consistency, Isolation, Durability) 속성을 제공합니다. InnoDB는 또한 행 수준의 잠금 및 외래 키 제약을 지원하여 동시성과 데이터 무결성을 강화합니다. InnoDB의 동작 원리는 다중 버전 동시성 제어(MVCC)를 사용하여 동시에 여러 트랜잭션이 데이터에 접근할 수 있도록 하면서도, 각 트랜잭션이 마치 독립적으로 데이터베이스에 작업을 수행하는 것처럼 만들어줍니다. Storage 엔진의 선택은 애플리케이션의 요구 사항, 데이터 무결성, 백업 요구 사항, 성능 기준 등 다양한 요인을 고려하여 결정되어야 합니다. 이러한 Storage 엔진은 MySQL 서버의 Plug-in 형태로 구현되어 있으며, 설정을 통해 특정 테이블 또는 테이블 그룹에 대해 다른 Storage 엔진을 사용할 수 있습니다.

 

Q. MySQL과 PostgreSQL 중 어떤 데이터베이스를 선택할지 고려할 때 어떤 기준을 사용하시나요?

A. MySQL과 PostgreSQL 선택은 프로젝트의 요구 사항과 기술적 필요성에 따라 달라집니다. MySQL은 Oracle에 의해 관리되며, 설정이 상대적으로 간단하고, 읽기 작업과 동시 다수 연결 처리에 강점을 가지고 있어서 많은 웹 애플리케이션에서 널리 사용됩니다. 반면, PostgreSQL은 뛰어난 확장성과 다양한 고급 기능을 제공합니다. 예를 들어, PostGIS와 같은 강력한 지리 공간 처리 기능과 pgVector, pg_cron 같은 다양한 확장 플러그인을 제공하여, 복잡한 트랜잭션 처리나 쓰기 중심의 작업에 적합합니다. 따라서, 단순한 CRUD 작업보다는 복잡한 데이터 처리가 필요한 프로젝트에 더 적합할 수 있습니다. 선택 시에는 프로젝트의 기술적 요구 사항, 팀의 경험, 커뮤니티 지원 및 라이브러리의 가용성을 고려해야 합니다.

 

Q. MVCC(Multi-Version Concurrency Control)란 무엇이며, 데이터베이스에서 어떻게 활용됩니까?

A. MVCC, 즉 다중 버전 동시성 제어는 데이터베이스 시스템에서 동시성을 향상시키기 위해 사용되는 기술입니다. 이 기술은 각 트랜잭션에 데이터의 특정 시점의 스냅샷을 제공하여, 한 사용자의 작업이 다른 사용자의 작업에 불필요하게 방해받지 않도록 합니다. 각 트랜잭션이 데이터의 버전을 만들 때, 데이터베이스는 이전 데이터의 복사본을 보관하고, 새로운 데이터 변경 사항을 기록합니다. 이로 인해, 데이터를 읽는 동안에는 락이 필요 없어, 읽기 작업이 쓰기 작업에 의해 차단되지 않으므로 동시성과 성능이 향상됩니다. MVCC는 특히 PostgreSQL과 MySQL의 InnoDB 스토리지 엔진과 같이 고도로 동시에 많은 작업을 처리해야 하는 데이터베이스 시스템에서 매우 중요합니다.

 

Q. MySQL 서버의 구조와 MySQL 엔진의 동작 원리에 대해 설명해주세요.

A. MySQL 서버는 크게 세 가지 주요 구성 요소로 나눌 수 있습니다: Connection Pool, MySQL 엔진, 스토리지 엔진. Connection Pool은 데이터베이스 연결을 관리하며, 클라이언트에게 데이터베이스 연결을 제공하는 역할을 합니다. MySQL 엔진은 클라이언트로부터 받은 쿼리를 분석하고 실행 계획을 수립하는데, 이는 SQL Interface를 통해 이루어지며, 쿼리 캐시, 파서, 전처리기, 최적화기 등 여러 구성 요소로 이루어져 있습니다. 스토리지 엔진은 실제로 데이터를 디스크에 읽고 쓰는 역할을 담당하며, InnoDB가 가장 널리 사용되는 예입니다. MySQL 엔진과 스토리지 엔진은 Handler API를 통해 통신합니다. 이 구조는 높은 성능과 확장성을 제공하도록 설계되었습니다.

 

Q. SQL 쿼리 최적화 기법에는 어떤 것들이 있으며, 특정 기법을 사용했을 때의 예상 시간 절감은 어느 정도인가요?

A. SQL 쿼리 최적화 기법은 데이터베이스 성능을 향상시키고 응답 시간을 단축하기 위해 다양하게 사용됩니다. 다음은 몇 가지 주요 쿼리 최적화 기법과 각 기법의 예상 시간 절감입니다:

  1. 컬럼 이름 사용하기: SELECT * 대신 필요한 컬럼 이름을 명시적으로 지정하여 데이터 전송량을 줄이고, 쿼리 속도를 향상시킬 수 있습니다. 이 방법은 평균적으로 27%의 시간 절감을 가져올 수 있습니다.
  2. HAVING 절 제거하기: GROUP BY와 함께 사용되는 HAVING 절 대신 WHERE 절을 사용하여 불필요한 로우를 조기에 필터링합니다. 이는 31%의 시간 절감 효과가 있습니다.
  3. DISTINCT 제거하기: 기본 키가 있는 테이블에서는 DISTINCT를 제거함으로써 쿼리의 속도를 빠르게 할 수 있으며, 이는 최대 85%의 시간을 절약할 수 있습니다.
  4. 서브쿼리 풀기: 가능한 경우 서브쿼리를 조인으로 바꾸어 처리 효율을 높입니다. 이는 61%의 시간을 줄일 수 있습니다.
  5. IN 절 활용하기: IN 절을 사용하면 인덱스를 효율적으로 활용하여 검색 속도를 빠르게 할 수 있습니다. 이 기법은 73%의 시간 절감을 기대할 수 있습니다.
  6. EXISTS 사용하기: DISTINCT와 테이블 조인 대신 EXISTS를 사용하여 불필요한 데이터 검사를 줄입니다. 이 방법은 61%의 시간을 절약할 수 있습니다.
  7. UNION ALL 사용하기: UNION 대신 UNION ALL을 사용하여 중복 검사 과정을 생략함으로써 처리 속도를 향상시킬 수 있으며, 81%의 시간 절감 효과가 있습니다.
  8. OR 조건 최적화하기: 조인 조건에서 OR을 사용할 경우 성능 저하를 일으킬 수 있으므로 가능하면 피하고 UNION ALL로 대체하는 것이 좋습니다. 이는 70%의 시간 절감을 가져올 수 있습니다.

이러한 기법들은 쿼리를 효율적으로 실행하고 데이터베이스의 부하를 줄이는 데 큰 도움이 됩니다.