sori.studio 기술 명세
프로젝트 개요
- 프로젝트명: sori.studio
- 유형: 커스텀 블로그/CMS
- 목표: 개인 블로그 중심 운영, 기존 포털성 링크와 서비스 진입점은 블로그 내부 구조에 통합
- 참조: Ghost(관리자 UX/글쓰기), Thred 테마(사용자 화면)
- 현재 상태: Nuxt 3 초기 스캐폴딩과 PostgreSQL 저장소 계층 구성 완료
- 원격 저장소: https://git.sori.studio/zenn/sori.studio.git
화면 구조
메인 화면 (3단 레이아웃)
| 요소 |
크기/속성 |
| Header |
높이 57px |
| Left Aside |
너비 287px, 최소 높이 calc(100vh - 57px), 패딩 12px 12px 12px 0 |
| Main |
너비 720px, 패딩 32px 24px (헤더), 16px 24px (섹션) |
| Right Aside |
너비 287px, 최소 높이 calc(100vh - 57px), 패딩 20px 0 20px 20px |
메뉴 토글
- 헤더 좌측 아이콘은 브랜드 마크가 아니라 왼쪽 사이드바 열기/닫기 버튼
- 메뉴 상태는 Nuxt/Vue 상태로 관리
- 브라우저에서는
localStorage.MENU_STATE에 open 또는 closed 저장
- 닫힘 상태에서는 왼쪽 사이드바를 숨기고 중앙/오른쪽 컬럼만 표시
공개 화면 색상
- 라이트/다크 모드는 CSS 변수로 관리
- 기본 배경, 패널, 라인, 텍스트, 보조 텍스트, 입력, 강조 버튼 색상을 분리
- 시스템 다크 모드는
prefers-color-scheme: dark 기준으로 우선 대응
- Thred 참고 화면처럼 사이드바와 본문은 같은 화면 안에서 구분되는 패널과 라인으로 표현
Post 페이지
- Main 좌우 패딩: 24px → 20px
- 공개 게시물 본문은 콘텐츠 타입별 컴포넌트로 분리해 추후 스타일 변경이 쉽도록 구성
Page 페이지
- About, Projects, Links, Contact, 서비스 소개 페이지 등 고정 콘텐츠에 사용
- 기본 게시물 목록에는 노출하지 않음
- 헤더와 사이드바를 사용하지 않고 본문 중심 전체 화면으로 표시
- 진입 경로는 추후 메뉴/링크 설정을 통해 연결
레이아웃 파일
컴포넌트 구조
사이트 컴포넌트
콘텐츠 렌더러
데이터베이스 구조
환경 분리 원칙
- 데이터베이스는 PostgreSQL을 기준으로 한다.
- 로컬 개발 환경과 NAS 운영 환경은 서로 다른 DB를 사용
- 로컬 개발 서버는 개발 DB만 연결
- NAS 배포 환경은 운영 DB만 연결
- 운영 DB 접속 정보는 로컬 기본
.env에 기록하지 않음
- DB 관리 도구는 CloudBeaver 등을 사용할 수 있도록 접속 정보를 환경별로 분리
Posts (블로그 글)
| 필드 |
타입 |
설명 |
| id |
UUID |
Primary Key |
| title |
String |
제목 |
| slug |
String |
URL 슬러그 |
| content |
Text |
마크다운 콘텐츠 |
| excerpt |
String |
요약 |
| featured_image |
String nullable |
대표 이미지 |
| status |
Enum |
published/draft/private |
| published_at |
DateTime |
발행일 |
| created_at |
DateTime |
생성일 |
| updated_at |
DateTime |
수정일 |
Pages (고정 페이지)
| 필드 |
타입 |
설명 |
| id |
UUID |
Primary Key |
| title |
String |
제목 |
| slug |
String |
URL 슬러그 |
| content |
Text |
마크다운 콘텐츠 |
| featured_image |
String nullable |
대표 이미지 |
| created_at |
DateTime |
생성일 |
| updated_at |
DateTime |
수정일 |
Tags
| 필드 |
타입 |
설명 |
| id |
UUID |
Primary Key |
| name |
String |
태그명 |
| slug |
String |
URL 슬러그 |
| description |
String |
설명 |
| sort_order |
Integer |
사용자 화면 표시 순서 |
| color |
String |
태그 색상 코드 |
| created_at |
DateTime |
생성일 |
| updated_at |
DateTime |
수정일 |
PostTags (다대다)
| 필드 |
타입 |
설명 |
| post_id |
UUID |
FK → Posts |
| tag_id |
UUID |
FK → Tags |
| created_at |
DateTime |
생성일 |
API 구조
현재 API는 Nuxt server/api 내부에 샘플 데이터 기반으로 구현되어 있다. DB 연결 후 같은 응답 구조를 유지하되 저장소만 교체한다.
백엔드 구성
- 별도
backend/ 앱을 두지 않고 Nuxt/Nitro 서버 기능을 사용
- 공개 API는
server/api에 작성
- 서버 공통 스키마와 샘플 데이터는
server/utils에 작성
- PostgreSQL 연결과 조회 로직은
server/repositories에 작성
DATABASE_URL이 없으면 샘플 데이터 저장소를 사용
- 초기 단계에서는 같은 앱 배포로 관리 비용을 낮춤
- 독립 API 서버가 필요해지는 시점에만 백엔드 분리를 재검토
공개 API (/api/)
GET /api/posts - 게시물 목록
GET /api/posts/:slug - 게시물 상세
GET /api/pages - 고정 페이지 목록
GET /api/pages/:slug - 고정 페이지 상세
GET /api/tags - 태그 목록
관리자 API (/admin/api/)
POST /admin/api/auth/login - 로그인
POST /admin/api/auth/logout - 로그아웃
GET /admin/api/auth/me - 현재 관리자 세션 조회
GET /admin/api/posts - 글 목록
POST /admin/api/posts - 글 작성
GET /admin/api/posts/:id - 글 상세
PUT /admin/api/posts/:id - 글 수정
DELETE /admin/api/posts/:id - 글 삭제
GET /admin/api/tags - 태그 목록
POST /admin/api/tags - 태그 생성
GET /admin/api/tags/:id - 태그 상세
PUT /admin/api/tags/:id - 태그 수정
DELETE /admin/api/tags/:id - 태그 삭제
글 발행/초안/비공개 전환은 현재 PUT /admin/api/posts/:id의 status 값으로 처리한다.
태그 삭제 시 post_tags 연결도 데이터베이스 외래 키 규칙에 따라 함께 삭제된다.
태그 목록은 sort_order ASC, name ASC 기준으로 정렬한다.
태그 color는 #RRGGBB 형식이며 사용자 화면 태그 색상 표시와 배지 배경색에 사용한다.
관리자 글 편집
- 글 작성/수정 화면은 Ghost 스타일을 참고한 블록형 에디터를 사용한다.
- 저장 데이터는 기존
content 필드의 마크다운 문자열을 유지한다.
/ 입력 시 블록 선택 메뉴를 표시한다.
/ 명령 메뉴는 화면 하단 공간이 부족하면 현재 블록 위쪽으로 표시한다.
/ 명령 메뉴가 열린 상태에서 Enter를 누르면 현재 강조된 메뉴 항목을 적용한다.
/ 명령 메뉴가 열린 상태에서 위/아래 방향키로 강조 항목을 이동한다.
- 블록 메뉴는 문단, 제목 2, 제목 3, 인용, 목록, 코드, 구분선을 제공한다.
#, ##, ###, >, - 입력 후 공백을 누르면 현재 블록 타입을 즉시 변환한다.
- 빈 문단에서 Enter를 누르면 다음 빈 문단 블록을 생성한다.
- 빈 블록 placeholder는 현재 활성 블록 또는 첫 빈 블록에만 표시한다.
- 제목은 별도 라벨 영역이 아니라 에디터 상단의 큰 제목 입력으로 표시한다.
- 제목 입력에서 Enter를 누르면 본문 첫 블록으로 포커스를 이동한다.
- 관리자 글 에디터의 실제 입력 텍스트 색상은 placeholder보다 진하게 표시한다.
- 관리자 작성 화면과 공개 본문은 같은 마크다운 렌더링 기준을 사용한다.
관리자 인증
- 초기 관리자 인증은
ADMIN_EMAIL, ADMIN_PASSWORD 환경 변수를 사용
- 로그인 성공 시 httpOnly 세션 쿠키를
/admin 경로에 설정
- 관리자 페이지 접근은
/admin/api/auth/me 확인 후 허용
- 세션 토큰은
ADMIN_PASSWORD 기반 HMAC 서명으로 검증
미디어 관리
업로드 경로 규칙
환경 변수 (.env)
공통 키
환경 파일 기준
| 파일 |
용도 |
DB |
.env.development |
로컬 개발, Git 제외 |
개발 DB |
.env.production |
NAS 운영, Git 제외 |
운영 DB |
.env.example |
공유 예시, Git 포함 |
실제 접속 정보 없음 |
.env.example에는 실제 이메일, 비밀번호, 토큰, 운영 서버 주소를 기록하지 않음
.env.development와 .env.production의 DB 비밀번호와 관리자 비밀번호는 서로 다른 랜덤 값을 사용
- 로컬 개발
DATABASE_URL은 호스트 기준 127.0.0.1:43119를 사용
- NAS Docker 내부
DATABASE_URL은 서비스명 기준 sori-studio-db:5432를 사용
포트 기준
| 용도 |
포트 |
| 로컬 개발 서버 |
43117 |
| NAS Docker 외부 포트 |
43118 |
| 컨테이너 내부 포트 |
3000 |
| PostgreSQL 외부 포트 |
43119 |
버전 관리
- 현재 버전: v0.0.13
- 첫 커밋 이후 변경사항을 커밋할 때마다 패치 버전 증가
- 메이저/마이너 버전은 구조 변경 또는 기능 묶음 단위로 결정