Skip to content

제6.5장: API 보안 기초

학습 시간: 45분


1. API 보안: 다단계 방어 체계

여러분의 우주 정거장(API)이 적대적인 우주 구역에 있다고 상상해 보세요. 하나의 보호막(인증)만으로는 부족합니다. 복합적인 방어 시스템이 필요합니다:

  • 보호막 (HTTPS): 모든 트래픽 암호화.
  • 이상 감지 센서 (Rate Limiting): 과도한 요청으로부터 보호.
  • 내부 격벽 (권한 부여): 접근 권한 분리.
  • 화물 검사 (유효성 검사): 모든 들어오는 데이터를 신뢰하지 않음.
  • 비밀 금고 (환경 변수): 키를 안전하게 저장.

각각의 방어 단계를 설정해 봅시다.


2. 보호막: 항상 HTTPS 사용

무엇인가요? HTTPS(HyperText Transfer Protocol Secure)는 클라이언트와 서버 간의 모든 데이터를 암호화하는 HTTP 프로토콜의 버전입니다. HTTPS가 없으면 네트워크를 "엿듣는" 사람(예: 공용 Wi-Fi에서)은 로그인, 암호 및 토큰을 가로챌 수 있습니다.

어떻게 구현하나요?

  • 프로덕션에서는 필수입니다. 실제 서버(Heroku, DigitalOcean 등)에 API를 배포할 때, 웹 서버(Nginx, Apache)를 SSL 인증서와 함께 작동하도록 설정하세요. Let's Encrypt와 같은 서비스는 무료 인증서를 제공합니다.
  • 로컬 개발에서는 덜 중요하지만, Laravel Herd 또는 mkcert와 같은 도구를 사용하면 로컬 HTTPS를 쉽게 설정할 수 있습니다.

💡 API 보안 규칙 #1: HTTPS가 없으면 보안도 없습니다.


3. 이상 감지 센서: 요청 빈도 제한 (Rate Limiting)

무엇인가요? 무차별 대입 공격(공격자가 초당 수천 개의 요청을 보내 비밀번호를 추측하려는 경우) 및 DoS 공격(서버가 요청으로 "과부하"되어 응답하지 못하게 되는 경우)으로부터 보호합니다. Rate Limiting은 한 사용자(또는 IP 주소)가 특정 시간 동안 보낼 수 있는 요청 수를 제한합니다.

어떻게 구현하나요?

  • Laravel: 제한용 미들웨어는 이미 내장되어 있습니다! app/Http/Kernel.php를 열고 middlewareGroups['api'] 키를 확인해 보세요. 이미 'throttle:api'가 있습니다. 이 제한 설정은 app/Providers/RouteServiceProvider.phpconfigureRateLimiting() 메서드에 있습니다.

    // app/Providers/RouteServiceProvider.php
    protected function configureRateLimiting()
    {
        RateLimiter::for('api', function (Request $request) {
            return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
        });
    }
    
    이는 사용자당(인증된 경우) 또는 IP 주소당 분당 60개의 요청을 의미합니다.

  • FastAPI: 예를 들어, slowapi와 같은 서드파티 패키지가 사용됩니다.

  • 설치: pip install slowapi

  • main.py에 통합:
    # main.py
    from slowapi import Limiter, _rate_limit_exceeded_handler
    from slowapi.util import get_remote_address
    from slowapi.errors import RateLimitExceeded
    
    limiter = Limiter(key_func=get_remote_address)
    app = FastAPI(...)
    
    # 오류 핸들러와 리미터를 연결합니다.
    app.state.limiter = limiter
    app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
    
    # 특정 엔드포인트에 적용합니다.
    @router.get("/planets")
    @limiter.limit("5/minute") # 분당 5개 요청
    def get_planets(request: Request):
        # ...
    

4. 내부 격벽: 권한 부여 (인증과 혼동하지 마세요!)

무엇인가요?

  • 인증은 "당신은 누구인가요?"라는 질문에 답합니다.
  • 권한 부여는 "무엇을 할 수 있나요?"라는 질문에 답합니다.

예를 들어, 일반 사용자는 행성을 볼 수 있지만, "관리자" 역할을 가진 사용자만 행성을 삭제할 수 있습니다.

어떻게 구현하나요?

  • Laravel: Policies(정책) 또는 Gates(게이트)가 사용됩니다.

  • 정책 생성: php artisan make:policy PlanetPolicy --model=Planet

  • app/Policies/PlanetPolicy.php에 규칙 정의:
    class PlanetPolicy
    {
        // 'admin' 역할을 가진 사용자에게만 삭제 허용
        public function delete(User $user, Planet $planet): bool
        {
            return $user->role === 'admin';
        }
    }
    
  • PlanetController.php 컨트롤러에 정책 적용:

    public function destroy(Planet $planet)
    {
        // 현재 사용자에게 삭제 권한이 있는지 확인
        $this->authorize('delete', $planet);
    
        $planet->delete();
        return response()->json(null, 204);
    }
    

  • FastAPI: 권한 부여 로직은 일반적으로 토큰에서 얻은 사용자 정보를 사용하여 엔드포인트 내에서 수동으로 작성됩니다.

# (토큰에 'roles' 필드가 있다고 가정)
def get_current_active_user(token: str = Depends(oauth2_scheme)):
    # ... 토큰을 디코딩하고 DB에서 역할과 함께 사용자 가져오기
    # user = get_user_from_db(username)
    return user # 사용자 객체 반환

@router.delete("/planets/{planet_id}")
def delete_planet(
    planet_id: int,
    current_user: User = Depends(get_current_active_user)
):
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="이 작업을 수행할 권한이 충분하지 않습니다.",
        )
    # ... 삭제 로직 ...

5. 화물 검사 및 비밀 금고: 유효성 검사 및 환경 변수

이 두 가지는 이미 구현했지만, 보안에서의 중요성을 강조하는 것이 중요합니다.

  • 들어오는 데이터를 절대 신뢰하지 마세요 (유효성 검사):

  • 우리는 Laravel에서 $request->validate()를 사용했고 FastAPI에서 Pydantic 모델을 사용했습니다. 이는 우리를 SQL 인젝션(Eloquent/SQLAlchemy 사용 시)과 애플리케이션을 손상시킬 수 있는 잘못된 데이터로부터 보호합니다. 외부에서 들어오는 모든 것을 항상 유효성 검사하세요!

  • 비밀을 .env에 저장하세요 (환경 변수):

  • 데이터베이스 키, JWT용 비밀 키(SECRET_KEY), 서드파티 서비스 키 등 이 모든 것은 버전 관리 시스템(Git)에 절대 포함되어서는 안 됩니다. 이를 위해 .gitignore에 추가되는 .env 파일이 존재합니다.


복습 퀴즈

1. 공용 네트워크에서 데이터 가로채기를 방지하기 위해 다음이 사용됩니다:

2. 요청 빈도 제한(Rate Limiting)은 주로 다음으로부터 보호합니다:

3. "이 사용자에게 무엇을 할 수 있도록 허용하는가?"라는 질문에 답하는 것은:

4. API 비밀 키와 DB 비밀번호는 다음에 저장해야 합니다:


🚀 코스 완료 축하합니다, 사령관님! 모든 임무를 성공적으로 완료했습니다.

당신은 API에 대해 들어본 적만 있는 초보자에서, 자체 생태계에서 가장 인기 있는 두 가지 기술을 사용하여 완전한 웹 서비스를 독립적으로 설계, 개발, 문서화, 보호 및 테스트할 수 있는 엔지니어로 성장했습니다.

당신은 범용 REST 언어를 마스터하고 Laravel과 FastAPI를 배웠으며, 순수 JavaScript로 이들을 위한 "비행 관제 센터"를 구축했습니다.

이것은 엄청난 성과입니다. 이제 API 개발의 세계가 당신에게 열렸습니다. 계속해서 탐구하고, 배우고, 놀라운 것들을 만들어 나가십시오.

통신 종료. 🚀

☄ 미션 지원하기

이 튜토리얼을 만드는 것은 많은 시간과 에너지를 필요로 하는 길고 복잡한 비행입니다. 이 자료가 유용하다고 생각되시면, 저희 탐험대의 연료 탱크를 채우는 데 도움을 주실 수 있습니다. 모든 지원은 새로운 유용한 자료를 향한 또 하나의 궤도 진입입니다.

ko-fi.com에서 커피 한 잔 사주기