React 주니어 데이터베이스 기술면접
새 면접Q. React 애플리케이션에서 결제 기능을 구현할 때, 백엔드에서 주문 생성과 재고 차감을 처리합니다. 이 두 작업이 트랜잭션으로 묶여야 하는 이유와 ACID 속성 중 어떤 특성이 중요한지 설명해주세요.
두 작업 중 하나만 성공하고 다른 하나가 실패하면 어떤 문제가 발생할지 생각해보세요.
트랜잭션은 여러 작업을 하나의 논리적 단위로 묶어 모두 성공하거나 모두 실패하도록 보장합니다. 결제 시나리오에서 주문은 생성되었지만 재고 차감이 실패하면 실제 재고보다 많은 주문이 발생하는 데이터 불일치 문제가 생깁니다. ACID 속성 중 원자성(Atomicity)이 가장 중요한데, 이는 트랜잭션 내 모든 작업이 완전히 수행되거나 전혀 수행되지 않음을 보장합니다. 일관성(Consistency)도 중요하며, 데이터베이스가 트랜잭션 전후로 유효한 상태를 유지하도록 합니다. 트랜잭션 실패 시 롤백을 통해 이전 상태로 되돌릴 수 있습니다.
- • 트랜잭션은 여러 작업을 논리적 단위로 묶어 all-or-nothing 보장
- • 원자성(Atomicity)이 데이터 불일치 방지
- • 롤백을 통한 이전 상태 복구
전자상거래에서 주문-결제-재고 처리 등 여러 테이블을 동시에 수정할 때 데이터 무결성을 보장하기 위해 사용됩니다.
트랜잭션 격리 수준(Isolation Level)에 대해 알고 있나요? Read Committed와 Serializable의 차이를 설명해주세요.
Q. 이벤트 페이지에서 선착순 100명에게만 쿠폰을 지급하는 기능을 구현합니다. 동시에 1000명이 접속해서 쿠폰을 요청할 때 발생할 수 있는 Race Condition 문제와, 이를 해결하기 위한 데이터베이스 락(Lock) 방식을 설명해주세요.
여러 사용자가 동시에 같은 데이터를 읽고 수정하려 할 때 발생하는 문제를 생각해보세요.
Race Condition은 여러 요청이 동시에 쿠폰 잔여 수량을 조회하고 차감할 때, 실제보다 많은 쿠폰이 발급되는 문제입니다. 예를 들어 잔여 1개일 때 10명이 동시에 조회하면 모두 발급 가능하다고 판단해 10개가 발급될 수 있습니다. 이를 해결하기 위해 비관적 락(Pessimistic Lock)을 사용하면 SELECT FOR UPDATE 구문으로 데이터를 읽는 동안 다른 트랜잭션의 접근을 차단합니다. 낙관적 락(Optimistic Lock)은 버전 컬럼을 두고 수정 시 버전을 확인해 충돌을 감지합니다. 선착순 이벤트처럼 충돌이 빈번한 경우 비관적 락이 더 적합하며, Redis 같은 인메모리 DB의 원자적 연산도 대안이 될 수 있습니다.
- • Race Condition은 동시 접근으로 데이터 불일치 발생
- • 비관적 락은 SELECT FOR UPDATE로 선점
- • 낙관적 락은 버전 관리로 충돌 감지
한정 수량 이벤트, 좌석 예매, 재고 관리 등 동시 다발적인 요청에서 데이터 정합성을 보장해야 할 때 사용됩니다.
비관적 락 사용 시 데드락(Deadlock)이 발생할 수 있는 상황을 설명하고, 이를 방지하는 방법을 말씀해주세요.
Q. React 관리자 페이지에서 10만 건의 주문 데이터를 날짜 범위로 검색하는 기능이 있습니다. 쿼리 실행 시간이 5초 이상 걸려 사용자가 불편을 겪고 있습니다. 쿼리 성능을 개선하기 위해 어떤 방법들을 사용할 수 있는지 설명해주세요.
데이터베이스에서 원하는 데이터를 빠르게 찾기 위한 자료구조와 쿼리 실행 계획을 생각해보세요.
먼저 날짜 컬럼에 인덱스가 있는지 확인해야 합니다. 인덱스가 없으면 Full Table Scan이 발생해 모든 데이터를 검색하므로 느립니다. 날짜 범위 검색에는 B-Tree 인덱스를 생성하면 효과적입니다. EXPLAIN 명령어로 실행 계획을 분석해 인덱스가 실제로 사용되는지 확인해야 합니다. WHERE 절에서 날짜 컬럼에 함수를 적용하면 인덱스를 타지 않으므로 피해야 합니다. 필요한 컬럼만 SELECT하고 불필요한 JOIN을 제거하며, 결과가 많다면 페이지네이션을 적용해 한 번에 가져오는 데이터 양을 줄여야 합니다. 복합 인덱스가 필요한 경우 WHERE 절의 조건 순서를 고려해 생성합니다.
- • 날짜 컬럼에 인덱스 생성으로 검색 속도 향상
- • EXPLAIN으로 실행 계획 분석
- • WHERE 절 함수 사용 지양 및 필요한 컬럼만 조회
대용량 데이터를 다루는 관리자 페이지나 리포트 기능에서 사용자 경험 개선을 위해 쿼리 성능 튜닝이 필수적입니다.
복합 인덱스를 생성할 때 컬럼 순서가 중요한 이유와, 어떤 순서로 컬럼을 배치해야 하는지 설명해주세요.
Q. React로 만드는 쇼핑몰에서 하나의 주문(Order)에 여러 상품(Product)이 포함될 수 있고, 하나의 상품은 여러 주문에 포함될 수 있습니다. 이런 다대다(N:M) 관계를 데이터베이스에서 어떻게 설계해야 하는지 설명해주세요.
두 테이블 사이의 다대다 관계를 표현하기 위해 필요한 추가 테이블을 생각해보세요.
다대다 관계는 중간 테이블(Junction Table 또는 Bridge Table)을 사용해 두 개의 일대다 관계로 분해합니다. Order와 Product 사이에 OrderItem이라는 중간 테이블을 생성합니다. OrderItem 테이블은 order_id와 product_id를 외래키로 가지며, 두 컬럼을 조합해 복합 기본키로 설정하거나 별도의 id를 기본키로 둡니다. 중간 테이블에는 수량(quantity), 가격(price) 같은 관계에 대한 추가 속성도 저장할 수 있습니다. 이렇게 설계하면 한 주문에 여러 상품을, 한 상품이 여러 주문에 포함되는 것을 표현할 수 있으며 데이터 중복도 방지됩니다.
- • 다대다 관계는 중간 테이블로 분해
- • 중간 테이블에 양쪽 외래키 포함
- • 관계에 대한 추가 속성 저장 가능
쇼핑몰의 주문-상품, 학생-수업, 사용자-그룹 등 다대다 관계가 필요한 모든 도메인에서 사용됩니다.
중간 테이블에 복합 기본키를 사용하는 방식과 별도의 auto increment id를 사용하는 방식의 장단점을 비교해주세요.
Q. 사용자 테이블에 이메일(email) 컬럼이 있고, 로그인 시 이메일로 사용자를 조회합니다. 이 컬럼에 인덱스를 생성하면 조회 성능이 향상되지만, 인덱스 생성으로 인한 단점도 존재합니다. 인덱스의 단점과 어떤 경우에 인덱스를 생성하지 않는 것이 나을지 설명해주세요.
인덱스는 별도의 자료구조이므로 저장 공간과 데이터 변경 시의 영향을 생각해보세요.
인덱스는 추가 저장 공간을 차지하며, 테이블 크기의 10-20% 정도를 사용합니다. INSERT, UPDATE, DELETE 작업 시 인덱스도 함께 수정해야 하므로 쓰기 성능이 저하됩니다. 특히 인덱스가 많을수록 쓰기 작업이 느려집니다. 카디널리티가 낮은 컬럼(성별, boolean 같이 값의 종류가 적은 경우)은 인덱스 효과가 미미합니다. 테이블 크기가 작거나(수천 건 이하) 조회보다 쓰기가 빈번한 경우 인덱스가 오히려 성능을 저하시킬 수 있습니다. 따라서 조회가 빈번하고, 카디널리티가 높으며, 테이블 크기가 충분히 큰 컬럼에만 선택적으로 인덱스를 생성해야 합니다.
- • 인덱스는 추가 저장 공간 필요 및 쓰기 성능 저하
- • 카디널리티가 낮으면 효과 미미
- • 조회 빈도와 테이블 크기를 고려해 선택적 생성
서비스 초기에는 인덱스를 최소화하고, 실제 쿼리 패턴을 모니터링하며 필요한 곳에만 추가하는 방식으로 운영합니다.
인덱스를 너무 많이 생성했을 때 발생하는 구체적인 문제와, 불필요한 인덱스를 찾아내는 방법을 설명해주세요.
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!