Skip to content

Latest commit

 

History

1,110 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PinLog

장소의 좌표보다 그곳을 기억하는 이유를 기록하는 AI 기반 장소 아카이빙 플랫폼

PinLog는 장소와 함께 사용자의 경험·감정·목적을 Context로 기록하고, 장소 이름이 기억나지 않아도 자연어로 다시 찾게 해줍니다. 기록은 익명 컬렉션으로 엮어 공유하며, 타인의 Context 원문은 공개하지 않고 장소와 AI Keyword만 노출합니다.

이 저장소는 포트폴리오와 프로젝트 탐색을 위한 대표 모노레포입니다. Backend, Frontend, AI, Infrastructure, 공식 명세 저장소의 Git 이력을 보존해 한곳에 모았습니다.

PinLog 홈 — 지도 위에 기록한 장소와 자연어 검색

전체 서비스 화면 보기 · 아키텍처 자세히 보기 · 전체 ERD 보기

핵심 기능

  • 맥락 중심 장소 기록: Kakao 장소 검색·지도로 장소를 선택하고 방문 이유와 경험을 Context로 남깁니다.
  • AI 자연어 검색: 임베딩, Keyword, 문자열 검색, LLM 관련도 신호를 결합해 개인 기록을 다시 찾습니다.
  • 이미지 기반 장소 제안: 대화·사진을 분석해 장소 후보와 기록할 맥락을 제안합니다.
  • 익명 컬렉션과 탐색: 기록을 책처럼 묶어 발행하고 다른 사용자의 공개 컬렉션과 선반을 탐색합니다.
  • 개인정보 경계: 타인의 Context 원문과 내부 식별자는 숨기고 공개 가능한 장소·Keyword만 응답합니다.
  • 관측 가능한 GitOps 운영: k3s, Argo CD, Sealed Secrets, Prometheus/Grafana 기반으로 배포와 운영을 자동화합니다.

Product Experience

1. 장소가 아니라 그곳을 기억하는 이유를 기록합니다

장소명·주소 검색 또는 대화 캡처 이미지 분석으로 장소 후보를 찾습니다. 사용자가 장소와 Context를 함께 저장해야 Record가 만들어지므로 위치만 남고 이유가 사라지는 기록을 허용하지 않습니다.

장소 검색·이미지 분석 Context 작성
장소명 검색과 대화 캡처 업로드 선택한 장소에 Context 기록

2. 장소 이름이 기억나지 않아도 당시의 맥락으로 찾습니다

“치즈케이크 한 조각과 진한 커피를 앞에 두고 쉬었던 곳”처럼 사용자가 남긴 Context를 자연어로 검색합니다. AI 서버가 후보를 찾고 Backend가 소유권과 원문을 다시 확인한 뒤 Record 단위 결과를 지도와 함께 제공합니다.

자연어 검색 결과와 지도 위 Record

3. 개인 기록을 책으로 묶고 익명으로 발견합니다

내 Record를 Collection으로 구성하면 지도와 목차를 가진 한 권의 책이 됩니다. 다른 사용자는 공개 Collection의 장소와 공개 Keyword만 볼 수 있으며 작성자의 Context 원문과 내부 ID는 볼 수 없습니다.

익명 Collection 탐색 Collection 상세
다른 사용자의 공개 컬렉션 탐색 지도와 목차로 구성된 컬렉션

4. 내 Collection과 팔로우한 선반을 한곳에서 관리합니다

Library는 내 Collection과 팔로우한 사용자의 선반을 함께 보여줍니다. 팔로우 대상에게 사용자가 직접 별칭을 붙일 수 있고, 같은 선반도 사람마다 다른 이름으로 관리할 수 있습니다.

나의 책장 활동 기록
내 컬렉션과 팔로우한 책장 기록한 장소와 활동 통계

17개 화면을 기능 흐름대로 설명한 Product Tour →

Repository Map

경로 원본 저장소 책임 주요 기술
back/ Team-PinLog/back 인증, 장소·기록·컬렉션·팔로우, AI 오케스트레이션 API Java 21, Spring Boot, PostgreSQL, Redis, Kafka
front/ Team-PinLog/front 지도 기반 기록, 자연어 검색, 컬렉션·피드 UI React 19, TypeScript, Vite, TanStack Query/Router
ai/ Team-PinLog/ai 임베딩·Keyword 판정, 개인 검색, 이미지 장소 제안 Python 3.12, FastAPI, pgvector, LLM/Embedding API
infra/ Team-PinLog/infra Kubernetes 배포, 보안, 관측, 백업, GitOps k3s, Argo CD, Helm, Sealed Secrets, Prometheus/Grafana
specs/ Team-PinLog/docs 제품 정책, AI 설계, 데이터 모델, API 계약 Markdown, Mermaid

cowork, image, seed, mockup, pico-agent는 제품 개발을 지원한 별도 도구·실험 저장소이므로 대표 저장소의 실행 구성에서는 제외했습니다.

System Architecture

flowchart LR
    User[Web User] -->|HTTPS| Edge[Cloudflare Tunnel / Ingress]
    Edge --> Front[React SPA]
    Edge -->|/api/core| Back[Spring Boot API]
    Front --> Kakao[Kakao Maps / Local API]
    Back --> Redis[(Redis)]
    Back --> Core[(PostgreSQL core)]
    Back --> Kafka[(Kafka)]
    Back -->|Internal API| AI[FastAPI AI]
    Kafka --> AI
    AI --> Derived[(PostgreSQL ai + pgvector)]
    AI --> Models[Embedding / LLM / Vision]
    Argo[Argo CD] --> Edge
    Monitor[Prometheus / Grafana / Loki] -. observe .-> Back
    Monitor -. observe .-> AI
Loading

브라우저는 Backend를 통해 개인 데이터와 권한이 필요한 작업을 수행합니다. AI 서버는 외부에 노출되지 않으며 ai 스키마의 파생 데이터만 소유합니다. Backend가 core 도메인, 인증, 최종 응답 조립을 담당해 AI 모델과 개인정보 사이의 신뢰 경계를 유지합니다.

Core Data Model

erDiagram
    MEMBER ||--o{ SOCIAL_ACCOUNT : authenticates
    MEMBER ||--o{ RECORD : owns
    PLACE ||--o{ RECORD : identifies
    RECORD ||--|{ CONTEXT : contains
    MEMBER ||--o{ COLLECTION : creates
    COLLECTION ||--|{ COLLECTION_RECORD : contains
    RECORD ||--o{ COLLECTION_RECORD : included_in
    MEMBER ||--o{ FOLLOW : follows
    CONTEXT ||--o| CONTEXT_AI_STATE : tracks
    CONTEXT ||--o| CONTEXT_EMBEDDING : indexed_as
    CONTEXT ||--o{ CONTEXT_KEYWORD : tagged_with
    KEYWORD_PRESET ||--o{ CONTEXT_KEYWORD : classifies
Loading

Core와 AI 스키마는 같은 PostgreSQL 인스턴스를 사용하지만 소유권과 DB Role을 분리합니다. Context 수정은 기존 행을 덮어쓰지 않고 새 Context를 생성하며, 삭제·수정 중 도착한 AI 결과는 CANCELLED 상태와 저장 직전 재검사로 폐기합니다.

Key Engineering Decisions

검색 신호의 단계적 결합

개인별 pgvector exact cosine 검색을 기본 경로로 두고 질의 재작성·Keyword 재정렬·본문 문자열 검색·LLM 관련도 판정을 강등 가능한 보조 신호로 결합했습니다. 단어형 질의는 별도의 절대 임계값을 적용하고, Record마다 가장 유사한 Context 하나만 남깁니다. 외부 모델 호출이 실패하면 기본 벡터 검색으로 복귀하며, 오프라인 실측 게이트를 통과한 신호만 운영 환경에 활성화했습니다.

AI 비동기 처리의 stale 결과 차단

Context 저장 요청은 즉시 사용할 수 있도록 먼저 완료하고 Embedding·Keyword 분석은 비동기로 처리합니다. AI 서버는 모델 호출 전후 상태를 검사하고 저장 직전에 짧은 행 잠금을 사용합니다. PENDING → PROCESSING → COMPLETED/FAILED 전이를 단계별로 관리하며, 처리 중 Context가 삭제·교체되면 CANCELLED를 확인해 늦게 도착한 결과를 폐기합니다. Embedding만 성공했다면 Keyword 단계부터 부분 재개합니다.

회전형 Refresh Token 동시성 제어

Google·Kakao·Naver OAuth 로그인 뒤 Access·Refresh Token을 HttpOnly Cookie로 전달하고 별도 CSRF Cookie/Header 계약을 적용합니다. Refresh Token은 사용할 때마다 회전하며 이전 토큰 재사용이 감지되면 회원 단위 세션을 폐기합니다. Frontend는 탭 내부 Promise 공유와 Web Locks로 여러 탭의 동시 재발급을 single-flight 처리하고, DB 장애로 발생한 503은 인증 거절인 401과 분리해 세션을 유지합니다.

데이터 무결성과 공개 범위를 같은 모델에서 보장

활성 Record는 Context를 최소 하나, 활성 Collection은 Record를 최소 하나 가져야 합니다. 마지막 Context·Record를 제거할 때는 상위 객체까지 함께 사라질 수 있음을 안내하고 강제 삭제 경로에서만 연쇄 처리합니다. 타인 조회는 활성·발행 상태와 공개 Keyword를 쿼리 단계에서 제한하고, 응답 DTO에서도 내부 Member·Record·Context ID와 Context 원문을 제외합니다.

GitOps와 불변 이미지 배포

각 애플리케이션 CI가 검증된 commit SHA 기반 불변 이미지 태그를 GHCR에 발행하면 Infra 저장소의 후보 검증과 PR을 거쳐 Argo CD가 선언 상태를 k3s 클러스터에 동기화합니다. Cloudflare Tunnel과 Traefik이 공개 진입점을 담당하고, Sealed Secrets·NetworkPolicy·Pod Security·리소스 제한을 배포 선언과 함께 관리합니다. Prometheus·Grafana·Loki로 메트릭과 로그를 관측하며 PostgreSQL 백업·복구 절차를 Runbook으로 고정했습니다.

기술적 문제와 해결 전략

문제 적용한 해결책 사용자·운영 효과
AI 처리 중 Context가 삭제되거나 수정됨 불변 Context ID, 상태 재검사, 저장 직전 행 잠금, CANCELLED 전이 삭제한 기록의 Keyword·Embedding이 검색에 다시 나타나지 않음
짧은 단어와 긴 문장 검색의 점수 분포가 다름 질의 길이별 임계값, 벡터·Keyword·문자열·LLM 신호의 단계적 결합 장소 이름을 몰라도 당시 표현으로 찾되 관련도 낮은 결과를 억제
여러 탭이 Refresh Token을 동시에 회전 Promise 공유, Web Locks, 재사용 감지 시 회원 세션 폐기 정상 사용자는 로그아웃되지 않고 탈취·재사용은 차단
서비스별 배포 버전과 GitOps 선언 불일치 SHA 불변 이미지, 후보 검증, Argo CD 선언 상태 동기화 어떤 코드가 배포됐는지 추적하고 이전 버전으로 되돌리기 쉬움
익명 탐색에서 개인정보가 노출될 위험 공개 Keyword Preset, 타인 조회 전용 Projection, 내부 ID·Context 원문 제외 공개 Collection은 탐색할 수 있지만 작성자의 원문과 신원은 보호

User Flows

flowchart LR
    Login[소셜 로그인] --> Map[지도에서 장소 탐색]
    Map --> Record[장소 + Context 기록]
    Record -. async .-> Analyze[Embedding + Keyword 분석]
    Analyze --> Search[자연어로 내 기록 검색]
    Record --> Collection[기록을 Collection으로 구성]
    Collection --> Feed[익명 발행·탐색]
    Feed --> Follow[선반 팔로우]
Loading

가입·로그인, 장소 기록, Context 관리, AI 검색, 컬렉션 생성·편집, 피드·팔로우, 탈퇴까지의 예외 조건은 전체 유저플로우에 정리되어 있습니다.

Team Contributions

GitHub 이름 역할 주요 작업
@minyongP 박민용 Backend / Data Core 스키마와 Record·Context·Collection·Follow 도메인, 연쇄 삭제·동시성 제어, 지도·피드 조회 성능 개선, 대용량 데이터 벤치마크와 API 계약을 구현했습니다.
@cherry-go-round 홍석호 Backend / Security Google·Kakao·Naver OAuth, Cookie 기반 JWT·Refresh 회전, CSRF와 세션 재사용 방어, 회원 탈퇴 시 공급자 연결 해제 및 인증 장애 계약을 담당했습니다.
@colosair 이정헌 AI / Search Context 임베딩·Keyword 파이프라인, pgvector 개인 검색, 질의 재작성·Keyword 재정렬·문자열 RRF·LLM 관련도 판정, 로그 비식별화와 실측 게이트를 구현했습니다.
@tpals0409 김세민 Infra / DevOps k3s·Argo CD GitOps, 불변 이미지 자동 배포, Sealed Secrets·NetworkPolicy·Pod Security, PostgreSQL 백업, Prometheus/Grafana/Loki 관측 체계를 구축했습니다.
@ghkim1632 김가현 AI Feature / Frontend 이미지 업로드 기반 장소·맥락 제안 기능을 AI–Backend–Frontend 전 구간에 연결하고 검색 결합 신뢰도 게이트와 장소 기록 UI를 구현했습니다.
@TrossYou 유승주 Frontend / UX 지도·검색·피드·책장·컬렉션 화면과 서버 상태 계층을 구현하고 종이·책 메타포의 반응형 UI, 접근성, 폰트·이미지 성능과 상호작용 회귀를 개선했습니다.

Contribution Evidence

Local Development

각 구성요소는 독립 실행·배포 단위를 유지합니다. 환경변수의 실제 값은 저장소에 포함하지 않습니다.

# Backend: Java 21, Docker 필요
cd back
docker compose up -d
./gradlew bootRun

# Frontend: Node.js 22
cd front
npm ci
npm run dev

# AI: Python 3.12, Backend Flyway 완료 후 실행
cd ai
python3.12 -m venv .venv
python -m pip install -r requirements.lock -r requirements-dev.lock
uvicorn app.main:app --port 8000

운영 배포 절차는 infra/README.md, 환경변수 이름과 테스트 명령은 각 하위 디렉터리의 README를 따릅니다.

Documentation

History

back/, front/, ai/, infra/, specs/는 각 원본 저장소의 전체 Git 이력을 subtree 방식으로 보존합니다. 기능 개발과 이슈·PR은 기존 구성요소 저장소에서 확인할 수 있습니다.

About

장소의 맥락을 기록하고 AI 자연어 검색과 익명 컬렉션으로 다시 발견하는 장소 아카이빙 플랫폼

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages