특강
간단한 소개와 함께 튜터님이 구현 라이브 코딩을 진행했다.
ELK
Elasticsearch, Logstash, Kibana 세 가지 오픈 소스 도구로 구성된 로그 및 데이터 분석 스택을 의미한다.
실무에서는 클라우드 서비스로 사용하는 경우가 많지만, 이번 특강에서는 로컬 환경에서 구성하는 방법을 배웠다.
- Elasticsearch: 분산 검색 및 실시간 데이터 분석 서비스
- Logstash: 데이터 처리 파이프라인 도구
- Kibana: 시각화 대시보드 도구
사용 이유
배포 후 버그가 발생하면 문제 해결을 위한 효율적인 로그 모니터링 시스템이 필수적이다. 배포된 EC2나 컨테이너에 매번 접속해 로그 파일을 일일이 확인하는 것은 시간 소모가 크고 비효율적이기 때문이다. 엄청나게 늘어나는 DB의 Raw 문제를 해결하기 위해 실무에서는 CQRS 패턴을 적용하고, 조회 성능을 최적화한다.
빠른 이유
엘라스틱서치는 데이터를 저장할 때 역 인덱스(역색인) 방식을 사용한다. 키워드를 기준으로 데이터를 정렬한다.
피드백
AI 예측률을 높이는 방법
Q. AI를 사용해 웨이팅 대기 소요 시간을 예측하는 기능이 있습니다. 예측률을 높이기 위해 전체 웨이팅 수, 웨이팅 시작 시간, 자신의 순번, 팀의 인원 수, 가게 업종을 사용할 예정이고 MVP 이후에 이력 및 환경 데이터를 사용하는 것을 고려하고 있습니다. 난이도가 생각하는 것보다 많이 높을까요?
A. AI를 사용한다면 두 가지 방향으로 접근할 수 있을 것 같다.
프롬프트 최적화
- MVP 이전에 어떤 데이터를 반영할지 리스트업하는 게 좋다.
- Mock 데이터를 사용하는 것도 방법이지만, 신뢰할 수 있는 데이터나 실시간 정보를 사용하는 것이 더 완성도가 높아질 것이다.
- 공공 데이터를 활용하여 날씨, 지역, 밀도, 식품업 정보를 분석하거나 외부 연동을 많이 해보는 것이 취업에 유리하게 작용할 것 같다.
이력 데이터 기반 트레이닝
- 과거 데이터를 사용해 시퀀스 모델 또는 추정 모델로 학습하며, n개월치 데이터를 트레이닝할 수 있다.
- 동종 업계의 웨이팅 소요 시간을 구할 수 있으면 가장 좋겠지만, 이런 데이터를 얻는 것이 쉽지 않을 수도 있다. 더 조사해보는 것이 필요하다.
알림 메시지의 템플릿 분리
Q. 알림 메시지를 그대로 보관하는 것보다, 활용 가치를 높이려면 알림 템플릿과 매핑되는 값을 따로 보관하면 좋을 것 같은데 어떻게 생각하시나요?
A. 데이터를 구조화하며 DB를 고도화하는 것은 좋은 접근이다. 볼륨이 줄어들고, 이후 템플릿 추가 상황에서도 빠르게 대응할 수 있다.
표현식이 포함된 문자열이나 JSON을 DB에 저장하는 방식 외에 다른 방법이 떠오르지는 않는다. 개발 시 실제 구현은 프론트에서 JS로 처리하는 방향이 될 가능성이 높다.
외부 연동 유의할 점
안정적인 서비스를 위해 다음 사항을 고려해야 한다.
Fallback 및 Retry 처리
외부 서버의 오류로 인해 발송이 실패했을 경우 이메일로 대체 발송하거나, 스케줄러와 배치를 활용해 재시도한다. 예외 처리 및 재처리가 잘 되어있는지를 확인해야 한다.
문제 상황 대처 계획
외부 서버와 문제가 생겼을 때 어떤 방식으로 대처할지 사전에 계획을 세우는 것이 중요하다.
팀 활동
DDD 패키지 구조의 레포지토리 분리
이번 프로젝트에서는 레포지토리가 4개로 나뉘어 있어 혼란스러웠다. 조사 중 Service와 Repository를 완전히 분리하기 (with. DDD) 포스팅을 찾을 수 있었고, 이해를 돕기 위해 설계를 담당하신 팀장님과 논의하며 정리해보았다.
레포지토리 구성과 역할
- 도메인관점 개념적 인터페이스
domain.repository.PaymentRepository
- 실제 데이터에 관여하는 인터페이스(JPA, QueryDSL 상속)
infrastructure.repository.PaymentRepositoryImpl
- QueryDSL 인터페이스
infrastructure.repository.PaymentRepositoryCustom
- QueryDSL 구현체
infrastructure.repository.PaymentRepositoryCustomImpl
인프라에서 도메인의 레포지토리를 상속하는 이유
Q. PaymentRepositoryImpl에서 domain의 PaymentRepository를 추가로 상속받는 이유는 메서드 이중 작성을 줄이기 위해서일까요?
A. 상속을 하지 않으면 도메인의 PaymentRepository 구현체를 스프링 컨텍스트에서 생성할 수 없기 때문이다. 인터페이스로 만들어 놓으면 스프링 컨텍스트가 해당 구현체를 자동으로 생성해준다. PaymentRepositoryImpl이 JpaRepository를 상속받으니 SimpleJpaRepository 구현체가 주입이 될 것이고, QueryDSL 인터페이스에 따른 구현체도 구현하므로, 스프링 빈 주입이 가능해진다.