# Pennybase - 초경량 파일 기반 오픈소스 BaaS

> Clean Markdown view of GeekNews topic #21959. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=21959](https://news.hada.io/topic?id=21959)
- GeekNews Markdown: [https://news.hada.io/topic/21959.md](https://news.hada.io/topic/21959.md)
- Type: news
- Author: [xguru](https://news.hada.io/@xguru)
- Published: 2025-07-14T09:46:02+09:00
- Updated: 2025-07-14T09:46:02+09:00
- Original source: [github.com/zserge](https://github.com/zserge/pennybase)
- Points: 21
- Comments: 1

## Summary

**Go 표준 라이브러리만으로 약 1,000줄 미만**의 코드로 구현된 초경량 **BaaS(Backend-as-a-Service)** 솔루션으로, 서버 없는 프로토타입이나 소규모 프로젝트에서 **데이터 저장, REST API, 인증·권한 관리**를 바로 활용할 수 있습니다. 모든 데이터와 권한 관리는 사람이 읽을 수 있는 **CSV 파일**을 직접 수정하는 방식이며, 빠른 조회를 위해 최신 레코드의 **파일 오프셋 메모리 인덱스**를 유지합니다. Go 템플릿에 기반한 **HTML 렌더링**, 커스텀 훅 함수로 동작 확장 등 최소한의 기능만을 제공하여 **학습용/간이 개발 환경**에 적합합니다.

## Topic Body

- Go 표준 라이브러리만으로 1,000줄 미만의 코드로 구현된 **초소형 BaaS(Backend-as-a-Service)**  
- Firebase/Supabase/Pocketbase와 유사한 핵심 백엔드 기능을 **로컬 파일** 기반으로 제공  
  - CSV에 버저닝된 레코드를 사용한 **파일 기반 데이터 저장**  
  - JSON을 리턴하는 **REST API**  
  - 세션 쿠키와 Basic Auth 기반의 **인증**   
  - **RBAC** 및 소유자 기반 **권한 시스템** 지원  
  - 스키마 검증  
  - Go 템플릿 기반 **템플릿 렌더링**   
  
### 작동 방식   
- ## 데이터 저장   
  - 모든 데이터를 사람이 읽을 수 있는 **CSV 파일**에 한 행당 한 레코드씩 저장  
  - **첫 번째 컬럼은 레코드 ID**, **두 번째 컬럼은 버전 번호**로 고정  
  - 저장 방식은 **append-only**로, 기존 레코드를 덮어쓰지 않고 업데이트할 때마다 항상 새 버전 행을 추가  
  - 읽기 작업 시 항상 가장 최신 버전의 레코드만 사용  
  - 빠른 조회와 업데이트를 위해, 각 리소스별 **최신 버전 레코드의 파일 오프셋 정보를 메모리 인덱스**로 유지함  
    ```csv  
    s1,1,_permissions,_id,text,,,^.+$  
    s2,1,_permissions,_v,number,1,,  
    s3,1,_permissions,resource,text,,,^.+$  
    s4,1,_permissions,action,text,,,^.+$  
    s5,1,_permissions,field,text,,,^.*$  
    s6,1,_permissions,role,text,,,^.*$  
    s7,1,_users,_id,text,,,^.+$  
    s8,1,_users,_v,number,1,,  
    s9,1,_users,salt,text,,,  
    s10,1,_users,password,text,,,^.+$  
    s11,1,_users,roles,list,,,  
    s12,1,todo,_id,text,,,^.+$  
    s13,1,todo,_v,number,1,,  
    s14,1,todo,description,text,0,0,".+"  
    s15,1,todo,completed,number,0,1,""  
    ```  
- ## 사용자 및 권한 관리  
  - 사용자 인증 정보와 역할(Role) 목록은 `_users.csv` 파일에 저장  
    ```csv  
    admin,1,salt,5V5R4S...====,"admin"  
    alice,1,salt,PXHQWN...====,  
    ```  
  - 모든 리소스와 동일한 CSV 구조이나, 컬렉션명이 `_users`  
  - API로 사용자 생성이 불가하며, 반드시 파일을 직접 편집해야 함  
- ## 권한 관리   
  - 리소스별 접근 제어 규칙을 `_permissions.csv`에서 정의  
    ```csv  
    p1,1,todo,read,,*,"인증된 누구나 ToDo 읽기 가능"  
    p2,1,todo,create,,*,"인증된 누구나 새로운 ToDo 추가 가능"  
    p3,1,todo,update,owner,"admin,editor","admin/editor ToDo 갱신 가능"  
    p4,1,todo,delete,owner,"admin,editor","admin/editor ToDo 삭제 가능"  
    ```  
  - 각 행이 한 개의 권한 규칙을 의미  
  
### REST API   
- `_schemas.csv`에 정의된 리소스(컬렉션)를 기반으로 **REST API**를 자동으로 제공  
- `GET /api/{resource}?sort_by={field}` : 해당 리소스의 모든 레코드를 조회, 정렬 가능   
- `GET /api/{resource}/{id}` : 특정 ID를 가진 단일 레코드 조회  
- `POST /api/{resource}` : 새 레코드 생성, **"create" 권한** 필요  
- `PUT /api/{resource}/{id}` : 기존 레코드 수정, **"update" 권한** 필요  
- `DELETE /api/{resource}/{id}` : 특정 레코드 삭제, **"delete" 권한** 필요  
- `GET /api/events/{resource}` : 해당 리소스의 서버-사이드 이벤트(SSE) 실시간 스트림 구독, **"read" 권한** 필요  
- # 인증 방식  
  - API 요청 인증은 **Basic Auth** 또는 **세션 쿠키** 방식 지원  
  - 세션 쿠키 생성:  
    - `POST /api/login`에 `username`과 `password`를 body에 담아 요청  
    - 응답에 세션 쿠키가 포함되어, 이후 요청 시 자동 인증  
  - 로그아웃:  
    - `/api/logout` 호출 시 세션 무효화 및 쿠키 삭제  
  
### 정적 파일 및 템플릿  
  
- `static` 디렉터리 내에 위치한 **HTML, CSS, JavaScript 등 정적 파일**을 직접 서빙할 수 있음  
  - 예시: `static/index.html` 파일을 `http://서버주소/index.html`로 접근 가능  
- 추가로, Go의 `html/template` 패키지를 활용하여 **HTML 템플릿 렌더링**도 지원함  
  - 템플릿 파일은 `templates` 디렉터리에 위치하며, URL로 접근 시 자동 렌더링 제공  
- 템플릿에서 사용할 수 있는 데이터 및 함수  
  - `.User`: 현재 인증된 사용자 정보(인증되지 않았으면 `nil`)  
  - `.Store`: Pennybase의 스토어 인스턴스(리소스 조회, 목록화에 사용)  
  - `.Request`: 현재 HTTP 요청 객체  
  - `.ID`: 접근 중인 리소스의 ID(해당되는 경우)  
  - `.Authorize`: 특정 리소스에 대한 액션 권한을 확인하는 함수  
  
### 훅(Hooks) 기능  
  
- 단일 훅(hook) 함수로 동작을 확장할 수 있음  
- 훅 함수는 **모든 리소스의 생성(create), 수정(update), 삭제(delete)** 작업 시 자동 호출됨  
- # 동작 원리  
  - 훅 함수는 아래 네 가지 인자를 받아 동작:  
    - `trigger`: 액션 종류(예: create, update, delete)  
    - `resource`: 작업 대상 리소스명  
    - `user`: 요청을 수행하는 사용자 정보  
    - `res`: 변경되는 리소스 데이터  
  - **후킹 지점에서 추가 검증 또는 데이터 수정**을 할 수 있음  
    - 예시처럼 메시지 리소스 생성 시 자동으로 author, 생성 시각을 입력  
    - 훅 함수에서 **에러를 반환하면 해당 액션은 즉시 중단**되며, 클라이언트에 에러 응답이 전달됨  
    - 이를 활용해 권한 추가 체크, 데이터 자동 보정, 외부 이벤트 트리거 등 다양한 커스텀 로직 구현 가능  
  
### 제한 및 주의점  
  
- 모든 사용자/권한/스키마 관리는 **CSV 파일 직접 편집 필요**  
- 대규모 데이터, 복잡한 권한 분기, 고성능 분산환경엔 적합하지 않음  
- 외부 라이브러리 없이 오직 표준 Go 코드만으로 동작(학습용/간이용 지향)  
- MIT 라이선스, 소스 코드 및 구조 자유 활용 가능  
- 기여는 환영하지만 **코드 단순성/명료성**을 유지하는 것을 지켜 줄 것. 더 이상의 기능 추가보다는 버그 수정 위주로 관리예정

## Comments



### Comment 41396

- Author: nemorize
- Created: 2025-07-14T22:59:39+09:00
- Points: 1

wow...
