All In Auction 경매 서비스 프로젝트를 진행하며 발생한 문제와 이를 해결하기 위한 고민 및 해결 과정입니다.
이번 프로젝트는 모노리틱에서 MSA로 전환하며 경매(Auction) 서버와 포인트(Point) 서버를 분리한 구조로 설계되었습니다.
모노리틱 구조에서는 서버 간 호출이 필요하지 않아 비교적 빠르고 안정적인 처리 속도를 유지할 수 있었습니다. 하지만 MSA로 전환한 이후, 각 서버 간 호출을 위해 OpenFeign을 사용했고, 이를 기반으로 시나리오 테스트를 진행했습니다.
구분 | 표본 수 | 평균 (ms) | 최소값 (ms) | 최대값 (ms) | 표준편차 | 오류 % | 초당 요청 수 | 수신 KB/초 | 전송 KB/초 | 평균 바이트 수 |
---|---|---|---|---|---|---|---|---|---|---|
HTTP 요청 | 1000 | 8208 | 79 | 14911 | 3899.81 | 0.00% | 56.3/sec | 33.86 | 23.62 | 615.8 |
테스트 결과 평균 응답 시간은 8.2초로 확인되었습니다.
이는 사용자 경험에 치명적일 수 있는 결과이며, 유저 이탈 가능성이 높은 지연 속도였습니다.
문제 원인 가설
모노리틱 구조에서는 동일한 서버 내에서 처리가 이루어졌으나, MSA 구조에서는 서버 간 데이터 호출이 추가되었습니다.
따라서, 서버 간 통신 방식에 문제가 있을 가능성을 우선적으로 검토하였습니다.
원인 결론
OpenFeign의 설계 특성상 높은 동시 요청 처리에 적합하지 않은 방식으로 판단되었습니다.
특히, HTTP/1.1의 단일 요청-응답 처리 방식과 JSON 직렬화 오버헤드가 병목 현상을 야기한 주요 원인으로 보였습니다.
다음 두 가지 조건을 충족하는 방식을 우선적으로 고려하였습니다.
- 정산 관련 로직이므로 동기식 처리가 필요
- OpenFeign보다 빠른 성능이 보장될 것
gRPC 로 선정하게 되었고 도입 이유는 아래와 같습니다.
gRPC 도입은 크게
Proto 파일 정의, gRPC 환경 설정, 타 서버 호출 적용, 에러헨들링 , 성능 테스트,
다섯 단계로 나누어 진행하였습니다.
gRPC는 Proto 파일을 기반으로 서비스 인터페이스를 생성합니다. 이는 서버 간 호출 규격을 명확히 정의하며, 서버와 클라이언트 모두 이 규격을 구현합니다.
Proto 파일의 세부 내용은 아래 사진 참조:
gRPC는 서버와 클라이언트 간의 연결을 관리하는 채널 설정이 중요합니다. 여기서는 Eureka를 활용하여 서비스 디스커버리를 구현하고, 각 서버에서 포트와 채널을 구성했습니다.
@GrpcService
를 사용하여 gRPC 호출을 처리.환경 설정 관련 코드는 아래 사진 참조:
gRPC 환경 설정 이후, 실제 입찰 로직에서 gRPC 호출을 적용했습니다.
이는 기존 OpenFeign 호출을 대체하며, 경매 서버에서 포인트 서버로의 통신을 처리합니다.
AuctionService
호출.구현 코드의 세부 내용은 아래 사진 참조:
gRPC ErrorHandling 설정을 통해 gRPC 에서 StreamObserver 에서 발생한 에러를 출력할 수 있도록 설정하였으며, 예외 발생 시 트랜잭션 롤백을 통해 데이터 일관성을 유지할 수 있도록 하였습니다.
gRPC를 도입한 이후, 기존 OpenFeign 기반과 동일한 시나리오로 성능 테스트를 진행했습니다.
구분 | 표본 수 | 평균 (ms) | 최소값 (ms) | 최대값 (ms) | 표준편차 | 오류 % | 초당 요청 수 | 수신 KB/초 | 전송 KB/초 | 평균 바이트 수 |
---|---|---|---|---|---|---|---|---|---|---|
HTTP 요청 | 1000 | 4428 | 14 | 8169 | 2254.94 | 0.00% | 89.5/sec | 51.38 | 37.73 | 585.8 |
gRPC 도입은 서버 간 통신의 병목을 해소하고, 시스템 성능을 크게 향상시켰습니다.
특히, HTTP/2 기반의 멀티플렉싱과 Protocol Buffers의 직렬화 효율성이 대규모 트래픽 처리에 효과적이었습니다.
이번 도입 과정을 통해 MSA 환경에서 통신 방식 선택이 얼마나 중요한지 실감할 수 있었습니다. gRPC는 성능과 안정성을 모두 확보한 선택이었으며, 이후 확장 가능한 아키텍처의 기반이 되었습니다.
마지막으로, 대용량 트래픽 발생 시 4초 때의 시간이 걸리는 로직을 보다 개선할 점에 대해 파악 중이며 시도해볼 예정입니다.