오래걸리는 외부 API의 결과를 데이터베이스에 저장하는 기능을 개발해야한다면, 어떻게 구현해야할까?
내부 API는 30ms~100ms 내외의 응답속도를 보장해야하기도 해서, 큰부담없이 사용할수있겠지만,
외부에서 제공하는 API들은 기능에 따라서 길게는 수초에서 수십초가 걸리는 것도 있다.
(스크래핑, 대용량 데이터 응답(빅데이터 조회)등)
이경우 해당 응답을 데이터베이스에 저장을 해야하는 비즈니스 로직이 존재한다면,
어떻게 구현을 해야, 개발 잘했다고 소문이날까?!!
우리는 몇가지를 고려해야한다.
>>>
1) 외부API의 장애에 대한 처리가 있어야 한다.
- 외부API의 응답속도가 현저히 떨어지거나, 장애로 인해 접속에 문제가 있는경우는 지속적으로 외부API를 호출하지 않도록,
방어장치가 있어야 한다.
- 간단한 방법으로는, 서킷브레이커를 설정하고, connection, read timeout 설정을 하면 대응할수있을것 같다.
- 서킷브레이커를 사용하여, 장애가 난 경우, 호출을 중지하도록 하고, 이후에 샘플링 호출을 통해,
실제 장애복구가 되는시점에 다시 호출을 하도록 하면 해결가능하다.
- connection, read timeout설정을 적절히 하여, 연결, 응답에 많은 시간을 대기하지 않도록 설정하면 좋을것같다.
>>>
2) 외부API와 디비 트랜잭션 코드 블럭을 분리해야한다.
트랜잭션 코드 블록안에서 오래걸리는 외부 API호출 코드가 같이 존재하게 되면,
외부API의 오랜대기로 인해, 디비 커넥션을 장기간 점유하게 되고, 다수의 이런 케이스가 늘게 되면, 디비 커넥션이 고갈되게 된다.
- 디비 저장시 트랜잭션 필요여부를 파악하고, 트랜잭션이 필요없다면, 과감히 트랜잭션을 사용하지않는것이 좋고,
만약 롤백처리등을 위해서 사용을 해야한다면,
@Transactional 블록안에 외부API호출 코드를 포함하지 않도록 해야한다.
@Transactional 코드블록 바깥에서 외부API호출을 해서 결과를 인자로 전달하여, 저장하는 방법을 사용해야 안전하다.
>>>
3) 오래걸리는 외부 API호출을 서버에서 해야하는 기능은 별도로 Request Thread고갈을 방지하기위해, 별도 쓰레드 벌크해드 처리를 해야한다.
- Callable, DefferedResult, WebAsyncTask등의 방법을 통해, 톰캣 요청 쓰레드를 사용하지않고, 별도 쓰레드풀에서 동작하도록 하여, 톰캣 요청 쓰레드 고갈을 방지하도록 해야한다.
>>>
4) 버철 쓰레드 사용을 고려해 본다.
스프링부트 3.1버전 이상, 자바 21부터는
spring.threads.virtual.enabled=true
설정을 통해, 스프링부트의 쓰레드를 버철스레드로 사용하도록 설정할수있다.
ThreadLocal 사용을 많이 하지않는 서비스라고 하면, 설정하는것을 고려해 볼만하다.
(ThreadLocal을 적극정으로 사용하는 서비스는 메모리 증가의 문제가 발생가능함
- 대량의 가상스레드별 ThreadLocal이 생성되기때문에)
외부연동 API의 결과를 데이터베이스에 저장하는 비즈니스 로직의 흐름은 일반적으로 서비스 코드에서 많이 나오는 패턴이다.
하지만, API의 응답속도에 따라,
그 코드를 어떻게 구현해야하는지에 대해서는 간과하기 싶다.
이 부분의 문제는 실제 오픈하고, 트래픽이 몰릴때 발생하기에 선제적으로 고려하지않으면, 그 영향/피해가 상당히 크다.
항상, 대량 트래픽에 대한 처리에 대해서 간과하지 말자...
'MY개발생각' 카테고리의 다른 글
| [개발생각] 원팀이 무얼까? (0) | 2026.03.13 |
|---|---|
| [개발생각] Apache Camel에 대해서 (0) | 2026.03.10 |
| [개발생각] Kafka 이벤트와 트랜잭션에 대해서 (0) | 2026.03.04 |
| [개발생각] 우수한 개발 집단이란? (0) | 2026.03.04 |
| [개발생각] Webview앱 vs Native앱 (0) | 2026.03.03 |
