광고 차단 프로그램이 감지되었습니다

이 사이트는 광고 수익을 통해 무료로 콘텐츠와 서비스를 제공하고 있습니다.

더 나은 서비스를 위해 광고 차단 프로그램을 비활성화 해주세요.

광고 차단 해제 방법 보기
Loading...

라이센스서버 개발 기록

Ran tool

다음은 제공된 라이센스 기능 서버/클라이언트의 전체 코드와 설정을 기반으로 작성된 기술 보고서입니다.

라이센스 관리 시스템 기술 보고서

1. 아키텍처 개요

이 시스템은 FastAPI 기반의 라이센스 서버와 MongoDB, Redis를 활용하여 라이센스 발급, 관리, 유효성 검사를 수행합니다. 클라이언트는 서버에 라이센스 유효성 검사를 요청하고, 서버는 클라이언트의 하드웨어 정보를 기반으로 라이센스를 관리합니다.

아키텍처 다이어그램

graph TD
    subgraph Client
        C[Client Application] -- Request License Check --> LS
    end

    subgraph License Server (FastAPI Uvicorn)
        LS[FastAPI Application] -- Admin UI --> AUI(Admin Web UI)
        LS -- Interact with --> MongoDB[MongoDB]
        LS -- Caches active licenses --> Redis[Redis]
        LS -- Serves static files --> Static[Static Files (images/)]
    end

    subgraph Data Stores
        MongoDB -- Stores License Data --> MDB[(License DB)]
        Redis -- Stores Active License TTL --> RDB[(Active License Cache)]
    end

    subgraph Docker Containers
        LS -- Docker Container --> FastAPIContainer[license-api]
        MongoDB -- Docker Container --> MongoContainer[mongo_db]
        Redis -- Docker Container --> RedisContainer[redis_cache]
    end

    subgraph User Interaction
        AdminUser[Admin User] -- Manages Licenses via --> AUI
    end

    FastAPIContainer --- C
    MongoContainer --- FastAPIContainer
    RedisContainer --- FastAPIContainer

    style FastAPIContainer fill:#f9f,stroke:#333,stroke-width:2px
    style MongoContainer fill:#bbf,stroke:#333,stroke-width:2px
    style RedisContainer fill:#bfb,stroke:#333,stroke-width:2px
    style C fill:#ccf,stroke:#333,stroke-width:2px
    style AdminUser fill:#ccf,stroke:#333,stroke-width:2px

주요 구성 요소 및 데이터 흐름

  • 클라이언트 애플리케이션 (Client Application).exe 프로그램으로 상정되며, 서버에 라이센스 유효성 검사 (/check 엔드포인트)를 요청합니다. 이때 MAC 주소, IP 주소, client_id 등의 하드웨어 식별 정보를 포함하여 전송합니다. 또한 주기적인 Heartbeat 요청을 통해 라이센스 활성 상태를 유지합니다.
  • 라이센스 서버 (FastAPI Application):
  • FastAPI: Python 기반의 비동기 웹 프레임워크로, API 엔드포인트와 관리자 웹 UI를 제공합니다. uvicorn을 통해 실행됩니다.
  • Jinja2Templates: 관리자 웹 UI (admin.htmllogin.htmledit_license.html) 렌더링을 담당합니다.
  • SessionMiddleware: 관리자 로그인 상태 유지를 위한 세션 관리를 처리합니다.
  • StaticFiles: 광고 배너 이미지(images/)와 같은 정적 파일을 제공합니다.
  • MongoDB: 모든 라이센스 정보를 영구적으로 저장하는 주 데이터베이스입니다. motor 라이브러리를 통해 비동기적으로 접근합니다.
  • Redis: 라이센스의 실시간 동시 접속 제어 및 활성 상태(TTL)를 관리하는 캐시 데이터베이스입니다.
  • 데이터 흐름:
  • 관리자 UI: 관리자는 /admin/login/admin 엔드포인트를 통해 라이센스를 생성, 삭제, 수정합니다. 이 과정에서 MongoDB에 데이터를 읽고 씁니다.
  • 라이센스 검증: 클라이언트가 /check 엔드포인트로 라이센스 키와 하드웨어 정보를 전송하면, 서버는 MongoDB에서 라이센스 정보를 조회하고 Redis를 통해 동시 접속 여부를 확인합니다. 필요한 경우 MongoDB에 하드웨어 바인딩 정보를 업데이트하고, Redis에 라이센스 활성 상태를 갱신합니다.
  • 정적 파일 제공: 클라이언트 또는 웹 브라우저는 /banners 경로를 통해 images/ 폴더의 정적 파일을 요청합니다.

2. 각 구성요소(서버/클라이언트/DB 등)별 역할 및 책임

2.1. 라이센스 서버 (FastAPI Application)

  • 역할: 라이센스 발급, 수정, 삭제, 유효성 검증, 동시 접속 제어, 관리자 인터페이스 제공.
  • 책임:
  • 라이센스 키 생성 및 관리.
  • 사용자 이메일, 제품명, 만료일 등 라이센스 속성 관리.
  • 하드웨어 (MAC 주소, IP 주소) 바인딩 및 재바인딩 처리.
  • Redis를 이용한 라이센스 동시 접속 제어 (Heartbeat 기반).
  • 만료된 라이센스 상태 자동 업데이트.
  • 관리자 인증 및 세션 관리.
  • 정적 파일(이미지) 제공.
  • 모든 시간 정보를 한국 시간대 (KST) 기준으로 처리.

2.2. MongoDB

  • 역할: 라이센스 정보의 영구 저장.
  • 책임:
  • 개별 라이센스 문서(license_key, product_name, user_email, created_at, expires_at, status, bound_system_identifier 등) 저장.
  • 라이센스 정보의 검색, 삽입, 업데이트, 삭제.
  • 하드웨어 바인딩 정보 (MAC 주소, IP 주소 등) 저장.

2.3. Redis

  • 역할: 라이센스의 실시간 활성 상태 및 동시 접속 제어 캐시.
  • 책임:
  • 활성 라이센스 키와 현재 사용 중인 클라이언트 ID(client_id)를 LICENSE_ACTIVE_TTL_SECONDS 기간 동안 저장.
  • 동일한 라이센스 키에 대해 다른 클라이언트의 동시 접속 시도 감지 및 차단.
  • Heartbeat 요청 시 라이센스 TTL 갱신.

2.4. 클라이언트 애플리케이션 (Client Application - .exe 프로그램, 코드 미포함)

  • 역할: 라이센스 서버에 라이센스 유효성 검사 요청 및 Heartbeat 전송.
  • 책임:
  • 고유하고 영구적인 client_id 생성 및 관리 (매 실행마다 동일한 ID 사용).
  • 현재 시스템의 MAC 주소, IP 주소 등 하드웨어 식별 정보 수집.
  • LICENSE_ACTIVE_TTL_SECONDS보다 짧은 주기로 서버에 Heartbeat 요청 (/check 엔드포인트) 전송.
  • 서버 응답에 따라 라이센스 유효성 판단 및 기능 활성화/중단.
  • 서버 응답에 client_id 누락 시 경고 및 에러 처리.

2.5. Docker 및 Docker Compose

  • 역할: 시스템 구성 요소(FastAPI, Redis)의 컨테이너화 및 오케스트레이션.
  • 책임:
  • Dockerfile: FastAPI 애플리케이션의 실행 환경(Python 3.11, 필요한 라이브러리)을 정의하고, 소스 코드를 컨테이너 이미지로 빌드.
  • docker-compose.ymllicense-api (FastAPI), redis 서비스 정의. 포트 매핑, 네트워크 설정, 환경 변수 로드, 재시작 정책 등을 관리하여 서비스 간의 연동을 용이하게 함.

3. 보안 및 장애 대응 구조

3.1. 보안 구조

  • 관리자 인증:
  • 관리자 로그인 (/admin/login)은 환경 변수 ADMIN_USERNAME과 ADMIN_PASSWORD_HASH를 사용합니다. ADMIN_PASSWORD_HASH는 bcrypt로 해싱된 비밀번호를 사용하며, 이는 노출 위험을 줄입니다.
  • SessionMiddleware를 사용하여 로그인 세션을 관리하며, SESSION_SECRET_KEY는 환경 변수로 설정하여 세션 하이재킹 공격을 방지합니다.
  • 하드웨어 바인딩:
  • 라이센스 키는 특정 하드웨어(MAC 주소)에 바인딩될 수 있습니다. 이를 통해 라이센스의 무단 복제 및 사용을 방지합니다.
  • 초기 바인딩 후, 다른 MAC 주소에서 접근 시 바인딩 정보가 갱신되며, 이는 라이센스 관리자가 추적할 수 있도록 경고를 로깅합니다.
  • 동시 접속 제어 (Redis):
  • Redis를 사용하여 하나의 라이센스 키가 동시에 여러 클라이언트에서 사용되는 것을 방지합니다.
  • client_id를 기반으로 현재 라이센스를 사용 중인 클라이언트를 식별하며, 다른 클라이언트가 접근하면 즉시 거부합니다.
  • 환경 변수 관리:
  • ADMIN_PASSWORD_HASHMONGODB_URLSESSION_SECRET_KEY와 같은 민감 정보는 .env 파일을 통해 환경 변수로 관리하며, .gitignore에 추가하여 버전 관리 시스템에 노출되지 않도록 합니다.
  • IP 주소 로깅:
  • 클라이언트의 IP 주소를 수집하여 라이센스 사용 패턴 분석 및 비정상적인 접근 감지에 활용될 수 있습니다.

3.2. 장애 대응 구조

  • MongoDB 연결:
  • FastAPI 애플리케이션 시작 시 AsyncIOMotorClient를 통해 MongoDB에 연결하며, 종료 시 연결을 해제합니다. 연결 실패 시 로그를 남겨 관리자가 문제를 인지할 수 있도록 합니다.
  • Redis 연결:
  • 애플리케이션 시작 시 Redis에 연결을 시도하고 ping()을 통해 연결 상태를 확인합니다. 연결 실패 시 app.redis_client를 None으로 설정하여 이후 Redis 사용 로직에서 if not app.redis_client:와 같이 체크하여 오류를 회피합니다.
  • Redis 연결 실패 시에도 MongoDB 기반의 라이센스 유효성 검사 (만료 여부, 상태)는 동작하지만, 동시 접속 제어는 불가능해집니다.
  • 컨테이너 재시작 정책:
  • docker-compose.yml에서 restart: unless-stopped 설정을 통해 컨테이너가 예기치 않게 종료되었을 때 자동으로 재시작되도록 합니다. 이는 서비스의 가용성을 높입니다.
  • 로깅:
  • logging 모듈을 사용하여 애플리케이션의 주요 동작(MongoDB/Redis 연결, 라이센스 검증 결과, 경고 등)을 기록합니다. 이는 문제 발생 시 원인 분석에 중요한 자료가 됩니다.

4. 주요 폴더 및 파일 구조

.
├── .env                  {# 환경 변수 설정 파일 (gitignore에 포함) #}
├── .gitignore            {# Git 버전 관리에서 제외할 파일 지정 #}
├── docker-compose.yml    {# Docker Compose 설정 파일 #}
├── dockerfile            {# FastAPI 애플리케이션의 Docker 이미지 빌드 파일 #}
├── images/               {# 정적 파일 (광고 배너 등) 저장 디렉토리 #}
│   └── example_banner.png
├── main.py               {# FastAPI 애플리케이션의 메인 로직 파일 #}
├── requirements.txt      {# Python 패키지 의존성 목록 #}
├── robots.txt            {# 웹 크롤러 접근 제어 파일 #}
├── templates/            {# Jinja2 템플릿 파일 저장 디렉토리 #}
│   ├── admin.html        {# 관리자 라이센스 목록 및 생성 UI #}
│   ├── edit_license.html {# 라이센스 수정 UI #}
│   └── login.html        {# 관리자 로그인 UI #}
└── 진행사항.md           {# 프로젝트 진행 상황 및 TODO 목록 #}
  • .env: 민감한 정보(DB URL, 관리자 비밀번호 해시, 세션 시크릿 키)를 환경 변수로 관리하여 코드와 분리하고 보안을 강화합니다.
  • docker-compose.ymllicense-api 및 redis 서비스의 빌드, 네트워크, 포트, 볼륨 등을 정의합니다.
  • dockerfile: FastAPI 애플리케이션을 위한 Python 런타임, 의존성 설치, 소스 코드 복사 등의 빌드 단계를 명시합니다.
  • images/: 클라이언트 애플리케이션 또는 웹에서 접근할 수 있는 정적 이미지 파일들을 저장합니다. (/banners 엔드포인트를 통해 제공)
  • main.py: FastAPI 애플리케이션의 핵심 로직 (루트 엔드포인트, 관리자 API, 라이센스 검증 API, DB/Redis 연결 로직, 모델 정의 등)이 포함됩니다.
  • requirements.txt: 프로젝트에 필요한 모든 Python 라이브러리와 그 버전을 명시하여 환경 일관성을 유지합니다.
  • robots.txt: 웹 크롤러가 / 경로를 포함한 모든 경로에 접근하지 못하도록 설정하여, 불필요한 서버 부하를 줄이고 관리자 페이지 등의 노출을 방지합니다.
  • templates/: 관리자 웹 UI를 구성하는 HTML 템플릿 파일들입니다.

5. 배포 및 운영 정책

5.1. 배포 방식

  • Docker Composedocker-compose up -d 명령어를 사용하여 FastAPI 애플리케이션과 Redis를 포함한 전체 시스템을 컨테이너화하여 쉽게 배포하고 관리할 수 있습니다.
  • 환경 변수: 배포 환경에 따라 .env 파일을 적절히 구성하여 MongoDB URL, 관리자 비밀번호, 세션 키 등을 유연하게 설정할 수 있습니다.
  • 빌드 과정dockerfile은 Python 런타임, 의존성 설치, 소스 코드 복사 등의 단계를 포함하여 깨끗하고 일관된 빌드 환경을 제공합니다. requirements.txt를 통해 의존성 관리가 명확합니다.

5.2. 운영 정책

  • 모니터링:
  • FastAPI의 로깅 기능을 활용하여 애플리케이션의 Health Check, 라이센스 검증 요청, 오류 발생 등을 모니터링합니다.
  • Docker 컨테이너의 로그를 수집하여 시스템 상태를 지속적으로 확인합니다.
  • MongoDB 및 Redis의 상태와 성능을 모니터링하여 데이터베이스 문제를 조기에 감지합니다.
  • 백업:
  • MongoDB 데이터는 주기적으로 백업하여 데이터 손실에 대비해야 합니다.
  • Redis는 휘발성 데이터(캐시)를 주로 다루지만, 중요한 설정이나 지속성을 위한 AOF(Append Only File) 설정이 필요할 수 있습니다.
  • 보안 업데이트:
  • 사용된 라이브러리(FastAPI, Uvicorn, Motor, Redis 등) 및 Python 런타임의 보안 취약점을 주기적으로 확인하고 업데이트합니다.
  • Docker 이미지의 기반 이미지(Python 3.11-slim)도 최신 보안 패치를 적용합니다.
  • 관리자 접근:
  • 관리자 페이지는 반드시 안전한 네트워크 환경에서만 접근하도록 제한하거나, 추가적인 VPN/IP 화이트리스트 등의 보안 장치를 마련해야 합니다.
  • ADMIN_PASSWORD_HASH는 강력한 비밀번호와 함께 정기적으로 갱신되어야 합니다.

6. 확장성·유지보수 고려사항

6.1. 확장성 (Scalability)

  • FastAPI: 비동기 프레임워크인 FastAPI는 높은 동시성을 처리할 수 있으며, uvicorn과 같은 ASGI 서버를 통해 멀티프로세스 워커를 사용하여 수평 확장이 용이합니다. 여러 license-api 컨테이너를 로드 밸런서 뒤에 배치하여 트래픽을 분산할 수 있습니다.
  • MongoDB: MongoDB는 분산 데이터베이스 시스템으로, 샤딩(Sharding)을 통해 데이터 볼륨과 트래픽 증가에 따라 손쉽게 수평 확장을 할 수 있습니다. 레플리카 셋(Replica Set)을 구성하여 고가용성을 확보할 수 있습니다.
  • Redis: Redis 또한 클러스터링을 통해 데이터를 여러 노드에 분산하고 처리량을 늘릴 수 있습니다. Sentinel을 통해 고가용성을 확보할 수 있습니다.
  • Stateless 서버 디자인main.py의 라이센스 서버 로직은 대부분 상태를 MongoDB와 Redis에 의존하며, 서버 자체는 클라이언트 세션(SessionMiddleware)을 제외하고는 상태를 유지하지 않으므로 수평 확장이 용이합니다.
  • 데이터 모델 분리: 라이센스 정보, 하드웨어 바인딩 정보 등이 MongoDB 문서 내에 함께 저장되어 있어, 관련 데이터를 한 번의 조회로 가져올 수 있어 효율적입니다.

6.2. 유지보수 고려사항

  • 모듈화main.py 파일 하나에 모든 로직이 집중되어 있어, 향후 기능이 복잡해질 경우 servicesmodelsrouters 등으로 파일을 분리하여 모듈성을 높이고 가독성을 향상시키는 것이 좋습니다.
  • 테스트 코드: 현재는 테스트 코드가 없지만, 엔드포인트별 단위 테스트 및 통합 테스트를 작성하여 코드 변경 시 회귀 오류를 방지하고 안정성을 확보해야 합니다.
  • API 버전 관리: 클라이언트 애플리케이션과의 호환성을 위해 API 변경 시 버전 관리를 고려해야 합니다 (예: /v1/check/v2/check).
  • 문서화: OpenAPI/Swagger UI가 FastAPI에 내장되어 있어 API 문서화가 자동 생성되지만, 클라이언트 개발자를 위한 상세한 API 명세 및 사용 가이드를 별도로 제공하는 것이 좋습니다.
  • 코드 컨벤션 및 린트pylintflake8black 등과 같은 린터와 포맷터를 적용하여 코드 품질과 일관성을 유지할 수 있습니다.
  • 환경 변수 명확화.env 파일에 각 환경 변수에 대한 주석을 추가하여 어떤 목적으로 사용되는지 명확히 하는 것이 좋습니다.

Ran tool

아키텍처 개요와 구성 요소별 역할을 설명하는 보고서 초안이 작성되었습니다. 다음으로 보안 및 장애 대응 구조에 대한 설명을 이어서 작성하겠습니다.

Ran tool

3. 보안 및 장애 대응 구조

3.1. 보안 구조

  • 관리자 인증:
  • 관리자 로그인 엔드포인트 (/admin/login)는 사용자 이름과 비밀번호를 Form 데이터로 받습니다.
  • 환경 변수 ADMIN_USERNAME과 ADMIN_PASSWORD_HASH를 사용하여 인증을 수행합니다. ADMIN_PASSWORD_HASH는 미리 bcrypt로 해싱된 비밀번호를 저장하여 실제 비밀번호 노출 위험을 최소화합니다.
  • passlib.context.CryptContext를 사용하여 비밀번호 해싱(hash_password) 및 검증(verify_password)을 안전하게 처리합니다.
  • 인증 성공 시 starlette.middleware.sessions.SessionMiddleware를 통해 admin_logged_in 세션 변수를 True로 설정하여 로그인 상태를 유지합니다. SESSION_SECRET_KEY는 환경 변수로 관리되며, 이는 세션 데이터의 무결성과 기밀성을 보장하여 세션 하이재킹 공격을 방지합니다.
  • 하드웨어 바인딩:
  • 라이센스 키는 최초 LicenseCheckWithHardware 요청 시 클라이언트의 MAC 주소와 기타 하드웨어 식별 정보에 바인딩됩니다. 이 정보는 MongoDB의 bound_system_identifier 필드에 저장됩니다.
  • 이후 동일한 라이센스 키로 다른 MAC 주소에서 접근이 시도될 경우, 서버는 이를 감지하고 MongoDB의 바인딩 정보를 갱신합니다. 이 과정에서 경고 로그를 남겨 관리자가 비정상적인 활동을 추적할 수 있도록 합니다. (현재 로직은 재바인딩을 허용하지만, last_bound_mac_address 및 rebound_cooldown_until 필드를 통해 더 엄격한 재바인딩 정책을 구현할 여지가 있습니다.)
  • 동시 접속 제어 (Redis):
  • app.redis_client를 활용하여 라이센스 키(data.license_key)를 Redis의 키로 사용하고, 값으로는 현재 라이센스를 사용 중인 클라이언트의 client_id와 last_activity_time을 JSON 형식으로 저장합니다.
  • LICENSE_ACTIVE_TTL_SECONDS (60초)를 TTL(Time-To-Live)로 설정하여 라이센스 활성 상태를 일정 시간 동안만 유지합니다.
  • 클라이언트가 Heartbeat 요청 시 client_id가 일치하면 Redis TTL을 갱신하여 라이센스 사용을 지속시킵니다.
  • 만약 다른 client_id에서 동일한 라이센스 키로 요청이 들어오면, Redis에 이미 정보가 존재하는 경우 "이미 다른 기기에서 사용 중입니다." 메시지와 함께 접근을 거부하여 동시 접속을 차단합니다.
  • 환경 변수 관리:
  • ADMIN_USERNAMEADMIN_PASSWORD_HASHMONGODB_URLSESSION_SECRET_KEY 등 민감한 설정 값들은 .env 파일에 저장하고 dotenv 라이브러리를 통해 로드합니다.
  • .gitignore 파일에 .env를 추가하여 이 파일이 Git 저장소에 포함되지 않도록 하여 보안을 강화합니다.
  • IP 주소 및 클라이언트 ID 로깅:
  • 라이센스 검증 요청 시 클라이언트의 IP 주소와 client_id를 수집하고 로그에 기록합니다. 이는 라이센스 사용 패턴을 분석하고 잠재적인 보안 위협(예: 비정상적인 접근 시도)을 감지하는 데 활용될 수 있습니다.
  • robots.txt: 웹 크롤러가 서버의 모든 경로에 접근하지 못하도록 설정하여 불필요한 정보 노출 및 서버 부하를 방지합니다.

3.2. 장애 대응 구조

  • MongoDB 연결 관리:
  • app.on_event("startup") 데코레이터를 사용하여 FastAPI 애플리케이션 시작 시 AsyncIOMotorClient를 통해 MongoDB에 비동기적으로 연결하고 app.db 객체를 초기화합니다.
  • app.on_event("shutdown") 데코레이터에서 app.mongodb_client.close()를 호출하여 애플리케이션 종료 시 MongoDB 연결을 안전하게 해제합니다.
  • 연결 과정에서 발생하는 오류는 logging.info를 통해 기록되어 관리자가 MongoDB 연결 상태를 쉽게 확인할 수 있습니다.
  • Redis 연결 관리:
  • MongoDB와 유사하게 app.on_event("startup")에서 redis.Redis 클라이언트를 초기화하고 ping() 메서드로 연결 상태를 확인합니다.
  • redis.exceptions.ConnectionError 발생 시 Redis 클라이언트를 None으로 설정하고 오류 로그를 남깁니다. 이렇게 함으로써 Redis 연결 실패가 전체 애플리케이션의 중단으로 이어지는 것을 방지하고, Redis가 없는 환경에서도 기본 라이센스 검증(만료 여부 등)은 동작할 수 있도록 합니다.
  • app.on_event("shutdown")에서 Redis 클라이언트가 존재할 경우 app.redis_client.close()를 호출하여 연결을 해제합니다.
  • 컨테이너 재시작 정책:
  • docker-compose.yml의 license-api 및 redis 서비스는 restart: unless-stopped 정책을 가집니다. 이는 컨테이너가 예기치 않게 종료되거나 서버가 재부팅될 때 자동으로 서비스를 재시작하여 시스템의 가용성을 높입니다.
  • 세분화된 로깅:
  • logging.basicConfig를 통해 INFO 레벨 이상의 로그를 기록합니다. logging.infologging.warninglogging.error를 사용하여 시스템의 현재 상태, 잠재적 문제, 심각한 오류를 구분하여 기록합니다.
  • 특히 라이센스 검증 로직에서는 client_id 누락, Redis 연결 오류, MAC 주소 불일치 등 중요한 상황들을 상세히 로깅하여 문제 발생 시 원인 분석에 필요한 충분한 정보를 제공합니다.
  • 만료 라이센스 자동 처리:
  • 관리자 페이지 (/admin) 접근 시, active 상태의 라이센스 중 만료일(expires_at)이 현재 시간(now_kst)보다 이전인 경우 자동으로 status를 expired로 업데이트합니다. 이는 관리자 개입 없이 라이센스 상태를 최신으로 유지합니다.
  • /check 엔드포인트에서도 동일한 로직이 동작하여 클라이언트 요청 시 만료된 라이센스의 상태를 업데이트합니다.
  • 의존성 관리requirements.txt에 모든 Python 의존성을 명확히 정의하여 배포 환경에서 필요한 라이브러리가 정확히 설치되도록 보장합니다.

4. 주요 폴더 및 파일 구조

.
├── .env                  {# 환경 변수 설정 파일 (gitignore에 포함) #}
├── .gitignore            {# Git 버전 관리에서 제외할 파일 지정 #}
├── docker-compose.yml    {# Docker Compose 설정 파일: FastAPI 앱과 Redis 서비스 정의 및 연동 #}
├── dockerfile            {# FastAPI 애플리케이션의 Docker 이미지 빌드 지시: Python 환경, 의존성, 소스 복사 #}
├── images/               {# 정적 파일 (광고 배너 이미지 등) 저장 디렉토리. FastAPI의 StaticFiles를 통해 '/banners' 경로로 제공 #}
│   └── example_banner.png
├── main.py               {# FastAPI 애플리케이션의 핵심 로직: #}
│                         {#   - 라이센스 모델 정의 (Pydantic) #}
│                         {#   - FastAPI 앱 인스턴스화, 미들웨어, 이벤트 핸들러 (DB/Redis 연결/해제) #}
│                         {#   - 관리자 로그인 및 라이센스 관리 UI 엔드포인트 ('/admin', '/admin/login', '/admin/edit') #}
│                         {#   - 라이센스 생성, 삭제, 수정 로직 #}
│                         {#   - 라이센스 유효성 검증 API 엔드포인트 ('/check', '/check/{license_key}') #}
│                         {#   - Redis를 활용한 동시 접속 제어 로직 #}
│                         {#   - MongoDB와의 데이터 상호작용 (비동기) #}
│                         {#   - 시간대(KST) 처리 로직 #}
├── requirements.txt      {# Python 패키지 의존성 목록: FastAPI, Uvicorn, Motor, Redis, Jinja2 등 #}
├── robots.txt            {# 웹 크롤러 접근 제어 파일: 모든 경로 Disallow로 설정하여 검색 엔진 노출 방지 #}
└── templates/            {# Jinja2 템플릿 파일 저장 디렉토리: #}
    ├── admin.html        {# 관리자 페이지의 라이센스 목록 표시, 신규 라이센스 발급 폼, 삭제/수정 버튼 제공 #}
    ├── edit_license.html {# 특정 라이센스 정보 수정 폼 제공 (제품명, 이메일, 만료일 변경 등) #}
    └── login.html        {# 관리자 로그인 페이지 폼 제공 #}

Ran tool

다음은 주요 폴더 및 파일 구조에 대한 설명입니다. 이어서 배포 및 운영 정책에 대해 작성하겠습니다.

Ran tool

5. 배포 및 운영 정책

5.1. 실 배포 환경에서의 통신

  • HTTP/HTTPS 통신: 클라이언트 애플리케이션과 FastAPI 서버 간의 통신은 HTTP 프로토콜을 사용합니다. 실제 운영 환경에서는 보안 강화를 위해 반드시 HTTPS를 적용해야 합니다. 이를 위해 로드 밸런서(예: Nginx, AWS ALB)나 API 게이트웨이에서 SSL/TLS를 종료하고, 내부적으로는 HTTP로 통신하거나, 내부 통신 또한 HTTPS로 암호화할 수 있습니다.
  • 포트 노출docker-compose.yml에서 license-api 서비스는 호스트의 8991번 포트를 컨테이너의 8000번 포트에 매핑하고 있습니다 ("8991:8000"). 클라이언트는 이 호스트의 8991번 포트를 통해 서버에 접근하게 됩니다. Redis는 6379번 포트를 사용합니다.
  • 네트워크 설정playmong_default라는 외부 네트워크를 통해 license-api와 redis 서비스가 통신하도록 설정되어 있습니다. 이는 서비스 간의 격리된 통신 환경을 제공하며, 다른 Docker 컨테이너들과도 쉽게 연동될 수 있습니다.

5.2. 모니터링

  • 애플리케이션 로그 모니터링:
  • FastAPI 애플리케이션은 logging 모듈을 통해 상세한 로그를 출력합니다. MongoDB 및 Redis 연결 상태, 라이센스 검증 요청 및 결과, 하드웨어 바인딩 변경, 동시 접속 차단 등 핵심적인 운영 정보를 INFOWARNINGERROR 레벨로 기록합니다.
  • 실제 배포 환경에서는 이러한 로그들을 중앙 집중식 로깅 시스템(예: ELK Stack, Grafana Loki)으로 수집하여 실시간으로 모니터링하고 분석해야 합니다.
  • 시스템 리소스 모니터링:
  • CPU 사용량, 메모리 사용량, 디스크 I/O, 네트워크 트래픽 등 서버 및 컨테이너의 리소스 사용량을 지속적으로 모니터링해야 합니다. 이는 성능 문제 및 잠재적인 장애를 사전에 감지하는 데 필수적입니다.
  • 데이터베이스 모니터링:
  • MongoDB: 쿼리 성능, 연결 수, 복제 상태, 디스크 사용량 등을 모니터링하여 데이터베이스의 건강 상태를 확인합니다.
  • Redis: 메모리 사용량, 연결된 클라이언트 수, 초당 명령 처리량, 키 만료율 등을 모니터링하여 캐시 서버의 효율성을 진단합니다.
  • Health Check 엔드포인트/ 엔드포인트는 "message": "라이센스 서버 실행중"을 반환하여 서버의 기본 동작 여부를 확인할 수 있는 간단한 Health Check 기능을 제공합니다. 로드 밸런서나 오케스트레이션 도구(예: Kubernetes)에서 이를 활용하여 서비스의 가용성을 판단할 수 있습니다.

5.3. 스케일링 방식

  • FastAPI 서버 (수평 확장):
  • FastAPI는 비동기 처리와 uvicorn의 멀티프로세스 워커 지원 덕분에 수평 확장이 매우 용이합니다. docker-compose.yml의 license-api 서비스를 여러 인스턴스로 복제하고, 그 앞에 로드 밸런서를 두어 트래픽을 분산할 수 있습니다.
  • 로드 밸런서는 클라이언트 요청을 여러 FastAPI 인스턴스로 효율적으로 분배하여 전체 처리량을 증가시키고 단일 장애 지점(SPOF)을 제거합니다.
  • MongoDB (수평/수직 확장):
  • 수평 확장 (샤딩): 데이터 양이 많아지거나 쿼리 부하가 증가할 경우, MongoDB는 샤딩 기능을 통해 데이터를 여러 서버(샤드)에 분산하여 저장하고 처리할 수 있습니다.
  • 수직 확장: 더 강력한 CPU, 더 많은 RAM, 빠른 디스크를 가진 서버로 교체하여 성능을 향상시킬 수 있습니다.
  • 고가용성 (레플리카 셋): 여러 MongoDB 인스턴스를 레플리카 셋으로 구성하여 프라이머리 노드 장애 시 자동으로 세컨더리 노드가 프라이머리로 승격되어 서비스 중단을 최소화합니다.
  • Redis (수평/수직 확장):
  • 수평 확장 (클러스터): Redis 클러스터를 구성하여 데이터를 여러 Redis 인스턴스에 분산하고 처리량을 늘릴 수 있습니다. 이는 특히 대량의 활성 라이센스 키를 관리해야 할 때 유용합니다.
  • 수직 확장: 더 많은 메모리와 CPU를 가진 서버를 사용하여 Redis 성능을 향상시킬 수 있습니다.
  • 고가용성 (Sentinel/Cluster): Redis Sentinel 또는 Redis Cluster를 사용하여 Redis 서버의 고가용성을 확보할 수 있습니다. 장애 발생 시 자동으로 마스터-슬레이브 전환을 수행합니다.
  • 주의사항: Redis의 동시 접속 제어 로직은 setex를 사용하여 특정 라이센스 키에 대한 client_id를 저장합니다. 클러스터 환경에서는 해시 태그(Hash Tag)를 사용하여 특정 라이센스 키와 관련된 데이터가 항상 동일한 Redis 슬롯에 저장되도록 해야 일관성이 유지됩니다.

5.4. 배포 정책

  • 자동화된 배포 파이프라인 (CI/CD): Git 레포지토리에 코드가 푸시되면 자동으로 테스트를 실행하고, Docker 이미지를 빌드하여 컨테이너 레지스트리에 푸시한 후, 배포 환경에 서비스를 업데이트하는 CI/CD 파이프라인을 구축하는 것이 이상적입니다.
  • 롤링 업데이트: 서비스 중단 없이 새로운 버전의 애플리케이션을 배포하기 위해 롤링 업데이트 전략을 사용합니다. 새로운 컨테이너 인스턴스를 점진적으로 배포하고, 기존 인스턴스를 서서히 제거합니다.
  • 환경별 설정: 개발, 스테이징, 운영 환경에 따라 다른 .env 파일을 관리하고, 각 환경에 맞는 데이터베이스 URL, API 키 등을 설정하여 환경 간 격리를 유지합니다.

5.5. 운영 정책

  • 정기적인 백업: MongoDB 데이터는 정기적으로 백업하고, 재해 복구 계획을 수립하여 데이터 손실에 대비합니다.
  • 보안 패치 및 업데이트: 운영체제, Docker, Python 런타임, 설치된 라이브러리(FastAPI, Redis 등)에 대한 보안 패치 및 업데이트를 주기적으로 적용하여 최신 보안 위협으로부터 시스템을 보호합니다.
  • 접근 제어: 관리자 페이지 (/admin) 및 서버에 대한 접근은 엄격하게 통제해야 합니다. VPN, IP 화이트리스트, MFA(Multi-Factor Authentication) 등을 적용하여 무단 접근을 방지합니다.
  • 성능 튜닝: 모니터링 데이터를 기반으로 MongoDB 인덱스 최적화, Redis 설정 튜닝, FastAPI 애플리케이션 코드 최적화 등을 통해 시스템 성능을 지속적으로 향상시킵니다.
  • 장애 복구 계획: 시스템 장애 발생 시 신속하게 복구하기 위한 상세한 절차(장애 감지, 원인 분석, 복구 단계, 검증)를 포함하는 재해 복구 계획(DRP)을 수립해야 합니다.
  • 로그 관리: 로그는 중요한 보안 및 운영 정보를 포함하므로, 로그 보존 정책을 수립하고 무단 접근으로부터 보호해야 합니다.

6. 확장성·유지보수 고려사항

6.1. 확장성 (Scalability)

  • FastAPI 기반의 API Gateway/Microservices:
  • 현재 main.py는 모든 라이센스 관련 로직을 포함하고 있습니다. 향후 시스템이 복잡해지면, FastAPI를 사용하여 API Gateway를 구축하고, 라이센스 발급, 검증, 관리 등 기능을 각각의 마이크로서비스로 분리하여 더욱 유연한 확장을 도모할 수 있습니다.
  • 각 마이크로서비스는 독립적으로 배포 및 스케일링이 가능하며, 특정 서비스의 부하가 증가하더라도 전체 시스템에 미치는 영향을 최소화할 수 있습니다.
  • 비동기 처리의 활용:
  • FastAPI는 async/await 문법을 적극적으로 활용하여 비동기 I/O 작업을 효율적으로 처리합니다. 이는 데이터베이스 조회나 외부 API 호출과 같은 I/O 바운드 작업 시 서버의 응답성을 높여 더 많은 동시 요청을 처리할 수 있게 합니다.
  • Redis 활용 극대화:
  • 현재 Redis는 동시 접속 제어에 주로 사용되지만, 라이센스 검증 과정에서 자주 조회되는 정적 데이터(예: 제품 정보)나 임시 캐싱이 필요한 데이터에 대한 캐시 계층으로 확장하여 MongoDB의 부하를 줄일 수 있습니다.

6.2. 유지보수 고려사항

  • 코드 모듈화 및 재구성 (Refactoring):
  • 현재 main.py 파일 하나에 모든 로직(모델, DB 연결, API 엔드포인트, 관리자 UI 로직)이 응집되어 있습니다. 이는 초기 개발 단계에서는 간편하지만, 코드가 복잡해질수록 가독성과 유지보수성을 저해합니다.
  • 향후 models/routers/services/dependencies/database/ 등의 디렉토리로 코드를 분리하여 각 모듈의 역할을 명확히 하고 응집도를 높여야 합니다.
  • models/: Pydantic 모델 정의
  • routers/: 각 엔드포인트(admin, license check 등)별 라우터 분리
  • services/: 비즈니스 로직(라이센스 생성, 검증, 업데이트 등)
  • database/: MongoDB 및 Redis 연결 및 CRUD 함수
  • dependencies/: 인증/인가 로직, 공통 의존성 주입
  • 테스트 코드 작성:
  • 현재 테스트 코드가 부재합니다. pytest와 httpx (또는 FastAPI의 TestClient)를 사용하여 단위 테스트, 통합 테스트, 엔드투엔드 테스트를 작성해야 합니다.
  • 테스트 코드는 기능 변경 시 기존 기능의 오작동 여부를 빠르게 확인하고, 새로운 기능 개발 시 안정성을 보장하는 데 필수적입니다.
  • API 버전 관리:
  • 클라이언트 애플리케이션과의 호환성을 유지하기 위해 API 변경 시 버전 관리를 도입하는 것이 중요합니다. URL에 버전을 포함하거나 (예: /api/v1/check), Accept 헤더를 활용하는 방법이 있습니다.
  • 문서화:
  • FastAPI는 Swagger UI를 통해 자동으로 API 문서를 생성하지만, 클라이언트 개발자를 위한 상세한 사용 예제, 인증 방법, 오류 코드 등에 대한 추가 문서화를 제공하는 것이 좋습니다.
  • 내부 개발자를 위한 코드 주석, 아키텍처 문서, 데이터베이스 스키마 문서 등도 지속적으로 관리해야 합니다.
  • 코드 컨벤션 및 린트/포맷터 적용:
  • Black (코드 포맷터), isort (임포트 정렬), Flake8 또는 Pylint (린터)와 같은 도구를 CI/CD 파이프라인에 통합하여 코드 품질과 일관성을 자동으로 유지합니다.
  • 환경 변수 주석 및 예시:
  • .env 파일 또는 .env.example 파일에 각 환경 변수가 어떤 역할을 하는지 상세한 주석과 함께 예시 값을 제공하여 새로운 개발자나 운영자가 시스템 설정을 쉽게 이해하고 구성할 수 있도록 합니다.

Ran tool

보고서의 배포 및 운영 정책 부분까지 작성되었습니다. 이제 마지막으로 확장성 및 유지보수 고려사항을 작성하겠습니다.

Ran tool

6. 확장성·유지보수 고려사항

6.1. 확장성 (Scalability)

  • FastAPI 기반의 API Gateway/Microservices:
  • 현재 main.py는 모든 라이센스 관련 로직을 포함하고 있습니다. 향후 시스템이 복잡해지면, FastAPI를 사용하여 API Gateway를 구축하고, 라이센스 발급, 검증, 관리 등 기능을 각각의 마이크로서비스로 분리하여 더욱 유연한 확장을 도모할 수 있습니다.
  • 각 마이크로서비스는 독립적으로 배포 및 스케일링이 가능하며, 특정 서비스의 부하가 증가하더라도 전체 시스템에 미치는 영향을 최소화할 수 있습니다.
  • 비동기 처리의 활용:
  • FastAPI는 async/await 문법을 적극적으로 활용하여 비동기 I/O 작업을 효율적으로 처리합니다. 이는 데이터베이스 조회나 외부 API 호출과 같은 I/O 바운드 작업 시 서버의 응답성을 높여 더 많은 동시 요청을 처리할 수 있게 합니다.
  • Redis 활용 극대화:
  • 현재 Redis는 동시 접속 제어에 주로 사용되지만, 라이센스 검증 과정에서 자주 조회되는 정적 데이터(예: 제품 정보)나 임시 캐싱이 필요한 데이터에 대한 캐시 계층으로 확장하여 MongoDB의 부하를 줄일 수 있습니다.
  • MongoDB의 수평 확장 (샤딩) 및 고가용성 (레플리카 셋):
  • 데이터 양이 많아지거나 쿼리 부하가 증가할 경우, MongoDB는 샤딩(Sharding) 기능을 통해 데이터를 여러 서버(샤드)에 분산하여 저장하고 처리할 수 있습니다.
  • 여러 MongoDB 인스턴스를 레플리카 셋(Replica Set)으로 구성하여 프라이머리 노드 장애 시 자동으로 세컨더리 노드가 프라이머리로 승격되어 서비스 중단을 최소화하고 고가용성을 확보할 수 있습니다.
  • Redis의 클러스터링 및 고가용성 (Sentinel/Cluster):
  • Redis 클러스터를 구성하여 데이터를 여러 Redis 인스턴스에 분산하고 처리량을 늘릴 수 있습니다. 이는 특히 대량의 활성 라이센스 키를 관리해야 할 때 유용합니다.
  • Redis Sentinel 또는 Redis Cluster를 사용하여 Redis 서버의 고가용성을 확보할 수 있습니다. 장애 발생 시 자동으로 마스터-슬레이브 전환을 수행합니다.

6.2. 유지보수 고려사항

  • 코드 모듈화 및 재구성 (Refactoring):
  • 현재 main.py 파일 하나에 모든 로직(모델, DB 연결, API 엔드포인트, 관리자 UI 로직)이 응집되어 있습니다. 이는 초기 개발 단계에서는 간편하지만, 코드가 복잡해질수록 가독성과 유지보수성을 저해합니다.
  • 향후 models/routers/services/dependencies/database/ 등의 디렉토리로 코드를 분리하여 각 모듈의 역할을 명확히 하고 응집도를 높여야 합니다.
  • models/: Pydantic 모델 정의
  • routers/: 각 엔드포인트(admin, license check 등)별 라우터 분리
  • services/: 비즈니스 로직(라이센스 생성, 검증, 업데이트 등)
  • database/: MongoDB 및 Redis 연결 및 CRUD 함수
  • dependencies/: 인증/인가 로직, 공통 의존성 주입
  • 테스트 코드 작성:
  • 현재 테스트 코드가 부재합니다. pytest와 httpx (또는 FastAPI의 TestClient)를 사용하여 단위 테스트, 통합 테스트, 엔드투엔드 테스트를 작성해야 합니다.
  • 테스트 코드는 기능 변경 시 기존 기능의 오작동 여부를 빠르게 확인하고, 새로운 기능 개발 시 안정성을 보장하는 데 필수적입니다.
  • API 버전 관리:
  • 클라이언트 애플리케이션과의 호환성을 유지하기 위해 API 변경 시 버전 관리를 도입하는 것이 중요합니다. URL에 버전을 포함하거나 (예: /api/v1/check), Accept 헤더를 활용하는 방법이 있습니다.
  • 문서화:
  • FastAPI는 Swagger UI를 통해 자동으로 API 문서를 생성하지만, 클라이언트 개발자를 위한 상세한 사용 예제, 인증 방법, 오류 코드 등에 대한 추가 문서화를 제공하는 것이 좋습니다.
  • 내부 개발자를 위한 코드 주석, 아키텍처 문서, 데이터베이스 스키마 문서 등도 지속적으로 관리해야 합니다.
  • 코드 컨벤션 및 린트/포맷터 적용:
  • Black (코드 포맷터), isort (임포트 정렬), Flake8 또는 Pylint (린터)와 같은 도구를 CI/CD 파이프라인에 통합하여 코드 품질과 일관성을 자동으로 유지합니다.
  • 환경 변수 주석 및 예시:
  • .env 파일 또는 .env.example 파일에 각 환경 변수가 어떤 역할을 하는지 상세한 주석과 함께 예시 값을 제공하여 새로운 개발자나 운영자가 시스템 설정을 쉽게 이해하고 구성할 수 있도록 합니다.

모든 요청하신 내용을 바탕으로 기술 보고서를 완성했습니다. 더 필요한 사항이 있으시면 말씀해 주세요.

목차
목차를 불러오는 중...

댓글

Loading...

댓글 로딩 중...

구글 검색