본문 바로가기

School/프로젝트 실습

프로젝트 실습 7주차 (2022. 05. 11. ~ 2022. 05. 17)

이번 주에는 AWS를 사용하여 서버를 배포하려고 했는데, 이것 저것 해보다 실패했다. 코드를 조금 더 수정하고 다시 올려봐야겠다.

 

 

  • 현재 개발 상황
    • Front-End
      sessionStroage에 토큰 존재 유무에 따른 라우터 변경 코드 작성
    • Back-End
      AWS RDS DB 연동 (이것으로 인해 서버 응답 시간 지연)
      Response Data Pagination 구현

 

아래는 이번주에 개발하면서 해결한 문제점이나 새롭게 알게 된 것을 적어보았다.

 

  • AWS RDS DB로 인한 서버 응답시간 지연
    이번 주에는 AWS에 서버를 배포하려고 이것저것 찾아보았다. 제일 먼저 DB먼저 AWS의 RDS에 연동을 하고 로컬에서 서버를 돌리면서 나머지 프론트 작업을 마무리하려고 했다.
    근데 프론트에서 서버로 요청을 보내면 응답 시간이 약 3초가량 걸리는 것을 보곤, '이게 왜 이렇게 오래 걸리는 걸까?' 하고 생각을 해보았다.
    친구들에게 물어보고 하면서 처음으로 얻은 답은 '내가 짠 코드에 불필요한 로직으로 인해 서버의 응답 시간이 지연된다.' 였다. 이걸 듣곤 로직 중에 DAuth와 통신하는 로직을 비동기로 처리하기로 마음먹었다. 몇 시간을 끙끙대며 비동기로 처리하고 다시 테스트를 해보니 똑같은 응답 시간이 나왔다.
    여기서 멘붕이 왔었다. 하나 하나 코드를 주석처리하면서 테스트를 해본 결과, DB에 저장하는 코드를 주석 처리하고 request를 날리니 약 400ms대의 응답 시간을 보여주었다. 내 로직이나 코드의 문제가 아닌 RDS의 문제였던 것이다.
    지금은 그냥 로컬 DB를 사용하고, 나중에 서버 배포를 할때 Docker로 배포를 하고, Docker에 MySQL을 깔아서 사용하기로 변경했다.
     
# 비동기 http 통신을 사용하기 전 코드
# view.py
@method_decorator(csrf_exempt, name='dispatch')
class GetDodamUser(APIView):
  def post(self, request):
    try:
      code = request.data['code']
      DAUTH_ID = os.environ.get('DAUTH_ID')
      DAUTH_SECRET = os.environ.get('DAUTH_SECRET')
    except (KeyError, ValueError, TypeError):
      if TypeError:
        return Response(
          status=status.HTTP_500_INTERNAL_SERVER_ERROR,
          data=CUSTOM_CODE(status=500, message='값을 가져오는 도중 문제가 생겼습니다.')
        )
      else:
        return Response(
          status=status.HTTP_400_BAD_REQUEST,
          data=BAD_REQUEST_400(message='Some Values are missing.')
        )

    loop = asyncio.new_event_loop()
    
    body = {
      'code': code,
      'client_id': DAUTH_ID,
      'client_secret': DAUTH_SECRET
    }
    
    try:
      response = requests.post(os.environ.get('DODAM_TOKEN_API'), data=body)
      dodam_token = response.json()['access_token']
    except (KeyError, ValueError):
      return Response(
        status=status.HTTP_400_BAD_REQUEST,
        data=CUSTOM_CODE(status=400, message='도담 서버 토큰을 가져오지 못했습니다.')
      )
    
		header = {
      'Authorization': 'Bearer ' + dodam_token
    }

    try:
      response = requests.get(os.environ.get('DODAM_USER_API'), headers=header)
      user_data = response.json()['data']
    except (KeyError, ValueError):
      return Response(
        status=status.HTTP_400_BAD_REQUEST,
        data=BAD_REQUEST_400(message='Some Values are missing.')
      )

    try:
      userModel = User.object.get(unique_id=user_data['uniqueId'])
    except ObjectDoesNotExist:
      userModel = User.object.create_user(
        username=user_data['name'],
        unique_id=user_data['uniqueId'],
        grade=user_data['grade'],
        room=user_data['room'],
        number=user_data['number'],
        profile_image=user_data['profileImage']
      )
      userModel.save()
    
    try:
      token = Token.objects.create(user=userModel)
    except IntegrityError:
      token = Token.objects.get(user=userModel)

    return Response(
      status=status.HTTP_200_OK,
      data=OK_200(message='도담의 유저 정보를 성공적으로 불러와 저장했습니다.', data={'token': token.key})
    )

 

# 비동기 http를 사용한 코드
# view.py
@method_decorator(csrf_exempt, name='dispatch')
class GetDodamUser(APIView):
  def post(self, request):
    try:
      code = request.data['code']
      DAUTH_ID = os.environ.get('DAUTH_ID')
      DAUTH_SECRET = os.environ.get('DAUTH_SECRET')
    except (KeyError, ValueError):
      return Response(
        status=status.HTTP_400_BAD_REQUEST,
        data=BAD_REQUEST_400(message='code가 존재하지 않습니다.')
      )

    loop = asyncio.new_event_loop()
    
    body = {
      'code': code,
      'client_id': DAUTH_ID,
      'client_secret': DAUTH_SECRET
    }
    
    try:
      dodam_token = loop.run_until_complete(get_dodam_token(body=body))
      token = dodam_token['access_token']
    except (KeyError, ValueError, TypeError):
      if TypeError:
        return Response(
          status=status.HTTP_403_FORBIDDEN,
          data=CUSTOM_CODE(status=403, message='위조된 코드입니다.')
        )
      else:
        return Response(
          status=status.HTTP_400_BAD_REQUEST,
          data=CUSTOM_CODE(status=400, message='도담 서버 토큰을 가져오지 못했습니다.')
        )
    
    header = {
      'Authorization': 'Bearer ' + token
    }

    try:
      user_data = loop.run_until_complete(get_dodam_user(header=header))
      user_data = user_data['data']
    except (KeyError, ValueError):
      return Response(
        status=status.HTTP_400_BAD_REQUEST,
        data=BAD_REQUEST_400(message='Some Values are missing.')
      )

    try:
      userModel = User.object.get(unique_id=user_data['uniqueId'])
    except ObjectDoesNotExist:
      userModel = User.object.create_user(
        username=user_data['name'],
        unique_id=user_data['uniqueId'],
        grade=user_data['grade'],
        room=user_data['room'],
        number=user_data['number'],
        profile_image=user_data['profileImage']
      )
      userModel.save()
    
    try:
      token = Token.objects.create(user=userModel)
    except IntegrityError:
      token = Token.objects.get(user=userModel)

    return Response(
      status=status.HTTP_200_OK,
      data=OK_200(message='도담의 유저 정보를 성공적으로 불러와 저장했습니다.', data={'token': token.key})
    )

# get_dodam_token.py
import os
import aiohttp

async def get_dodam_token(body):
  async with aiohttp.ClientSession() as sess:
    async with sess.post(os.environ.get('DODAM_TOKEN_API'), data=body) as res:
      return await res.json()

# get_dodam_user.py
import os
import aiohttp

async def get_dodam_user(header):
  async with aiohttp.ClientSession() as sess:
    async with sess.get(os.environ.get('DODAM_USER_API'), headers=header) as res:
      return await res.json()