[장고] Google Maps API 키 안전하게 관리하기

카초·2023년 12월 24일
0
post-thumbnail

23.12.24
vscode / django / anaconda / window

  1. Django 프로젝트에서 Google Maps API 키를 index.html에 노출하지 않는 방법

문제 제기

클라우드 배포 연습을 목적으로 Django를 사용하여 웹 개발을 진행 중이다. 이때 구글 맵스(Google Maps) API 키와 같은 정보를 안전하게 관리하는 방법에 대한 고민이 생겼다. 현재 index.html에는 내 API 키가 하드코딩되어 있기 때문이다. 따라서 본 포스팅은 개인 API 키를 노출하지 않고 안전하게 관리하는 방법에 대해 다루도록 한다.

1차 문제 상황

Google Maps API 키가 클라이언트 측 코드(index.html)에 직접 포함되어 있어, 이를 서버에 배포할 때 보안상 문제가 발생할 수 있다고 한다. 이 키는 웹 페이지 Elements를 통해 바로 노출된다.

1차 해결 방향

  1. 환경 변수 사용: Django 프로젝트의 설정 파일에 API 키를 직접 쓰지 않고, 환경 변수를 통해 관리한다.

  2. 템플릿 변수 사용: Django의 템플릿 시스템을 이용해 서버에서 API 키를 동적으로 HTML에 삽입한다.

    그러나 이는 근본적인 해결책이 아니었다...
    elements에선 안보이는 것 같은데 소스코드에서 바로 보이기 때문...



구체적인 1차 해결 과정 (볼 필요 x)

1. 환경 변수 설정

  • .env 파일을 프로젝트 루트에 생성하고, 여기에 Google Maps API 키를 저장

    GOOGLE_MAPS_API_KEY=여기에_당신의_API_키

2. Django 설정 파일 수정

  • settings.py에서 dotenv를 사용하여 .env 파일에서 API 키를 불러오기.

    import os
    from dotenv import load_dotenv
    
    load_dotenv()  # 환경 변수 로드
    GOOGLE_MAPS_API_KEY = os.getenv('GOOGLE_MAPS_API_KEY')

    dotenv가 없다면 pip install python-dotenv을 해야 한다.

3. View 수정

  • views.py에서 settings.py의 변수를 불러와 템플릿으로 전달하기.

    from django.conf import settings
    from django.shortcuts import render
    from rest_framework.views import APIView
    
    class Main(APIView):
        def get(self, request):
            context = {'google_maps_api_key': settings.GOOGLE_MAPS_API_KEY}
            return render(request, "index.html", context)

    참고로 이 코드는 복붙해서 쓰시면 안 됩니다. 자기 코드에 맞게 쓰셔야 해요.
    요지는 변수를 쓸 view 위치에 API키 가져와야 한다는 겁니다.

4. HTML 템플릿 수정

  • index.html에서 해당 템플릿 변수를 사용하여 API 키를 삽입하기

          <div class="map_container">
            <div class="map-responsive">
              <iframe 
                src="https://www.google.com/maps/embed/v1/view?key={{ google_maps_api_key }}&center=37.651222229003906,127.01603698730469&zoom=16&maptype=roadmap" 
                width="600" 
                height="300" 
                frameborder="0" 
                style="border:0; width: 100%; height:100%" 
                allowfullscreen>
             </iframe>
            </div>
          </div>

5. manage.py 수정

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'aws_django.settings')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)


from dotenv import load_dotenv

if __name__ == '__main__':
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'aws_django.settings')
    
    # 환경 변수 로드
    load_dotenv()

    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)

중간 from dotenv import load_dotenv 줄부터 쓰시되,
'~.settings'의 ~는 자기 프젝으로 고치세요.



그렇다면 근본적인 해결책은 ?

  • 백엔드 프록시 사용: 클라이언트 대신 서버가 API 요청을 중계하기
  • API 키 제한 설정: Google Cloud Console에서 리퍼러, IP 주소 등에 대한 제한을 설정하기
  • API 키 사용량 모니터링: 정기적으로 사용량을 확인하여 비정상적인 활동을 감지하기

==> 아마 백엔드 프록시 엔드포인트 어쩌구 방식을 이용해야 하는 것 같다. 아직 지식이 짧고 경험이 없어서 이해가 안 된다. 어서 공부해가야지.

0개의 댓글