FastAPI 서버개발, OAuth2와 JWT를 사용한 애플리케이션 보안

현대 웹 애플리케이션은 다양한 보안 위협에 노출되어 있으며, 사용자 인증 및 권한 부여는 이러한 위협으로부터 애플리케이션을 보호하는 데 필수적입니다. 본 블로그에서는 FastAPI를 사용하여 OAuth2 프로토콜과 JWT(JSON Web Token)를 통한 인증 및 권한 부여 시스템을 구축하는 방법을 자세히 설명하겠습니다. 이 글을 통해 독자들은 FastAPI로 안전한 애플리케이션을 개발하는 데 필요한 지식을 습득할 수 있을 것입니다.

1. FastAPI 소개

FastAPI는 Python으로 작성된 최신 웹 프레임워크로, 매우 빠르고 현대적인 API를 개발하기 위해 설계되었습니다. FastAPI는 다음과 같은 주요 특징을 가지고 있습니다:

  • 높은 성능: FastAPI는 Starlette를 기반으로 하여 비동기 처리를 최적화하고, Uvicorn 등의 비동기 서버와 함께 사용할 수 있습니다.
  • 자동 문서화: FastAPI는 OpenAPI 및 JSON Schema를 지원하여 문서화를 자동으로 생성할 수 있습니다.
  • 쉬운 사용: 간단한 코드로 복잡한 API를 구축할 수 있습니다.

1.1 FastAPI 설치

FastAPI를 사용하려면 먼저 FastAPI와 Uvicorn을 설치해야 합니다. 다음 명령어를 사용하여 설치할 수 있습니다:

pip install fastapi uvicorn

2. OAuth2와 JWT 개요

OAuth2는 사용자가 제3자 애플리케이션에 대한 접근을 제어할 수 있도록 해주는 권한 부여 프레임워크입니다. JWT는 인증 정보를 안전하게 전송하기 위해 정보의 전자 서명된 JSON 객체입니다. 이 두 기술을 결합하면 안전하고 신뢰할 수 있는 인증 시스템을 구축할 수 있습니다.

2.1 OAuth2 흐름

OAuth2는 다음과 같은 흐름을 따릅니다:

  1. 사용자가 클라이언트 애플리케이션에서 로그인 요청을 합니다.
  2. 클라이언트 애플리케이션은 인증 서버에 사용자 인증을 요청합니다.
  3. 인증 서버는 사용자 자격 증명을 검증한 후, 클라이언트에 액세스 토큰과 갱신 토큰을 발급합니다.
  4. 클라이언트는 API 요청 시 이 액세스 토큰을 사용하여 보호된 리소스에 접근합니다.

2.2 JWT 구조

JWT는 세 부분으로 구성됩니다:

  • Header: 토큰의 타입과 서명 알고리즘 정보를 포함합니다.
  • Payload: 사용자 정보와 같은 클레임(Claims)를 포함합니다.
  • Signature: Header와 Payload를 인코딩하여 비밀 키로 서명한 값입니다.

3. FastAPI에서 OAuth2와 JWT 구현하기

이제 FastAPI를 사용하여 OAuth2와 JWT를 통한 인증 시스템을 구현해 보겠습니다. 이를 위해 기본적인 FastAPI 애플리케이션을 설정하고, OAuth2와 JWT 로직을 추가하겠습니다.

3.1 FastAPI 애플리케이션 기본 설정


from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello": "World"}

위 코드는 FastAPI 애플리케이션의 기본 구조입니다. 이제 이 앱에 OAuth2와 JWT를 구현할 것입니다.

3.2 사용자 모델 및 데이터베이스 설정


from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from passlib.context import CryptContext
from typing import Optional
from datetime import datetime, timedelta
import jwt

# 사용자 데이터베이스 시뮬레이션
fake_users_db = {
    "user@example.com": {
        "username": "johndoe",
        "full_name": "John Doe",
        "email": "user@example.com",
        "hashed_password": "$2b$12$KIXyhuOfCJcZawGBY5frXOCeC7g0BU6oq/6kyPzA/9eT4M1Og1Wiy",  # 비밀번호: secret
        "disabled": False,
    }
}

# 유효성 검사 및 해싱 암호화
class User(BaseModel):
    username: str
    full_name: Optional[str] = None
    email: str
    disabled: Optional[bool] = None

class UserInDB(User):
    hashed_password: str

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_user(db, email: str):
    if email in db:
        user_data = db[email]
        return UserInDB(**user_data)

# OAuth2PasswordBearer 설정
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

3.3 사용자 인증


def authenticate_user(db, email: str, password: str):
    user = get_user(db, email)
    if not user or not verify_password(password, user.hashed_password):
        return False
    return user

# JWT 생성
SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=15)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt

3.4 토큰 경로 추가


@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
    user = authenticate_user(fake_users_db, form_data.username, form_data.password)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="잘못된 사용자 이름 또는 비밀번호",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(
        data={"sub": user.email}, expires_delta=access_token_expires
    )
    return {"access_token": access_token, "token_type": "bearer"}

3.5 보호된 경로 추가


@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="유효하지 않은 토큰",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        email: str = payload.get("sub")
        if email is None:
            raise credentials_exception
    except jwt.PyJWTError:
        raise credentials_exception
    user = get_user(fake_users_db, email)
    if user is None:
        raise credentials_exception
    return user

3.6 애플리케이션 실행

모든 설정이 완료되었으면 FastAPI 서버를 실행할 수 있습니다. 아래 명령어를 사용하여 서버를 실행하십시오:

uvicorn main:app --reload

이제 브라우저를 통해 http://127.0.0.1:8000/docs에 접속하여 API 명세를 확인하고, Swagger UI를 통해 API를 테스트할 수 있습니다.

4. 결론

FastAPI와 함께 OAuth2 및 JWT를 사용하여 애플리케이션의 인증 및 권한 부여 시스템을 구현하는 방법을 살펴보았습니다. 이 강좌를 통해 기본적인 사용자 인증 로직을 이해하고 FastAPI에서 어떻게 구현할 수 있는지를 배울 수 있었습니다. 실제 환경에서는 보다 복잡한 요구 사항이 있을 수 있으므로, 추가적인 보안 조치(예: SSL/TLS 암호화, 비밀 키 관리 등)를 고려하는 것이 중요합니다. FastAPI를 사용하여 더 안전하고 강력한 백엔드 애플리케이션을 구축하시길 바랍니다.

FastAPI 서버개발, 보안, FastAPI의 인증 방식

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 뛰어난 성능과 직관적인 문법으로 인기를 끌고 있습니다. 이 글에서는 FastAPI를 사용하여 서버를 개발하는 방법, 보안의 중요성, 그리고 다양한 인증 방법에 대해 자세히 설명하겠습니다.

1. FastAPI 개요

FastAPI는 RESTful API를 빠르게 구축하기 위한 프레임워크입니다. Python의 타입 힌트를 활용하여 코드의 가독성과 유효성을 높이면서, 자동으로 API 문서를 생성하는 기능을 제공합니다. FastAPI는 Starlette와 Pydantic을 기반으로 하여 높은 성능과 데이터 검증 기능을 함께 제공합니다.

2. FastAPI의 설치와 기본 설정

FastAPI와 함께 Uvicorn ASGI 서버를 설치해야 합니다. 다음과 같은 명령어를 사용하여 설치할 수 있습니다:

pip install fastapi uvicorn

2.1 Hello World 예제

FastAPI의 기본적인 구조를 이해하기 위해 간단한 Hello World API를 만들어보겠습니다.


from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"Hello": "World"}
    

위의 코드를 main.py 파일로 저장한 뒤, 다음 명령어로 서버를 실행할 수 있습니다:

uvicorn main:app --reload

이제 브라우저에서 http://127.0.0.1:8000를 열면 “Hello, World” JSON 응답을 확인할 수 있습니다.

3. 서버 보안의 중요성

소프트웨어 개발에서 보안은 매우 중요한 요소입니다. 특히, API를 통해 데이터와 기능에 접근하게 될 경우, 보안이 취약하다면 해킹의 위험성이 높아집니다. FastAPI를 사용할 때는 다음과 같은 보안 요소를 고려해야 합니다:

  • 데이터 암호화
  • 사용자 인증 및 권한 부여
  • 입력 데이터 검증
  • 로그 기록 및 모니터링

4. FastAPI의 인증 방식

FastAPI는 다양한 인증 방식을 지원합니다. 그 중에서 가장 일반적인 방식은 JWT 토큰 인증과 OAuth2입니다. 이번 섹션에서는 JWT 인증 방식을 중심으로 설명하겠습니다.

4.1 JWT( JSON Web Token) 인증

JWT는 두 개의 엔드포인트(로그인과 인증된 사용자 확인)를 통해 사용됩니다. 사용자 정보를 안전하게 저장하고 전달하는 방법 중 하나입니다. JWT 웹 토큰은 주로 사용자 인증 및 정보 교환에 사용되며, 다음과 같은 구조를 가집니다:

  • Header: 토큰의 유형과 서명 알고리즘을 정의합니다.
  • Payload: 사용자 정보나 기타 데이터를 포함합니다.
  • Signature: Header와 Payload를 인코딩하여 비밀 키로 서명한 값입니다.

4.2 FastAPI로 JWT 인증 구현하기

FastAPI에서 JWT 인증을 구현하는 방법은 다음과 같습니다:

4.2.1 필요한 라이브러리 설치

JWT를 사용하기 위해서는 PyJWT와 passlib를 설치해야 합니다. 아래 명령어로 설치할 수 있습니다:

pip install pyjwt passlib[bcrypt]

4.2.2 JWT 유틸리티 함수

토큰 생성 및 검증을 위한 헬퍼 함수를 작성합니다.


import jwt
from datetime import datetime, timedelta
from typing import Dict

SECRET_KEY = "your_secret_key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt
    

4.2.3 FastAPI 사용자 모델

사용자 모델을 작성하고, 인증을 위한 엔드포인트를 추가합니다.


from fastapi import FastAPI, Depends, HTTPException
from passlib.context import CryptContext

app = FastAPI()

class User:
    def __init__(self, username: str, password: str):
        self.username = username
        self.password = password

fake_users_db = {
    "johndoe": User(username="johndoe", password="$2b$12$KIXT8j/Nu1H3VzOZL5rO.ulpYb/JgVdY2VZ5ZFkElXju2GZBeY1Fe")
}

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

def verify_password(plain_password, hashed_password):
    return pwd_context.verify(plain_password, hashed_password)

def get_user(db, username: str):
    if username in db:
        return db[username]
    return None

@app.post("/token")
async def login(username: str, password: str):
    user = get_user(fake_users_db, username)
    if not user or not verify_password(password, user.password):
        raise HTTPException(
            status_code=401,
            detail="Incorrect username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    access_token = create_access_token(data={"sub": user.username}, expires_delta=access_token_expires)
    return {"access_token": access_token, "token_type": "bearer"}
    

4.2.4 보호된 엔드포인트 생성

인증된 사용자만 접근할 수 있는 보호된 엔드포인트를 추가합니다.


from fastapi import Security
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

@app.get("/users/me")
async def read_users_me(token: str = Depends(oauth2_scheme)):
    credentials_exception = HTTPException(
        status_code=401,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )
    try:
        payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
        username: str = payload.get("sub")
        if username is None:
            raise credentials_exception
    except jwt.PyJWTError:
        raise credentials_exception
    return {"username": username}
    

5. 결론

FastAPI는 높은 성능과 가독성을 제공하는 훌륭한 웹 프레임워크입니다. 보안은 애플리케이션 개발에 있어 중요한 요소로, JWT 인증은 사용자 인증을 안전하게 수행할 수 있는 방법 중 하나입니다. 이번 글에서 рассмотрены(JWT) 인증 구현 방법을 통해 FastAPI의 발전 가능성과 효율성을 알 수 있는 기회가 되었기를 바랍니다.

FastAPI와 관련하여 더 많은 자료를 참고하시려면 FastAPI 공식 문서를 참조하시기 바랍니다.

FastAPI 서버개발, AWS 배포의 개요

최근 몇 년간 웹 애플리케이션 개발은 급속도로 발전해왔고, 그중에서도 Python을 기반으로 한 웹 프레임워크들은 주목을 받고 있습니다. 특히, FastAPI는 Python의 비동기 기능을 활용하여 뛰어난 성능과 쉽고 간결한 문법을 제공하여 많은 개발자들 사이에서 인기를 끌고 있습니다. 본 포스트에서는 FastAPI를 사용한 백엔드 서버 개발의 기본 개념과 AWS에 배포하는 방법에 대해 알아보겠습니다.

1. FastAPI란?

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, API 서버 구축의 효율성을 극대화하는 데 초점을 두고 있습니다. 주요 특징은 다음과 같습니다.

  • 빠른 실행 속도: Starlette와 Pydantic을 기반으로 하여 최고 수준의 성능을 자랑합니다.
  • 타입 힌트 지원: Python의 타입 힌트를 활용하여 코드의 가독성을 높이고, 자동 문서화를 지원합니다.
  • 비동기 지원: 비동기 프로그래밍을 쉽게 활용할 수 있도록 도와줍니다.
  • 자동 문서화: OpenAPI 명세를 자동으로 생성하여 API 문서를 쉽게 확인할 수 있습니다.

2. FastAPI 설치하기

FastAPI를 설치하기 위해서는 Python이 필요합니다. 아래와 같이 pip를 사용하여 FastAPI와 uvicorn을 설치할 수 있습니다:

pip install fastapi uvicorn
    

3. FastAPI 기본 예제

이제 FastAPI로 간단한 API 서버를 만들어보겠습니다. 다음 코드는 “Hello, World!”를 반환하는 기본적인 FastAPI 서버입니다:

from fastapi import FastAPI

app = FastAPI()

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

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
    

위 코드를 main.py라는 파일명으로 저장한 후, 아래 명령어로 실행할 수 있습니다:

uvicorn main:app --reload
    

4. FastAPI의 데이터 모델 사용하기

FastAPI는 Pydantic을 통해 데이터 모델을 정의하고 검증할 수 있습니다. 아래 예시는 사용자 정보를 POST 요청으로 받는 API를 구현한 것입니다:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    age: int

@app.post("/users/")
async def create_user(user: User):
    return {"name": user.name, "age": user.age}
    

5. AWS에 FastAPI 애플리케이션 배포하기

AWS에 FastAPI 애플리케이션을 배포하기 위해 여러 가지 방법이 있지만, 여기서는 Amazon EC2를 이용한 방법을 설명하겠습니다.

5.1. EC2 인스턴스 생성하기

AWS Management Console에 로그인 후, EC2 대시보드로 이동하여 새로운 인스턴스를 생성합니다. 여기서는 Amazon Linux 2 AMI를 사용하는 것이 일반적입니다.

5.2. 인스턴스 SSH로 접속하기

인스턴스를 생성한 후, SSH를 이용해 접속할 수 있습니다. 아래의 명령어를 사용합니다:

ssh -i your_key.pem ec2-user@your_instance_public_ip
    

5.3. FastAPI 및 필요한 패키지 설치하기

SSH로 접속한 후, 아래 명령어로 FastAPI와 uvicorn을 설치합니다:

sudo yum update -y
sudo yum install python3 -y
pip3 install fastapi uvicorn
    

5.4. FastAPI 서버 실행하기

이제 FastAPI 애플리케이션을 실행할 차례입니다. 새 프로젝트 디렉토리를 만들고, 앞서 만든 main.py 파일을 업로드합니다:

mkdir fastapi-app
cd fastapi-app
# 파일 전송: scp -i your_key.pem main.py ec2-user@your_instance_public_ip:~/fastapi-app/
uvicorn main:app --host 0.0.0.0 --port 8000
    

5.5. AWS Security Group 설정하기

FastAPI 서버가 외부에서 접근 가능하려면, EC2 인스턴스의 Security Group settings에서 포트 8000을 열어줘야 합니다. 다음 단계를 따라주세요:

  1. AWS Management Console에서 EC2 대시보드로 이동합니다.
  2. 좌측 메뉴에서 “Security Groups”를 클릭합니다.
  3. 인스턴스와 연결된 Security Group을 선택합니다.
  4. “Inbound rules” 탭에서 “Edit inbound rules”를 클릭하여 포트 8000을 추가합니다.

5.6. FastAPI 애플리케이션에 접근하기

이제 웹 브라우저를 열고 `http://your_instance_public_ip:8000`를 입력하여 FastAPI 애플리케이션에 접근할 수 있습니다.

6. 추가적인 배포 방법

AWS EC2 외에도 FastAPI 애플리케이션을 배포할 수 있는 다른 방법들이 있습니다:

  • AWS Elastic Beanstalk: 복잡한 서버 설정이 필요 없이 웹 애플리케이션을 관리할 수 있습니다.
  • AWS Lambda: 서버리스 아키텍처를 사용하여 비용 효율적으로 애플리케이션을 운영할 수 있습니다.
  • Docker: Docker를 사용하여 컨테이너화된 FastAPI 애플리케이션을 배포할 수 있습니다.

7. 마치며

FastAPI는 강력하고 사용하기 쉬운 프레임워크로, 특히 비동기 프로그래밍에 적합합니다. AWS에 배포하는 과정은 조금 복잡할 수 있지만, AWS의 다양한 도구를 활용하여 배포를 쉽게 할 수 있습니다. 앞으로 FastAPI와 함께 멋진 웹 애플리케이션을 만들어 보세요!

이 글이 FastAPI와 AWS 배포에 대한 이해를 돕는 데 유용했기를 바랍니다. 더 많은 정보와 예제 코드가 필요하시면, GitHub에서 FastAPI 공식 문서를 참조해보세요.

FastAPI 서버개발, DB 조작, D Delete

FastAPI는 현대적인 웹 프레임워크 중 하나로, Python으로 API를 손쉽게 만들 수 있도록 돕습니다. 비동기 처리를 지원하며 높은 성능을 자랑하는 FastAPI는 RESTful API 개발에 최적화되어 있습니다. 이 글에서는 FastAPI를 사용한 서버 개발 주제로 CRUD(Create, Read, Update, Delete) 연산 중 ‘Delete’ 작업에 대해 다루어 보겠습니다.

1. FastAPI 소개

FastAPI는 Starlette와 Pydantic을 기반으로 하며, OpenAPI와 JSON Schema를 지원하여 사용자와의 상호작용을 더욱 매끄럽게 해줍니다. Python 타입 힌트와 문서화 기능 덕분에, 개발자는 오류를 줄이고 빠르게 개발할 수 있습니다.

1.1 FastAPI 특징

  • 비동기 지원
  • 자동 문서화
  • 높은 성능
  • 유형 기반 데이터 검증
  • 간단한 라우팅

2. 환경 설정

이 프로젝트에서는 FastAPI와 SQLAlchemy를 사용하여 데이터베이스와의 상호작용을 구현합니다. 아래의 과정을 통해 FastAPI 환경을 설정해보겠습니다.

2.1 FastAPI 및 필요한 패키지 설치

FastAPI와 SQLAlchemy를 설치하기 위해서는 먼저 pip를 사용합니다. 아래의 명령어를 실행하여 설치합니다.

pip install fastapi[all] sqlalchemy

2.2 프로젝트 구조 설정

아래와 같은 기본적인 디렉터리 구조를 설정합니다.


my_fastapi_app/
│
├── app/
│   ├── main.py
│   ├── models.py
│   ├── schemas.py
│   └── database.py
└── requirements.txt
    

3. 데이터베이스 설정

아래는 SQLAlchemy를 사용하여 SQLite 데이터베이스를 설정하는 예제입니다.

3.1 database.py


from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"

engine = create_engine(SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
    

3.2 모델 정의하기

데이터베이스와 상호작용하기 위한 모델을 정의합니다.

3.2.1 models.py


from sqlalchemy import Column, Integer, String
from .database import Base

class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String, index=True)
    price = Column(Integer)
    is_active = Column(Boolean, default=True)
    

4. 데이터 조작

이제 삭제 작업을 포함한 CRUD 연산을 구현할 수 있도록 API 엔드포인트를 생성하겠습니다.

4.1 스키마 정의하기

API 요청과 응답을 정의하기 위해 Pydantic을 사용하여 스키마를 만듭니다.

4.1.1 schemas.py


from pydantic import BaseModel

class ItemBase(BaseModel):
    name: str
    description: str
    price: int

class ItemCreate(ItemBase):
    pass

class Item(ItemBase):
    id: int
    is_active: bool

    class Config:
        orm_mode = True
    

4.2 CRUD 연산 구현

이제 FastAPI와 SQLAlchemy를 통합하여 CRUD 연산을 구현하겠습니다.

4.2.1 main.py


from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import models, schemas
from .database import SessionLocal, engine

models.Base.metadata.create_all(bind=engine)

app = FastAPI()

# Dependency
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.delete("/items/{item_id}", response_model=schemas.Item)
def delete_item(item_id: int, db: Session = Depends(get_db)):
    item = db.query(models.Item).filter(models.Item.id == item_id).first()
    if not item:
        raise HTTPException(status_code=404, detail="Item not found")
    db.delete(item)
    db.commit()
    return item
    

5. 설명 및 사용

위의 코드에서 /items/{item_id} 경로로 DELETE 요청을 보내면 해당 ID를 가진 아이템이 데이터베이스에서 삭제됩니다. 만약 아이템이 존재하지 않으면 404 Not Found 오류가 발생합니다.

5.1 사용 예시

Postman과 같은 API 클라이언트를 사용하여 요청을 테스트할 수 있습니다. 예를 들어, 다음과 같은 DELETE 요청을 보낼 수 있습니다:


DELETE http://127.0.0.1:8000/items/1
    

5.2 결과 확인하기

DELETE 요청이 성공적으로 처리되면, 해당 아이템의 데이터가 삭제되며, 삭제된 아이템의 정보가 응답으로 반환됩니다.

6. 결론

이 글에서는 FastAPI를 사용하여 Delete 연산을 구현하는 방법을 배웠습니다. FastAPI는 Python으로 API를 개발할 때 매우 유용한 도구이며, 데이터베이스와의 상호작용을 통해 유연한 서비스를 제공할 수 있습니다. CRUD 연산의 기본적인 사용법을 익혔다면, 실제 비즈니스 로직을 구현하는 데 더 나아갈 수 있을 것입니다.

7. 참고 문헌

FastAPI 서버개발, 패스워드 해싱

현대 웹 애플리케이션에서 사용자 인증 및 보안을 확보하는 것은 매우 중요한 문제입니다. 특히, 비밀번호와 같은 민감한 정보는 적절하게 보호되어야 합니다. 이를 위해 우리는 FastAPI를 사용하여 백엔드 서버를 개발하고, 비밀번호 해싱을 통해 사용자 비밀번호를 안전하게 저장하는 방법을 알아보겠습니다.

1. FastAPI 소개

FastAPI는 Python으로 작성된 현대적인 웹 프레임워크로, 비동기 프로그래밍을 지원하고, OpenAPI 및 JSON Schema를 자동으로 생성할 수 있습니다. 성능이 뛰어나며, 신속한 프로토타이핑과 설계 검증에 적합합니다. FastAPI는 RESTful API 개발을 위한 매우 직관적이고 간편한 접근 방식을 제공합니다.

2. 패스워드 해싱이란?

패스워드 해싱은 사용자가 입력한 비밀번호를 해시 함수를 통해 변형해 저장하는 작업입니다. 이를 통해 비밀번호가 노출되더라도 원래 비밀번호를 알아낼 수 없도록 방지할 수 있습니다. 해싱 알고리즘으로는 BCrypt, Argon2, PBKDF2 등이 있으며, 이들 각각은 복잡성과 보안 수준이 다릅니다.

2.1 해싱 알고리즘

비밀번호 해싱에서 가장 널리 사용되는 알고리즘은 다음과 같습니다:

  • BCrypt: 비밀번호를 해싱할 때 적절한 비용 인자를 사용하여 보안을 강화하는 알고리즘입니다.
  • Argon2: 2015년 패스워드 해싱 대회에서 우승한 알고리즘으로, 메모리 요구 사항을 증가시켜 공격에 대한 저항력을 높입니다.
  • PBKDF2: 반복적 해싱을 통해 비밀번호의 복잡성을 높이는 알고리즘으로, 일정량의 시간과 메모리를 소모하도록 설계되었습니다.

3. FastAPI 환경 구축

이제 FastAPI 프로젝트를 설정하고 비밀번호를 안전하게 해싱하기 위한 준비를 해보겠습니다.

3.1 FastAPI 설치

FastAPI 및 해싱을 위한 필요한 라이브러리를 설치합니다. 다음 명령어를 실행하여 필요한 패키지를 설치합니다:

pip install fastapi uvicorn passlib[bcrypt]

3.2 프로젝트 구조

다음과 같은 디렉토리 구조를 생성합니다:


project/
│
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── models.py
└── requirements.txt
    

3.3 기본 FastAPI 앱 작성

이제 FastAPI 애플리케이션을 작성해보겠습니다. main.py 파일에 기본 API를 설정합니다.


from fastapi import FastAPI
from pydantic import BaseModel
from passlib.context import CryptContext

app = FastAPI()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# 사용자 모델 정의
class User(BaseModel):
    username: str
    password: str

# 비밀번호 해싱 함수
def hash_password(password: str) -> str:
    return pwd_context.hash(password)

# 사용자 등록 엔드포인트
@app.post("/register/")
async def register(user: User):
    hashed_password = hash_password(user.password)
    return {"username": user.username, "hashed_password": hashed_password}
    

4. 비밀번호 해싱 구현

위 코드에서는 비밀번호 해싱을 위한 간단한 FastAPI 애플리케이션을 작성하였습니다. 이 애플리케이션은 사용자가 등록할 때 비밀번호를 해싱하여 반환합니다.

4.1 비밀번호 해싱 과정 설명

  • 사용자가 등록하면, register 엔드포인트가 호출됩니다.
  • 입력받은 비밀번호는 hash_password 함수를 통해 해싱됩니다.
  • 해싱된 비밀번호는 JSON 응답으로 반환됩니다.

5. 서버 실행하기

FastAPI 서버를 실행하기 위해 터미널에서 다음 명령어를 입력합니다:

uvicorn app.main:app --reload

서버가 성공적으로 실행되면, http://127.0.0.1:8000/docs를 방문하여 Swagger UI에서 API를 테스트할 수 있습니다.

6. 비밀번호 검증

사용자가 로그인하면, 입력한 비밀번호와 DB에 저장된 해싱된 비밀번호를 비교해야 합니다. 이를 위해 비밀번호 검증 함수를 추가해 보겠습니다.


# 비밀번호 검증 함수
def verify_password(plain_password: str, hashed_password: str) -> bool:
    return pwd_context.verify(plain_password, hashed_password)

@app.post("/login/")
async def login(user: User):
    # 비밀번호 검증 로직 (여기서는 간단히 하드코딩)
    stored_hashed_password = "$2b$12$KixR7Pq2B7lZq5NOsx.xreOS5Jz4P3qv1E8pF8ozFpXZKLaMvvWry"  # 예시 해시
    if verify_password(user.password, stored_hashed_password):
        return {"message": f"Welcome {user.username}"}
    else:
        return {"message": "Invalid credentials"}
    

7. 결론

이번 글에서는 FastAPI로 간단한 백엔드 서버를 구성하고 패스워드 해싱 기능을 추가하는 방법을 배웠습니다. 비밀번호는 해싱을 통해 저장함으로써 사용자의 정보를 안전하게 보호할 수 있습니다. 본 예제는 간단한 형태이므로, 실제 서비스에서는 데이터베이스와의 연동, 에러 처리, 유효성 검증 등 추가적인 로직이 필요합니다.

8. 추가 자료

FastAPI 및 패스워드 해싱 관련 추가 자료를 아래와 같이 추천합니다:

FastAPI를 통해 성능 좋고 안전한 웹 API를 구축해 보세요!

© 2023 FastAPI 개발 강좌. All rights reserved.