지난 해커톤에서 MSA 구조를 채택하여 구현하였을 때 발생했던 문제점과 해당 문제를 해결한 점에 대하여 설명하도록 하겠습니다.
해커톤에서 개발할 당시 MSA구조를 구현하기 위해서 MSA의 구조가 무엇인지와 Kafka에 대하여 공부를 진행하고 구현했습니다.
1. 데이터베이스와 서버를 분산시키면서 생기는 복잡성 문제
기존의 책에서 읽어보던 것처럼 간단하게 기능을 통해서 분리시키면 될거라고 생각했지만 아니었다.
또한 Spring Boot의 구조처럼 Repository를 관리하는 기능을 하는 마이크로서비스를 만들고 그 서버를 기반으로 비즈니스 로직만을 수행하는 Service서버를 구현해서 사용하면 될 것이라고 생각했으나 이는 서버를 수평적으로 분리시키는 잘못된 생각이었고 기능의 관점에서 수직으로 분리시켜야 했다.
모놀로식 구조가 아닌 마이크로서비스 구조를 채택함에 따라오는 복잡성을 예상하지 못했고 프로젝트를 진행하면서 많은 수정사항들이 있었으며 철저하게 잘 분리해야겠다고 생각했습니다.
2. Kafka의 사용
프로젝트를 진행하기 이전에는 Api Gateway 서버로 들어온 작업을 해당 기능에 맞게 카프카를 통하여 메시지를 처리하고 Api Gateway가 카프카의 토픽을 듣고 있다가 응답이 왔을 때 읽으면 된다고 생각했다.
하지만 이것은 잘못된 생각이었다.
Api Gateway는 들어온 HTTP 요청을 기능 마이크로서비스로 보내기 위해 카프카로 메시지를 전송하고 카프카를 통해서 들어온 응답을 다시 클라이언트에게 전송해야 했지만 카프카로 돌아온 메시지가 어떤 요청에대한 응답인지를 알 방법이 없었다.
그래서 우리는 Api Gateway에서 카프카로 메시지를 보낼 때 RequestID를 추가하여 Response의 RequestID와 같은지 체크를 하려고 하였으나 Api Gateway에서 카프카로 읽어온 메시지에 대한 버퍼링을 수행하지 않으면 먼저 들어온 요청들이 사라져 버리는 문제가있었다.
따라서 우리는 응답을 받기 위해서 Redis를 사용하였고 Api Gateway에서 요청이 카프카로 보내질 때 RequestID를 추가하고 해당 응답은 Redis 저장소의 Hash의 Key값으로 사용하여 요청-응답을 매칭시켜 사용하여 해결하였다.
하지만 이 방식이 올바른 방식인지는 아직 잘 모르겠다.
3. 리소스 낭비
Api Gateway에서 모든 API 요청을 받아서 kafka로 분산처리를 해주도록 설계하였기 때문에 Api Gateway는 하나의 요청을 처리하면서 응답이 돌아올 때까지(카프카를 이용하여 처리하고 레디스를 받아 응답하기 때문에 기존의 모놀로식 구조보다 통신이 오래 걸림) 기다릴 수 밖에 없었고 기다리면서 응답이 레디스로 돌아오면 바로 값을 가져와 클라이언트로 응답해주기 위해서 For문을 통해 지속적으로 Redis의 값이 Null이 아닐 때 까지 반복하였으나 별다른 해결 방안이 떠오르지 않았습니다.
4. 이미지 저장 문제
Api Gateway로 들어온 요청에 대해서 이미지를 저장하려 했으나 카프카를 이용한 메시지가 최대 1MB까지의 용량만 처리할 수 있는 문제가 있었습니다.
이를 위한 해결방안으로 카프카를 이용하지 않은 HTTP로 통신하는 이미지 저장 마이크로서비스를 구성하였고 이미지는 모두 해당 마이크로서비스에 저장되고 다른 기능의 서버에는 URL만 저장하여 해결하였습니다.
5. JSON 직렬화 문제
Kafka로 보내는 메시지는 JSON 메시지를 이용하였습니다.
자바 기반으로 동작하는 Spring Boot에서 직렬화된 JSON 파일은 Python 기반의 Django에서 받아서 사용할 때는 문제가 없었지만 Django에서 보내오는 JSON은 Spring Boot Jackson Library와의 구조와 달라 Exception이 발생하는 문제가 있었고 결국 이는 Django에서 해당 구조에 맞게 사람이 일일이 코딩하여 해결하였습니다.
Django에서 오는 JSON 파일에는 Java의 자료형에 대한 설명이 명시되어있지 않아 발생하는 문제였고 이는 아직도 정확하게 어떻게 해결하여야 하는 지 모른채 구현하였습니다.
6. 인증 및 인가 문제
클라이언트로 오는 메시지에 대해서 인증 및 인가처리를 하기 위해서 Api Gateway에 Spring Security를 사용하여 인증 인가처리를 진행하였습니다.
하지만 Api Gateway는 이름 그대로 Api를 해당 기능을 하는 서버로 매핑해주는 역할을 해야 한다고 생각했고 클라이언트와 맞닿아 있는 부분인 만큼 보안에 취약하다고 생각했지만 다른 방법을 찾지 못하였고 Api Gateway에서 토큰을 발급해서 클라이언트에게 전달하였습니다.
이번 프로젝트에서 MSA 구조를 이용하여 구현해보면서 MSA 구조에서 발생하는 복잡성이 생각보다 컸고 단일 프레임워크가 아닌 Django와 Spring Boot 두 가지 프레임워크를 사용하여 발생하는 호환성 문제 등 예상하지 못한 문제점들이 있었으나 결과적으로는 잘 해결하였다고 생각합니다.
구글링을 진행하면서 MSA에 관한 문제점들이 생각보다 찾을 수 없었고 저희와 동일한 문제가 발생했던 글은 정말 찾을 수가 없었습니다.
프로젝트 이후에 Spring Cloud라는 분산 구조를 만들기 위해서 제공하는 Dependency들에 대해서 알게되었고 이를 공부하면서 정확히 어떤식으로 MSA를 구현해야하는지 공부해볼 생각입니다.
'웹' 카테고리의 다른 글
Image 데이터를 RestTemplate로 통신하면서 발생한 에러 (0) | 2023.11.13 |
---|---|
Spring Cloud Eureka란? (0) | 2023.10.30 |
Spring Boot에서 보안을 위한 JWT를 발급하는 방법 (0) | 2023.10.27 |
JWT란? (0) | 2023.10.26 |
Spring Boot 이미지 받는 방법 (0) | 2023.09.18 |