Sniff & Steps 프로젝트 예상 질문:
Docker를 선택한 이유는? AWS ECS, Lambda 같은 서비스를 사용하기에는 충분히 학습되지 않았고 여러개의 EC2 인스턴스를 띄우기에는 비용적인 부담이 컸습니다. 이에 Docker를 사용하여 하나의 EC2에서 웹서버, 데이터베이스, 애플리케이션을 컨테이너로 분리 실행하여 환경 통일을 얻었습니다. 배포 자동화는 GitHub Actions를 통해 CI/CD 파이프라인을 구축했고, 코드 푸시 시 자동으로 빌드되고 배포되도록 했습니다. 결과적으로 제한된 리소스로도 서비스 격리와 배포 자동화를 구현할 수 있었고, Docker와 CI/CD에 대한 실전 경험을 쌓는 좋은 프로젝트였습니다.
멀티 스테이지 빌드를 어떻게 구현했나요? 스니프 스텝은 싱글 스테이지로 구성되어 있습니다. 추후 리팩토링을 하게 된다면 멀티 스테이지 빌드를 적용하면 이미지를 30~50% 줄일수 있습니다 빌드 환경과 실행 환경을 분리해서 최종 이미지에는 JAR 파일과 JRE만 포함시키는 방식으로 최적화할 계획입니다.
Docker 네트워크와 볼륨 관리는 어떻게 했나요?
Nginx를 리버스 프록시로 사용한 이유는? 복잡한 포트 관리를 단순화하고 사용자 요청을 받아서 Nginx가 적절히 프론트엔드와 백엔드로 연결해주기에 추후 확장시 백엔드 인스턴스로 요청 분산도 가능하여 확장성까지 생각하기에 좋았습니다.
리소스 최적화는 구체적으로 어떻게 했나요? 비동기 파일 처리로 S3 업로드를 비동기 처리한 점과 Nginx를 사용해 서비스 분리를 하여 정적 파일 처리를 분담시켜 애플리케이션 서버 부하를 줄였습니다.
S3 업로드 관련: 서버를 통한 업로드 방식을 선택한 이유는? S3 접근 키를 클라이언트에게 노출하지 않아도 되고 서버에서 파일을 직접 검증하고 처리할 수 있어서 악성 파일 업로드를 방지하는 측면에서 보안까지 신경쓸수 있다는 점도 있었습니다.
또한 수정이 필요할때 서버 코드만 수정하기만 하면 되서 유지보수도 용이한 점도 있습니다.
200ms 성능 차이보다 보안을 우선시한 이유는? S3 직접 업로드보다 200ms 정도 느리지만, 보안성을 최우선으로 고려해서 서버 경유 방식으로 선택했습니다.
대용량 파일 업로드 시 서버 부하는 어떻게 해결했나요? 비동기처리로 여러 파일을 순차적으로 업로드하는 것이 아닌 병렬로 동시 업로드하게 만들고 파일을 메모리에 전체 업로드하지 않고 스트림으로 처리해서 메모리 사용량을 최소화 했습니다. 또한 개별 파일 업로드 실패 시에도 전체 프로세스가 중단되지 않도록 예외 처리를 했습니다.
비동기 처리는 어떻게 구현했나요? Spring Async와 CompletableFuture 를 활용했습니다.
인증/인가는 어떻게 처리했나요?” “JWT 토큰 기반 인증을 구현했습니다. 로그인 시 JWT 토큰을 발급하고, API 요청 시 Authorization: Bearer 헤더로 토큰을 전송해서 사용자 인증을 처리했습니다
GateStatus 프로젝트 예상 질문:
아키텍처 설계:
멀티 데이터베이스 전략을 선택한 이유는?(PostgreSQL, MongoDB, Redis를 각각 어떤 용도로 사용했나요?) 프로젝트 특성상 데이터 별로 분리하는 전략이 좋다고 생각했습니다. Postgre로 국회의원 기본정보, 투표 기록 등 정확한 관계와 트랜잭션이 중요한 내용 MongoDB로 발언내용, AI 분석 키워드 등 유연한 스키마가 필요한 AI 분석 결과 Redis로 빠른 조회가 필요한 실시간 데이터용으로 각 데이터베이스의 장점을 최대화해서 조회 성능 70% 향상을 달성했습니다.
도메인별 모듈 분리는 어떻게 설계했나요? 도메인의 특성에 맞게 기능별로 모듈을 분리했습니다. 각 도메인마다 독립적인 Repository, Controller, Service 구조 도메인별 전용 예외 처리와 Request/Response 객체와 Global 패키지로 공통 설정과 인프라 관심사 분리
높은 응집도로 관련 기능들을 하나의 도메인에 집중시키고 도메인간 의존성을 최소화 시키고 확장성을 생각했습니다.
성능 최적화:
N+1 쿼리 문제를 어떻게 발견하고 해결했나요? 국회의원 목록 조회시 성능이 급격히 느려지는 현상이 발견되었습니다. 선택적 패치 조인 적용을 하고 쿼리수 를 95퍼센트 감소시켰습니다. 응답 시간도 크게 줄였습니다.
캐싱 전략에서 Redis와 Caffeine을 함께 사용한 이유는? 둘 다 사용한 이유는 각각의 장점을 모두 활용하고 싶었습니다. 카페인은 내 서버 메모리에 저장되니까 빠르지만, 서버마다 다른 데이터를 가질 수 있고 Redis는 모든 서버가 공유하니까 데이터 일관성은 좋지만 네트워크를 거쳐야해서 상대적으로 느렸습니다.
그래서 자주 사용하는 데이터는 카페인 내부에서 가져오고, 없으면 Redis에서 찾고 거기서도 데이터가 없으면 데이터베이스에서 조회하는 단계별 방식을 사용했습니다.
대량 데이터 동기화에서 메모리 문제를 어떻게 해결했나요? 300명의 국회의원 데이터 동기화 시 메모리 부족과 타임아웃이 발생했습니다. 각 의원별 법안,이슈 데이터가 너무 방대해서 Async 병렬처리와 배치 처리를 10개씨 나누어 처리하니 처리 시간은 80퍼 이상 줄고 안정적으로 대량 데이터 처리가 되었고 메모리 사용량도 60퍼센트 감소했습니다
배치 처리 크기를 10개로 정한 기준은? 전체 300개를 처리하다 에러가 발생해서 너무 크면 안되니 적당한 크기로 10개를 선택했고 10개로 테스트하다보니 잘 동작하고 보기에도 편한거같아서 그대로 진행하게 되었습니다. 아무래도 일단 동작에 더 집중했지만 다음번에는 더 체계적인 성능 최적화를 고려할거같습니다.
AI 연동: OpenAI API 사용 시 비용은 어떻게 관리했나요? OpenAI API는 무료 크레딧 범위 내에서 사용했습니다. 학습 목적이고 프로젝트 자체가 큰 프로젝트는 아니였기에 초기 무료 크레딧으로 충분했습니다.
정치인의 발언 키워드 분석 및 감정 분석 정도의 기본적인 기능, 뉴스나 발언 데이터를 간단히 요약하고 분석하는 정도여서 과도한 API 호출보단 핵심 기능 검증에 집중했습니다.
AI 분석 결과의 정확도는 어떻게 검증했나요?
트러블슈팅:
15분에서 2분으로 단축한 구체적인 방법은? 순차처리에서 병렬 처리로 바뀌면서 시간이 대폭 단축되었습니다. @Async 비동기 병렬 처리와 배치 처리로 10개씩 나누어 여러 작업을 실행하고 트랜잭션 분리로 개별 트랜잭션으로 락 대기 시간을 제거했습니다.
트랜잭션 분리 시 데이터 일관성은 어떻게 보장했나요?