21. 설계 하신 ERD 에서 Entity를 나눈 기준은 어떤 것이며, 팔로우 팔로잉 관계를 저장, 구현 하기 위해 어떤 구조를 사용 하셨나요?
"ERD를 설계할 때 주안점을 둔 것은 엔티티 간의 명확한 관계 설정, 데이터 무결성의 보장, 시스템의 확장성 및 유지 보수성, 그리고 사용자 경험의 최적화였습니다. 예를 들어, 사용자와 게시글 간의 관계를 명확히 하기 위해 'posts' 테이블에서 'userId'를 외래 키로 사용하여 'users'와의 연결을 정의했습니다. 이러한 방식은 데이터의 정확성을 유지하며, 시스템 변경에 유연하게 대응할 수 있도록 합니다.
특히, 팔로우 기능 구현을 위해서는 'follows' 테이블을 디자인했는데, 여기서는 사용자 간의 팔로우 관계를 나타내기 위해 '팔로우ID'와 '팔로워ID'라는 외래 키를 사용하고, 관계의 시작 및 수정 날짜를 추적할 수 있는 '시작날짜', '수정날짜' 필드를 포함시켜 관계의 동적 변화를 관리할 수 있게 했습니다. 이는 사용자 간의 상호작용을 명확히 파악하고, 시스템의 사회적 연결망 기능을 효과적으로 지원합니다."
꼬리 질문 > 댓글 기능을 구현하기 위해 포스트 Entity와 댓글 Entity를 어떻게 설계하셨는지 자세히 설명해주세요.
"댓글 기능 구현에 있어 'posts' 엔티티와 'comments' 엔티티 간의 관계를 효과적으로 매핑하는 것이 중요합니다. 저희는 이를 위해 'posts' 엔티티에 각 포스트를 식별하는 고유 ID와 필요한 포스트 정보를 포함시켰습니다. 그리고 'comments' 엔티티에는 댓글 고유 ID, 댓글이 속한 포스트의 ID를 외래 키로 참조하도록 했습니다. 이 외래 키 매핑을 통해 하나의 포스트에 여러 댓글이 달릴 수 있는 일대다 관계를 구현했습니다.
또한, 이러한 관계 설정은 ORM(객체 관계 매핑) 프레임워크를 사용할 때 'posts' 엔티티에서 관련 'comments' 엔티티를 쉽게 조회하거나, 반대로 댓글로부터 해당 댓글이 속한 포스트를 찾는 작업을 용이하게 합니다. 이는 개발 과정에서의 효율성을 높이고, 데이터의 무결성을 보장하는 데 중요한 역할을 합니다."
꼬리 질문 > JPA를 사용하시는 것에 있어 ERD 설계에 영향이 있으셨는지 설명해주세요
"JPA는 객체 지향 프로그래밍과 관계형 데이터베이스 사이의 간극을 메우는 ORM(Object-Relational Mapping) 프레임워크로, 데이터를 보다 직관적으로 관리할 수 있게 해줍니다. 이러한 특성 때문에, 설계 단계에서부터 데이터 모델을 객체 지향적인 관점에서 접근할 수 있었습니다.
예를 들어, 엔티티 간의 관계를 정의할 때, JPA를 사용하면 @OneToMany, @ManyToOne 같은 어노테이션을 통해 관계를 명시적으로 표현할 수 있습니다. 이는 ERD 설계에 있어서 실제 데이터베이스의 테이블 관계보다는, 객체 간의 관계에 초점을 맞출 수 있게 했습니다. 즉, 실제 데이터베이스 스키마를 설계하기 전에, 어떻게 객체들이 서로 상호작용할지에 대한 설계를 먼저 할 수 있었던 것입니다.
또한, JPA를 사용함으로써 데이터베이스 스키마 변경 시 그에 따른 영향을 최소화할 수 있는 설계를 고려할 수 있었습니다. JPA는 데이터베이스 스키마와 자바 코드 간의 동기화를 자동으로 관리해주기 때문에, ERD 설계 시에도 이러한 유연성을 고려하여 보다 적응적이고 확장 가능한 모델을 만들 수 있었습니다.
결론적으로, JPA의 사용은 ERD 설계에 객체 지향적 관점을 더하고, 데이터 모델의 유연성과 확장성을 높이는 데 큰 영향을 주었습니다. 이는 개발 과정에서의 생산성 향상과 유지보수의 용이성으로 이어졌습니다."
꼬리 질문 > ERD 설계를 하면서 가장 중요하게 생각하신 부분을 설명해주세요
"ERD(Entity Relationship Diagram) 설계 과정에서 저는 특히 세 가지 핵심 요소에 중점을 두었습니다: 데이터 무결성, 시스템 확장성, 그리고 사용자 경험.
첫째로, 데이터 무결성은 데이터베이스 설계의 근간입니다. 올바른 데이터 모델링과 엄격한 무결성 규칙의 적용을 통해, 데이터의 정확성과 일관성을 보장하는 것이 중요했습니다. 이를 위해, 엔티티 간의 관계를 명확하게 정의하고, 적절한 제약 조건과 키를 설정하여 데이터가 올바르게 입력, 수정, 삭제될 수 있도록 했습니다.
둘째로, 시스템의 확장성에 대한 고려 역시 중요했습니다. 비즈니스 요구사항은 시간이 지남에 따라 변할 수 있기 때문에, ERD를 설계할 때는 향후 시스템이 성장하거나 변화하는 요구사항을 수용할 수 있는 유연성을 고려해야 했습니다. 이를 위해 모듈화된 설계를 적용하고, 엔티티 간의 결합도를 낮추는 방식으로 설계를 진행했습니다.
마지막으로, 사용자 경험을 고려한 설계 방식을 채택했습니다. 최종적으로 시스템을 사용하는 것은 사람이기 때문에, 데이터 모델이 사용자의 행동 패턴과 비즈니스 로직을 자연스럽게 반영할 수 있도록 하였습니다. 예를 들어, 사용자의 작업 흐름을 단순화할 수 있는 방식으로 엔티티와 관계를 구성하여, 사용자가 시스템을 더 쉽고 효율적으로 사용할 수 있도록 했습니다.
요약하자면, ERD 설계 시 데이터 무결성의 보장, 시스템의 확장 가능성, 그리고 우수한 사용자 경험 제공이라는 세 가지 핵심 요소를 가장 중요하게 생각했습니다. 이러한 접근 방식은 효율적이고 유지보수가 용이한 데이터 모델을 생성하는 데 도움이 되었습니다."
22. 부하테스트를 어떻게 하셨는지 설명해주세요.
"부하 테스트를 수행하는 과정에서 저희 팀은 Python 기반의 자동화 도구를 사용하여 시뮬레이션을 구현했습니다. 목표는 시스템이 1000명의 동시 사용자와 그들이 발생시키는 총 10,000건의 주문을 원활하게 처리할 수 있는지 평가하는 것이었습니다.
첫 단계로, 결제 화면 진입 API에 대해 10,000건의 요청을 발생시켰습니다. 이 과정에서 각 요청은 고유한 사용자 ID를 가지도록 설계하여, 실제 사용 환경에서와 같이 다양한 사용자가 시스템을 이용하는 상황을 모방했습니다.
다음으로, 앞서 발생시킨 10,000건 중 8,000건에 대해 결제 시도 API를 테스트했습니다. 이 때, 결제 시도는 앞서 결제 화면 진입을 시도한 동일한 사용자 ID들을 대상으로 진행되었습니다. 이 과정을 통해, 실제 사용자가 결제 과정을 진행할 때 발생할 수 있는 다양한 시나리오를 테스트하고, 시스템의 안정성을 검증했습니다.
마지막으로, 서비스의 오픈 시간 전후로 남은 수량 확인 API의 성능을 테스트했습니다. 이는 사용자가 실시간으로 상품의 재고 상태를 확인할 수 있도록 하는 중요한 기능입니다. 특히, 오픈 시간 전후는 사용자의 요청이 급증하는 시간대이므로, 이 시간대에 대한 부하 테스트는 시스템의 성능을 평가하는 데 매우 중요했습니다.
이러한 접근 방식을 통해, 저희는 시스템의 성능을 다양한 측면에서 평가하고, 잠재적인 성능 병목 현상을 사전에 식별하여 개선할 수 있었습니다. 결과적으로, 이 부하 테스트는 시스템이 실제 사용 환경에서 예상되는 트래픽을 효과적으로 처리할 수 있는지에 대한 중요한 인사이트를 제공했습니다."
꼬리 질문 > 부하 테스트 과정에서 특정 API에 대한 성능 병목 현상을 발견했다면, 이 문제를 어떻게 해결했나요?
"예, 부하 테스트 중 결제 시도 API에서 성능 병목 현상을 발견했습니다. 이 문제를 해결하기 위해 저희 팀은 Redis를 활용한 캐싱 전략을 도입했습니다. Redis는 메모리 기반의 데이터 구조 저장소로, 빠른 읽기 및 쓰기 속도를 제공합니다. 따라서, 자주 요청되는 데이터를 Redis에 캐시함으로써 데이터베이스의 부하를 크게 줄일 수 있었습니다.
구체적으로는, 사용자가 결제 화면에 진입할 때마다 발생하는 데이터 조회 요청을 Redis에서 처리할 수 있도록 캐시 로직을 구현했습니다. 이러한 접근 방식으로, 결제 관련 정보, 사용자 세션, 재고 상태 등을 Redis에 저장하고, 동일한 요청이 들어올 때 직접 데이터베이스를 쿼리하는 대신 Redis에서 빠르게 응답할 수 있게 되었습니다.
Redis를 활용한 결과, 결제 시도 API의 응답 시간이 크게 단축되었고, 시스템 전체의 처리량도 개선되었습니다. 이를 통해 고부하 상황에서도 사용자에게 안정적인 서비스를 제공할 수 있게 되었습니다. 또한, 데이터베이스에 대한 부하가 감소하여, 다른 작업들에 대한 처리 속도도 향상되는 효과를 얻을 수 있었습니다. Redis 도입은 저희 시스템의 성능을 획기적으로 개선하는 중요한 결정이었습니다."
23. MSA를 하셨는데 모듈들을 이렇게 분리하신 이유가 있을까요?
"MSA(Microservices Architecture)로 분리한 주된 이유는 각 기능의 독립성을 확보하고, 특화된 관리 및 개발의 유연성을 제공하기 위함이었습니다. 이러한 접근 방식은 프로젝트의 복잡성을 관리 가능한 수준으로 낮추고, 각 서비스의 개발과 배포를 보다 효율적으로 만들어줍니다.
커뮤니티 관련 서비스와 예약 구매 관련 서비스는 서로 다른 비즈니스 로직과 사용자 요구사항을 가지고 있습니다. MSA를 적용함으로써, 각각의 서비스가 독립적으로 기능 개발, 데이터 관리, 그리고 성능 최적화를 진행할 수 있었습니다. 예를 들어, 커뮤니티 서비스는 사용자의 상호작용과 콘텐츠 관리에 초점을 맞출 수 있으며, 예약 구매 서비스는 주문 처리, 재고 관리, 결제 시스템과 같은 기능에 집중할 수 있습니다.
이러한 분리는 또한 각 서비스의 개별적인 확장성을 보장합니다. 사용자 수나 트래픽이 증가함에 따라 필요한 서비스만을 타겟으로 리소스를 할당하거나 확장할 수 있습니다. 예를 들어, 특정 이벤트나 프로모션으로 인해 예약 구매 서비스의 수요가 급증하면 해당 서비스만을 즉시 확장하여 처리 능력을 증대시킬 수 있습니다.
결론적으로, 이러한 구조는 개별 서비스가 특정 기능에 집중하면서도 전체 시스템의 일관성과 효율성을 유지할 수 있도록 합니다. 특히, 개인 프로젝트에서는 자원과 시간이 제한적이므로, MSA는 각 기능별로 최적화된 관리와 개발을 통해 전반적인 프로젝트의 성공 가능성을 높이는 중요한 전략이 될 수 있습니다."
꼬리 질문 > 모듈들의 공통 코드는 어떻게 관리하셨나요?
"MSA(Microservices Architecture) 환경에서 각 모듈 간에 공통되는 코드를 효율적으로 관리하기 위해 저는 코어 모듈이라는 공통 라이브러리를 구축했습니다. 이 코어 모듈은 모든 서비스가 공유하는 기능, 유틸리티, 도메인 모델, 인증 메커니즘 등을 포함하고 있습니다. 이러한 접근 방식을 통해 코드의 중복을 최소화하고, 공통 기능의 중앙집중식 관리를 가능하게 했습니다.
코어 모듈의 사용은 여러 면에서 프로젝트의 효율성을 높였습니다. 첫째, 공통 로직의 중복 개발을 방지함으로써, 개발 시간과 리소스를 절약할 수 있었습니다. 각 서비스 개발 시, 필요한 공통 기능을 코어 모듈에서 바로 가져다 사용함으로써, 개발 과정을 더욱 빠르고 간결하게 만들 수 있었습니다.
둘째로, 코어 모듈을 통한 공통 코드의 중앙 관리는 유지 보수의 용이성을 크게 향상시켰습니다. 예를 들어, 인증 방식에 변경이 필요한 경우, 코어 모듈 내에서만 수정을 진행하면 모든 서비스에 자동으로 적용되어, 일관된 보안 정책을 유지할 수 있었습니다.
셋째, 코어 모듈은 공통 코드에 대한 버전 관리를 단순화했습니다. 모듈의 버전 업데이트가 필요할 때, 각 서비스에서 개별적으로 업데이트를 진행하는 대신 코어 모듈만을 업데이트하여, 전체 시스템의 일관성을 보장할 수 있었습니다.
이처럼 코어 모듈을 도입함으로써, 개발 및 운영 과정에서의 일관성과 효율성을 확보할 수 있었습니다. 또한, 코드의 재사용성을 높이고, 개발 과정을 표준화함으로써 전반적인 프로젝트의 품질과 신뢰성을 향상시킬 수 있었습니다."
꼬리 질문 > 모듈들간의 로그들을 한 군데서 모아 관리하려면 어떻게 해야할까요?
"모듈 간의 로그를 효과적으로 중앙에서 모아 관리하기 위해서는, 로그 데이터의 수집, 저장, 분석, 그리고 시각화를 위한 종합적인 시스템이 필요합니다. 저희 프로젝트에서는 이를 위해 ELK 스택(Elasticsearch, Logstash, Kibana)을 주로 사용했습니다.
먼저, 각 모듈에서 발생하는 로그의 포맷을 JSON으로 통일하여, 로그 데이터를 구조화하고 표준화했습니다. 이렇게 하면 다양한 소스에서 발생하는 로그 데이터를 보다 쉽게 처리할 수 있습니다.
다음으로, Logstash 또는 Filebeat 같은 로그 수집 도구를 각 서비스에 배포하여 로그 데이터를 실시간으로 수집하고, Elasticsearch로 전송했습니다. Elasticsearch에서는 이러한 로그 데이터를 효율적으로 저장하고 관리합니다.
로깅 데이터의 분석과 모니터링을 위해서는 Kibana를 사용했습니다. Kibana는 Elasticsearch에 저장된 데이터를 기반으로 대시보드를 구성하고, 로그 데이터를 시각화할 수 있는 강력한 도구입니다. 이를 통해 시스템의 상태를 실시간으로 모니터링하고, 잠재적인 문제를 조기에 발견할 수 있었습니다.
또한, 중요한 로그 이벤트나 에러 발생 시 즉시 알림을 받을 수 있도록 경고 시스템을 구축했습니다. 이는 운영 팀이 시스템의 이상 상태를 빠르게 인지하고, 적시에 대응할 수 있도록 하는 중요한 기능입니다.
종합적으로, 이러한 로그 관리 시스템의 도입은 시스템 운영의 투명성을 높이고, 문제 해결 과정을 가속화하는 데 큰 도움이 되었습니다. 효과적인 로그 관리는 모듈화된 시스템의 복잡성을 효율적으로 관리하고, 전반적인 시스템의 안정성을 보장하는 핵심 요소입니다."
24. 동기와 비동기에 대해 설명해주세요.
"동기(Synchronous)와 비동기(Asynchronous)는 프로그래밍에서 데이터 처리 패턴을 설명할 때 사용되는 중요한 개념입니다.
동기 방식에서는 어떤 작업을 수행할 때 해당 작업이 완료될 때까지 기다렸다가 다음 작업을 진행합니다. 즉, 한 작업의 완료가 다음 작업의 시작 조건이 되는 것이죠. 예를 들어, 데이터베이스에서 정보를 조회하는 동작이 완료되어야만, 그 결과를 바탕으로 다음 로직을 실행할 수 있습니다. 이 방식의 장점은 작업의 순서가 명확하기 때문에 프로그램의 흐름을 이해하기 쉽다는 것입니다. 하지만, 각 작업이 순차적으로 이루어져야 하므로 대기 시간이 길어지는 단점이 있습니다.
반면, 비동기 방식에서는 어떤 작업을 시작한 후, 그 작업의 완료 여부와 상관없이 바로 다음 작업을 진행합니다. 작업이 완료되면 그 결과를 나중에 처리하게 됩니다. 이 방식은 예를 들어, 웹 애플리케이션에서 서버로부터 데이터를 요청하고 받아오는 과정에서 사용자의 인터페이스가 멈추지 않도록 할 때 자주 사용됩니다. 비동기 방식의 장점은 시스템의 자원을 효율적으로 사용할 수 있고, 사용자 경험을 개선할 수 있다는 점입니다. 하지만, 작업의 처리 결과를 예측하고 관리해야 하는 복잡성이 증가한다는 단점이 있습니다.
요약하자면, 동기 방식은 작업 처리의 명확한 순서가 필요할 때 사용하며, 비동기 방식은 시스템의 효율성과 반응성을 높이고자 할 때 주로 사용됩니다. 각각의 방식은 그 특성에 따라 적절히 선택하여 사용하는 것이 중요합니다."
꼬리 질문 > 프로젝트에서 비동기 처리를 적용한 예를 들어 설명해주실 수 있나요?
"프로젝트에서 비동기 처리를 활용한 주요 사례는 실시간 재고 관리 서비스의 구축입니다. 이 과정에서 Redis를 사용하여, 사용자의 주문 처리와 재고 업데이트를 비동기적으로 관리했습니다.
Redis의 비동기 처리 방식을 통해, 사용자가 상품을 주문할 때 그 정보를 Redis에 저장했습니다. 이 방식은 주문 처리 로직이 주문 데이터를 Redis에서 비동기적으로 처리하게 함으로써, 시스템이 사용자로부터 새로운 주문을 받는 동안에도 지속적으로 재고 상태를 업데이트할 수 있도록 지원합니다.
이러한 비동기 처리는 시스템의 반응성과 처리 능력을 크게 향상시켰습니다. 사용자가 주문을 완료하면, 시스템은 즉시 주문 성공 응답을 사용자에게 반환할 수 있으며, 실제 재고 업데이트 처리는 사용자와 독립적으로 백그라운드에서 이루어집니다.
이 방식의 이점은 크게 두 가지입니다. 첫째, 사용자 경험의 향상입니다. 사용자는 주문 접수가 바로 이루어진 것을 확인하고, 시스템의 처리 상태를 기다리지 않고 즉시 다른 활동을 계속할 수 있습니다. 둘째, 시스템의 효율성과 안정성 측면에서, Redis를 사용한 비동기 처리는 고객의 주문 처리와 재고 관리의 부하를 분산시켜, 트래픽이 집중되는 시간에도 시스템의 성능을 유지하게 도와줍니다.
결과적으로, Redis를 통한 비동기 처리는 실시간 재고 관리 서비스를 위한 강력한 솔루션이 되었으며, 사용자 경험의 개선과 시스템 성능의 최적화에 크게 기여했습니다."
'면접 (Java) > 준비' 카테고리의 다른 글
[면접] 프로젝트 면접 (29~32) (0) | 2024.04.03 |
---|---|
[면접] 프로젝트 면접 (25~28) (0) | 2024.04.02 |
[면접] 프로젝트 면접 (17~20) (0) | 2024.03.29 |
[면접] 기초 면접 (25~30) (0) | 2024.03.29 |
[면접] 프로젝트 면접 (13~16) (0) | 2024.03.28 |