Hchanghyeon / dev-troubleshooting

개발하며 마주쳤던 크고 작은 문제들과 고민들
1 stars 0 forks source link

[비동기] 여러 개의 비동기 API 요청 처리 트러블 슈팅 #6

Open Hchanghyeon opened 8 months ago

Hchanghyeon commented 8 months ago

문제 상황

클라이언트의 페이지에 출력되는 데이터가, Spring 서버를 통해 게임사 서버로 여러 API를 요청하여 불러와서 하나로 모아 클라이언트로 보내주어야하는 상황입니다.

public void getMapleStoryMCharacterInfo(final String characterName, final String worldName) {
        final MultiValueMap<String, String> characterInformationParams = createRequestParams(characterName, worldName);
        final String ocid = mapleStoryMHttpClient.getCharacterOcid(characterInformationParams); // api 첫번째 요청

        final MultiValueMap<String, String> ocidParams = createRequestParams(ocid);
        final CharacterBasic characterBasic = mapleStoryMHttpClient.getCharacterBasic(ocidParams); // api 두번째 요청
        final CharacterItemEquipment characterItemEquipment = mapleStoryMHttpClient.getCharacterItemEquipment(
                ocidParams); // api 세번째 요청
}

그래서 저는 위와 같이 Spring 서버에서 다른 서버로 첫번째 요청부터 세번째 요청까지 별다른 설정을 하지 않고 HttpInterface를 이용하여 비동기로 요청해보았습니다.

Spring 서버에 해당 페이지에 필요한 API를 요청하게 되면 getMapleStoryMCharacterInfo라는 메서드가 실행되고, 해당 메서드를 통해 게임사의 서버로 각기 다른 3개의 API가 요청되어 응답을 받게 됩니다.

image

하지만 요청 후 위와 같은 에러가 발생되었습니다.

에러 분석

위 에러가 가르키고 있는 게임사 API 요청 주소는 getCharacterBasic(ocidParms)라는 메서드에서 요청하는 주소로, 첫번째 API가 아닌 두번째 API 요청에서 발생되고 있습니다. 그래서 첫번째 메서드가 동작하는 것에는 문제가 없다고 판단해서 아래와 같이 다시 동작시켜보았습니다.

public void getMapleStoryMCharacterInfo(final String characterName, final String worldName) {
        final MultiValueMap<String, String> characterInformationParams = createRequestParams(characterName, worldName);
        final String ocid = mapleStoryMHttpClient.getCharacterOcid(characterInformationParams); // api 첫번째 요청

        final MultiValueMap<String, String> ocidParams = createRequestParams("캐릭터 ocid를 직접 기입");
        final CharacterBasic characterBasic = mapleStoryMHttpClient.getCharacterBasic(ocidParams); // api 두번째 요청
        final CharacterItemEquipment characterItemEquipment = mapleStoryMHttpClient.getCharacterItemEquipment(
                ocidParams); // api 세번째 요청
}

제가 작성한 로직은 캐릭터의 이름과 캐릭터의 월드 이름을 받아서 우선 게임사 서버에 요청하여 게임 캐릭터의 고유 ID값인 ocid를 받아오고, ocid를 이용하여 캐릭터 정보와 캐릭터가 착용한 아이템 정보를 받기 위한 API를 요청하는 것입니다. 하지만 위와 같이 캐릭터의 ocid를 직접 기입해서 요청하는 순간 에러가 나지 않게 됩니다.

이로써 알 수 있는 것은 캐릭터의 ocid를 직접 기입하지 않고 캐릭터의 ocid를 받아 오는 api를 요청했을 때, 해당 API와 나머지 2개 API도 비동기로 동작되어 blocking을 하지 않아 발생하는 문제로 볼 수 있습니다.

3개의 API 요청 모두 연관이 없는 경우 정상적으로 비동기를 이용하여 동작했겠지만, 첫번째 캐릭터의 ocid를 받아와서 해당 정보로 나머지 2개의 API를 요청해야했기 때문에 정상적으로 작동하지 않았던 것입니다.