-
Notifications
You must be signed in to change notification settings - Fork 1
release: v1.0.0 배포를 위한 develop 병합 #146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aad092b
8b7882b
b711de6
f2d055e
ff1fc15
ce6504d
25cf7f1
883c026
f400ea3
681861a
c5c4e9a
0788497
2627af5
222cc2d
5dc72f9
f64df7d
1a3d75f
546d199
23b1795
5f8d315
604607d
bda329e
0966f50
0b28e24
9b246e3
5a20e32
b5c87f7
59ee248
bca7d9b
3dbebd9
83d6301
a388f31
5f1e523
936da34
af82d46
8d27991
f32211f
7acf822
731f6fa
e2b89e0
942a52d
a4f2511
a8d51b3
6fb7aa4
f694b49
023b3ff
26d0d00
22feae1
669b8b2
9e9b055
41df425
4ae67bd
b39f483
e643248
334f904
4ed090c
403434b
ab9f560
54758f9
68c9f3a
98df8d1
df2d122
e26aa0b
daf8850
cb13d94
ad2945f
815046f
6d57329
d44ec3d
f7a7412
ef99218
dc0a167
c47a704
742f4c0
9d51291
d4fcc79
991c732
987371f
8b09fe3
7e2ea72
12042d5
653dc4e
745c565
b5658dd
ab0b065
cc6cd15
155e6d4
9c804e7
816f243
0bc101b
b9cf4d5
ef9bfed
f1ad099
a2c41ed
bdff645
532af74
aca8697
b95a34b
e6b0d4e
4b0f934
50ac470
5e42954
d85e2a3
86d7d5e
6854d7b
a849e2f
cc772a2
833d241
771b3c3
69ca274
6ef7b93
858ff84
9bd0198
a66de85
e4f8039
46b4b0a
4541fd7
50b4b3f
c586cc0
a8957d2
d47fa33
c608e60
e1126cc
131784b
4d528dd
557aca0
d302e9a
8ee1812
709b466
c75bc05
9435d91
05a43c5
f938fec
6792d94
3dea5d8
13068dd
32504b0
f3dd3a4
cda1d00
d7cbf1a
62721f4
b4b4fd1
41eeae2
f4344ba
eb4f28f
4affd4e
bdceacd
bc5c340
1887e25
47b3890
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| .git | ||
| .gradle | ||
| build/ | ||
| out/ | ||
| bin/ | ||
| Dockerfile | ||
| .dockerignore | ||
| README.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "ui": { | ||
| "theme": "ANSI Light" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| name: Pace Project CI/CD # 워크플로우 이름 설정 | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ "main", "develop" ] # 해당 브랜치에 코드가 push될 때만 실행 | ||
|
|
||
| jobs: | ||
| deploy: | ||
| runs-on: ubuntu-latest # 깃허브가 제공하는 최신 우분투 가상 환경에서 작업 | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 # 깃허브 서버로 내 소스 코드를 가져옴 | ||
|
|
||
| - name: Set up JDK 21 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| java-version: '21' | ||
| distribution: 'temurin' | ||
| cache: 'gradle' | ||
|
|
||
| - name: Grant execute permission for gradlew | ||
| run: chmod +x gradlew | ||
|
|
||
| - name: Run Tests with Gradle | ||
| run: ./gradlew test | ||
|
|
||
| - name: Login to Docker Hub | ||
| uses: docker/login-action@v3 # 도커 허브 접속 시도 | ||
| with: | ||
| username: ${{ secrets.DOCKERHUB_USERNAME }} # 깃허브 시크릿에서 아이디 가져옴 | ||
| password: ${{ secrets.DOCKERHUB_TOKEN }} # 깃허브 시크릿에서 토큰 가져옴 | ||
|
|
||
| - name: Build and push Docker image | ||
| uses: docker/build-push-action@v5 # 도커 이미지 빌드 및 전송 | ||
| with: | ||
| context: . # 현재 위치의 파일을 바탕으로 빌드 | ||
| push: true # 빌드 성공 시 도커 허브로 즉시 보냄 | ||
| tags: ${{ secrets.DOCKERHUB_USERNAME }}/pace-project:latest # 이미지 이름과 태그 붙임 | ||
|
|
||
| - name: Prepare directory on EC2 | ||
| uses: appleboy/ssh-action@v1.0.3 | ||
| with: | ||
| host: ${{ secrets.EC2_HOST }} | ||
| username: ${{ secrets.EC2_USERNAME }} | ||
| key: ${{ secrets.EC2_SSH_KEY }} | ||
| script: mkdir -p ~/pace-project/nginx | ||
|
|
||
| - name: Copy docker-compose.yml via scp | ||
| uses: appleboy/scp-action@v0.1.7 | ||
| with: | ||
| host: ${{ secrets.EC2_HOST }} | ||
| username: ${{ secrets.EC2_USERNAME }} | ||
| key: ${{ secrets.EC2_SSH_KEY }} | ||
| source: "docker-compose.yml,nginx/default.conf" # 내 깃허브에 있는 파일 이름 | ||
| target: "~/pace-project" # 서버에 저장될 폴더 이름 | ||
|
|
||
| - name: Deploy to EC2 | ||
| uses: appleboy/ssh-action@v1.0.3 # SSH를 통해 AWS EC2 서버에 접속 | ||
| with: | ||
| host: ${{ secrets.EC2_HOST }} # EC2의 IP 주소로 연결 | ||
| username: ${{ secrets.EC2_USERNAME }} # 접속 계정(보통 ubuntu) 사용 | ||
| key: ${{ secrets.EC2_SSH_KEY }} # .pem 키 내용으로 인증 | ||
| script: | # 접속 후 실행할 명령어들 시작 | ||
| mkdir -p ~/pace-project # 프로젝트 폴더가 없으면 생성 | ||
| cd ~/pace-project # 해당 폴더로 이동 | ||
|
|
||
| docker pull ${{ secrets.DOCKERHUB_USERNAME }}/pace-project:latest # 창고에서 새 이미지 가져옴 | ||
|
|
||
| # 서버에서 사용할 비밀 장부(.env)를 시크릿 값으로 새로 만듦 | ||
| echo "MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}" > .env | ||
| echo "MYSQL_DATABASE=${{ secrets.MYSQL_DATABASE }}" >> .env | ||
| echo "MYSQL_USER=${{ secrets.MYSQL_USER }}" >> .env | ||
| echo "MYSQL_PASSWORD=${{ secrets.MYSQL_PASSWORD }}" >> .env | ||
| echo "REDIS_PASSWORD=${{ secrets.REDIS_PASSWORD }}" >> .env | ||
| echo "JWT_SECRET=${{ secrets.JWT_SECRET }}" >> .env | ||
| echo "KAKAO_CLIENT_ID=${{ secrets.KAKAO_CLIENT_ID }}" >> .env | ||
| echo "KAKAO_REDIRECT_URI=${{ secrets.KAKAO_REDIRECT_URI }}" >> .env | ||
| echo "GOOGLE_MAPS_API_KEY=${{ secrets.GOOGLE_MAPS_API_KEY }}" >> .env | ||
| echo "SEOUL_SUBWAY_API_KEY=${{ secrets.SEOUL_SUBWAY_API_KEY }}" >> .env | ||
| docker-compose up -d --remove-orphans # 새 이미지로 세트 메뉴(DB+앱) 다시 실행 | ||
| docker image prune -f | ||
|
|
||
| # 헬스 체크: 서버가 제대로 떴는지 10번 확인함 | ||
| echo "Starting health check..." | ||
| for i in {1..10}; do | ||
| RESPONSE=$(curl -s -H "Host: pace-server.kro.kr" http://localhost/health) # 내 서버에 안부를 물어봄 | ||
| if [ "$RESPONSE" = "OK" ]; then # 대답이 "OK"면 성공 | ||
| echo "Health check passed!" | ||
| exit 0 | ||
| fi | ||
| echo "Waiting for server... ($i/10)" # 아직 안 떴으면 10초 기다림 | ||
| sleep 10 | ||
| done | ||
| echo "Health check failed." # 10번 다 실패하면 배포 실패 처리 | ||
| exit 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # 빌드 스테이지(eclipse-temurin을 사용하여 jar 파일 생성) | ||
| FROM eclipse-temurin:21-jdk-jammy AS build | ||
|
|
||
| # 컨테이너 내부의 작업 디렉토리를 /app으로 설정 | ||
| WORKDIR /workspace | ||
|
|
||
| # 의존성 캐시 단계 | ||
| COPY gradlew . | ||
| COPY gradle gradle | ||
| COPY settings.gradle build.gradle ./ | ||
|
|
||
| # Gradle 래퍼(/gradlew)에 실행 권한 부여 및 라이브러리 다운로드 | ||
| RUN chmod +x ./gradlew && ./gradlew --no-daemon dependencies | ||
|
|
||
| # 빌드 단계 | ||
| COPY src src | ||
| RUN ./gradlew --no-daemon clean bootJar -x test | ||
|
|
||
| # 실행 단계 | ||
| FROM eclipse-temurin:21-jre-jammy AS runtime | ||
| WORKDIR /app | ||
|
|
||
| # 보안을 위한 비관리자 유저 생성 | ||
| RUN useradd -ms /bin/bash appuser | ||
| USER appuser | ||
|
|
||
| # 빌드 결과물만 복사 | ||
| COPY --from=build /workspace/build/libs/*.jar app.jar | ||
|
|
||
| EXPOSE 8080 | ||
|
|
||
| # 한국 시간 설정 및 실행 | ||
| ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul", "-jar", "app.jar"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,70 @@ | ||
| # Pace_server | ||
| UMC 9기 'Pace' 서비스 server 팀 | ||
| # Pace Server 🏃♂️ | ||
|
|
||
| > **UMC 9기 'Pace' 서버팀** | ||
|
|
||
| ## 📖 프로젝트 개요 | ||
|
|
||
| **Pace**는 사용자의 일정과 이동 경로를 효율적으로 관리할 수 있도록 돕는 모바일 애플리케이션입니다. **카카오 로그인**을 통한 간편한 인증을 지원하며, 대중교통 데이터를 활용한 일정 관리, 경로 추천, 장소 저장 등의 기능을 제공합니다. | ||
|
|
||
| ## 🛠 백엔드 기술 스택 (Tech Stack) | ||
|
|
||
| ### 환경 (Environment) | ||
| *  | ||
| *  | ||
| *  | ||
|
|
||
| ### 데이터베이스 & ORM | ||
| *  | ||
| * **Spring Data JPA** | ||
| * **QueryDSL 5.0** | ||
|
|
||
| ### 보안 & 인증 (Security & Auth) | ||
| * **Spring Security** | ||
| * **OAuth 2.0 (Kakao Login)** | ||
| * **JWT (JSON Web Token)** | ||
|
|
||
| ### API & 문서화 | ||
| * **SpringDoc OpenAPI (Swagger UI)** | ||
| * **WebFlux (WebClient)** - 외부 API 연동 | ||
|
|
||
| ### 유틸리티 (Utilities) | ||
| * **Apache POI** - 엑셀 데이터 처리 (버스/지하철 정보) | ||
| * **Lombok** | ||
|
|
||
| ## 📂 프로젝트 구조 | ||
|
|
||
| ```bash | ||
| src/main/java/com/example/pace | ||
| ├── PaceApplication.java | ||
| ├── domain | ||
| │ ├── auth # 인증 (Kakao, JWT) | ||
| │ ├── member # 회원 관리, 장소 보관함, 설정 | ||
| │ ├── schedule # 일정 및 경로 관리 | ||
| │ ├── terms # 약관 관리 | ||
| │ └── transit # 대중교통 데이터 로직 | ||
| └── global | ||
| ├── apiPayload # 표준 API 응답 구조 | ||
| ├── auth # 시큐리티 설정, Custom User Details | ||
| ├── config # 앱 설정 (Swagger, WebClient 등) | ||
| └── entity # Base Entities | ||
| ``` | ||
|
|
||
| ## ✨ 주요 기능 | ||
|
|
||
| ### 1. 인증 (Authentication) | ||
| * **카카오 로그인**: Kakao OAuth2를 이용한 간편 로그인. | ||
| * **토큰 관리**: Access/Refresh Token 발급 및 재발급(Reissue). | ||
| * **계정 관리**: 로그아웃 및 회원 탈퇴 기능. | ||
|
|
||
| ### 2. 일정 관리 (Schedule Management) | ||
| * **생성/삭제**: 개인 일정 등록 및 삭제. | ||
| * **조회**: 일별, 월별 일정 목록 조회. | ||
| * **경로**: 대중교통 정보를 활용한 일정 경로 관리. | ||
|
|
||
| ### 3. 회원 및 설정 (Member & Settings) | ||
| * **프로필**: 사용자 정보 관리. | ||
| * **장소 보관함**: 자주 가는 장소 즐겨찾기 및 그룹 관리. | ||
| * **온보딩**: 초기 사용자 설정 프로세스. | ||
|
|
||
| ### 4. 대중교통 통합 (Transit Integration) | ||
| * **데이터 로딩**: 버스 및 지하철 데이터(Excel/JSON)를 로드하여 경로 계산에 활용. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,46 +1,97 @@ | ||
| plugins { | ||
| id 'java' | ||
| id 'org.springframework.boot' version '4.0.1' | ||
| id 'io.spring.dependency-management' version '1.1.7' | ||
| id 'java' | ||
| id 'org.springframework.boot' version '4.0.1' | ||
| id 'io.spring.dependency-management' version '1.1.7' | ||
| id 'org.jetbrains.kotlin.jvm' | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
| group = 'com.example' | ||
| version = '0.0.1-SNAPSHOT' | ||
| description = 'Demo project for Spring Boot' | ||
|
|
||
| java { | ||
| toolchain { | ||
| languageVersion = JavaLanguageVersion.of(21) | ||
| } | ||
| toolchain { | ||
| languageVersion = JavaLanguageVersion.of(21) | ||
| } | ||
| } | ||
|
|
||
| configurations { | ||
| compileOnly { | ||
| extendsFrom annotationProcessor | ||
| } | ||
| compileOnly { | ||
| extendsFrom annotationProcessor | ||
| } | ||
| } | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| mavenCentral() | ||
| } | ||
|
|
||
| dependencies { | ||
| implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
| implementation 'org.springframework.boot:spring-boot-starter-security' | ||
| implementation 'org.springframework.boot:spring-boot-starter-security-oauth2-client' | ||
| implementation 'org.springframework.boot:spring-boot-starter-webmvc' | ||
| compileOnly 'org.projectlombok:lombok' | ||
| developmentOnly 'org.springframework.boot:spring-boot-devtools' | ||
| runtimeOnly 'com.mysql:mysql-connector-j' | ||
| annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' | ||
| annotationProcessor 'org.projectlombok:lombok' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-security-oauth2-client-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-security-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' | ||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
| implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||
| implementation 'org.springframework.boot:spring-boot-starter-security' | ||
| implementation 'org.springframework.boot:spring-boot-starter-security-oauth2-client' | ||
|
|
||
| implementation 'org.springframework.boot:spring-boot-starter-web' | ||
| compileOnly 'org.projectlombok:lombok' | ||
| developmentOnly 'org.springframework.boot:spring-boot-devtools' | ||
| runtimeOnly 'com.mysql:mysql-connector-j' | ||
| annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' | ||
| annotationProcessor 'org.projectlombok:lombok' | ||
|
|
||
| testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-security-oauth2-client-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-security-test' | ||
| testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' | ||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||
| testRuntimeOnly 'com.h2database:h2' | ||
|
|
||
| // Swagger UI | ||
| implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.1") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| // jwt | ||
| implementation 'io.jsonwebtoken:jjwt-api:0.12.3' | ||
| implementation 'io.jsonwebtoken:jjwt-impl:0.12.3' | ||
| implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3' | ||
| implementation 'org.springframework.boot:spring-boot-configuration-processor' | ||
|
|
||
| // WebClient | ||
| implementation 'org.springframework.boot:spring-boot-starter-webflux' | ||
|
|
||
| // Excel (Apache POI) | ||
| implementation 'org.apache.poi:poi-ooxml:5.4.0' | ||
|
|
||
| // QueryDSL : OpenFeign | ||
| implementation "io.github.openfeign.querydsl:querydsl-jpa:7.0" | ||
| implementation "io.github.openfeign.querydsl:querydsl-core:7.0" | ||
| annotationProcessor "io.github.openfeign.querydsl:querydsl-apt:7.0:jpa" | ||
| annotationProcessor "jakarta.persistence:jakarta.persistence-api" | ||
| annotationProcessor "jakarta.annotation:jakarta.annotation-api" | ||
|
Comment on lines
+64
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. QueryDSL 의존성 정보가 잘못되었습니다. |
||
|
|
||
| // idk | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" | ||
|
|
||
| // redis | ||
| implementation 'org.springframework.boot:spring-boot-starter-data-redis' | ||
| } | ||
|
|
||
|
|
||
| tasks.named('test') { | ||
| useJUnitPlatform() | ||
| useJUnitPlatform() | ||
| } | ||
|
|
||
| def querydslDir = layout.buildDirectory.dir("generated/querydsl").get().asFile | ||
|
|
||
| // 소스 세트에 생성 경로 추가 | ||
| sourceSets { | ||
| main.java.srcDirs += [querydslDir] | ||
| } | ||
|
|
||
| // 컴파일 시 생성 경로 지정 | ||
| tasks.withType(JavaCompile).configureEach { | ||
| options.generatedSourceOutputDirectory.set(querydslDir) | ||
| } | ||
|
|
||
| // clean 태스크에 생성 폴더 삭제 로직 | ||
| clean.doLast { | ||
| file(querydslDir).deleteDir() | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spring Boot 버전
4.0.1은 존재하지 않는 버전입니다. 최신 안정화 버전(예:3.2.5) 또는 프로젝트에서 사용하기로 한 올바른 버전으로 수정해야 합니다. 현재 설정으로는 빌드가 실패합니다.