Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: CD

on:
push:
branches: [ main ]

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2

- name: Build Docker image
run: |
docker build -t focussu-backend:latest ./backend
docker tag focussu-backend:latest ${{ secrets.ECR_REPO_URI }}:latest

- name: Push Docker image
run: docker push ${{ secrets.ECR_REPO_URI }}:latest

- name: Run deploy script
run: bash ./deploy/deploy-prod.sh
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ap-northeast-2
BACKEND_IMAGE: ${{ secrets.ECR_REPO_URI }}:latest
SPRING_PROFILES_ACTIVE: prod
RDS_ENDPOINT: ${{ secrets.RDS_ENDPOINT }}
RDS_PORT: ${{ secrets.RDS_PORT }}
RDS_DATABASE: ${{ secrets.RDS_DATABASE }}
RDS_USER: ${{ secrets.RDS_USER }}
RDS_PASSWORD: ${{ secrets.RDS_PASSWORD }}
KAFKA_BOOTSTRAP_SERVERS: ${{ secrets.KAFKA_BOOTSTRAP_SERVERS }}

29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
pull_request:
branches: [ main ]

jobs:
build-only:
runs-on: ubuntu-latest

defaults:
run:
working-directory: ./backend

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin

- name: Grant execute permission to Gradle wrapper
run: chmod +x gradlew

- name: Build without tests
run: ./gradlew build -x test --no-daemon
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# === Secret Config Files (DO NOT COMMIT) ===
/.env
/backend/src/main/resources/application-secret.yml
/backend/src/main/resources/application-dev.yml
/backend/.idea/


Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ RUN gradle clean build -x test --no-daemon
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
EXPOSE 8080
EXPOSE 80
ENTRYPOINT ["java", "-jar", "app.jar"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@MappedSuperclass
@Getter
@Setter
Comment on lines 5 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Base 엔터티에 @Setter 추가는 재고해 볼 필요가 있습니다

BaseEntity@Setter 어노테이션을 추가하면 감사(audit) 필드와 같은 중요 필드에 무분별한 접근이 가능해져 데이터 무결성에 위험을 초래할 수 있습니다.

다음과 같은 접근 방식을 고려해보세요:

  1. 감사 필드(createdAt, updatedAt)는 불변으로 유지
  2. isDeleted 필드는 전용 메서드(예: markAsDeleted())를 통해서만 변경 가능하도록 제한
  3. 필요한 경우 특정 필드에 대해서만 개별적으로 setter를 설정
@MappedSuperclass
@Getter
-@Setter
public abstract class BaseEntity {

    @CreationTimestamp
    @Column(name = "created_at", updatable = false)
    private LocalDateTime createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    @Column(name = "is_deleted")
    private Boolean isDeleted = false;
    
+   public void markAsDeleted() {
+       this.isDeleted = true;
+   }
+   
+   public void restore() {
+       this.isDeleted = false;
+   }
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.LocalDateTime;
@MappedSuperclass
@Getter
@Setter
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import java.time.LocalDateTime;
@MappedSuperclass
@Getter
public abstract class BaseEntity {
@CreationTimestamp
@Column(name = "created_at", updatable = false)
private LocalDateTime createdAt;
@UpdateTimestamp
@Column(name = "updated_at")
private LocalDateTime updatedAt;
@Column(name = "is_deleted")
private Boolean isDeleted = false;
public void markAsDeleted() {
this.isDeleted = true;
}
public void restore() {
this.isDeleted = false;
}
}

public abstract class BaseEntity {

@CreationTimestamp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public class SwaggerConfig {
@Bean
public OpenAPI openAPI() {
Server localServer = new Server()
.url("http://localhost:8080")
.url("http://localhost:80")
.description("Local 서버");

Server prodServer = new Server()
.url("https://focussu-api.life")
.description("개발 서버");
.url("https://focussu-api.com")
.description("프로덕션 서버");

// Bearer 토큰을 위한 스키마 설정
SecurityScheme bearerScheme = new SecurityScheme()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ public class StudyRoomQueryService {
private final StudyRoomRepository studyRoomRepository;

public StudyRoomCreateResponse getStudyRoom(Long id) {
// TODO: 예외 커스텀
StudyRoom studyRoom = studyRoomRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회원입니다."));
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 스터디룸입니다."));
return StudyRoomCreateResponse.from(studyRoom);
}
}
19 changes: 10 additions & 9 deletions backend/src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# src/main/resources/application-dev.yml

server:
port: 8080
port: 80

spring:
config:
import: optional:classpath:application-secret.yml

application:
name: focussu-backend

datasource:
url: jdbc:mysql://focussu-mysql:3306/focussu-db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: admin
password: wlqwndgo1!
Comment on lines +12 to +13
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

평문 비밀번호 노출 주의
개발 환경 설정에 DB 비밀번호(wlqwndgo1!)가 하드코딩되어 있습니다. application-secret.yml 또는 환경 변수로 민감 정보를 분리 관리하는 리팩토링이 필요합니다.

driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
Expand All @@ -31,14 +32,14 @@ spring:
listener:
missing-topics-fatal: false

data:
redis:
port: 6379
host: redis

springdoc:
default-produces-media-type: application/json
api-docs:
resolve-schema-properties: true
swagger-ui:
path: /docs

security:
jwt:
secret-key: de740246db0e808088253b1bbd8afb062dfcf5e661f20cb41cc7283366d1d8fcccbdbacf3ef8af9ac7159c9ac3a4302fc2321dba0d510a5695a62dd9728ea1ade417542d25e6d80312bc66b13852621f3be0a0188c9e122fedb30186455a4ee2f6ad6bf6daac10db65e9386f3bdf099bee7a18f2e1ef572ab212d7c3a87248d5f1e55243559adfc539df7a2d9110840a825ef27d14899ce630eed7e5366485b642d0f516f468b20af3a6bd67051f00be7a27f122c785f80091bcff6e510330a6f3f30629397a4439281559647cd9c6922d560fd2bd158b527357ff01377eb5333ea9e77f48908b9f96781eaa0fc5f67e7fa4d54d6088ef26c61e43ffb647412b
expiration-time: 86400
40 changes: 40 additions & 0 deletions backend/src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# src/main/resources/application-prod.yml

spring:
config:
import: optional:application-secret.yml
Comment on lines +3 to +5
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

시크릿 파일 import 경로 일관성
optional:application-secret.yml 대신 optional:classpath:application-secret.yml로 베이스 설정과 동일하게 classpath 경로를 명시하는 것이 안전합니다.


application:
name: focussu-backend

datasource:
url: jdbc:mysql://${RDS_ENDPOINT}:${RDS_PORT}/${RDS_DATABASE}?serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: none
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect

kafka:
bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS}
properties:
security.protocol: SSL

Comment on lines +22 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Kafka 설정 환경 변수 누락
bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS} 설정이 있으나, CD 워크플로우에서 해당 변수를 전달하지 않습니다. 배포 시 Kafka 시크릿을 추가하거나 설정을 제거해주세요.

server:
port: 80

springdoc:
default-produces-media-type: application/json
api-docs:
resolve-schema-properties: true
swagger-ui:
path: /docs

security:
jwt:
secret-key: ${JWT_SECRET_KEY}
expiration-time: ${JWT_EXPIRATION_TIME}
7 changes: 7 additions & 0 deletions backend/src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# src/main/resources/application.yml

spring:
profiles:
active: prod
config:
import: optional:classpath:application-secret.yml