From b713225fd2683f7f38b466714054e1e128eb5bba Mon Sep 17 00:00:00 2001 From: kdh Date: Sat, 4 Jul 2026 22:18:24 +0900 Subject: [PATCH 01/20] =?UTF-8?q?[Setup/#1]=20chore:=20application.yml,=20?= =?UTF-8?q?application-local.yml=20=EA=B8=B0=EB=B3=B8=20=ED=99=98=EA=B2=BD?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application-local.yml | 18 ++++++++++ src/main/resources/application.yml | 46 ++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/application-local.yml diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml new file mode 100644 index 0000000..0906344 --- /dev/null +++ b/src/main/resources/application-local.yml @@ -0,0 +1,18 @@ +# 로컬 환경에서 사용하는 설정 +spring: + # 로컬 DB 접속 정보 (MySQL 사용) + datasource: + url: jdbc:mysql://localhost:3306/myapp?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + hibernate: + ddl-auto: update + show-sql: true + +logging: + level: + org.springframework.security: DEBUG + org.hibernate.SQL: DEBUG \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 11458d8..d7d9d83 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,3 +1,45 @@ spring: - application: - name: capstone + profiles: + active: local + + # 소셜 로그인 (구글, 페이스북 로그인) 설정 + security: + oauth2: + client: + registration: + google: + client-id: ${GOOGLE_CLIENT_ID} + client-secret: ${GOOGLE_CLIENT_SECRET} + scope: + - email + - profile + facebook: + client-id: ${FACEBOOK_CLIENT_ID} + client-secret: ${FACEBOOK_CLIENT_SECRET} + scope: + - email + - public_profile + + jpa: + hibernate: + ddl-auto: validate + properties: + hibernate: + format_sql: true + +custom: + # JWT 설정 + jwt: + secret-key: ${JWT_SECRET} + access-exp-min: ${JWT_ACCESS_EXP_MIN:60} # 토큰 유효시간 : 60분 + refresh-exp-day: ${JWT_REFRESH_EXP_DAY:30} # RT 유효시간 : 30일 + +# Swagger 설정 +springdoc: + swagger-ui: + path: /swagger-ui.html + tags-sorter: alpha # API 그룹 알파벳 순으로 정렬 + operations-sorter: alpha # 각 그룹 안의 API를 알파벳 순으로 정렬 + api-docs: + default-consumes-media-type: application/json # 요청 기본 타입을 JSON으로 설정 + default-produces-media-type: application/json # 응답 기본 타입을 JSON으로 설정 \ No newline at end of file From 30326e06effb43e057db3ee2b3f3e322f6496fd4 Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 09:17:26 +0900 Subject: [PATCH 02/20] =?UTF-8?q?[Setup/#1]=20chore:=20.env.example=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 33 +++++++++++++++++++++++++++++++++ .gitignore | 3 +++ 2 files changed, 36 insertions(+) create mode 100644 .env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..12d6fb7 --- /dev/null +++ b/.env.example @@ -0,0 +1,33 @@ +# Application +APP_BASE_URL=http://localhost:8080 +APP_FRONTEND_BASE_URL=http://localhost:8080 +APP_CORS_ALLOWED_ORIGINS=http://localhost:8080 + +# Database +DB_URL=jdbc:mysql://localhost:3306/loginmodule?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 +DB_USERNAME=root +DB_PASSWORD=change-me +DB_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver +JPA_DDL_AUTO=update +JPA_SHOW_SQL=true + +# JWT +# Must be at least 32 bytes. +JWT_SECRET=change-me-to-at-least-32-bytes-secret +JWT_ACCESS_TOKEN_EXPIRATION=3600000 +JWT_REFRESH_TOKEN_EXPIRATION=604800000 + +# OAuth redirect base +# Default: ${APP_FRONTEND_BASE_URL}/oauth/callback +# OAUTH_REDIRECT_BASE_URI=http://localhost:8080/oauth/callback + +# Google Developer Console +GOOGLE_CLIENT_ID=change-me +GOOGLE_CLIENT_SECRET=change-me +# GOOGLE_REDIRECT_URI=http://localhost:8080/oauth/callback/google + +# Meta for Developers / Facebook Login +FACEBOOK_CLIENT_ID=change-me +FACEBOOK_CLIENT_SECRET=change-me +FACEBOOK_GRAPH_API_VERSION=v21.0 +# FACEBOOK_REDIRECT_URI=http://localhost:8080/oauth/callback/facebook \ No newline at end of file diff --git a/.gitignore b/.gitignore index c2065bc..ab06448 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ out/ ### VS Code ### .vscode/ + +### .env ### +.env \ No newline at end of file From 7eda7852c9eb292e7ab66a00a20e8709997d0d33 Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 09:38:19 +0900 Subject: [PATCH 03/20] =?UTF-8?q?[Setup/#1]=20feat:=20GlobalEntity=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../capstone/global/entity/GlobalEntity.java | 28 +++++++++++++++++++ .../global/entity/GlobalEntityListener.java | 25 +++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java create mode 100644 src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntityListener.java diff --git a/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java new file mode 100644 index 0000000..7f63b85 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java @@ -0,0 +1,28 @@ +package com.daehanforeigner.capstone.global.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; + +import java.time.LocalDateTime; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +@MappedSuperclass +@EntityListeners(GlobalEntity.GlobalEntityBuilder.class) +public class GlobalEntity { + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updatted_at", nullable = false) + private LocalDateTime updatedAt; +} diff --git a/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntityListener.java b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntityListener.java new file mode 100644 index 0000000..be58cbe --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntityListener.java @@ -0,0 +1,25 @@ +package com.daehanforeigner.capstone.global.entity; + +import jakarta.persistence.PrePersist; +import jakarta.persistence.PreUpdate; + +import java.time.LocalDateTime; + +public class GlobalEntityListener { + + @PrePersist + public void prePersist(GlobalEntity entity) { + // 생성일과 수정일을 현재 시간으로 설정해서 저장 + LocalDateTime now = LocalDateTime.now(); + + entity.setCreatedAt(now); + + entity.setUpdatedAt(now); + } + + @PreUpdate + public void preUpdate(GlobalEntity entity) { + // 수정일을 현재 시간으로 설정해서 저장 + entity.setUpdatedAt(LocalDateTime.now()); + } +} From 32a38ee99f8c2c283585b9a85300f14aba7400a6 Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 10:59:53 +0900 Subject: [PATCH 04/20] =?UTF-8?q?[Setup/#1]=20feat:=20user=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/entity/NativeLangauge.java | 8 ++++ .../capstone/domain/user/entity/Role.java | 6 +++ .../capstone/domain/user/entity/Status.java | 6 +++ .../capstone/domain/user/entity/User.java | 47 +++++++++++++++++++ 4 files changed, 67 insertions(+) create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/user/entity/Role.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/user/entity/Status.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java new file mode 100644 index 0000000..efbb3cb --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java @@ -0,0 +1,8 @@ +package com.daehanforeigner.capstone.domain.user.entity; + +public enum NativeLangauge { + EN, // 영어 + CH, // 중국어 + JP, // 일본어 + KR // 한국어 +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Role.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Role.java new file mode 100644 index 0000000..4a9cbc2 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Role.java @@ -0,0 +1,6 @@ +package com.daehanforeigner.capstone.domain.user.entity; + +public enum Role { + USER, + ADMIN +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Status.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Status.java new file mode 100644 index 0000000..f7dd5f2 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/Status.java @@ -0,0 +1,6 @@ +package com.daehanforeigner.capstone.domain.user.entity; + +public enum Status { + ACTIVE, // 활성 + WITHDRAWN // 탈퇴 +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java new file mode 100644 index 0000000..eef4070 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java @@ -0,0 +1,47 @@ +package com.daehanforeigner.capstone.domain.user.entity; + +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "user") +public class User extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") // PK 유저 ID + private int userId; + + @Column(name = "email") // 이메일 + private String email; + + @Column(name = "password") // 비밀번호 (소셜은 null) + private String password; + + @Column(name = "nickname") // 닉네임 + private String nickname; + + @Enumerated(EnumType.STRING) + @Column(name = "native_language") // 모국어 + private NativeLangauge nativeLanguage; + + @Column(name = "profile_image_url") // 프로필 이미지 URL + private String profileImageUrl; + + @Enumerated(EnumType.STRING) + @Column(name = "role") // 권한 (USER, ADMIN) + private Role role; + + @Enumerated(EnumType.STRING) + @Column(name = "status") // 상태 (ACTIVE, WITHDRAWN) + private String status; + + @Column(name = "refresh_token") // 리프레시 토큰 + private String refreshToken; +} From 1c65a117314bd0aea4e2804623a5f7cf41c973dc Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 13:16:39 +0900 Subject: [PATCH 05/20] =?UTF-8?q?[Setup/#1]=20feat:=20social=5Faccount=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../social_account/entity/Provider.java | 6 ++++ .../social_account/entity/Social_account.java | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Provider.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java diff --git a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Provider.java b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Provider.java new file mode 100644 index 0000000..fe4c049 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Provider.java @@ -0,0 +1,6 @@ +package com.daehanforeigner.capstone.domain.social_account.entity; + +public enum Provider { + GOOGLE, + FACEBOOK +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java new file mode 100644 index 0000000..186e2f5 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java @@ -0,0 +1,29 @@ +package com.daehanforeigner.capstone.domain.social_account.entity; + +import com.daehanforeigner.capstone.domain.user.entity.User; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "social_account") +public class Social_account extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "social_id") + private int social_id; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @Enumerated(EnumType.STRING) + @Column(name = "provider") + private Provider provider; +} From a59e895aba7cccbf09f108f3878eb6e585a19dff Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 13:43:42 +0900 Subject: [PATCH 06/20] =?UTF-8?q?[Setup/#1]=20feat:=20content=5Fcategory?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../content_category/ContentCategory.java | 30 +++++++++++++++++++ .../domain/content_category/Type.java | 6 ++++ ...Social_account.java => SocialAccount.java} | 4 +-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java rename src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/{Social_account.java => SocialAccount.java} (89%) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java new file mode 100644 index 0000000..5f91504 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java @@ -0,0 +1,30 @@ +package com.daehanforeigner.capstone.domain.content_category; + +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "content_category") +public class ContentCategory extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "category_id") + private int categoryId; + + @Enumerated(EnumType.STRING) + @Column(name = "type") + private Type type; + + @Column(name = "name") // 카테고리 이름 ex) 학습, 드라마 대사, K문화, 신조어 등 + private String name; + + @Column(name = "description") // 카테고리 설명 + private String description; +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java b/src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java new file mode 100644 index 0000000..4e9cae3 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java @@ -0,0 +1,6 @@ +package com.daehanforeigner.capstone.domain.content_category; + +public enum Type { + BASIC, // 기본 학습 + CULTURE // 문화 학습 +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java similarity index 89% rename from src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java rename to src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java index 186e2f5..e484519 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/Social_account.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java @@ -12,12 +12,12 @@ @NoArgsConstructor @AllArgsConstructor @Table(name = "social_account") -public class Social_account extends GlobalEntity { +public class SocialAccount extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "social_id") - private int social_id; + private int socialId; @ManyToOne @JoinColumn(name = "user_id") From 6b268834935caa601955cb3a43a99f50496a4dd2 Mon Sep 17 00:00:00 2001 From: kdh Date: Mon, 6 Jul 2026 13:54:35 +0900 Subject: [PATCH 07/20] =?UTF-8?q?[Setup/#1]=20feat:=20learning=5Fcontent?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/learning_content/ContentType.java | 7 +++ .../domain/learning_content/Difficulty.java | 7 +++ .../learning_content/LearningContent.java | 44 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/learning_content/Difficulty.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java new file mode 100644 index 0000000..7958785 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java @@ -0,0 +1,7 @@ +package com.daehanforeigner.capstone.domain.learning_content; + +public enum ContentType { + SYLLABUS, // 음절 + WORD, // 단어 + SENTENCE // 문장 +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/Difficulty.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/Difficulty.java new file mode 100644 index 0000000..ca405f5 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/Difficulty.java @@ -0,0 +1,7 @@ +package com.daehanforeigner.capstone.domain.learning_content; + +public enum Difficulty { + BEGINNER, // 초급 + INTERMEDIATE, // 중급 + ADVANCED // 고급 +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java new file mode 100644 index 0000000..4d1e1cb --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java @@ -0,0 +1,44 @@ +package com.daehanforeigner.capstone.domain.learning_content; + +import com.daehanforeigner.capstone.domain.content_category.ContentCategory; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "learning_content") +public class LearningContent { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "content_id") + private int contentId; + + @ManyToOne + @JoinColumn(name = "category_id") + private ContentCategory contentCategory; + + @Enumerated(EnumType.STRING) + @Column(name = "content_type") // 음절, 단어, 문장 + private ContentType contentType; + + @Enumerated(EnumType.STRING) + @Column(name = "difficulty") // 쉬움, 보통, 난이도 + private Difficulty difficulty; + + @Column(name = "text") // 학습 텍스트 + private String text; + + @Column(name = "meaning") // 의미 + private String meaning; + + @Column(name = "example_sentence") // 예문 + private String exampleSentence; + + @Column(name = "pronunciation_guide") // 발음 가이드 + private String pronunciationGuide; +} From 87979a5b6063ccd16ff648c88d3cb598c321da17 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:31 +0900 Subject: [PATCH 08/20] =?UTF-8?q?[Setup/#1]=20feat:=20standard=5Fpronuncia?= =?UTF-8?q?tion=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/audio_file/entity/AudioFile.java | 4 +++ .../domain/feedback/entity/Feedback.java | 32 +++++++++++++++++ .../entity/GameFieldTable.java | 4 +++ .../domain/game_result/entity/GameResult.java | 4 +++ .../phoneme_score/entity/PhonemeScore.java | 4 +++ .../PronunciationAttempt.java | 4 +++ .../domain/ranking/entity/Ranking.java | 4 +++ .../entity/StandardPronunciation.java | 35 +++++++++++++++++++ .../wrong_answer/entity/WrongAnswer.java | 4 +++ 9 files changed, 95 insertions(+) create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java create mode 100644 src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java diff --git a/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java b/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java new file mode 100644 index 0000000..a6c8a57 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.audio_file.entity; + +public class AudioFile { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java b/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java new file mode 100644 index 0000000..ea6efa5 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java @@ -0,0 +1,32 @@ +package com.daehanforeigner.capstone.feedback.entity; + +import com.daehanforeigner.capstone.domain.pronunciation_attempt.PromunciationAttempt; +import com.daehanforeigner.capstone.domain.user.entity.NativeLangauge; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "feedback") +public class FeedBack extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "feedback_id") + private int feedbackId; + + @ManyToOne + @JoinColumn(name = "attempt_id") + private PromunciationAttempt attempt; + + @Column(name = "content") // 피드백 내용 + private String content; + + @Column(name = "language") // 피드백 언어 + private NativeLangauge language; +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java b/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java new file mode 100644 index 0000000..ee77104 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.game_field_table.entity; + +public class GameFieldTable { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java b/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java new file mode 100644 index 0000000..015d899 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.game_result.entity; + +public class GameResult { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java b/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java new file mode 100644 index 0000000..2042792 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.phoneme_score.entity; + +public class PhonemeScore { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java b/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java new file mode 100644 index 0000000..7a3d693 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.pronunciation_attempt; + +public class PromunciationAttempt { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java new file mode 100644 index 0000000..1a2d290 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.ranking.entity; + +public class Ranking { +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java b/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java new file mode 100644 index 0000000..e9da708 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java @@ -0,0 +1,35 @@ +package com.daehanforeigner.capstone.domain.standard_pronunciation.entity; + +import com.daehanforeigner.capstone.domain.learning_content.LearningContent; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.boot.jackson.autoconfigure.JacksonProperties; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "standard_pronunciation") +public class StandardPronunciation extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "pronunciation_id") + private Long pronunciationId; + + @ManyToOne + @JoinColumn(name = "content_id") + private LearningContent learningContent; + + @Column(name = "native_pitch_data", columnDefinition = "json") // 피치 데이터 + private String nativePitchData; + + @Column(name = "lip_sequence", columnDefinition = "json") // 입술 움직임 시퀀스 + private String lipSequence; + + @Column(name = "answer_audio_url") // 정답 오디오 URL + private String answerAudioUrl; +} diff --git a/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java new file mode 100644 index 0000000..1a4f19d --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java @@ -0,0 +1,4 @@ +package com.daehanforeigner.capstone.domain.wrong_answer.entity; + +public class WrongAnswer { +} From 4bba65b3f9bf5b03302790503b27c39c6d3eff1b Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:34 +0900 Subject: [PATCH 09/20] =?UTF-8?q?[Setup/#1]=20feat:=20ranking=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/ranking/entity/Ranking.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java index 1a2d290..c9b92e7 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java @@ -1,4 +1,30 @@ package com.daehanforeigner.capstone.domain.ranking.entity; +import com.daehanforeigner.capstone.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "ranking") public class Ranking { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "rank_id") + private Long rankId; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @Column(name = "best_score") + private int bestScore; + + @Column(name = "spoken_word_count") // 말한 단어 수 + private int spokenWordCount; } From ec8b0290294a0cfa6b5fa167c96b6e9e46aaf16d Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:38 +0900 Subject: [PATCH 10/20] =?UTF-8?q?[Setup/#1]=20feat:=20wrong=5Fanswer=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wrong_answer/entity/WrongAnswer.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java index 1a4f19d..60cf05e 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java @@ -1,4 +1,41 @@ package com.daehanforeigner.capstone.domain.wrong_answer.entity; +import com.daehanforeigner.capstone.domain.learning_content.LearningContent; +import com.daehanforeigner.capstone.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "wrong_answer") public class WrongAnswer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "wrong_id") + private Long wrongId; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne + @JoinColumn(name = "content_id") + private LearningContent learningContent; + + @Column(name = "wrong_count") // 틀린 횟수 + private int wrongCount; + + @Column(name = "is_solved") // 해결 여부 + private boolean isSolved; + + @Column(name = "last_attempted_at") // 마지막 시도 날짜 + private LocalDateTime lastAttemptedAt; } + From ed4ee56aacebb4d6121c0a7a04df44ffb29d31f9 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:40 +0900 Subject: [PATCH 11/20] =?UTF-8?q?[Setup/#1]=20feat:=20pronunciation=5Fatte?= =?UTF-8?q?mpt=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PronunciationAttempt.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java b/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java index 7a3d693..697bfcc 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/pronunciation_attempt/PronunciationAttempt.java @@ -1,4 +1,47 @@ package com.daehanforeigner.capstone.domain.pronunciation_attempt; -public class PromunciationAttempt { +import com.daehanforeigner.capstone.domain.learning_content.LearningContent; +import com.daehanforeigner.capstone.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "pronunciation_attempt") +public class PronunciationAttempt { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "attempt_id") + private Long attemptId; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne + @JoinColumn(name = "content_id") + private LearningContent learningContent; + + @Column(name = "recognized_text") // STT 인식 결과 + private String recognizedText; + + @Column(name = "voice_score") // 발음 점수 + private int voiceScore; + + @Column(name = "lip_score") // 입모양 점수 + private int lipScore; + + @Column(name = "accuracy") // 정확도 (음성 70%, 입모양 30%) + private double accuracy; + + @Column(name = "is_passed") // 합격 여부 (85% 이상 합격) + private boolean isPassed; + + @Column(name = "user_pitch_data", columnDefinition = "json") // 사용자의 피치 데이터 (JSON 형식) + private String userPitchData; } From f7edfda2455701fe9a30e612927252184260dc20 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:45 +0900 Subject: [PATCH 12/20] =?UTF-8?q?[Setup/#1]=20feat:=20audio=5Ffile=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/audio_file/entity/AudioFile.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java b/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java index a6c8a57..f69c3a8 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/audio_file/entity/AudioFile.java @@ -1,4 +1,34 @@ package com.daehanforeigner.capstone.domain.audio_file.entity; -public class AudioFile { +import com.daehanforeigner.capstone.domain.pronunciation_attempt.PronunciationAttempt; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "audio_file") +public class AudioFile extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "audio_file_id") + private Long audioFileId; + + @ManyToOne + @JoinColumn(name = "attempt_id") + private PronunciationAttempt attempt; + + @Column(name = "file_url") // 오디오 파일 URL + private String fileUrl; + + @Column(name = "file_size") // 오디오 파일 크기 + private int fileSize; + + @Column(name = "duration_ms") // 오디오 파일 길이 (밀리초 단위) + private int durationMs; } From 8be6aaa7e84b6947f51d9f65e827488e25fba713 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:49 +0900 Subject: [PATCH 13/20] =?UTF-8?q?[Setup/#1]=20feat:=20phoneme=5Fscore=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../phoneme_score/entity/PhonemeScore.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java b/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java index 2042792..bf6f4b6 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/phoneme_score/entity/PhonemeScore.java @@ -1,4 +1,31 @@ package com.daehanforeigner.capstone.domain.phoneme_score.entity; -public class PhonemeScore { +import com.daehanforeigner.capstone.domain.pronunciation_attempt.PronunciationAttempt; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "phoneme_score") +public class PhonemeScore extends GlobalEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "phoneme_score_id") + private Long phonemeScoreId; + + @ManyToOne + @JoinColumn(name = "attempt_id") + private PronunciationAttempt attempt; + + @Column(name = "phoneme") // 음소 + private String phoneme; + + @Column(name = "score") // 점수 + private int score; } From 996f578e298ad7b082d7d0056d4355f85083fffe Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:53 +0900 Subject: [PATCH 14/20] =?UTF-8?q?[Setup/#1]=20feat:=20feedback=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../capstone/domain/feedback/entity/Feedback.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java b/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java index ea6efa5..6e724b5 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/feedback/entity/Feedback.java @@ -1,6 +1,6 @@ -package com.daehanforeigner.capstone.feedback.entity; +package com.daehanforeigner.capstone.domain.feedback.entity; -import com.daehanforeigner.capstone.domain.pronunciation_attempt.PromunciationAttempt; +import com.daehanforeigner.capstone.domain.pronunciation_attempt.PronunciationAttempt; import com.daehanforeigner.capstone.domain.user.entity.NativeLangauge; import com.daehanforeigner.capstone.global.entity.GlobalEntity; import jakarta.persistence.*; @@ -13,20 +13,21 @@ @NoArgsConstructor @AllArgsConstructor @Table(name = "feedback") -public class FeedBack extends GlobalEntity { +public class Feedback extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "feedback_id") - private int feedbackId; + private Long feedbackId; @ManyToOne @JoinColumn(name = "attempt_id") - private PromunciationAttempt attempt; + private PronunciationAttempt attempt; @Column(name = "content") // 피드백 내용 private String content; + @Enumerated(EnumType.STRING) @Column(name = "language") // 피드백 언어 private NativeLangauge language; } From 21d1788732cd68369b125a5d68914b245126a5c7 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:11:56 +0900 Subject: [PATCH 15/20] =?UTF-8?q?[Setup/#1]=20feat:=20game=5Fresult=20?= =?UTF-8?q?=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/game_result/entity/GameResult.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java b/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java index 015d899..6694c06 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/game_result/entity/GameResult.java @@ -1,4 +1,40 @@ package com.daehanforeigner.capstone.domain.game_result.entity; +import com.daehanforeigner.capstone.domain.content_category.ContentCategory; +import com.daehanforeigner.capstone.domain.user.entity.User; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "game_result") public class GameResult { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "game_result_id") + private Long gameResultId; + + @ManyToOne + @JoinColumn(name = "user_id") + private User user; + + @ManyToOne + @JoinColumn(name = "category_id") + private ContentCategory category; + + @Column(name = "score") + private int score; + + @Column(name = "is_passed") + private boolean isPassed; + + @Column(name = "played_at") + private LocalDateTime playedAt; } From d21c87f171c6b8caebd28b5e85c7c862d4ba5512 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:12:00 +0900 Subject: [PATCH 16/20] =?UTF-8?q?[Setup/#1]=20feat:=20game=5Ffield=5Ftable?= =?UTF-8?q?=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4=EA=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/GameFieldTable.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java b/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java index ee77104..1dc4545 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/game_field_table/entity/GameFieldTable.java @@ -1,4 +1,30 @@ package com.daehanforeigner.capstone.domain.game_field_table.entity; +import com.daehanforeigner.capstone.domain.game_result.entity.GameResult; +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "game_field_table") public class GameFieldTable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "game_sentence_id") // 게임 문장 ID + private Long gameSentenceId; + + @ManyToOne + @JoinColumn(name = "game_result_id") // 게임 결과 ID + private GameResult gameResult; + + @Column(name = "is_sentence") // 문장 여부 + private boolean isSentence; + + @Column(name = "game_field") // 내용 + private String gameField; } From ea8466916b6908962bd7678ec7a8d2edb1ebefbe Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:12:14 +0900 Subject: [PATCH 17/20] =?UTF-8?q?[Setup/#1]=20fix:=20GlobalEntity=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=EB=84=88=20=EC=97=B0=EA=B2=B0=20=EB=B0=8F=20?= =?UTF-8?q?updated=5Fat=20=EC=BB=AC=EB=9F=BC=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daehanforeigner/capstone/global/entity/GlobalEntity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java index 7f63b85..73282b5 100644 --- a/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java +++ b/src/main/java/com/daehanforeigner/capstone/global/entity/GlobalEntity.java @@ -17,12 +17,12 @@ @AllArgsConstructor @SuperBuilder @MappedSuperclass -@EntityListeners(GlobalEntity.GlobalEntityBuilder.class) +@EntityListeners(GlobalEntityListener.class) public class GlobalEntity { @Column(name = "created_at", nullable = false) private LocalDateTime createdAt; - @Column(name = "updatted_at", nullable = false) + @Column(name = "updated_at", nullable = false) private LocalDateTime updatedAt; } From db93bd994ecd0403d35bd3da9331889880ee123b Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:12:25 +0900 Subject: [PATCH 18/20] =?UTF-8?q?[Setup/#1]=20fix:=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20PK=20=ED=83=80=EC=9E=85=20int=20=E2=86=92=20Long=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20User=20status=20enum=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../capstone/domain/content_category/ContentCategory.java | 2 +- .../capstone/domain/learning_content/LearningContent.java | 2 +- .../capstone/domain/social_account/entity/SocialAccount.java | 2 +- .../com/daehanforeigner/capstone/domain/user/entity/User.java | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java index 5f91504..06a9eb2 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java @@ -16,7 +16,7 @@ public class ContentCategory extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "category_id") - private int categoryId; + private Long categoryId; @Enumerated(EnumType.STRING) @Column(name = "type") diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java index 4d1e1cb..064c08f 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java @@ -16,7 +16,7 @@ public class LearningContent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "content_id") - private int contentId; + private Long contentId; @ManyToOne @JoinColumn(name = "category_id") diff --git a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java index e484519..b19df75 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/social_account/entity/SocialAccount.java @@ -17,7 +17,7 @@ public class SocialAccount extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "social_id") - private int socialId; + private Long socialId; @ManyToOne @JoinColumn(name = "user_id") diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java index eef4070..284fbce 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/User.java @@ -16,7 +16,7 @@ public class User extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") // PK 유저 ID - private int userId; + private Long userId; @Column(name = "email") // 이메일 private String email; @@ -40,7 +40,7 @@ public class User extends GlobalEntity { @Enumerated(EnumType.STRING) @Column(name = "status") // 상태 (ACTIVE, WITHDRAWN) - private String status; + private Status status; @Column(name = "refresh_token") // 리프레시 토큰 private String refreshToken; From 7529cb00c880a7fbe6bbc353d32a57f9517e2480 Mon Sep 17 00:00:00 2001 From: kdh Date: Tue, 7 Jul 2026 00:39:40 +0900 Subject: [PATCH 19/20] =?UTF-8?q?[Setup/#1]=20feat:=20SecurityConfig=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/SecurityConfig.java | 53 +++++++++++++++++++ src/main/resources/application-local.yml | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/daehanforeigner/capstone/global/config/SecurityConfig.java diff --git a/src/main/java/com/daehanforeigner/capstone/global/config/SecurityConfig.java b/src/main/java/com/daehanforeigner/capstone/global/config/SecurityConfig.java new file mode 100644 index 0000000..7793581 --- /dev/null +++ b/src/main/java/com/daehanforeigner/capstone/global/config/SecurityConfig.java @@ -0,0 +1,53 @@ +package com.daehanforeigner.capstone.global.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; + +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + // CORS 활성화 (아래 corsConfigurationSource 사용) + .cors(cors -> cors.configurationSource(corsConfigurationSource())) + // REST API + JWT 예정이므로 CSRF 비활성화 + .csrf(AbstractHttpConfigurer::disable) + // 세션 사용 안 함 (무상태) + .sessionManagement(session -> + session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + // 인가 규칙 (지금은 뼈대 → 우선 전체 허용, 이후 좁혀나가기) + .authorizeHttpRequests(auth -> auth + .anyRequest().permitAll() + ); + + return http.build(); + } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedOrigins(List.of( + "http://localhost:3000", // 프론트 개발 서버 (필요시 수정) + "http://localhost:8080" + )); + config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); + config.setAllowedHeaders(List.of("*")); + config.setAllowCredentials(true); // 쿠키/인증정보 허용 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } +} \ No newline at end of file diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 0906344..2b29a1b 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -2,7 +2,7 @@ spring: # 로컬 DB 접속 정보 (MySQL 사용) datasource: - url: jdbc:mysql://localhost:3306/myapp?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 + url: ${DB_URL} username: ${DB_USERNAME} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver From 93980236fb02a0367b52ccac05b113e28216c623 Mon Sep 17 00:00:00 2001 From: kdh Date: Wed, 8 Jul 2026 14:37:58 +0900 Subject: [PATCH 20/20] =?UTF-8?q?[Fix/Setup#1]=20Fix:=20PR=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 4 ++-- .../content_category/{Type.java => CategoryType.java} | 2 +- .../capstone/domain/content_category/ContentCategory.java | 2 +- .../capstone/domain/learning_content/ContentType.java | 2 +- .../capstone/domain/learning_content/LearningContent.java | 2 +- .../capstone/domain/ranking/entity/Ranking.java | 3 ++- .../entity/StandardPronunciation.java | 1 - .../entity/{NativeLangauge.java => NativeLanguage.java} | 6 +++--- .../capstone/domain/wrong_answer/entity/WrongAnswer.java | 3 ++- 9 files changed, 13 insertions(+), 12 deletions(-) rename src/main/java/com/daehanforeigner/capstone/domain/content_category/{Type.java => CategoryType.java} (81%) rename src/main/java/com/daehanforeigner/capstone/domain/user/entity/{NativeLangauge.java => NativeLanguage.java} (58%) diff --git a/.env.example b/.env.example index 12d6fb7..fbefbe6 100644 --- a/.env.example +++ b/.env.example @@ -14,8 +14,8 @@ JPA_SHOW_SQL=true # JWT # Must be at least 32 bytes. JWT_SECRET=change-me-to-at-least-32-bytes-secret -JWT_ACCESS_TOKEN_EXPIRATION=3600000 -JWT_REFRESH_TOKEN_EXPIRATION=604800000 +JWT_ACCESS_EXP_MIN=60 +JWT_REFRESH_EXP_DAY=30 # OAuth redirect base # Default: ${APP_FRONTEND_BASE_URL}/oauth/callback diff --git a/src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java b/src/main/java/com/daehanforeigner/capstone/domain/content_category/CategoryType.java similarity index 81% rename from src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java rename to src/main/java/com/daehanforeigner/capstone/domain/content_category/CategoryType.java index 4e9cae3..71989c5 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/content_category/Type.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/content_category/CategoryType.java @@ -1,6 +1,6 @@ package com.daehanforeigner.capstone.domain.content_category; -public enum Type { +public enum CategoryType { BASIC, // 기본 학습 CULTURE // 문화 학습 } diff --git a/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java index 06a9eb2..ba05bc9 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/content_category/ContentCategory.java @@ -20,7 +20,7 @@ public class ContentCategory extends GlobalEntity { @Enumerated(EnumType.STRING) @Column(name = "type") - private Type type; + private CategoryType type; @Column(name = "name") // 카테고리 이름 ex) 학습, 드라마 대사, K문화, 신조어 등 private String name; diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java index 7958785..590f436 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/ContentType.java @@ -1,7 +1,7 @@ package com.daehanforeigner.capstone.domain.learning_content; public enum ContentType { - SYLLABUS, // 음절 + SYLLABLE, // 음절 WORD, // 단어 SENTENCE // 문장 } diff --git a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java index 064c08f..cc7610b 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/learning_content/LearningContent.java @@ -27,7 +27,7 @@ public class LearningContent { private ContentType contentType; @Enumerated(EnumType.STRING) - @Column(name = "difficulty") // 쉬움, 보통, 난이도 + @Column(name = "difficulty") // 초급, 중급, 고급 private Difficulty difficulty; @Column(name = "text") // 학습 텍스트 diff --git a/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java index c9b92e7..9b778da 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/ranking/entity/Ranking.java @@ -1,6 +1,7 @@ package com.daehanforeigner.capstone.domain.ranking.entity; import com.daehanforeigner.capstone.domain.user.entity.User; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -11,7 +12,7 @@ @NoArgsConstructor @AllArgsConstructor @Table(name = "ranking") -public class Ranking { +public class Ranking extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java b/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java index e9da708..bff4120 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/standard_pronunciation/entity/StandardPronunciation.java @@ -6,7 +6,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.boot.jackson.autoconfigure.JacksonProperties; @Entity @Getter diff --git a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLanguage.java similarity index 58% rename from src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java rename to src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLanguage.java index efbb3cb..e49f571 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLangauge.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/user/entity/NativeLanguage.java @@ -1,8 +1,8 @@ package com.daehanforeigner.capstone.domain.user.entity; -public enum NativeLangauge { +public enum NativeLanguage { + KR, // 한국어 EN, // 영어 - CH, // 중국어 JP, // 일본어 - KR // 한국어 + CN, // 중국어 } diff --git a/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java index 60cf05e..ea56c32 100644 --- a/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java +++ b/src/main/java/com/daehanforeigner/capstone/domain/wrong_answer/entity/WrongAnswer.java @@ -2,6 +2,7 @@ import com.daehanforeigner.capstone.domain.learning_content.LearningContent; import com.daehanforeigner.capstone.domain.user.entity.User; +import com.daehanforeigner.capstone.global.entity.GlobalEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -14,7 +15,7 @@ @NoArgsConstructor @AllArgsConstructor @Table(name = "wrong_answer") -public class WrongAnswer { +public class WrongAnswer extends GlobalEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY)