Skip to content

JeongGihun/Project_RoboSenseAPI

Repository files navigation

RoboSense API

부제

High-Performance Sensor Data Processing API for Robotics
(로보틱스를 위한 고성능 센서 데이터 처리 API)

목적

대용량 센서 데이터를 실시간으로 처리 후, 대규모 트래픽 처리 경험을 극한까지 설정 및 최적화
Python과 C++ 병합

개발 타임라인

  • '25. 12. 13 ~ '26. 01. 03 : 프로토 타입 작성
  • '26. 01. 04 : 첫 부하 테스트 진행 [TPS : 26]
  • '26. 01. 04 ~ '26. 01. 11 : Redis 도입, 페이징네이션 도입(Cursor)
  • '26. 01. 11 ~ '26. 01. 18 : Docker Compose 작성, 2번째 부하 테스트 [TPS : 489]
    • FastAPI 5개 + Nginx + Docker
  • '26. 01. 18 ~ '26. 01. 25 : 복합 인덱스 추가, N+1문제 해결, 최적화 여부 확인 [TPS : 653]
  • '26. 01. 25 ~ '26. 02. 01 : 쿼리 최적화, 캐시워밍, Bulk insert 도입, 배치 간격 최적화 [TPS : 1,001]
  • '26. 02. 01 ~ '26. 02. 08 : C++ 모듈 도입 (센서 데이터, stats) [TPS : 1,001]
  • '26. 02. 09 ~ '26. 02. 17 : C++ 모듈 도입 (filtered), C++과 Python 연산 속도 비교
  • '26. 02. 27 : 워커 병렬 도입 (2개)
  • '26. 02. 28 : keepalive 설정
  • '26. 02. 28 ~ '26. 03. 06 : 워커 병렬 실행, asyncpg 도입 [TPS : 1,010]
  • '26. 03. 07 ~ '26. 03. 14 : read_replica + synchronous_commit 도입 -> TPS 오히려 하락해서 제거
  • '26. 03. 15 : AWS EC2 배포 최초 성공
  • '26. 03. 22 : 인터랙티브 API 랜딩페이지 배포, 데이터 초기화 엔드포인트 추가

주요 기능

Method Endpoint 설명
POST /api/robots 로봇 등록
GET /api/robots 로봇 목록 조회 (status 필터 지원)
GET /api/robots/{id} 특정 로봇 상세 조회 (최근 센서 포함)
PUT /api/robots/{id} 로봇 상태/배터리 업데이트
POST /api/sensors 센서 데이터 수집
GET /api/sensors 센서 데이터 조회 (커서 기반 페이징)
GET /api/sensors/{id} 특정 센서 데이터 조회
GET /api/sensors/filtered 이동평균 필터링 (robot_id, sensor_type, field, window_size)
GET /stats 통계 조회 (start_time, end_time)
DELETE /api/reset 전체 데이터 초기화 (로봇 + 센서 + 캐시)

실행 방법

1. PostgreSQL 시작

docker start postgres-robosense

2. 가상환경 생성 및 활성화

python -m venv .venv
.venv\Scripts\activate  # Windows

3. 서버 실행

uvicorn app.main:app --reload

4. API 문서 확인

Swagger UI: http://127.0.0.1:80/docs

5. Locust 부하 테스트

locust -f test/locustfile.py --host=http://localhost:8000

6. Docker 도입 이후

docker compose up -d --build (생성)
docker compose down (삭제)
docker compose ps (상태 조회)
docker compose logs -f fastapi-1 (특정 서비스)
locust -f test/locustfile.py --host=http://localhost (Locust)

7. AWS EC2 배포

My IP 확인 및 수정
ssh -i "키파일경로" ubuntu@퍼블릭IP (접속)
docker compose up -d --build (생성)

프로젝트 구조

RobosenseAPI/
├── app/
│   ├── __init__.py
│   ├── main.py                 # FastAPI 앱 (랜딩페이지 서빙 포함)
│   ├── database.py             # DB 연결 및 세션 관리
│   ├── redis_client.py         # Redis 클라이언트
│   ├── context.py              # 컨텍스트 관리
│   ├── middleware.py            # 미들웨어
│   ├── logging_config.py        # 로깅 설정
│   ├── models/
│   │   ├── __init__.py
│   │   ├── db_models.py        # SQLAlchemy ORM 모델
│   │   ├── sensor.py           # 센서 Pydantic 스키마
│   │   ├── robot.py            # 로봇 Pydantic 스키마
│   │   └── enum.py             # Enum 타입 정의
│   ├── routes/
│   │   ├── __init__.py
│   │   ├── sensor_routes.py    # 센서 데이터 API
│   │   ├── robot_routes.py     # 로봇 관리 API
│   │   └── stats_routes.py     # 통계 API
│   └── utils/
│       └── retry.py            # 재시도 유틸리티
├── cpp_modules/                # C++ 연산 모듈
│   └── sensor_cpp/
│       ├── sensor.cpp          # C++ 직렬화 & 필터링 & 통계 계산
│       ├── sensor.h            # 헤더 파일
│       ├── setup.py            # pybind11 빌드 설정
│       └── test/
│           ├── test_sensor_cpp.py      # pytest 단위 테스트
│           └── test_bindings.py        # Catch2 테스트 (참고용)
├── scripts/
│   ├── quick_mock.py           # Mock 데이터 생성
│   ├── mock_data.py            # Mock 데이터 스크립트
│   └── reset_db.py             # DB 초기화 스크립트
├── test/
│   ├── locustfile.py           # Locust 부하 테스트
│   ├── puttest.py              # PUT 테스트
│   └── test_single_request.py  # 단일 요청 테스트
├── postgres/
│   └── primary/
│       ├── postgresql.conf     # PostgreSQL 설정
│       └── pg_hba.conf         # PostgreSQL 인증 설정
├── images/                     # 아키텍처 다이어그램 등
├── index.html                  # 인터랙티브 API 랜딩페이지
├── Dockerfile                  # FastAPI 이미지 빌드
├── docker-compose.yml          # 전체 시스템 구성
├── nginx.conf                  # Nginx 로드 밸런서 설정
├── performance_test.py         # 성능 테스트
├── requirements.txt            # Python 의존성
├── .env / .env.docker          # 환경 변수 (gitignore)
├── .dockerignore
├── .gitignore
└── README.md

시스템 아키텍처

System Architecture

컨테이너 구성 (총 8개):

  • Nginx: 1개 (리버스 프록시 / 로드 밸런서)
  • FastAPI: 5개 (애플리케이션 서버, 각 Uvicorn 워커 2개)
  • PostgreSQL: 1개 (데이터베이스)
  • Redis: 1개 (캐시 레이어)

기술 스택 / 사용 Tool

  • Python (3.11) / C++ (17)
  • FastAPI + Uvicorn
  • PostgreSQL (16) + SQLAlchemy (Async)
  • Redis (7.1.0)
  • Nginx (리버스 프록시 / 로드 밸런서)
  • Docker / Docker Compose
  • Pybind11 (Python-C++ 바인딩)
  • Locust (부하 테스트)
  • Py-spy (프로파일링)
  • Pytest
  • AWS EC2 (배포)

부하 테스트

  • Week 10 ('26. 01. 04.)
기준 : User 50명, Spawn Rate 5명/초, Data 50,000개
결과 : TPS (26) / Fail (0%)

< 분석사항 >
1. 평균 응답도 늦지만, 특정 타입 / 로봇에 대한 센서 조회가 터무니 없이 늦음
2. 커넥션풀 사이즈 변경 (10,5 -> 50,50) / TPS 변동 없음
3. DB 쿼리 속도 확인 : SELECT(2.5ms), JOIN(33.9) / 문제 없음

< 결론 >
어디서 문제인지 모르겠음. 문제 파악하면서, 당장 조금이라도 줄일 수 있는 방법은 Redis로 변경해보자
  • Week 12 ('26. 01. 18.)
기준 : User 100명, Spawn Rate 10명/초, Data 300개 (데이터 재생성)
변경점 : 페이징네이션, Redis, Docker 도입
결과 : TPS (489) / Fail (0%)

< 분석사항 >
1. TPS가 최대 800까지 상승. 긍정적임
2. 다만 stats에서 1분 단위로 캐시무효화 전략을 할 때마다 TPS가 급격히 낮아짐
3. DB가 늘어남에 따라 속도가 점점 낮아짐

< 결론 >
1. 캐시 워밍업 필요
2. 쿼리 최적화, 커넥션 풀 사이즈 재조정
  • Week 15 ('26. 02. 08.)
기준 : User 500명, Spawn Rate 50명/초, Data 재생성
변경점 : C++ 모듈 도입
결과 : TPS (1,001) / Fail (0%)

< 분석사항 >
1. TPS가 최대 1,001까지 상승. 긍정적임
2. C++ 모듈을 넣었지만, 임팩트 있는 효과는 보지 못함. 그러나 이런 기능이 있고 구현 했다는 것에 의의
3. Py-spy 분석 결과 : PostgreSQL이 98% 병목 (CPU 600%)
4. 배치 간격 최적화 : 1.0s -> 0.3s
5. C++ 도입 간 CMake와 Setup 방식이 있음. 나는 Setup으로 사용함

< 결론 >
1. 모든 엔드포인트가 전부 400~500ms가 소요. 
2. DB 커밋이 주요 병목 (평균 ~70ms → 0.3s 배치로 ~21ms 개선)
3. C++ 효과는 미미(2~3%)하지만 학습 가치 있음
4. 추가 최적화: Nginx keepalive, asyncpg COPY, 워커 병렬화 검토 필요
  • Week 16 ('26. 02. 17.)
기준 : User 100명, Spawn Rate 10명/초, Data 재생성
변경점 : C++ 모듈 도입. 최적화는 하지 않아, 단순 C++과 Python의 속도 차이 비교
C++ 결과 : 720 ~ 880ms / Fail (0%)
Python 결과 : 940 ~ 1100ms / Fail (0%)

< 분석사항 >
1. 우선 filtered 엔드포인트 최적화를 하지 않은 상태인 것을 감안
2. C++과 Python의 경우 전체 20%의 속도 차이를 보임

< 결론 >
1. 해당 엔드포인트 최적화 필요. (측정 시간도 1분 측정 기준이지만, 현실을 기준으로 5초로 변경 필요)
2. 이동평균 계산만으로도 20% 차이라면, 응용 시 굉장한 속도 차이를 보일 것으로 판단
3. 해당 엔드포인트만 계산 시 더 많은 차이를 보일 것으로 예상됨
  • Week 19 ('26. 03. 15.)
기준 : User 500명, Spawn Rate 100명/초
변경점 : read_replica + synchronous_commit 도입
결과 : TPS (927) / Fail (0%)

< 분석사항 >
1. read_replica를 도입해 DB read부분을 향상하려 했지만, 오히려 TPS가 하락
2. read부분이 locust의 17% 정도만 사용. 오히려 오버헤드가 커서 하락한 것으로 추정

< 결론 >
1. 현재 상황에서의 TPS의 극적인 향상은 한계가 보임
2. 전반적인 아키텍쳐 수정 혹은 하드웨어 성능을 올려야 할 것 같음
3. 우선 현 상황 유지하고, 오버헤드를 최소화하면서 배포 준비 예정

회고

  • 10주차 : FastAPI 사용해서 프로그램 만들 때까지, 처음 보는 것들이 너무 많아 힘들다고 생각했는데 산 넘어 산인 것 같다. TPS를 측정하고 분석하니 어디서부터 손을 대야할 지도 모르겠다. 하지만 좌절하지는 않았다. 분명 내가 모르는 어느 지점에서 문제가 생긴 것이고 찾으면 되니. 매주 쉬는 날 없이 개발을 공부하다보니 지친 날도 있지만 그보단 고양감이 올라온다. 다음주에도 깨닫음을 얻을 수 있길.

  • 12주차 : 11주차도 했지만, 중간에 페이징네이션 도입이 필요하다는 것을 느껴 같이 하다보니 생략됨. 우선 내가 CS 지식으로만 알던 것을 도입하다보니 왜 필요하고, 코드 작성도 중요하지만 이를 어떻게 해결할 것인지도 굉장히 중요하다는 것을 깨닫은 2주였다. 그러다 보니 회사에서는 어떻게 도입을 했고 왜 그랬는지 자연스럽게 관심이 간다. 물론 워낙 방대하고, 당장 있는 Task가 있어 전부 알 순 없지만 시간이 가용할 때마다 조사해봐야겠다는 생각이 들었다.

  • 15주차 : 드디어 하고 싶던 C++ 모듈과 Python을 결합해보았다. Python자체가 중요한 부분은 c++로 연산처리하기에 효과적인 TPS의 상승은 없었지만, 굉장히 만족한다. 다만 갈수록 내가 알지 못하는 것, 어떤 부분을 병목 상태인지 해결할 것인지 모르겠다. 더 세부적으로 알아보고 극한으로 올릴 방법에 대해 공부해볼 필요가 있을 듯.

  • 16주차 : C++과 연동하면서 갑자기 어려운 지점들이 나와 쉽지 않았다. 다행히 설날이 겹쳐 많은 시간을 투자했더니, 어느 정도 이해가 되는 부분이 많았다. 놀란 부분은 내가 이론적으로 알고 있던 속도 차이가 실제로 일어났을때다. 전체적으로 29%에다 User도 100으로 설정했으니 C++의 장점을 분명히 알 수 있었다. 물론 Python의 연산에서 중요한 부분은 C++로 실행하지만, 세밀한 옵션에 차이를 두면 좋다는 것도 깨닫았다.

  • 19주차 : 서버를 늘리거나, 부하를 줄이는 등 어려운 기술을 도입하면 조금씩이나마 올라갈 것이란 생각과 다르게 오히려 성능이 하락을 했다. 개발자로서 단순 기술 도입만이 아닌 현 상황과 아키텍쳐를 파악하고 그에 맞는 기술을 도입하는 것이 진정 실력이 있는 사람이란 것을 깨닫았다. 앞으로는 배포와 최적화에 좀 더 비중을 두고 작업해야겠다.

About

High-Performance Sensor Data Processing API for Robotics (로보틱스를 위한 고성능 센서 데이터 처리 API)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors