EV

한국 충전사업자를 위한 OCPP 화이트라벨 플랫폼 구축 가이드: 개발 기간 60% 단축하는 방법

한국의 EV 충전 인프라는 빠르게 성숙하고 있습니다. 환경부의 무공해차 보급 목표(2030년까지 신차 판매의 30% 이상), 한국전력(KEPCO)의 공공 충전 인프라 확장, 그리고 현대·기아·제네시스의 국산 EV 라인업 확대가 맞물리면서 충전사업자 수는 빠르게 늘고 있습니다.

그런데 충전 인프라 소프트웨어 레이어에서 실제로 경쟁 우위가 결정됩니다. 하드웨어는 SK시그넷, 대영채비, 에버온, 차지비 등 수십 개 업체가 공급합니다. 차별화는 플랫폼입니다 — 운영 대시보드, 과금 엔진, 환경부 보조금 정산 API 연동, 그리고 드라이버 앱.

이 글은 한국 충전사업자가 OCPP 기반 화이트라벨 플랫폼을 처음부터 구축하거나, 기존 플랫폼을 대체하거나, 멀티 테넌트 구조로 확장할 때 마주치는 핵심 아키텍처 결정과 한국 특유의 통합 과제를 다룹니다.


왜 직접 구축하는가: 한국 시장의 맥락

글로벌 OCPP SaaS 플랫폼들은 한국 시장에서 치명적인 공백을 가지고 있습니다.

flowchart TD
    A["글로벌 OCPP SaaS의 한국 공백"] --> B["환경부 보조금 정산 API 미지원"]
    A --> C["한국전력 스마트 충전 요금 체계 미적용"]
    A --> D["카카오페이·네이버페이·토스 결제 미지원"]
    A --> E["한국어 UI/CS 지원 부재"]
    A --> F["ISMS-P / 개인정보보호법 대응 미흡"]
    B --> G["직접 구축 또는 화이트라벨이 합리적"]
    C --> G
    D --> G
    E --> G
    F --> G

반면 자체 OCPP 플랫폼을 보유하면:

접근법 통제권 규모 확장 비용 브랜드 소유권 한국 규제 대응
글로벌 SaaS 낮음 높음 없음 부분적
화이트라벨 리셀러 중간 중간 부분적 제한적
커스텀 OCPP 플랫폼 완전 낮음 완전 완전

충전기 100대 이상을 운영하거나 B2B 멀티 사이트를 관리하는 사업자라면, 자체 플랫폼이 장기적으로 거의 항상 옳은 선택입니다.


1. OCPP 기초: 한국 사업자가 알아야 할 것

OCPP(Open Charge Point Protocol)는 충전기(하드웨어)와 중앙 시스템(백엔드) 사이의 통신을 정의하는 오픈 표준입니다. Open Charge Alliance(OCA)가 관리하며, 충전기의 연결·인증·상태 보고·트랜잭션 처리 방식을 규정합니다.

버전 선택

  • OCPP 1.6 — 현재 한국 시장에서 가장 광범위하게 배포된 버전. WebSocket 기반 JSON. SK시그넷, 대영채비, 에버온 하드웨어 대부분이 지원합니다. 환경부 충전 인프라 보조금 사업의 기준 버전입니다.
  • OCPP 2.0.1 — 차세대 표준. JSON only, 향상된 보안 프로파일, 스마트 충전, 기기 관리. 신규 인증 및 유럽 수출 대상 사업자에게 필요합니다.

한국 시장 권장: 현재 운영 사업자는 OCPP 1.6으로 시작하고, 2.0.1 마이그레이션 경로를 아키텍처 설계 단계부터 고려하십시오.


2. 시스템 아키텍처 — 한국 충전사업자 맞춤

flowchart TD
    A["드라이버 앱\n(iOS / Android)"] --> B["API 게이트웨이\n(FastAPI / REST)"]
    C["운영자 대시보드\n(React 화이트라벨)"] --> B
    B --> D["OCPP 중앙 시스템\n(WebSocket 서버)"]
    B --> E["비즈니스 로직 레이어"]
    D --> F["충전기 이벤트 처리\n(Celery / Kafka)"]
    E --> F
    F --> G["PostgreSQL\n(세션·거래·사용자)"]
    F --> H["Redis\n(실시간 상태·세션)"]
    E --> I["환경부 보조금 API\n정산 연동"]
    E --> J["결제 게이트웨이\n(카카오페이·토스·KG이니시스)"]
    E --> K["한국전력 스마트 충전\n요금 정보 API"]
    E --> L["알림 서비스\n(카카오 알림톡·SMS)"]

컴포넌트별 권장 기술

컴포넌트 역할 권장 기술
OCPP WebSocket 서버 충전기 연결 관리 Python (mobilityhouse/ocpp)
REST API 운영자·드라이버 API FastAPI
세션 매니저 활성 충전 세션 추적 Redis + PostgreSQL
이벤트 버스 비동기 충전기 이벤트 처리 Celery + Redis
과금 엔진 사용량 계산·인보이스 커스텀 + 카카오페이/토스
환경부 API 커넥터 보조금 정산 데이터 전송 FastAPI 어댑터
알림 서비스 충전 시작·종료·오류 알림 카카오 알림톡 API
운영자 대시보드 화이트라벨 관리 UI React / Next.js
드라이버 모바일 앱 최종 사용자 앱 React Native

3. OCPP 중앙 시스템 구축

중앙 시스템은 플랫폼의 심장입니다 — 모든 충전기와 지속적인 WebSocket 연결을 유지합니다.

3.1 Python 기반 OCPP 서버 기본 구조

import asyncio
import websockets
from ocpp.routing import on
from ocpp.v16 import ChargePoint as cp
from ocpp.v16 import call_result
from ocpp.v16.enums import Action, RegistrationStatus
from datetime import datetime

class ChargePoint(cp):

    @on(Action.BootNotification)
    async def on_boot_notification(
        self, charge_point_vendor, charge_point_model, **kwargs
    ):
        return call_result.BootNotificationPayload(
            current_time=datetime.utcnow().isoformat(),
            interval=10,
            status=RegistrationStatus.accepted
        )

    @on(Action.Heartbeat)
    async def on_heartbeat(self):
        return call_result.HeartbeatPayload(
            current_time=datetime.utcnow().isoformat()
        )

    @on(Action.StartTransaction)
    async def on_start_transaction(
        self, connector_id, id_tag, meter_start, timestamp, **kwargs
    ):
        # 세션 DB 기록 + 환경부 API 전송 시작
        session_id = await db.create_session(
            cp_id=self.id,
            connector_id=connector_id,
            id_tag=id_tag,
            meter_start=meter_start
        )
        return call_result.StartTransactionPayload(
            transaction_id=session_id,
            id_tag_info={"status": "Accepted"}
        )

async def on_connect(websocket, path):
    ocpp_id = path.strip("/")
    charge_point = ChargePoint(ocpp_id, websocket)
    await charge_point.start()

async def main():
    server = await websockets.serve(
        on_connect,
        "0.0.0.0",
        9000,
        subprotocols=["ocpp1.6"]
    )
    await server.wait_closed()

asyncio.run(main())

3.2 구현 필수 OCPP 메시지

Core Profile (필수)

  • BootNotification — 충전기가 시스템에 등록
  • Heartbeat — 주기적 생존 신호
  • Authorize — RFID·앱 토큰 검증
  • StartTransaction / StopTransaction — 충전 세션 생명주기
  • MeterValues — 에너지 소비량 보고 (환경부 정산 데이터 핵심)
  • StatusNotification — 충전기 상태 변경

원격 제어 (운영자 필수)

  • RemoteStartTransaction — 대시보드에서 충전 시작
  • RemoteStopTransaction — 원격 충전 중지
  • ChangeAvailability — 커넥터 활성화/비활성화
  • Reset — 충전기 재시작

4. 한국 특유의 핵심 통합: 환경부 보조금 정산 API

이것이 글로벌 OCPP 가이드에서 다루지 않는, 한국 사업자에게 가장 중요한 통합입니다.

환경부 전기차 충전 인프라 보조금을 받는 사업자는 충전 데이터를 환경부 전기차 충전 인프라 관리시스템에 정기적으로 전송해야 합니다. 이 데이터가 보조금 정산의 근거가 됩니다.

flowchart TD
    A["충전기\n(OCPP 1.6)"] -->|"MeterValues\nStartTransaction\nStopTransaction"| B["OCPP 중앙 시스템"]
    B --> C["세션 데이터 정규화\n(kWh, 시간, 사용자)"]
    C --> D["환경부 API 포맷 변환\n(XML / REST)"]
    D --> E["환경부 전기차 충전\n인프라 관리시스템"]
    E -->|"정산 승인"| F["보조금 지급"]
    C --> G["자체 과금 엔진\n(카카오페이·토스 청구)"]
    G --> H["운영자 수익"]

환경부 API 데이터 요건

전송해야 하는 핵심 데이터 포인트:

# 환경부 충전 데이터 전송 스키마 예시
class MeVChargingRecord:
    station_id: str          # 충전소 고유번호 (환경부 등록번호)
    charger_id: str          # 충전기 고유번호
    connector_id: int        # 커넥터 번호
    start_time: datetime     # 충전 시작 시각
    end_time: datetime       # 충전 종료 시각
    energy_kwh: float        # 충전 전력량 (kWh)
    user_id: str             # 사용자 식별자 (카드번호 또는 앱 ID)
    charging_fee: int        # 충전 요금 (원)
    charger_type: str        # 완속/급속 구분

구현 주의사항:

  • MeterValues 주기를 충전 중 60초 이하로 설정 — 환경부 검증 기준
  • StopTransaction의 reason 필드를 반드시 기록 — 비정상 종료 구분
  • 데이터 전송 실패 시 재전송 큐(DLQ) 필수 — 보조금 정산 누락 방지

5. 멀티 테넌트 화이트라벨 구조

복수의 충전사업자를 하나의 플랫폼으로 서비스하는 구조입니다. 각 테넌트(사업자)는 독립된 브랜딩, 데이터, 과금 정책을 가집니다.

5.1 테넌트 데이터 모델

-- 테넌트(충전사업자)
CREATE TABLE tenants (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    slug        TEXT UNIQUE NOT NULL,       -- 예: "greenenergy-korea"
    name        TEXT NOT NULL,             -- 브랜드명
    domain      TEXT,                      -- 커스텀 도메인
    logo_url    TEXT,
    theme       JSONB,                     -- { primary_color, font }
    env_ministry_id TEXT,                  -- 환경부 충전사업자 등록번호
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

-- 충전기는 특정 테넌트에 귀속
CREATE TABLE charge_points (
    id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    tenant_id   UUID REFERENCES tenants(id),
    ocpp_id     TEXT UNIQUE NOT NULL,
    name        TEXT,
    location    JSONB,
    status      TEXT DEFAULT 'Unknown',
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

5.2 테넌트 연결 라우팅

async def on_connect(websocket, path):
    ocpp_id = path.strip("/")

    # 충전기 ID로 테넌트 조회
    tenant = await db.get_tenant_by_ocpp_id(ocpp_id)
    if not tenant:
        await websocket.close(code=1008, reason="미등록 충전기")
        return

    # 테넌트 컨텍스트를 가진 ChargePoint 인스턴스 생성
    cp = TenantAwareChargePoint(ocpp_id, websocket, tenant)
    await cp.start()

6. 한국 결제 게이트웨이 연동

글로벌 플랫폼들이 Stripe만 지원할 때, 한국 드라이버들은 카카오페이, 네이버페이, 토스, KG이니시스를 씁니다.

flowchart TD
    A["충전 완료\n(StopTransaction)"] --> B["과금 엔진\n(kWh × 단가 계산)"]
    B --> C{"결제 수단"}
    C -->|"카카오페이"| D["카카오페이 API\n자동 결제 청구"]
    C -->|"토스페이"| E["토스페이먼츠 API\n빌링키 청구"]
    C -->|"신용카드"| F["KG이니시스 / KCP\n정기 결제"]
    C -->|"법인 후불"| G["월별 인보이스\n이메일 발송"]
    D --> H["충전 영수증\n카카오 알림톡 발송"]
    E --> H
    F --> H
    G --> H

빌링키 기반 자동 결제 구조

한국 충전 앱의 표준 패턴은 최초 앱 등록 시 빌링키를 발급하고, 이후 충전 완료마다 자동 청구하는 것입니다.

async def process_charge_completion(session_id: str):
    session = await db.get_session(session_id)
    tenant = await db.get_tenant(session.tenant_id)

    # 충전량 기반 요금 계산
    energy_kwh = (session.meter_stop - session.meter_start) / 1000
    amount = calculate_fee(energy_kwh, tenant.pricing_policy)

    # 빌링키로 자동 청구
    if session.user.billing_key:
        await kakao_pay.charge(
            billing_key=session.user.billing_key,
            amount=amount,
            order_name=f"충전 요금 ({energy_kwh:.2f}kWh)"
        )

    # 카카오 알림톡 영수증 발송
    await kakao_notify.send(
        phone=session.user.phone,
        template="charging_receipt",
        variables={
            "energy": f"{energy_kwh:.2f}kWh",
            "amount": f"{amount:,}원",
            "duration": session.duration_minutes
        }
    )

    # 환경부 API 전송
    await mev_api.submit_charging_record(session)

7. 운영자 대시보드 — 화이트라벨 핵심 기능

flowchart TD
    A["운영자 대시보드\n(브랜드 커스텀)"] --> B["충전소 지도 뷰\n실시간 상태"]
    A --> C["충전기 상태 모니터링\n(Available/Charging/Faulted)"]
    A --> D["세션 이력 조회\n(날짜·사용자·충전량)"]
    A --> E["과금 정책 설정\n(kWh단가·시간대별·회원등급)"]
    A --> F["환경부 보조금\n정산 현황"]
    A --> G["원격 제어\n(시작·중지·재시작)"]
    A --> H["알림 설정\n(오류·오프라인 알림)"]
    A --> I["수익 보고서\n(일·월·충전소별)"]

8. 배포 아키텍처

flowchart TD
    A["클라이언트 네트워크"] --> B["Load Balancer\n(Nginx)"]
    B --> C["OCPP WebSocket 서버\n(Docker)"]
    B --> D["FastAPI REST 서버\n(Docker)"]
    C --> E["Redis\n(세션·상태 캐시)"]
    C --> F["Celery Workers\n(이벤트 처리)"]
    D --> F
    F --> G["PostgreSQL\n(주 데이터베이스)"]
    F --> H["환경부 API\n커넥터"]
    F --> I["카카오페이·토스\n결제 커넥터"]
    F --> J["카카오 알림톡\n알림 서비스"]

온프레미스 배포 옵션도 지원합니다. 일부 한국 공공기관 충전소 사업자는 데이터 레지던시 요건상 클라우드 외부 배포가 필요합니다.


한국 시장 OCPP 플랫폼 체크리스트

항목 설명
☐ OCPP 1.6 WebSocket 서버 JSON over WebSocket, ocpp1.6 서브프로토콜
☐ 환경부 보조금 정산 API 연동 충전 데이터 자동 전송 + 재전송 큐
☐ 카카오페이 / 토스페이 빌링키 자동 충전 후 결제
☐ 카카오 알림톡 영수증 충전 완료 알림
☐ 한국전력 스마트 충전 요금 시간대별 차등 요금 반영
☐ 멀티 테넌트 구조 복수 사업자 독립 운영
☐ 개인정보보호법(PIPA) 준수 사용자 데이터 암호화·마스킹
☐ ISMS-P 감사 로그 접근 기록·이상 탐지 증적
☐ 원격 제어 API 운영자 대시보드 연동
☐ 오프라인 내성 연결 끊김 시 로컬 세션 지속

마치며

한국 EV 충전 시장에서 소프트웨어 플랫폼은 이미 단순한 "앱"이 아닙니다. 환경부 보조금 정산, 한국전력 요금 체계, 카카오·토스 결제 생태계, 그리고 PIPA·ISMS-P 규제가 교차하는 복합적인 인프라입니다. 글로벌 OCPP SaaS는 이 레이어를 지원하지 않습니다.

Simplico는 FastAPI + OCPP 스택으로 화이트라벨 충전 플랫폼을 구축한 경험을 보유하고 있습니다. 한국 충전사업자로서 플랫폼 구축, 기존 시스템 교체, 또는 멀티 테넌트 확장을 검토 중이라면 대화를 나눠보고 싶습니다.

문의: tum@simplico.net | simplico.net


Simplico Co., Ltd.는 방콕 기반의 소프트웨어 엔지니어링 스튜디오입니다. AI/RAG 애플리케이션, ERP 통합, EV 충전 플랫폼, 사이버보안 툴링을 전문으로 합니다. 태국·일본·글로벌 시장에서 10년 이상의 엔터프라이즈 납품 경험을 보유합니다.