개발새발/웹

넥슨 API 사용해보기

YSW_dev 2024. 2. 8. 02:23

넥슨의 메이플스토리에서 유저들이 사용할 수 있는 API를 출시했습니다.

이것을 이용해서 간단한 인게임 정보를 불러오는 서버 기능을 만들어보려 합니다.

 

서버는 Django를 이용해서 만들어 보겠습니다.

Django 프로젝트를 한 개 만들고 api라는 이름의 앱을 생성해주었습니다.

 


 

구현

 

대부분의 API를 살펴보면, 인게임 캐릭터의 정보를 가져올땐 세 가지 정보가 필요합니다.

  • 사용자의 API
  • 조회할 캐릭터의 OCID
  • 조회할 날짜

 

API는 사용자로부터 입력받는다고 가정하고, 가장 최신의 정보를 자동으로 불러오기 위해 날짜는 바로 어제로 설정합니다. 그렇다면 필요한 것은 캐릭터 OCID입니다.

 

캐릭터 OCID를 우선 가져올 view를 한 개 만들어줍시다. 사용자로부터 받아야 할 정보는 API키와 캐릭터의 닉네임입니다.

 

BASE_URL = "https://open.api.nexon.com/maplestory/v1/"

def get_ocid_by_api(api, userName):
    headers = {
        "Content-Type": "application/json",
        "x-nxopen-api-key": api,
    }
    data = {"character_name": userName}

    response = get(BASE_URL + "id", data, headers=headers)

    try:
        return response.json()
    except:
        return {"Error": "Issue with request"}
#serializers.py
class userSerializer(serializers.Serializer):
    api = serializers.CharField(max_length=150)
    userName = serializers.CharField(max_length=20)

#views.py
class GetUserOcid(APIView):
    serializer_class = userSerializer

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            api = serializer.data.get("api")
            userName = serializer.data.get("userName")
            #요청으로부터 api와 닉네임을 추출

            response = get_ocid_by_api(api, userName)
            #ocid를 넥슨에 요청할 함수 호출
            
            return Response(response, status=status.HTTP_200_OK)
        return Response({"message": "error"}, status=status.HTTP_400_BAD_REQUEST)

 

함수를 구현하기에 앞서, 넥슨 api들의 엔드포인트는 모두 https://open.api.nexon.com/maplestory/v1/~ 로 구성이 된 것을 확인할 수 있습니다. 이를 BASE_URL이라는 이름으로 묶어 매 호출마다 사용하면 가독성이 좋아질 것 같네요.

 

 

api 요구사항을 보면 api키는 x-nxopen-api-key라는 이름으로 보내야 하며 헤더 부분에 위치시켜야 합니다. 반대로 캐릭터 명은 character_name이라는 이름으로 body에 위치시켜야 합니다.

 

 

OCID 다음에는 여러가지 정보를 가져올 호출용 함수를 만들어주면 됩니다.

 

def excute_maplestory_api(api, ocid, date, endpoint):
    headers = {
        "Content-Type": "application/json",
        "x-nxopen-api-key": api,
    }
    data = {"ocid": ocid, "date": date}

    response = get(BASE_URL + endpoint, data, headers=headers)
    #모든 요청은 GET이어야 한다.

    try:
        return response.json()
    except:
        return {"Error": "Issue with request"}
#serializers.py
class ocidSerializer(serializers.Serializer):
    api = serializers.CharField(max_length=150)
    ocid = serializers.CharField(max_length=64)
    
#views.py
class GetUserInfo(APIView):
    serializer_class = ocidSerializer

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            api = serializer.data.get("api")
            ocid = serializer.data.get("ocid")
            yesterday_str = get_yesterday()

            endpoint_list = {
                "character/basic",
                "character/popularity",
                "character/stat",
                ...
                #필요한 정보에 따라 추가
            }

            response = {}
            for endpoint in endpoint_list:
                response.update(
                    excute_maplestory_api(
                        api=api,
                        ocid=ocid,
                        date=yesterday_str,
                        endpoint=endpoint,
                    )
                )

            fin_response = {
                "character_level": response.get("character_level"),
                "stat": response.get("final_stat")[42].get("stat_value"),
                #stat의 42번째 항목인 전투력만 추출
                "popularity": response.get("popularity"),
                ...
            }

            return Response(fin_response, status=status.HTTP_200_OK)
        return Response({}, status=status.HTTP_400_BAD_REQUEST)

 

api가 요구하는 정보들이 모두 같기 때문에 endpoint_list를 이용하여 필요한 api호출을 쉽게 더하거나 뺄 수 있습니다.

 

이렇게 추출한 정보들을 바탕으로 여러가지 기능들을 만드는 것이 가능합니다.

 

마지막으로 urls을 이용하여 내 서버의 엔드포인트를 지정해주면 됩니다.

 

#프로젝트명/urls.py
urlpatterns = [
    path("api/", include("api.urls")),
]

#api/urls.py
urlpatterns = [
    path("get-ocid", GetUserOcid.as_view()),
    path("get-info", GetUserInfo.as_view()),
    ...
]

 

서버를 실행시켜 지정한 url에 접속해보면 post요청을 보내 테스트 해볼 수 있습니다.

 

stat은 전투력만 표시하도록 따로 추출했다

 

 

만약 바르지 않은 응답이 올 경우 넥슨 API 페이지에서 각 호출에 따른 가능한 응답들을 찾아볼 수 있는데,

거기에 내가 받아온 응답이 포함되어 있는지 살펴보고 아닐 경우엔 나의 코드를 의심해보면 됩니다.

 

주의할 점

 

특정 유저의 API가 있으면 그 유저의 캐릭터의 ocid만 조회되는 것이 아닌, 존재하는 모든 캐릭터의 ocid 조회가 가능합니다. 따라서 자신의 캐릭터 ocid만 조회할 수 있도록 구현하려면 별도의 인증 과정을 만들어야 합니다.

 

인증 과정도 API를 사용해서 만들려면, 대부분의 정보들은 모두 00시 이전의 정보만 반영되므로 사실상 실시간 인증이 불가능합니다.

 

딱 한 가지, 스타포스 강화 목록 조회만 실시간으로 가능하므로 이 부분을 고려해보는 것도 좋은 방법일 것 같습니다.