Redis 신입 테스트 · 코드품질 면접
새 면접Q. Redis를 사용하는 캐시 로직을 단위 테스트할 때, 실제 Redis 서버 대신 Mock 객체를 사용해야 하는 이유를 설명해주세요.
단위 테스트의 독립성과 실행 속도 측면에서 생각해보세요.
단위 테스트는 외부 의존성 없이 빠르고 독립적으로 실행되어야 합니다. 실제 Redis 서버를 사용하면 네트워크 연결이 필요하고, 테스트 속도가 느려지며, CI/CD 환경에서 Redis 서버 구성이 필요합니다. Mock 객체를 사용하면 Redis 연결 없이도 비즈니스 로직만 검증할 수 있고, 테스트가 빠르게 실행됩니다. 또한 다양한 예외 상황(연결 실패, 타임아웃 등)을 쉽게 시뮬레이션할 수 있어 엣지 케이스 테스트가 용이합니다.
- • 단위 테스트의 독립성 보장
- • 빠른 테스트 실행 속도
- • 외부 의존성 제거로 안정적인 테스트 환경 구축
CI/CD 파이프라인에서 수백 개의 테스트를 빠르게 실행하기 위해 Mock을 활용합니다.
그렇다면 통합 테스트에서는 어떤 방식으로 Redis를 테스트해야 할까요?
Q. Redis를 사용하는 애플리케이션의 통합 테스트를 작성할 때, 테스트용 Redis 환경을 구성하는 방법에는 어떤 것들이 있나요? 각각의 장단점을 설명해주세요.
실제 Redis 인스턴스, 임베디드 Redis, 컨테이너 기반 접근법을 고려해보세요.
첫 번째는 로컬에 설치된 실제 Redis 인스턴스를 사용하는 방법으로, 실제 환경과 동일하지만 개발자마다 환경 설정이 필요합니다. 두 번째는 임베디드 Redis를 사용하는 방법으로, 테스트 코드에서 Redis를 직접 실행해 별도 설치가 불필요하지만 실제 Redis와 동작이 다를 수 있습니다. 세 번째는 Docker나 Testcontainers를 사용하는 방법으로, 실제 Redis 이미지를 컨테이너로 실행해 실제 환경과 동일하면서도 격리된 환경을 제공합니다. 현대적인 프로젝트에서는 Testcontainers를 가장 많이 사용하며, CI/CD 환경에서도 일관된 테스트가 가능합니다.
- • 임베디드 Redis는 편리하지만 실제 환경과 차이 존재
- • Testcontainers는 실제 Redis를 격리된 환경에서 실행
- • CI/CD 환경에서의 일관성 확보가 중요
마이크로서비스 환경에서 실제 Redis 동작을 검증하기 위해 통합 테스트에서 Testcontainers를 활용합니다.
Testcontainers를 사용할 때 테스트 실행 속도가 느려지는 문제를 어떻게 해결할 수 있을까요?
Q. Redis를 사용하는 테스트에서 각 테스트 케이스가 서로 영향을 주지 않도록 하려면 어떻게 해야 하나요?
테스트 전후로 Redis 데이터를 어떻게 관리해야 할지 생각해보세요.
각 테스트는 독립적으로 실행되어야 하므로, 테스트 전후로 Redis 데이터를 정리해야 합니다. 가장 일반적인 방법은 각 테스트 후에 FLUSHDB 또는 FLUSHALL 명령으로 모든 데이터를 삭제하는 것입니다. 또는 테스트마다 고유한 키 prefix를 사용해 데이터를 격리하고, 테스트 종료 시 해당 prefix의 키만 삭제할 수 있습니다. 통합 테스트에서는 각 테스트마다 새로운 Redis 인스턴스를 시작하거나, 트랜잭션을 활용해 롤백하는 방법도 있습니다. 테스트 프레임워크의 setUp과 tearDown 메서드를 활용하면 일관되게 데이터를 관리할 수 있습니다.
- • 각 테스트 후 FLUSHDB로 데이터 정리
- • 고유한 키 prefix로 테스트 간 데이터 격리
- • setUp/tearDown으로 일관된 데이터 관리
여러 개발자가 동시에 테스트를 실행할 때 데이터 충돌을 방지하기 위해 테스트 격리 전략이 필요합니다.
FLUSHDB와 FLUSHALL의 차이는 무엇이며, 테스트에서는 어떤 것을 사용하는 것이 좋을까요?
Q. Redis 연결을 관리하는 코드를 작성할 때, 코드 리뷰에서 반드시 확인해야 할 품질 요소는 무엇인가요?
리소스 관리, 에러 처리, 재사용성 측면에서 생각해보세요.
첫째, Redis 연결이 제대로 종료되는지 확인해야 합니다. 연결 풀을 사용하는 경우 반환이 제대로 되는지, try-finally나 with 구문으로 자원 해제가 보장되는지 검토합니다. 둘째, 연결 실패나 타임아웃 등의 예외 처리가 적절한지 확인합니다. 셋째, Redis 연결 설정이 하드코딩되지 않고 환경 변수나 설정 파일로 관리되는지 점검합니다. 넷째, 연결 풀 설정이 적절한지 확인하며, 최대 연결 수나 타임아웃 값이 합리적인지 검토합니다. 다섯째, 싱글톤 패턴 등으로 불필요한 연결 생성을 방지하는지 확인합니다.
- • 연결 자원의 적절한 해제 보장
- • 예외 상황에 대한 에러 처리
- • 설정값의 외부화 및 연결 풀 관리
프로덕션 환경에서 연결 누수가 발생하면 Redis 서버에 과부하가 걸려 전체 서비스가 중단될 수 있습니다.
Redis 연결 풀의 최대 연결 수는 어떤 기준으로 설정해야 할까요?
Q. 캐시 조회, 저장, 삭제 로직이 여러 곳에 중복되어 있는 코드를 발견했습니다. 이를 어떻게 리팩토링하시겠습니까?
공통 로직을 추상화하고 재사용 가능한 구조로 만드는 방법을 고려하세요.
먼저 Redis 캐시 작업을 담당하는 별도의 CacheService 또는 CacheRepository 클래스를 만들어 공통 로직을 집중시킵니다. 이 클래스에 get, set, delete 등의 메서드를 구현하고, 직렬화/역직렬화, TTL 설정, 에러 처리 등의 공통 로직을 포함시킵니다. 제네릭을 활용해 다양한 데이터 타입을 처리할 수 있도록 하고, 캐시 키 생성 규칙도 통일합니다. 데코레이터 패턴이나 AOP를 사용하면 비즈니스 로직과 캐싱 로직을 완전히 분리할 수 있습니다. 리팩토링 후에는 기존 테스트가 모두 통과하는지 확인하고, 새로운 캐시 서비스에 대한 단위 테스트도 추가합니다.
- • 공통 캐시 로직을 별도 서비스 클래스로 추출
- • 제네릭과 추상화를 통한 재사용성 향상
- • 리팩토링 후 테스트로 동작 보장
캐시 로직이 중복되면 TTL 변경이나 직렬화 방식 수정 시 여러 곳을 수정해야 해 유지보수가 어렵습니다.
캐시 로직을 비즈니스 로직과 완전히 분리하기 위해 어떤 디자인 패턴을 사용할 수 있을까요?
Q. Redis를 활용한 조회수 카운터 기능을 TDD 방식으로 개발한다면, 어떤 순서로 테스트를 작성하고 구현하시겠습니까?
가장 단순한 케이스부터 시작해서 점진적으로 복잡한 시나리오로 확장하는 방법을 생각해보세요.
첫 번째 테스트는 조회수가 0인 상태에서 카운트를 증가시키면 1이 되는지 검증합니다. 이를 통과하는 최소한의 코드로 INCR 명령을 구현합니다. 두 번째 테스트는 이미 조회수가 있는 경우 정상적으로 증가하는지 확인합니다. 세 번째 테스트는 존재하지 않는 키에 대한 조회수 조회 시 0을 반환하는지 검증합니다. 네 번째 테스트는 여러 번 호출 시 정확히 카운트되는지 확인합니다. 다섯 번째로 Redis 연결 실패 등의 예외 상황을 테스트하고 적절한 에러 처리를 추가합니다. 각 단계마다 실패하는 테스트를 먼저 작성하고, 테스트를 통과하는 최소한의 코드를 구현한 후, 리팩토링하는 Red-Green-Refactor 사이클을 반복합니다.
- • 단순한 케이스부터 시작해 점진적으로 확장
- • Red-Green-Refactor 사이클 준수
- • 예외 상황까지 테스트로 커버
TDD를 통해 요구사항을 명확히 하고, 회귀 버그를 방지하며, 리팩토링에 대한 자신감을 얻을 수 있습니다.
TDD로 개발할 때 Mock을 사용하는 단위 테스트와 실제 Redis를 사용하는 통합 테스트를 어떻게 병행하시겠습니까?
Q. Redis를 사용하는 캐시 계층의 테스트 커버리지를 측정하고 개선하려고 합니다. 어떤 부분을 중점적으로 테스트해야 할까요?
정상 동작뿐만 아니라 캐시 미스, 만료, 에러 상황 등을 고려하세요.
첫째, 캐시 히트 시나리오로 데이터가 캐시에 있을 때 정상적으로 조회되는지 테스트합니다. 둘째, 캐시 미스 시나리오로 데이터가 없을 때 원본 소스에서 가져오고 캐시에 저장하는지 검증합니다. 셋째, 캐시 만료(TTL) 로직이 제대로 동작하는지 시간 기반 테스트를 작성합니다. 넷째, 캐시 무효화(삭제) 로직이 정확히 동작하는지 확인합니다. 다섯째, Redis 연결 실패나 타임아웃 등의 예외 상황에서 적절히 처리되는지 테스트합니다. 마지막으로 직렬화/역직렬화가 다양한 데이터 타입에서 정상 동작하는지 검증합니다.
- • 캐시 히트와 미스 시나리오 모두 테스트
- • TTL과 무효화 로직 검증
- • 예외 상황과 엣지 케이스 커버
캐시 로직의 버그는 데이터 정합성 문제나 성능 저하로 이어지므로 충분한 테스트가 필수적입니다.
테스트 커버리지가 100%라면 버그가 없다고 보장할 수 있을까요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!