{"id":15074366,"url":"https://github.com/joosomi/aletheia","last_synced_at":"2026-02-13T12:03:04.191Z","repository":{"id":255860523,"uuid":"852614984","full_name":"joosomi/aletheia","owner":"joosomi","description":"[NestJS] gRPC를 활용한 주문을 관리하는 자원 서버와 인증 서버 구현 개인 프로젝트","archived":false,"fork":false,"pushed_at":"2024-10-03T15:31:42.000Z","size":1641,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2025-03-24T16:34:40.611Z","etag":null,"topics":["grpc","mariadb","nestjs","nestjs-microservices","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joosomi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-05T05:45:37.000Z","updated_at":"2024-10-03T15:31:45.000Z","dependencies_parsed_at":"2024-10-13T06:00:25.039Z","dependency_job_id":null,"html_url":"https://github.com/joosomi/aletheia","commit_stats":{"total_commits":29,"total_committers":2,"mean_commits":14.5,"dds":0.06896551724137934,"last_synced_commit":"504a3d75d2e484f5a4fecac61ca31059daeb810a"},"previous_names":["joosomi/aletheia"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joosomi%2Faletheia","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joosomi%2Faletheia/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joosomi%2Faletheia/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joosomi%2Faletheia/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joosomi","download_url":"https://codeload.github.com/joosomi/aletheia/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248271924,"owners_count":21075800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["grpc","mariadb","nestjs","nestjs-microservices","typescript"],"created_at":"2024-09-25T03:32:38.341Z","updated_at":"2026-02-13T12:02:59.151Z","avatar_url":"https://github.com/joosomi.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 📑 **목차**\n\n1. [Quick Start - 서버 구동 가이드](#quick-start---서버-구동-가이드)\n   - [환경 변수 설정 (.env 파일)](#환경-변수-설정-env-파일)\n   - [Docker 실행 가이드](#docker-실행-가이드)\n2. [서버 구동 가이드](#서버-구동-가이드)\n3. [ERD 다이어그램](#erd-다이어그램)\n4. [API Swagger 문서화](#api-swagger-문서화)\n5. [디렉토리 구조](#디렉토리-구조)\n6. [Git Issue를 활용한 Task 관리](#git-issue를-활용한-task-관리)\n\n\u003cbr\u003e\n\n# 👑 Aletheia API\n\n금 거래 및 판매를 위한 주문 관리 서비스입니다.\n\n#### 프로젝트 구조\n\n1. **자원 서버(api)** - 구매, 판매 주문 관리 (주문 CRUD를 위한 RESTful API)\n\n   - 구매 및 판매 주문 생성, 조회, 수정, 삭제 기능을 담당합니다.\n   - JWT 인증을 사용하여 로그인된 사용자만 주문 기능을 이용할 수 있도록 설정되었습니다.\n\n2. **인증 서버(auth)** - 인증 서비스 (gRPC를 통한 인증 처리)\n   - gRPC를 통해 자원 서버와 통신하며, JWT 액세스 토큰을 검증하고 인증된 사용자라면 사용자 정보를 반환합니다.\n   - 회원가입, 로그인, Access Token과 Refresh Token 발급, 로그아웃 기능을 구현하였습니다.\n\n#### 📅 개발 기간\n\n24.09.04 ~ 24.09.11\n\n#### 🛠️ 개발 환경\n\n![NestJS](https://img.shields.io/badge/NestJS-E0234E?style=for-the-badge\u0026logo=nestjs\u0026logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge\u0026logo=typescript\u0026logoColor=white) ![gRPC](https://img.shields.io/badge/gRPC-009688?style=for-the-badge\u0026logo=grpc\u0026logoColor=white) ![MariaDB](https://img.shields.io/badge/MariaDB-003545?style=for-the-badge\u0026logo=mariadb\u0026logoColor=white) ![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white) ![Swagger](https://img.shields.io/badge/Swagger-85EA2D?style=for-the-badge\u0026logo=swagger\u0026logoColor=white) ![JWT](https://img.shields.io/badge/JWT-000000?style=for-the-badge\u0026logo=JSON%20web%20tokens\u0026logoColor=white)\n\n---\n\n## Quick Start - 서버 구동 가이드\n\n### 환경 변수 설정 (.env 파일)\n\n프로젝트 루트 디렉토리에 `.env` 파일을 생성하고, 다음과 같은 환경 변수를 설정하세요:\n\n```bash\n# API Database\nAPI_DB_HOST=\nAPI_DB_PORT=\nAPI_DB_NAME=\nAPI_DB_USER=\nAPI_DB_PASSWORD=\nAPI_DB_ROOT_PASSWORD=\n\n# Auth Database\nAUTH_DB_HOST=\nAUTH_DB_PORT=\nAUTH_DB_NAME=\nAUTH_DB_USER=\nAUTH_DB_PASSWORD=\nAUTH_DB_ROOT_PASSWORD=\n\n# Application Ports\nAPI_PORT=\nAPI_GRPC_PORT=\n\nAUTH_PORT=\nAUTH_GRPC_PORT=\n\n# Other settings\nNODE_ENV=\n\n# JWT\nJWT_SECRET=\nJWT_EXPIRES_IN=\n\nJWT_REFRESH_SECRET=\nJWT_REFRESH_EXPIRES_IN=\n```\n\n---\n\n### Docker 실행 가이드\n\n프로젝트의 데이터베이스 및 필요한 서비스를 Docker로 실행하려면, 아래 단계를 따르세요.\n\n### 1. Docker Compose 설정 확인\n\n루트 디렉토리에 있는 `docker-compose.yml` 파일을 확인하고, `.env` 파일이 제대로 설정되었는지 확인하세요.\n\n### 2. Docker 컨테이너 실행\n\n아래 명령어를 사용하여 Docker 컨테이너를 백그라운드에서 실행합니다:\n\n```bash\ndocker-compose up -d\n```\n\n---\n\n## 서버 구동 가이드\n\n### 1. 패키지 설치\n\nDocker 컨테이너가 실행된 후, 프로젝트의 모든 의존성을 설치해야 합니다.\n\n```bash\nnpm install\n```\n\n### 2. 서버 실행\n\n개별 서버 실행\n\n```\nnpm run start:api\nnpm run start:auth\n```\n\n두 서버 동시에 실행\n\n```\nnpm run start:all\n```\n\n개발 모드 실행\n\n```\nnpm run start:dev:all\n```\n\n---\n\n## ERD 다이어그램\n\n![ERD 다이어그램](/docs/erd.png)\n\n#### **BaseEntity**\n\nLibs에 정의하여, 공통적으로 사용되는 필드 (id, createdAt, updatedAt, deletedAt)를 포함하는 엔티티입니다. 각 테이블에서 이를 상속받아 중복을 줄이고 관리의 편의성을 높였습니다.\n\n#### **인증 서버 (Auth)**:\n\n    •  users 테이블은 사용자 정보를 관리하며, username, password, hashed refreshToken, role 필드를 포함합니다.\n    •  회원 가입을 하면 기본적으로 ‘USER` 역할이 부여됩니다.\n\n    USER (기본 역할):\n    •  회원 가입 시 자동으로 부여됩니다.\n    •  본인의 주문 생성, 조회, 수정, 취소가 가능합니다.\n    •  주문 상태 변경은 제한적으로 가능합니다 (예: 주문 완료 상태로만 변경).\n    ADMIN (관리자 역할):\n    •  모든 사용자의 주문을 조회하고 관리할 수 있습니다.\n    •  주문의 상태를 모든 단계로 변경할 수 있는 권한이 있습니다.\n\n#### **자원 서버 (API)**:\n\n    •  products 테이블은 금의 종류(GOLD_999, GOLD_9999) 및 구매/판매 가격을 관리합니다.\n    •  invoices 테이블은 각 주문 정보를 저장하며, 주문 유형(PURCHASE, SALE) 및 상태(ORDER_COMPLETED, PAYMENT_RECEIVED 등)를 기록합니다.\n    •  invoices는 products와 관계를 맺고 있으며, 사용자의 ID는 JWT 토큰을 통해 전달되어 각 주문에 연결됩니다.\n\n---\n\n## API Swagger 문서화\n\n각 API 서버의 Swagger 문서를 통해 API 명세를 확인할 수 있습니다. 다음 링크를 통해 Swagger UI에 접근할 수 있습니다.\n\n- [인증 서버 Swagger 문서](http://localhost:8888/api-docs) (http://localhost:8888/api-docs)\n- [API 서버 Swagger 문서](http://localhost:9999/api-docs) (http://localhost:9999/api-docs)\n\nSwagger UI를 통해 API 요청을 테스트하고, 각 엔드포인트의 상세 정보를 확인할 수 있습니다. \n\u003cbr\u003e\n![swagger](/docs/authswagger.png)\n![swagger](/docs/apiswagger.png)\n\n\u003cdetails\u003e\n  \u003csummary\u003e🔍 API 명세서\u003c/summary\u003e\n  \n## 1. 인증 API\n\n### 1.1 회원가입\n\n```\nPOST /auth/register\n```\n\n새로운 사용자를 등록합니다.\n\n**요청 본문 예시:**\n\n```json\n{\n  \"username\": \"john_doe\",\n  \"password\": \"strong_password_123\"\n}\n```\n\n**응답:**\n\n- `204 No Content`: 회원가입 성공\n- `400 Bad Request`: 잘못된 요청 (빈 값 또는 잘못된 형식)\n- `409 Conflict`: 이미 존재하는 계정명\n\n### 1.2 로그인\n\n```\nPOST /auth/login\n```\n\n사용자 로그인을 처리합니다.\n\n**요청 본문 예시:**\n\n```json\n{\n  \"username\": \"john_doe\",\n  \"password\": \"strong_password_123\"\n}\n```\n\n**응답:**\n\n- `200 OK`: 로그인 성공 (액세스 토큰과 리프레시 토큰 발급)\n- `400 Bad Request`: 잘못된 요청 (계정명이나 비밀번호가 빈 값)\n- `401 Unauthorized`: 로그인 실패 (아이디 또는 비밀번호 오류)\n\n### 1.3 토큰 갱신\n\n```\nPOST /auth/refresh\n```\n\n리프레시 토큰을 사용해 새로운 액세스 토큰을 발급받습니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {refresh_token}\n```\n\n**응답:**\n\n- `200 OK`: 새로운 액세스 토큰 발급 성공\n- `401 Unauthorized`: 리프레시 토큰이 유효하지 않거나 만료됨\n\n### 1.4 로그아웃\n\n```\nPOST /auth/logout\n```\n\n사용자 로그아웃을 처리합니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**응답:**\n\n- `204 No Content`: 로그아웃 성공\n- `401 Unauthorized`: 토큰이 유효하지 않거나 만료됨\n\n## 2. 주문 API\n\n### 2.1 주문 목록 조회\n\n```\nGET /orders\n```\n\n페이지네이션이 적용된 주문 목록을 조회합니다. 사용자는 본인의 주문만 조회할 수 있으며, 관리자는 모든 주문을 조회할 수 있습니다.\n\n**쿼리 매개변수:**\n\n- `date`: 날짜별 필터링 (YYYY-MM-DD 형식)\n- `limit`: 한 페이지당 항목 수 (기본값: 10)\n- `offset`: 건너뛸 항목 수 (기본값: 0)\n- `orderType`: 주문 유형별 필터링 (PURCHASE: 구매, SALE: 판매)\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**응답:**\n\n- `200 OK`: 주문 목록 조회 성공\n- `400 Bad Request`: 잘못된 입력 정보\n- `401 Unauthorized`: 인증 실패\n\n### 2.2 주문 상세 조회\n\n```\nGET /orders/{orderId}\n```\n\n주문 ID로 금 주문의 상세 정보를 조회합니다. 사용자는 본인의 주문만 조회할 수 있습니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**응답:**\n\n- `200 OK`: 주문 상세 조회 성공\n- `401 Unauthorized`: 인증 실패\n- `403 Forbidden`: 해당 주문에 접근할 권한이 없음\n- `404 Not Found`: 해당 주문을 찾을 수 없음\n\n### 2.3 주문 취소\n\n```\nDELETE /orders/{orderId}\n```\n\n주문을 취소합니다. 본인의 주문만 취소 가능하며, 주문 완료/입금 완료/송금 완료 상태에서만 취소가 가능합니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**응답:**\n\n- `200 OK`: 주문 취소 성공\n- `401 Unauthorized`: 인증 실패\n- `403 Forbidden`: 주문을 취소할 권한이 없음\n- `404 Not Found`: 해당 주문을 찾을 수 없음\n\n### 2.4 금 구매 주문 생성\n\n```\nPOST /orders/purchase\n```\n\n새로운 금 구매 주문을 생성합니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**요청 본문:**\n\n```json\n{\n  \"productType\": \"GOLD_999\",\n  \"quantity\": 10.5,\n  \"deliveryAddress\": \"서울시 강남구 테헤란로 123\",\n  \"recipientName\": \"홍길동\",\n  \"contactNumber\": \"010-1234-5678\",\n  \"postalCode\": \"12345\"\n}\n```\n\n**응답:**\n\n- `201 Created`: 주문 생성 성공\n- `400 Bad Request`: 잘못된 입력 정보\n- `401 Unauthorized`: 인증 실패\n\n### 2.5 금 판매 주문 생성\n\n```\nPOST /orders/sale\n```\n\n새로운 금 판매 주문을 생성합니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**요청 본문:**\n\n```json\n{\n  \"productType\": \"GOLD_999\",\n  \"quantity\": 10.5,\n  \"deliveryAddress\": \"서울시 강남구 테헤란로 123\",\n  \"recipientName\": \"홍길동\",\n  \"contactNumber\": \"010-1234-5678\",\n  \"postalCode\": \"12345\"\n}\n```\n\n**응답:**\n\n- `201 Created`: 주문 생성 성공\n- `400 Bad Request`: 잘못된 입력 정보\n- `401 Unauthorized`: 인증 실패\n\n### 2.6 주문 상태 변경\n\n```\nPATCH /orders/{orderId}/status\n```\n\n주문의 상태를 변경합니다. 관리자는 모든 상태로 변경이 가능하고, 일반 사용자는 주문 완료 상태로만 변경 가능합니다.\n\n**헤더:**\n\n```\nAuthorization: Bearer {access_token}\n```\n\n**요청 본문 예시:**\n\n```json\n{\n  \"status\": \"ORDER_COMPLETED\"\n}\n```\n\n**응답:**\n\n- `200 OK`: 주문 상태 변경 성공\n- `400 Bad Request`: 잘못된 입력 정보 또는 유효하지 않은 상태 변경\n- `401 Unauthorized`: 인증 실패\n- `403 Forbidden`: 주문 상태를 변경할 권한이 없음\n- `404 Not Found`: 해당 주문을 찾을 수 없음\n\u003c/details\u003e\n\n---\n\n### 디렉토리 구조\n\n\u003cdetails\u003e\n  \u003csummary\u003e🔍 디렉토리 구조\u003c/summary\u003e\n\n```\n├── apps\n│   ├── api\n│   │   ├── src\n│   │   │   ├── common\n│   │   │   │   └── pagination-response.interface.ts\n│   │   │   ├── dto\n│   │   │   │   ├── create-order.dto.ts\n│   │   │   │   ├── get-orders.dto.ts\n│   │   │   │   └── update-status.dto.ts\n│   │   │   ├── entities\n│   │   │   │   ├── invoice.entity.ts\n│   │   │   │   └── product.entity.ts\n│   │   │   ├── guards\n│   │   │   │   └── grpc-auth.guard.ts\n│   │   │   ├── main.ts\n│   │   │   ├── order.controller.spec.ts\n│   │   │   ├── order.controller.ts\n│   │   │   ├── order.module.ts\n│   │   │   ├── order.service.ts\n│   │   │   └── proto\n│   │   │       └── auth.proto\n│   │   ├── test\n│   │   │   ├── app.e2e-spec.ts\n│   │   │   └── jest-e2e.json\n│   │   └── tsconfig.app.json\n│   └── auth\n│       ├── src\n│       │   ├── auth-grpc.controller.ts\n│       │   ├── auth.controller.spec.ts\n│       │   ├── auth.controller.ts\n│       │   ├── auth.module.ts\n│       │   ├── auth.service.ts\n│       │   ├── dto\n│       │   │   ├── login.dto.ts\n│       │   │   └── register.dto.ts\n│       │   ├── entities\n│       │   │   └── user.entity.ts\n│       │   ├── guards\n│       │   │   ├── jwt-auth.guard.ts\n│       │   │   └── jwt-refresh.guard.ts\n│       │   ├── main.ts\n│       │   ├── proto\n│       │   │   └── auth.proto\n│       │   └── strategies\n│       │       ├── jwt-auth.strategy.ts\n│       │       ├── jwt-refresh.strategy.ts\n│       │       └── jwt.types.ts\n│       ├── test\n│       │   ├── app.e2e-spec.ts\n│       │   └── jest-e2e.json\n│       └── tsconfig.app.json\n├── db-init\n│   ├── api-init.sh\n│   └── auth-init.sh\n├── docker-compose.yml\n├── libs\n│   └── shared\n│       ├── src\n│       │   ├── database\n│       │   │   ├── base.entity.ts\n│       │   │   └── database.module.ts\n│       │   ├── filters\n│       │   │   └── global-exception.filter.ts\n│       │   ├── index.ts\n│       │   ├── logger\n│       │   │   └── logger.module.ts\n│       │   ├── shared.module.ts\n│       │   ├── shared.service.spec.ts\n│       │   └── shared.service.ts\n│       └── tsconfig.lib.json\n├── nest-cli.json\n├── package-lock.json\n├── package.json\n└── tsconfig.json\n```\n\n\u003c/details\u003e\n\n---\n\n### Git Issue를 활용한 Task 관리\n\n\u003cdetails\u003e\n  \u003csummary\u003e🔍 Git Issue 관리\u003c/summary\u003e\n\n![Issue](/docs/Issue.png)\n\n\u003c/details\u003e\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoosomi%2Faletheia","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoosomi%2Faletheia","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoosomi%2Faletheia/lists"}