다음을 통해 공유


Python 및 pyodbc 드라이버를 사용하여 Azure SQL 데이터베이스에 대한 연결 및 쿼리하기

적용 대상: Azure SQL 데이터베이스

이 빠른 시작에서는 애플리케이션을 Azure SQL 데이터베이스 데이터베이스에 연결하고 Python 및 Python SQL 드라이버 - pyodbc를 사용하여 연결하고 쿼리하는 방법을 설명합니다. 이 빠른 시작은 데이터베이스에 연결하는 데 권장되는 암호 없는 방법을 사용합니다. 암호 없는 허브의 암호 없는 연결에 대해 자세히 알아 보세요.

필수 조건

데이터베이스 구성

Azure SQL 데이터베이스에 대한 암호 없는 보안 연결에는 특정 데이터베이스 구성이 필요합니다. 로컬 및 호스팅된 환경 모두에서 Azure SQL 데이터베이스에 제대로 연결하려면 Azure의 논리 서버에서 다음 설정을 확인합니다.

  1. 로컬 개발 연결의 경우 논리 서버가 로컬 컴퓨터 IP 주소 및 기타 Azure 서비스에 연결할 수 있도록 구성되어 있는지 확인합니다.

    • 서버의 네트워킹 페이지로 이동합니다.

    • 선택한 네트워크 라디오 버튼을 눌러 추가 구성 옵션을 표시합니다.

    • 클라이언트 IPv4 주소 추가(xx.xx.xx.xx.xx)를 선택하여 로컬 컴퓨터 IPv4 주소에서 연결을 활성화하는 방화벽 규칙을 추가합니다. 또는 + 방화벽 규칙 추가를 선택하여 원하는 특정 IP 주소를 입력할 수도 있습니다.

    • Azure 서비스 및 리소스의 서버 액세스 허용 확인란을 선택합니다.

      방화벽 규칙을 구성하는 방법을 보여 주는 스크린샷.

      경고

      프로덕션 시나리오에는 Azure 서비스 및 리소스의 서버 액세스 허용을 보안상 권장하지 않습니다. 실제 애플리케이션에는 더 강력한 방화벽 제한 또는 가상 네트워크 구성과 같은 보다 강력한 보안 접근 방식을 적용해야 합니다.

      다음 리소스에서 데이터베이스 보안 구성에 대해 자세히 알아 보세요.

  2. 또한 서버에는 Microsoft Entra 인증이 활성화 되어 있어야 하며 Microsoft Entra 관리자 계정이 할당되어 있어야 합니다. 로컬 개발 연결의 경우, Microsoft Entra 관리자 계정은 로컬로 Visual Studio 또는 Azure CLI에 로그인할 수도 있는 계정이어야 합니다. 서버의 Microsoft Entra 인증이 활성화 여부는 논리 서버의 Microsoft Entra ID 페이지에서 확인할 수 있습니다.

    Microsoft Entra 인증을 활성화하는 방법을 보여 주는 스크린샷.

  3. 개인 Azure 계정을 사용하는 경우, 계정을 서버 관리자로 할당하기 위해 Azure SQL 데이터베이스에 Microsoft Entra를 설정 및 구성했는지 확인해야 합니다. 회사 계정을 사용하는 경우, Microsoft Entra ID가 이미 구성되어 있을 수 있습니다.

프로젝트를 만듭니다.

Visual Studio를 사용하여 새 Python 프로젝트를 만듭니다.

  1. Visual Studio Code를 열고 프로젝트를 만들 새 폴더를 만들고 디렉터리를 변경합니다.

    mkdir python-sql-azure
    cd python-sql-azure
    
  2. 앱을 만들 가상 환경을 만듭니다.

    py -m venv .venv
    .venv\scripts\activate
    
  3. app.py(이)라는 새 파일을 만듭니다.

pyodbc 드라이버를 설치합니다.

Python을 사용하여 Azure SQL 데이터베이스에 연결하려면 pyodbc 드라이버를 설치합니다. 이 패키지는 데이터베이스 연결에서 명령을 실행하고 결과를 검색하며 데이터 공급자 역할을 수행합니다. 이 빠른 시작에서는 API를 만들고 실행하는 flask, uvicorn, pydantic 패키지를 설치합니다.

각 운영 체제에 pyodbc 드라이버를 설치하기 위한 자세한 내용 및 구체적인 지침은 pyodbc Python 개발을 위한 개발 환경 구성을 참조하세요.

  1. 다음을 사용하여 requirements.txt 파일을 만듭니다.

    pyodbc
    fastapi
    uvicorn[standard]
    pydantic
    azure-identity
    
  2. 요구 사항을 설치합니다.

    pip install -r requirements.txt
    

로컬 연결 문자열 구성

로컬 개발 및 Azure SQL 데이터베이스에 연결하려면 다음 AZURE_SQL_CONNECTIONSTRING 환경 변수를 추가합니다. <database-server-name><database-name> 자리 표시자를 고유한 값으로 바꿉니다. Bash 셸에 대한 환경 변수 예시가 표시됩니다.

대화형 인증은 로컬로 실행할 때 암호 없는 옵션을 제공합니다.

Windows에서 Microsoft Entra Interactive Authentication은 Microsoft Entra 다단계 인증 기술을 사용하여 연결을 설정합니다. 이 모드에서 로그인 ID를 제공하면 Azure Authentication 대화 상자가 트리거되고 사용자가 암호를 입력하여 연결을 완료할 수 있습니다.

export AZURE_SQL_CONNECTIONSTRING='Driver={ODBC Driver 18 for SQL Server};Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30'

자세한 내용은 ODBC 드라이버와 Microsoft Entra ID 사용을 참조하세요. 이 옵션을 사용하는 경우 자격 증명을 묻는 창로 이동하세요.

Azure 포털에서 연결 문자열을 만드는데 필요한 세부 정보는 다음 단계를 통해 확인할 수 있습니다.

  1. Azure SQL Server로 이동하여 SQL 데이터베이스 페이지를 선택하여 데이터베이스 이름을 찾은 다음 데이터베이스를 선택합니다.

  2. 데이터베이스에서 연결 문자열 페이지로 이동하여 연결 문자열 정보를 가져옵니다. ODBC 탭을 찾습니다.

참고 사항

Azure Arc를 설치하고 Azure 구독과 연결한 경우, App Service에 배포된 앱에 사용하는 관리 ID 접근 방식을 사용할 수도 있습니다.

Azure SQL 데이터베이스에 코드 추가하여 연결하기

프로젝트 폴더에서 app.py 파일을 만들고 샘플 코드를 추가합니다. 이 코드는 다음과 같은 API를 만듭니다.

  • 환경 변수에서 Azure SQL 데이터베이스 연결 문자열 검색합니다.
  • 시작하는 동안 데이터베이스에 Persons 테이블을 만듭니다(테스트 시나리오에만 해당).
  • 데이터베이스에서 모든 Person 레코드를 검색하는 함수를 정의합니다.
  • 데이터베이스에서 하나의 Person 레코드를 검색하는 함수를 정의합니다.
  • 데이터베이스에 새 Person 레코드를 추가하는 함수를 정의합니다.
import os
import pyodbc, struct
from azure import identity

from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel

class Person(BaseModel):
    first_name: str
    last_name: Union[str, None] = None
    
connection_string = os.environ["AZURE_SQL_CONNECTIONSTRING"]

app = FastAPI()

@app.get("/")
def root():
    print("Root of Person API")
    try:
        conn = get_conn()
        cursor = conn.cursor()

        # Table should be created ahead of time in production app.
        cursor.execute("""
            CREATE TABLE Persons (
                ID int NOT NULL PRIMARY KEY IDENTITY,
                FirstName varchar(255),
                LastName varchar(255)
            );
        """)

        conn.commit()
    except Exception as e:
        # Table may already exist
        print(e)
    return "Person API"

@app.get("/all")
def get_persons():
    rows = []
    with get_conn() as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM Persons")

        for row in cursor.fetchall():
            print(row.FirstName, row.LastName)
            rows.append(f"{row.ID}, {row.FirstName}, {row.LastName}")
    return rows

@app.get("/person/{person_id}")
def get_person(person_id: int):
    with get_conn() as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM Persons WHERE ID = ?", person_id)

        row = cursor.fetchone()
        return f"{row.ID}, {row.FirstName}, {row.LastName}"

@app.post("/person")
def create_person(item: Person):
    with get_conn() as conn:
        cursor = conn.cursor()
        cursor.execute(f"INSERT INTO Persons (FirstName, LastName) VALUES (?, ?)", item.first_name, item.last_name)
        conn.commit()

    return item

def get_conn():
    credential = identity.DefaultAzureCredential(exclude_interactive_browser_credential=False)
    token_bytes = credential.get_token("https://database.windows.net/.default").token.encode("UTF-16-LE")
    token_struct = struct.pack(f'<I{len(token_bytes)}s', len(token_bytes), token_bytes)
    SQL_COPT_SS_ACCESS_TOKEN = 1256  # This connection option is defined by microsoft in msodbcsql.h
    conn = pyodbc.connect(connection_string, attrs_before={SQL_COPT_SS_ACCESS_TOKEN: token_struct})
    return conn

경고

샘플 코드는 프로덕션 코드에서 사용하면 안 되는 원시 SQL 문을 보여 줍니다. 이러한 SQL 문 대신 보다 안전한 개체 계층을 생성하는 SqlAlchemy와 같은 ORM(개체 관계형 매퍼) 패키지를 사용하여 데이터베이스에 액세스하세요.

로컬 앱 실행 및 테스트

이제 앱을 로컬로 테스트할 준비가 완료되었습니다.

  1. Visual Studio Code에서 app.py 파일을 엽니다.

    uvicorn app:app --reload
    
  2. http://127.0.0.1:8000/docs 앱의 Swagger UI 페이지에서 POST 메서드를 확장하고 시도를 선택합니다.

    try /redoc을 사용하여 API에 대해 생성된 다른 형태의 설명서를 확인할 수도 있습니다.

  3. 이름과 성의 값을 포함하도록 샘플 JSON을 수정합니다. 실행을 선택하여 데이터베이스에 새 기록을 추가합니다. API는 성공적인 응답을 반환합니다.

  4. Swagger UI 페이지에서 GET 메서드를 확장하고 시도를 선택합니다. 실행을 선택하면 방금 만든 사람이 반환됩니다.

Azure App Service에 배포

Azure에 앱을 배포할 준비가 완료되었습니다.

  1. Azure App Service의 gunicorn이 uvicorn을 실행할 수 있도록 start.sh 파일을 만듭니다. start.sh는 한 줄입니다.

    gunicorn -w 4 -k uvicorn.workers.UvicornWorker app:app
    
  2. az webapp up을 사용하여 App Service에 코드를 배포합니다. (-dryrun 옵션을 사용하면 리소스를 만들지 않고 명령이 수행하는 작업을 확인할 수 있습니다.)

    az webapp up \
        --resource-group <resource-group-name> \
        --name <web-app-name>         
    
  3. az webapp config set 명령을 사용하여 start.sh 파일을 사용하도록 App Service를 구성합니다.

    az webapp config set \
        --resource-group <resource-group-name> \
        --name <web-app-name> \
        --startup-file start.sh
    
  4. az webapp identity assign 명령을 사용하여 App Service의 시스템 할당 관리 ID를 사용하도록 설정합니다.

    az webapp identity assign \
        --resource-group <resource-group-name> \
        --name <web-app-name>
    

    이 빠른 시작에서는 시스템 할당 관리 ID를 사용하여 설명합니다. 사용자 할당 관리 ID는 광범위한 시나리오에서 더 효율적입니다. 관리 ID 모범 사례 권장 사항에서 더 자세히 알아 보세요. pyodbc에서 사용자 할당 관리 ID를 사용하는 예시는 암호 없는 연결 사용을 위해 Azure SQL 데이터베이스로 Python 애플리케이션 마이그레이션하기를 참조하세요.

Azure SQL Server Database에 App Service 연결

데이터베이스 구성 섹션에서 Azure SQL 데이터베이스 서버의 네트워킹 및 Microsoft Entra 인증을 구성했습니다. 이 섹션에서는 데이터베이스 구성을 완료하고 연결 문자열을 사용하여 App Service를 구성하여 데이터베이스 서버에 액세스합니다.

SSMS(SQL Server Management Studio), Azure Data StudioVisual Studio Code를 포함하여 Azure SQL 데이터베이스에 연결할 수 있는 모든 도구 또는 IDE와 SQL Server mssql 익스텐션을 사용하여 이러한 명령을 실행할 수 있습니다. 또한 빠른 시작: Azure 포털 쿼리 편집기를 통한 Azure SQL 데이터베이스 쿼리를 사용할 수도 있습니다.

  1. SQL 명령을 사용하여 Azure SQL 데이터베이스에 사용자를 추가하여 암호 없는 액세스에 대한 사용자 및 역할을 만듭니다.

    CREATE USER [<web-app-name>] FROM EXTERNAL PROVIDER
    ALTER ROLE db_datareader ADD MEMBER [<web-app-name>]
    ALTER ROLE db_datawriter ADD MEMBER [<web-app-name>]
    

    자세한 내용은 포함된 데이터베이스 사용자 - 데이터베이스를 이식 가능하게 만들기를 참조하세요. 동일한 원칙에 대한 Azure VM 적용 예시는 자습서: Windows VM 시스템 할당 관리 ID를 사용하여 Azure SQL에 액세스하는 방법을 참조하세요. 할당된 역할에 대한 자세한 내용은 고정 데이터베이스 역할을 참조하세요.

    App Service 시스템 할당 관리 ID를 비활성화했다가 다시 활성화한 경우, 사용자를 삭제하고 다시 만듭니다. DROP USER [<web-app-name>](을)를 명령을 실행하고 CREATEALTER 명령을 다시 실행합니다. 사용자를 보려면 SELECT * FROM sys.database_principals(을)를 사용합니다.

  2. az webapp config appsettings set 명령을 사용하여 연결 문자열에 대한 앱 설정을 추가합니다.

    az webapp config appsettings set \
        --resource-group <resource-group-name> \
        --name <web-app-name> \
        --settings AZURE_SQL_CONNECTIONSTRING="<connection-string>"
    

    배포된 앱의 경우 연결 문자열은 다음과 유사해야 합니다.

    Driver={ODBC Driver 18 for SQL Server};Server=tcp:<database-server-name>.database.windows.net,1433;Database=<database-name>;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30
    

    <dabaser-server-name><database-name>에 값을 입력합니다.

    암호 없는 연결 문자열은 사용자 이름 또는 암호를 포함하지 않습니다. 대신 앱이 Azure에서 실행되면 코드는 DefaultAzureCredential(을)를 사용하여 Azure ID 라이브러리에서 pyodbc와(과) 사용할 토큰을 가져옵니다.

배포된 애플리케이션 테스트

앱 URL로 이동하여 Azure SQL 데이터베이스 연결이 작동하는지 테스트합니다. 앱 URL는 App Service 개요 페이지에서 찾을 수 있습니다.

https://<web-app-name>.azurewebsites.net

URL에 /docs를 추가하여 Swagger UI를 확인하고 API 메서드를 테스트합니다.

축하합니다! 이제 애플리케이션이 로컬 및 호스팅된 환경 모두에서 Azure SQL 데이터베이스에 연결되었습니다.