본문 바로가기

python

python- OPEN API로 메이플 캐릭터 조회하기-2 [API 통신/python 에서 env/ 공통 service 만들기]

안녕하시렵니까?

저번에 python 설치하고 fastapi까지 설치랑 서버 접속까지 해봤는데 말입니다.

혹시 fastapi 설치랑 venv설정 방법 모르신다면 한번만 봐주시렵니까?

python- OPEN API로 메이플 캐릭터 조회하기-1

이번엔 이어서 nexon에서 test-api-key 발급받고 내 캐릭터 정보 가져오는것까지 한번 해보겠습니다.

https://openapi.nexon.com/ko/

 

NEXON Open API

NEXON Open API는 게임에서 제공하는 오픈 API 를 등록하고 관리하여 일반 사용자들에게 전달함으로써, 사용자들이 직접 게임 관련 애플리케이션을 제작할 수 있도록 도와주는 서비스입니다.

openapi.nexon.com

링크 들어가서 넥슨 아이디로 로그인 해줍니다. 그리고 게임은 메이플 선택, 개발단계선택 서비스명은 각자 센스껏 만들어 주시면 됩니다. 

그러고 마이페이지의 내 어플리케이션을 들어가보면

짜잔~! 메이플 정보를 마음껀 관음할 수 있는 열쇠를 획득하였습니다.

 

정신차리고 저번과 같은 방법으로 이번에 get_myMaple 이라는 프로젝트를 만들었습니다.

그럼 가장먼저 해야할일은 실제로 통신을 한번 해봐야 하지 않겠습니까?

1. Rest api 통신하기

/app/routes/character_route.py

위와 같은 경로에 route파일을 하나 만들어주고.

from fastapi import APIRouter

router = APIRouter()

@router.get("/maple/characters")
async def get_maple_characters():
	api_key = "abcdef"
    base_url = "base_url"
    async with httpx.AsyncClient() as client:
            res = await client.get(
                f"{base_url}/maplestory/v1/character/list",
                headers={"x-nxopen-api-key": api_key },
            )

        if res.is_error:
            raise HTTPException(status_code=res.status_code, detail=res.text)

        return res.json()

대충 이렇게 작성해보자. 그리고 main.py를 저렇게 만들고 실행 후 http://127.0.0.1:8000/docs 에 들어가면 테스트를 할 수있다.

( fastapi의 장점 swagger알아서 만들어줌ㄷㄷ;;)

from fastapi import FastAPI
from app.routes.character_routes import router as character_router

app = FastAPI()
app.include_router(character_router)


@app.get("/")
def read_root():
    return {"message": "Hello FastAPI!"}

통신 완료 

 

와우 그럼이제

https://openapi.nexon.com/ko/game/maplestory/?id=14

 

NEXON Open API | game

This is a list of the games provided by NEXON Open API.

openapi.nexon.com

여기 api리스트 들어가서 맘에 드는 API를 똑같이 다 만들고 git에 업로드하면 되겠다!

어딜 감히 저딴 코드를 그대로 git에 올렸다간 님 Api key 다 털리고 탈취하고 악용하고 난리남.

당연하게도 env에 저장해서 key git에 올리는 미련한 짓은 하지 말도록 하자. 

 

2. python에서 env 사용하기.

우선 루트 디렉토리에 .env 파일을 만들고 아래 처럼작성해보자.

NEXON_API_KEY=님 Api key
NEXON_BASE_URL=넥슨 base url

이후 dotenv 를 설치

pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()

main.py 에 저렇게 선언을 해주면 다른 파일에서 env 에 접근이 가능하다.

api_key = os.getenv("NEXON_API_KEY")
base_url = os.getenv("NEXON_BASE_URL")

이렇게 해야 님 api 키를 안전하게 저장 할 수있음

 

와 그럼이제 진짜 저렇게 해서 모든 API 통신 만들면 되겠다!!

어딜 감히. 그럼 똑같은 코드를 몇번이고 작성하겠단 소리?

위와 같은 코드를 반복하여 작성할경우

import os
from fastapi import APIRouter

router = APIRouter()

@router.get("/maple/characters")
async def get_maple_characters():

    api_key = os.getenv("NEXON_API_KEY")
    base_url = os.getenv("NEXON_BASE_URL")
    
    async with httpx.AsyncClient() as client:
            res = await client.get(
                f"{base_url}/maplestory/v1/character/list",
                headers={"x-nxopen-api-key": api_key },
            )

        if res.is_error:
            raise HTTPException(status_code=res.status_code, detail=res.text)

        return res.json()
        
        
@router.get("/maple/characters/{id}")
async def get_maple_characters(id:string):

    api_key = os.getenv("NEXON_API_KEY")
    base_url = os.getenv("NEXON_BASE_URL")
    
    async with httpx.AsyncClient() as client:
            res = await client.get(
                f"{base_url}/maplestory/v1/character/id",
                params={"ocid": id}
                headers={"x-nxopen-api-key": api_key },
            )

        if res.is_error:
            raise HTTPException(status_code=res.status_code, detail=res.text)

        return res.json()

이처럼 똑같은 코드가 동일하게 반복한다.

그냥 뒤에 end point와 param 이 두개만 다르고 나머지는 다 똑같은데. 굳이 반복 되는 코드를 작성해야하는가??

만약 저런 route가 100개 1000개 로 서비스가 확장했다. 

'x-nexon-api-key' 가 만약 'x-nexon-maple-api-key' 로 변경되었다고 해보자 그럼 1000개 모두 하나하나 일일이 수정할 것인가?

 

3. 공통 service 만들기

import os
import httpx
from fastapi import HTTPException

class NexonAPI:
    def __init__(self):
        self.api_key = os.getenv("NEXON_API_KEY")
        self.base_url = os.getenv("NEXON_BASE_URL")

        if not self.api_key:
            raise RuntimeError("NEXON_API_KEY is not configured")

        if not self.base_url:
            raise RuntimeError("NEXON_BASE_URL is not configured")

    async def get(self, path: str, params: dict | None = None):
        url = f"{self.base_url}{path}"

        async with httpx.AsyncClient() as client:
            res = await client.get(
                url,
                params=params,
                headers={"x-nxopen-api-key": self.api_key},
            )

        if res.is_error:
            raise HTTPException(status_code=res.status_code, detail=res.text)

        return res.json()

nexon api 클래스 만들어서 생성자 (__init__) 에서 api_key 와 base_url 미리 선언해주고

 

get method 에서 endpoint 와 params를 option으로 받고 모든 get api 통신 서비스에서 쓸 수 있도록 만들어 주었다.

이후 route 코드를 보면 획기적으로 줄어든 것을 확인 할 수있다.

@router.get("/maple/characters")
async def get_maple_characters():
    return await nexon.get("/maplestory/v1/character/list")


@router.get("/maple/character/id/{name}",tags=["character"])
async def get_character_id(name: str):
    return await nexon.get(
        "/maplestory/v1/id",
        params={"character_name": name}
    )

 

좋아 이러면 이제 진짜 메이플 모든 정보를 끌어올 수 있게 되었다.!!

내 github주소에서 코드 한번 참고해보면 좋을 거같다.

https://github.com/Choi-jae-min/get_myMaple