|
| 1 | +# 📒 FlipNote — FlipNote-Group |
| 2 | + |
| 3 | +**FlipNote 서비스의 그룹 백엔드 레포지토리입니다.** |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | + |
| 13 | +--- |
| 14 | + |
| 15 | +## 📑 목차 |
| 16 | + |
| 17 | +- [시작하기](#-시작하기) |
| 18 | +- [환경 변수](#-환경-변수) |
| 19 | +- [실행 및 배포](#-실행-및-배포) |
| 20 | +- [프로젝트 구조](#-프로젝트-구조) |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +## 🚀 시작하기 |
| 25 | + |
| 26 | +### 사전 요구사항 |
| 27 | + |
| 28 | +- **Java** 17 이상 |
| 29 | +- **Gradle** 8 이상 |
| 30 | +- MySQL 8 |
| 31 | +- RabbitMQ |
| 32 | +- gRPC 서비스 (User · Image) 실행 중 |
| 33 | + |
| 34 | +### 설치 |
| 35 | + |
| 36 | +```bash |
| 37 | +./gradlew build |
| 38 | +``` |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## 🔐 환경 변수 |
| 43 | + |
| 44 | +아래 환경 변수를 시스템 또는 배포 환경에 설정합니다. |
| 45 | + |
| 46 | +```application.yml |
| 47 | +# ─── 데이터베이스 ────────────────────────────────────── |
| 48 | +SPRING_DATASOURCE_URL= |
| 49 | +SPRING_DATASOURCE_USERNAME= |
| 50 | +SPRING_DATASOURCE_PASSWORD= |
| 51 | +
|
| 52 | +# ─── RabbitMQ ───────────────────────────────────────── |
| 53 | +RABBITMQ_HOST= |
| 54 | +RABBITMQ_PORT= |
| 55 | +RABBITMQ_USERNAME= |
| 56 | +RABBITMQ_PASSWORD= |
| 57 | +
|
| 58 | +# ─── gRPC 서비스 URL ─────────────────────────────────── |
| 59 | +GRPC_USER_URL= |
| 60 | +GRPC_IMAGE_URL= |
| 61 | +
|
| 62 | +# ─── 이메일 (Resend) ─────────────────────────────────── |
| 63 | +RESEND_API_KEY= |
| 64 | +RESEND_FROM_EMAIL= |
| 65 | +
|
| 66 | +# ─── 기본 이미지 URL ─────────────────────────────────── |
| 67 | +# 그룹 기본 이미지로 사용할 URL로 변경하세요 |
| 68 | +IMAGE_DEFAULT_GROUP= |
| 69 | +
|
| 70 | +# ─── 기타 ───────────────────────────────────────────── |
| 71 | +APP_CLIENT_URL= |
| 72 | +``` |
| 73 | + |
| 74 | +--- |
| 75 | + |
| 76 | +## 🖥️ 실행 및 배포 |
| 77 | + |
| 78 | +### 로컬 개발 서버 실행 |
| 79 | + |
| 80 | +```bash |
| 81 | +./gradlew bootRun |
| 82 | +``` |
| 83 | + |
| 84 | +- HTTP API: `http://localhost:8084` |
| 85 | +- gRPC: `localhost:9094` |
| 86 | +- Swagger: `http://localhost:8084/groups/swagger-ui.html` |
| 87 | + |
| 88 | +### 프로덕션 빌드 |
| 89 | + |
| 90 | +```bash |
| 91 | +./gradlew bootJar |
| 92 | +``` |
| 93 | + |
| 94 | +### 배포 (GitHub Actions) |
| 95 | + |
| 96 | +`main` 브랜치에 push 시 GitHub Actions가 자동으로 아래 과정을 실행합니다. |
| 97 | + |
| 98 | +#### CD (`cd.yml`) — `main` push 시 실행 |
| 99 | + |
| 100 | +1. Docker 이미지 빌드 |
| 101 | +2. GitHub Container Registry(`ghcr.io`)에 push |
| 102 | +3. Slack 알림 (성공/실패) |
| 103 | + |
| 104 | +> 배포에 필요한 시크릿은 GitHub Repository → Settings → Secrets and variables → Actions에 등록해야 합니다. |
| 105 | +
|
| 106 | +| Secret | 설명 | |
| 107 | +| ----------- | --------------------------------- | |
| 108 | +| `ORG_PAT` | GHCR push용 Personal Access Token | |
| 109 | + |
| 110 | +--- |
| 111 | + |
| 112 | +## 📁 프로젝트 구조 |
| 113 | + |
| 114 | +<details> |
| 115 | +<summary>간략화 버전</summary> |
| 116 | + |
| 117 | +``` |
| 118 | +src/main/java/flipnote/group/ |
| 119 | +├── adapter/ # 입출력 어댑터 (REST 컨트롤러, gRPC 엔드포인트, 영속성) |
| 120 | +├── api/ # 공통 응답 형식, 예외 핸들러, DTO |
| 121 | +├── application/ # 유스케이스, 커맨드/결과 포트, 서비스 |
| 122 | +├── domain/ # 도메인 모델, 정책, 이벤트 |
| 123 | +├── global/ # 설정, 상수, 응답 래퍼 |
| 124 | +└── infrastructure/ # 이메일, 메시징(RabbitMQ), QueryDSL 리포지토리 |
| 125 | +``` |
| 126 | +</details> |
| 127 | + |
| 128 | +<details> |
| 129 | +<summary>상세 구조 보기</summary> |
| 130 | + |
| 131 | +``` |
| 132 | +src/main/java/flipnote/group/ |
| 133 | +├── GroupApplication.java # 애플리케이션 진입점 |
| 134 | +│ |
| 135 | +├── adapter/ |
| 136 | +│ ├── in/ |
| 137 | +│ │ ├── grpc/ |
| 138 | +│ │ │ └── GroupCommandService.java # gRPC 서버 엔드포인트 |
| 139 | +│ │ └── web/ # REST 컨트롤러 |
| 140 | +│ │ ├── GroupController.java |
| 141 | +│ │ ├── InviteController.java |
| 142 | +│ │ ├── JoinController.java |
| 143 | +│ │ ├── MeController.java |
| 144 | +│ │ ├── MemberController.java |
| 145 | +│ │ └── PermissionController.java |
| 146 | +│ └── out/ |
| 147 | +│ ├── entity/ # JPA 엔티티 |
| 148 | +│ │ ├── GroupEntity.java |
| 149 | +│ │ ├── GroupMemberEntity.java |
| 150 | +│ │ ├── InviteEntity.java |
| 151 | +│ │ ├── JoinEntity.java |
| 152 | +│ │ ├── PermissionEntity.java |
| 153 | +│ │ └── RoleEntity.java |
| 154 | +│ └── persistence/ # 포트 구현체 (리포지토리 어댑터) |
| 155 | +│ ├── GroupRepositoryAdapter.java |
| 156 | +│ ├── GroupMemberRepositoryAdapter.java |
| 157 | +│ ├── GroupRoleRepositoryAdapter.java |
| 158 | +│ ├── InviteRepositoryAdapter.java |
| 159 | +│ └── JoinRepositoryAdapter.java |
| 160 | +│ |
| 161 | +├── api/ |
| 162 | +│ ├── advice/ |
| 163 | +│ │ └── GlobalExceptionHandler.java |
| 164 | +│ └── dto/ |
| 165 | +│ ├── request/ # 요청 DTO (23개) |
| 166 | +│ └── response/ # 응답 DTO (17개) |
| 167 | +│ |
| 168 | +├── application/ |
| 169 | +│ ├── dto/ # 메시지 DTO (RabbitMQ) |
| 170 | +│ ├── listener/ |
| 171 | +│ │ └── GuestInviteEventListener.java |
| 172 | +│ ├── port/ |
| 173 | +│ │ ├── in/ # 유스케이스 인터페이스 |
| 174 | +│ │ │ ├── command/ # 커맨드 객체 (29개) |
| 175 | +│ │ │ └── result/ # 결과 객체 (17개) |
| 176 | +│ │ └── out/ # 출력 포트 인터페이스 |
| 177 | +│ │ ├── GroupRepositoryPort.java |
| 178 | +│ │ ├── GroupMemberRepositoryPort.java |
| 179 | +│ │ ├── GroupRoleRepositoryPort.java |
| 180 | +│ │ ├── InviteRepositoryPort.java |
| 181 | +│ │ ├── JoinRepositoryPort.java |
| 182 | +│ │ └── NotificationMessagePort.java |
| 183 | +│ └── service/ # 유스케이스 구현체 (23개) |
| 184 | +│ |
| 185 | +├── domain/ |
| 186 | +│ ├── event/ |
| 187 | +│ │ └── GuestInviteCreatedEvent.java |
| 188 | +│ ├── model/ |
| 189 | +│ │ ├── group/ # Group, Category, Visibility, JoinPolicy |
| 190 | +│ │ ├── invite/ # InviteInfo, InviteStatus, InviteResponseStatus |
| 191 | +│ │ ├── join/ # JoinInfo, JoinStatus |
| 192 | +│ │ ├── member/ # MemberInfo, GroupMemberRole |
| 193 | +│ │ ├── permission/ # GroupPermission |
| 194 | +│ │ └── role/ # GroupRole |
| 195 | +│ └── policy/ |
| 196 | +│ ├── BusinessException.java |
| 197 | +│ └── ErrorCode.java |
| 198 | +│ |
| 199 | +├── global/ |
| 200 | +│ ├── config/ # 설정 (Async, Auditing, gRPC, QueryDSL, Swagger 등) |
| 201 | +│ ├── constants/ |
| 202 | +│ │ └── HttpConstants.java |
| 203 | +│ └── response/ |
| 204 | +│ ├── ApiResponse.java |
| 205 | +│ └── ApiResponseAdvice.java |
| 206 | +│ |
| 207 | +└── infrastructure/ |
| 208 | + ├── email/ |
| 209 | + │ ├── EmailService.java |
| 210 | + │ └── ResendEmailService.java # Resend 이메일 발송 구현체 |
| 211 | + ├── messaging/ |
| 212 | + │ ├── RabbitMQConfig.java |
| 213 | + │ └── GroupJoinRequestMessageProducer.java |
| 214 | + └── persistence/ |
| 215 | + ├── jpa/ # Spring Data JPA 리포지토리 |
| 216 | + └── querydsl/ # QueryDSL 커스텀 쿼리 구현체 |
| 217 | +
|
| 218 | +src/main/proto/ |
| 219 | +├── group.proto # GroupCommandService (그룹명 조회, 멤버십 확인, 내 그룹 목록) |
| 220 | +├── image.proto # ImageCommandService (이미지 URL 조회/변경) |
| 221 | +└── user.proto # UserQueryService (유저 조회) |
| 222 | +
|
| 223 | +src/main/resources/ |
| 224 | +├── application.yml |
| 225 | +└── templates/email/ |
| 226 | + └── guest-group-invitation.html # 게스트 초대 이메일 템플릿 |
| 227 | +``` |
| 228 | + |
| 229 | +</details> |
0 commit comments