사진과 글을 공유하는 앱의 백엔드 API.
- Rust (stable)
- Poem (HTTP 프레임워크)
- SQLite + sqlx (컴파일 타임 쿼리 검증)
- AWS Lightsail Object Storage (S3 호환) + CDN
- JWT (jsonwebtoken)
- Google OAuth (ID token 서버 측 검증)
imagecrate (JPEG/PNG/WebP 디코딩 및 검증)
cargo runcargo build --release| 메서드 | 경로 | 설명 |
|---|---|---|
POST |
/auth/login/google |
Google id_token → 서버 검증(tokeninfo) → JWT 발급 + 기존 계정 병합 |
GET |
/feed |
공개 피드 |
GET |
/s/:slug |
still 상세 (다중 이미지 포함) |
GET |
/u/:username |
유저 스틸 목록 |
GET |
/u/:username/profile |
유저 공개 프로필(bio 최대 100자) |
| 메서드 | 경로 | 설명 |
|---|---|---|
GET |
/auth/me |
내 정보 |
PUT |
/auth/me |
프로필 수정 (display_name, bio, avatar_url) |
GET |
/stills/mine |
내 스틸 목록 |
POST |
/stills |
스틸 생성 (multi-image body) |
DELETE |
/stills/:id |
스틸 삭제 |
POST |
/images/upload |
이미지 업로드 (multipart, 서버 검증 후 S3 + CDN) |
users : user_id, email, username, google_sub, display_name, avatar_url, bio(≤100)
stills : still_id, slug, user_id, caption, published_at
still_images : image_id, still_id, image_url, image_key, position
still_images는 position 컬럼으로 순서를 보존하는 별도 테이블로 분리해 다중 이미지를 1:N으로 관리한다. 스틸 단건 조회 시 JOIN 후 position 오름차순으로 배열 직렬화.
- 에러 응답 JSON 표준화: 모든 오류를
{ "error": "..." }형태로 통일. 과거에는 일부 경로가 plain text로 내려가 프론트의 JSON 파서가 터지는 문제가 있었다. - S3 ACL 정책 전환: 개별 오브젝트에
public-readACL을 붙이지 않고, 버킷 정책 + BlockPublicAcls 를 유지한 채 CDN URL만 외부 공개한다. 초기에 개별 object ACL로 공개하던 구조를 AWS의 기본 Block Public ACLs 정책과 충돌하지 않게 정리한 결과다. - Google 로그인 흐름: 프론트엔드가 받은
id_token을 서버가 Googletokeninfo엔드포인트로 재검증 →google_sub으로 기존 유저를 찾고 없으면 프로필을 생성, JWT 발급. - 이미지 업로드 검증:
imagecrate로 실제 디코드를 성공해야 저장(content-type 위조 방지). 실패 시 S3 업로드 자체를 스킵.
- GitHub Actions
pushonmaster→ Lightsail 인스턴스에서 직접cargo build --release(Mac arm64 ↔ Linux x86_64 크로스컴파일을 피하기 위함) → systemdinert-api서비스 재시작 → nginx 리버스 프록시 + Let's Encrypt HTTPS
cargo test- 프론트엔드: inert (TanStack Start + React)