[면접] 프로젝트 면접 (9~12)
9. 팔로우 기능을 구현하기 위해 설계하신 DB Schema에 대해 자세히 설명해주세요.
"팔로우 기능을 위해 설계한 DB 스키마에는 `follows`라는 테이블을 포함하고 있으며, 이 테이블은 `팔로우ID`, `팔로워ID`를 주요 컬럼으로 사용합니다. 여기에 추가적으로, 각 팔로우 관계의 시작 날짜와 최근 수정 날짜를 나타내는 `시작날짜`, `수정날짜` 컬럼도 포함하여, 팔로우 관계의 생성 및 수정 이력을 관리할 수 있게 했습니다.
`팔로우Id`와 `팔로워Id` 컬럼은 모두 `User` 테이블의 사용자 ID를 참조하는 외래 키입니다. 이를 통해 어떤 사용자가 다른 사용자를 팔로우하는지에 대한 정보를 저장하고, `User` 테이블과의 연관관계를 통해 사용자의 상세 정보를 불러올 수 있습니다.
연관관계 매핑을 사용하여 `User` 엔티티와 `follows` 테이블 간의 관계를 정의했습니다. 이는 객체 지향 프로그래밍에서 `User` 엔티티가 여러 `follows` 인스턴스를 관리할 수 있게 하며, ORM 프레임워크를 사용하여 이러한 관계를 쉽게 다룰 수 있습니다.
`시작날짜`와 `수정날짜` 컬럼은 팔로우 관계의 생명 주기를 더 명확하게 파악하는 데 도움을 주며, 이를 통해 사용자 간의 소셜 네트워크 동적인 변화를 시간에 따라 추적하고 분석할 수 있는 기반을 마련합니다."
꼬리 질문 > 팔로우 기능 구현을 위한 DB 스키마에서 '시작날짜'와 '수정날짜' 컬럼을 추가한 특별한 이유는 무엇이며, 이 데이터를 활용하여 어떤 추가 기능이나 분석을 제공할 수 있나요?
"시작날짜와 수정날짜 컬럼을 팔로우 기능의 DB 스키마에 추가한 주된 이유는, 팔로우 관계의 동적인 변화를 시간에 따라 정확하게 추적하고 기록하기 위함입니다. '시작날짜'는 사용자 간의 팔로우 관계가 처음 형성된 시점을 나타내며, 이는 사용자의 소셜 네트워크 활동 패턴이나 인기도 변화 등을 분석할 기본 데이터로 사용될 수 있습니다. 반면, '수정날짜'는 팔로우 관계가 변경되었을 때의 시점을 기록하며, 이는 사용자가 팔로우를 취소하거나 다시 팔로우하는 행동을 포함할 수 있습니다.
이러한 정보를 활용하여, 특정 사용자의 팔로워 증감 추이를 분석하거나, 소셜 네트워크 내에서의 영향력 변화를 시각화할 수 있습니다. 또한, 소셜 미디어 마케팅에서는 이 데이터를 기반으로 효과적인 캠페인 시점을 결정하거나, 타겟 사용자 그룹의 활동성을 평가하는 데 사용할 수도 있습니다. 즉, '시작날짜'와 '수정날짜' 컬럼은 팔로우 관계의 시간적인 측면을 이해하고, 이를 바탕으로 다양한 인사이트를 도출하는 데 중요한 역할을 합니다."
10. 각각의 나눠진 서비스 모듈끼리 어떻게 통신할 수 있는지 통신 방법에 대해 설명해주세요.
"분산된 서비스 모듈 간의 통신을 위해, WebFlux를 사용하는 비동기 및 논블로킹 통신 방법을 선택했습니다. WebFlux는 Spring Framework 5에 도입된 반응형 프로그래밍을 위한 모듈로, 데이터 스트림과 비동기 로직을 활용하여 높은 처리량과 빠른 응답 시간을 제공합니다. 서비스 간 통신에 WebFlux를 사용함으로써, 하나의 작업이 다른 작업의 처리 속도에 영향을 받지 않고, 각 서비스가 독립적으로 동시에 여러 요청을 처리할 수 있게 됩니다.
이 통신 방법에서는 주로 HTTP REST API를 통해 서비스 간에 데이터를 주고받습니다. WebFlux를 이용한 REST API 호출은 WebClient를 사용하여 수행되며, WebClient는 비동기적으로 서비스 간 요청을 보내고 응답을 받을 수 있는 높은 수준의 추상화를 제공합니다. 또한, WebFlux는 Flux와 Mono라는 두 가지 핵심 타입을 통해 데이터 스트림을 처리합니다. Flux는 0개 이상의 데이터를 처리하는 데 사용되고, Mono는 0개 또는 1개의 결과를 처리하는 데 사용됩니다.
서비스 간 통신에 WebFlux를 사용함으로써, 우리는 시스템 전반의 확장성과 유연성을 개선할 수 있었습니다. 이 방식은 특히, 고성능이 요구되거나, 대규모 데이터 스트림 처리가 필요한 마이크로서비스 아키텍처에 이상적입니다. WebFlux를 사용한 비동기 통신 방법을 통해, 서비스 모듈 간에 효율적이고 안정적인 데이터 교환을 실현할 수 있었습니다."
꼬리 질문 > 서버간의 통신 과정에서 디버깅은 어떻게 진행하셨는지 설명해주세요
"네, 우선 프로젝트에서 WebClient를 사용하여 다른 서비스와의 비동기 통신을 구현했습니다. 이 과정에서 로깅 레벨을 조정하여 요청과 응답에 대한 자세한 로그 정보를 얻을 수 있었습니다. 이를 통해 서버 간 요청이 정상적으로 발생하고 있는지, 어떤 응답을 받았는지 확인할 수 있었고, 문제가 발생했을 때 그 원인을 더 쉽게 파악할 수 있었습니다.
다음으로는 Slf4J 어노테이션을 사용하여 애플리케이션 전반에 걸친 로깅을 활성화했습니다. 이를 통해 비즈니스 로직과 서버 간 통신 과정에서 발생하는 주요 이벤트와 에러를 기록할 수 있었습니다. 로그를 통해 시스템의 동작 상태를 실시간으로 모니터링하며, 잠재적인 문제를 조기에 발견하고 대응할 수 있었습니다.
마지막으로 서버 간 통신 중 발생할 수 있는 다양한 예외를 효과적으로 관리하기 위해 GlobalExceptionHandler를 구현했습니다. 이를 통해 예외 상황 발생 시 일관된 방식으로 에러를 처리하고, 사용자에게 보다 명확한 에러 응답을 제공할 수 있었습니다. 또한, 에러 발생 시 해당 정보를 로깅하여 문제의 원인을 분석하는 데 도움이 되었습니다.
이러한 접근 방식을 통해, 서버 간 통신 과정에서 발생할 수 있는 문제를 효율적으로 관리하고, 신속한 디버깅과 문제 해결을 진행할 수 있었습니다. 또한, 로깅과 예외 처리 메커니즘을 통해 시스템의 안정성을 강화하고, 오류에 대한 투명한 정보 제공을 통해 개발 및 운영 효율성을 개선할 수 있었습니다."
11. 멀티 쓰레드 환경이 무엇인지? 그리고 어떠한 점을 주의해야하는지 설명해주세요.
"멀티 쓰레드 환경은 하나의 애플리케이션이 동시에 여러 작업을 수행할 수 있도록 여러 쓰레드를 사용하는 프로그래밍 환경을 말합니다. 이를 통해 리소스 사용을 최적화하고, 애플리케이션의 응답성을 향상시킬 수 있습니다. 멀티 쓰레드 프로그래밍은 특히 I/O 작업이 많거나, 사용자 요청을 동시에 처리해야 하는 웹 서버와 같은 애플리케이션에서 유용합니다.
그러나 멀티 쓰레드 환경에서는 다음과 같은 점들을 주의해야 합니다.
첫 번째로, 데이터 공유와 동기화입니다. 여러 쓰레드가 같은 데이터에 동시에 접근하려고 할 때, 데이터의 일관성과 무결성을 유지하기 위해 동기화 메커니즘이 필요합니다. synchronized 키워드, 락(lock) 등을 사용해 공유 자원에 대한 동시 접근을 제어해야 합니다.
두 번째로는 데드락(Deadlock)입니다. 두 개 이상의 쓰레드가 서로가 보유한 자원의 해제를 무한히 기다리는 상태로, 이는 시스템의 정지 상태로 이어질 수 있습니다. 데드락을 피하기 위해서는 자원을 요청하는 순서를 일정하게 하거나, 타임아웃을 설정하는 등의 방법을 사용할 수 있습니다.
세 번째로는 생성된 쓰레드의 라이프 싸이클을 적절히 관리해야 합니다. 쓰레드 풀을 사용하여 쓰레드의 생성과 소멸을 효율적으로 관리하고, 시스템 자원의 낭비를 방지할 수 있습니다.
마지막으로, 경쟁 상태(Race Condition)입니다. 이는 여러 쓰레드가 동시에 같은 데이터를 수정하려고 할 때, 결과의 정확성을 보장할 수 없는 상태를 말합니다. 적절한 동기화를 통해 이를 방지해야 합니다.
멀티 쓰레드 환경을 효과적으로 사용하려면 이러한 문제들을 인식하고, 쓰레드 간의 동기화, 자원 관리, 쓰레드의 안전한 생성 및 소멸에 주의를 기울여야 합니다."
꼬리 질문 > Thread란 무엇 이며 Multi-Thread 환경이 재고 관리 시스템에 끼칠 수 있는 영향은 무엇인가요?
"쓰레드(Thread)는 프로세스 내에서 실행되는 실행 단위로, 프로그램의 실제 작업을 수행합니다. 하나의 프로세스는 여러 쓰레드를 가질 수 있으며, 이 쓰레드들은 프로세스의 자원을 공유하면서 동시에 실행될 수 있습니다. 쓰레드를 사용하면 멀티태스킹을 구현하여 애플리케이션의 성능을 향상시킬 수 있습니다. 이러한 멀티 쓰레드 환경은 재고 관리 시스템에 다음과 같은 영향을 끼칠 수 있습니다.
첫 번째로 성능 향상입니다. 멀티 쓰레드를 사용하면 동시에 여러 작업(예: 재고 조회, 주문 처리, 재고 업데이트)을 처리할 수 있어 시스템의 응답성이 향상됩니다. 이는 특히 대용량의 트랜잭션을 처리하는 재고 관리 시스템에서 중요합니다.
두 번째 영향은 동시성 문제입니다. 여러 쓰레드가 동시에 같은 재고 데이터에 접근하려 할 때, 동기화가 제대로 이루어지지 않으면 데이터 불일치 문제가 발생할 수 있습니다. 예를 들어, 두 쓰레드가 동시에 같은 상품의 재고를 감소시키려고 할 때, 예상보다 적게 감소하는 문제가 발생할 수 있습니다.
세 번째로는 데드락 위험이 있습니다. 멀티 쓰레드 환경에서 잘못된 자원 접근 순서로 인해 데드락이 발생할 수 있으며, 이는 시스템의 정지를 초래할 수 있습니다. 예를 들어, 두 쓰레드가 각각 다른 상품의 재고를 업데이트하려고 서로 필요한 자원을 점유하고 있을 때 발생할 수 있습니다.
마지막으로는 복잡성 증가입니다. 멀티 쓰레드 프로그래밍은 코드의 복잡성을 증가시키며, 디버깅과 유지보수를 어렵게 만듭니다. 재고 관리 시스템과 같이 중요한 시스템에서는 이러한 복잡성이 실수로 이어질 수 있으므로, 충분한 테스트와 검증이 필요합니다.
멀티 쓰레드 환경을 재고 관리 시스템에 적용할 때는 성능 향상의 이점을 누리면서도 동시성 문제를 관리하고, 데드락을 방지하며, 코드 복잡성을 적절히 다루는 방안을 고려해야 합니다."
12. 데이터베이스 파티셔닝에 대해 아는 만큼 설명해주세요.
"데이터베이스 파티셔닝은 큰 테이블이나 인덱스를 더 관리하기 쉽고 효율적인 단위로 분할하는 기술입니다. 이 과정을 통해 데이터베이스의 성능을 향상시키고, 관리를 용이하게 하며, 데이터의 접근 시간을 단축할 수 있습니다. 파티셔닝은 데이터를 물리적으로 여러 부분으로 나누지만, 사용자에게는 하나의 테이블로 보이는 특성을 가집니다. 주요 파티셔닝 유형에는 범위, 리스트, 해시, 키 파티셔닝이 있습니다.
우선, 범위 파티셔닝(Range Partitioning)은 특정 범위에 따라 데이터를 분할합니다. 예를 들어, 날짜 범위나 숫자 범위로 데이터를 나눌 수 있으며, 시간별로 데이터를 구분해 저장하는 경우에 유용합니다.
리스트 파티셔닝(List Partitioning)은 특정 키 값의 목록을 기준으로 데이터를 분할합니다. 각 파티션은 지정된 값의 목록을 가진 행을 포함하며, 특정 지역이나 카테고리별로 데이터를 분리하는 데 적합합니다.
해시 파티셔닝(Hash Partitioning)은 해시 함수를 사용해 파티션 키의 값에 따라 행을 파티션에 균등하게 분배합니다. 이 방법은 데이터를 고르게 분산시키고 싶을 때 유용하며, 검색 성능을 최적화할 수 있습니다.
마지막으로, 키 파티셔닝(Key Partitioning)은 하나 이상의 열을 키로 사용하여 파티션을 구분합니다. 이는 해시 파티셔닝의 한 형태로 볼 수 있으며, 다중 열을 기준으로 데이터를 분할합니다.
파티셔닝의 장점은 대용량 데이터의 관리를 단순화하고, 쿼리 성능을 향상시킬 수 있다는 점입니다. 특히, 병렬 처리가 가능해져 데이터 로딩 시간이 단축되고, 백업 및 복구 과정이 간소화됩니다. 그러나 파티셔닝을 위해서는 초기 설계 시 충분한 계획과 분석이 필요하며, 잘못된 파티셔닝 전략은 오히려 성능 저하를 초래할 수 있습니다."
꼬리 질문 > 데이터베이스 파티셔닝을 적용할 때, 특히 대용량 데이터가 있는 경우, 성능에 미치는 구체적인 영향은 무엇이며, 파티셔닝 전략을 선정할 때 고려해야 할 주요 요소는 무엇인가요?
"데이터베이스 파티셔닝은 대용량 데이터를 다룰 때 쿼리 성능을 크게 향상시킬 수 있습니다. 파티셔닝을 통해 데이터를 더 작은 단위로 분리함으로써, 특정 쿼리가 전체 데이터셋 대신 관련 있는 파티션만을 대상으로 작업을 수행할 수 있게 됩니다. 이는 I/O 비용을 줄이고, 쿼리 처리 시간을 단축시키며, 전체 시스템의 부하를 감소시킵니다. 또한, 병렬 쿼리 실행이 가능해져 대규모 데이터 처리가 더욱 효율적으로 이루어질 수 있습니다. 이러한 파티셔닝 전략을 선정할 때 몇 가지 고려해야할 주요 요소들이 있습니다.
우선, 데이터 접근 패턴을 고려해야 합니다. 어떤 쿼리가 주로 실행되는지, 어떤 데이터에 가장 자주 접근하는지를 분석하여, 가장 효율적인 파티셔닝 기준을 결정해야 합니다.
다음으로는, 데이터가 파티션에 균등하게 분포되도록 해야 합니다. 불균형한 데이터 분포는 특정 파티션에 과부하를 초래하고, 성능 저하를 일으킬 수 있습니다.
다음으로, 유지보수성과 확장성을 고려해야 합니다. 파티셔닝 구조는 시스템의 변화에 유연하게 대응할 수 있도록 설계되어야 합니다. 또한, 파티션 관리 및 유지보수가 용이해야 합니다.
마지막으로,파티셔닝은 백업 및 복구 작업을 용이하게 할 수 있으므로, 이러한 작업을 어떻게 계획할 것인지도 고려해야 합니다.
적절한 파티셔닝 전략을 선정하고 구현함으로써, 대용량 데이터베이스의 성능을 최적화하고, 시스템의 전반적인 효율성을 개선할 수 있습니다."