From 6f0bf863b62b237ae6a8a353348bd52591f06bcf Mon Sep 17 00:00:00 2001 From: leejunnyeop Date: Sun, 18 May 2025 02:40:30 +0900 Subject: [PATCH 1/8] =?UTF-8?q?chore=20:=20sql=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _ h2 에서 mysql 로 변경 --- build.gradle | 2 -- src/main/resources/application.yml | 31 +++++++++++------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/build.gradle b/build.gradle index c1f58c0..961170b 100644 --- a/build.gradle +++ b/build.gradle @@ -39,8 +39,6 @@ dependencies { // DB runtimeOnly 'com.mysql:mysql-connector-j' - implementation 'com.h2database:h2' - // Lombok compileOnly 'org.projectlombok:lombok' diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 16c1908..7f20a07 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,30 +1,21 @@ spring: - application: - name: hackathon - server: - port: 8080 datasource: - url: jdbc:h2:mem:testdb - driver-class-name: org.h2.Driver - username: sa - password: + url: jdbc:mysql://hackthon-server-db-v.cwmf5niftwns.ap-northeast-2.rds.amazonaws.com:3306/hackthon_db?serverTimezone=Asia/Seoul + username: admin + password: hackthon + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: hibernate: - ddl-auto: update + ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect - format_sql: true - show_sql: true -springdoc: - use-fqn: true - api-docs: - enabled: true - swagger-ui: - enabled: true - cache: - disabled: true + show-sql: true + open-in-view: false +server: + port: 8080 oauth: kakao: @@ -33,4 +24,4 @@ oauth: jwt: secret: Lun7qvfZd1o6UvvdpE9eKB/qkDZzdTYwNI9TMIoj0iI= - expiration: 3600000 # ? + expiration: 3600000 # ? \ No newline at end of file From 79d6c92c4954d29b97dd96185d78948e16f32b34 Mon Sep 17 00:00:00 2001 From: Chris Jang Date: Sun, 18 May 2025 03:04:52 +0900 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20User=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=84=B1=EC=9D=B4=ED=95=9C=20=EC=98=81?= =?UTF-8?q?=EC=86=8D=20=EC=83=81=ED=83=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../activity/service/ActivityService.java | 2 +- .../domain/user/dto/UserProfileDto.java | 5 ++-- .../hackathon/domain/user/entity/User.java | 9 +++--- .../user/repository/UserRepository.java | 3 +- .../domain/user/service/UserService.java | 6 ++-- .../auth/service/KakaoOAuthService.java | 4 +-- .../global/jwt/JwtAuthenticationFilter.java | 2 +- src/main/resources/application.yml | 29 +++++++------------ 8 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/example/hackathon/domain/activity/service/ActivityService.java b/src/main/java/com/example/hackathon/domain/activity/service/ActivityService.java index c34e08b..a244c23 100644 --- a/src/main/java/com/example/hackathon/domain/activity/service/ActivityService.java +++ b/src/main/java/com/example/hackathon/domain/activity/service/ActivityService.java @@ -48,7 +48,7 @@ public ActivityResponseDto getActivity(Long activityId) { } public void addUserActivities(Long userId, ActivityNewRequestDto.AddActivity request) { - User user = userRepository.findById(userId) + User user = userRepository.findByKakaoId(userId) .orElseThrow(() -> new BusinessException(Code.USER_NOT_FOUND, "이미 오늘 참여한 활동입니다.")); Category category = categoryRepository.findByCategoryType(request.getCategoryType()) diff --git a/src/main/java/com/example/hackathon/domain/user/dto/UserProfileDto.java b/src/main/java/com/example/hackathon/domain/user/dto/UserProfileDto.java index 794da2b..910c046 100644 --- a/src/main/java/com/example/hackathon/domain/user/dto/UserProfileDto.java +++ b/src/main/java/com/example/hackathon/domain/user/dto/UserProfileDto.java @@ -7,12 +7,13 @@ @Getter @AllArgsConstructor public class UserProfileDto { - private Long id; + + private Long kakaoId; private String nickname; private String role; public UserProfileDto(User user) { - this.id = user.getId(); + this.kakaoId = user.getKakaoId(); this.nickname = user.getName(); } } diff --git a/src/main/java/com/example/hackathon/domain/user/entity/User.java b/src/main/java/com/example/hackathon/domain/user/entity/User.java index 92df1ab..e948a3c 100644 --- a/src/main/java/com/example/hackathon/domain/user/entity/User.java +++ b/src/main/java/com/example/hackathon/domain/user/entity/User.java @@ -26,24 +26,23 @@ public class User extends BaseEntity { @Comment("회원 고유값") private Long id; + @Column(name = "KAKAO_ID", unique = true) + @Comment("카카오 ID") + private Long kakaoId; + @Column(name = "NAME", nullable = false, length = 50) @Comment("이름") private String name; - @Column(name = "email", nullable = false, unique = true) - private String email; - @Enumerated(EnumType.STRING) @Column(name = "PROVIDER", nullable = false, length = 10) @Comment("소셜 로그인 제공자") private OAuthProvider oauthProvider; - @Column(name = "REG_ID", nullable = false, length = 50) @Comment("등록자") private String regId; - @Column(name = "UPD_ID", length = 50) @Comment("수정자") private String updId; diff --git a/src/main/java/com/example/hackathon/domain/user/repository/UserRepository.java b/src/main/java/com/example/hackathon/domain/user/repository/UserRepository.java index e72e8d8..ef5b6af 100644 --- a/src/main/java/com/example/hackathon/domain/user/repository/UserRepository.java +++ b/src/main/java/com/example/hackathon/domain/user/repository/UserRepository.java @@ -6,6 +6,7 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { - Optional findById(Long id); + + Optional findByKakaoId(Long kakaoId); } diff --git a/src/main/java/com/example/hackathon/domain/user/service/UserService.java b/src/main/java/com/example/hackathon/domain/user/service/UserService.java index d5b3c59..33515c5 100644 --- a/src/main/java/com/example/hackathon/domain/user/service/UserService.java +++ b/src/main/java/com/example/hackathon/domain/user/service/UserService.java @@ -16,12 +16,12 @@ public class UserService { private final UserRepository userRepository; public User findOrCreate(KakaoUserInfoDto userInfo) { - return userRepository.findById(userInfo.getId()) + return userRepository.findByKakaoId(userInfo.getId()) .orElseGet(() -> userRepository.save(userInfo.toEntity())); } - public UserProfileDto getProfile(Long email) { - User user = userRepository.findById(email) + public UserProfileDto getProfile(Long id) { + User user = userRepository.findByKakaoId(id) .orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다.")); return new UserProfileDto(user); } diff --git a/src/main/java/com/example/hackathon/global/auth/service/KakaoOAuthService.java b/src/main/java/com/example/hackathon/global/auth/service/KakaoOAuthService.java index 49e3c34..903133e 100644 --- a/src/main/java/com/example/hackathon/global/auth/service/KakaoOAuthService.java +++ b/src/main/java/com/example/hackathon/global/auth/service/KakaoOAuthService.java @@ -38,11 +38,11 @@ public String loginWithKakao(String code) { log.info("userInfo : {}", userInfo); // 3. 회원 조회 또는 저장 - User user = userRepository.findById(userInfo.getId()) + User user = userRepository.findByKakaoId(userInfo.getId()) .orElseGet(() -> userRepository.save(userInfo.toEntity())); // 4. JWT 토큰 발급 - return jwtUtil.generateToken(user.getId()); + return jwtUtil.generateToken(user.getKakaoId()); } } diff --git a/src/main/java/com/example/hackathon/global/jwt/JwtAuthenticationFilter.java b/src/main/java/com/example/hackathon/global/jwt/JwtAuthenticationFilter.java index f629a30..13d754e 100644 --- a/src/main/java/com/example/hackathon/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/example/hackathon/global/jwt/JwtAuthenticationFilter.java @@ -39,7 +39,7 @@ protected void doFilterInternal( if (token != null && jwtUtil.validateToken(token)) { String id = jwtUtil.extractKakaoId(token); - User user = userRepository.findById(Long.valueOf(id)) + User user = userRepository.findByKakaoId(Long.valueOf(id)) .orElseThrow(() -> new RuntimeException("사용자를 찾을 수 없습니다: " + id)); // 인증 객체 생성 (권한 정보는 생략하거나 필요시 추가) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 16c1908..8be7fb2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,30 +1,21 @@ spring: - application: - name: hackathon - server: - port: 8080 datasource: - url: jdbc:h2:mem:testdb - driver-class-name: org.h2.Driver - username: sa - password: + url: jdbc:mysql://hackthon-server-db-v.cwmf5niftwns.ap-northeast-2.rds.amazonaws.com:3306/hackthon_db?serverTimezone=Asia/Seoul + username: admin + password: hackthon + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect - format_sql: true - show_sql: true -springdoc: - use-fqn: true - api-docs: - enabled: true - swagger-ui: - enabled: true - cache: - disabled: true + show-sql: true + open-in-view: false +server: + port: 8080 oauth: kakao: @@ -33,4 +24,4 @@ oauth: jwt: secret: Lun7qvfZd1o6UvvdpE9eKB/qkDZzdTYwNI9TMIoj0iI= - expiration: 3600000 # ? + expiration: 3600000 # ? \ No newline at end of file From c74a102fc29bb81d403218ff0c1e8dc1e15e396a Mon Sep 17 00:00:00 2001 From: Chris Jang Date: Sun, 18 May 2025 03:11:18 +0900 Subject: [PATCH 3/8] =?UTF-8?q?fix:=20=EC=B9=B4=EC=B9=B4=EC=98=A4=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=20=EC=A0=95=EB=B3=B4=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?entity=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/hackathon/domain/user/entity/User.java | 2 +- .../example/hackathon/global/auth/dto/KakaoUserInfoDto.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/hackathon/domain/user/entity/User.java b/src/main/java/com/example/hackathon/domain/user/entity/User.java index e948a3c..3668229 100644 --- a/src/main/java/com/example/hackathon/domain/user/entity/User.java +++ b/src/main/java/com/example/hackathon/domain/user/entity/User.java @@ -26,7 +26,7 @@ public class User extends BaseEntity { @Comment("회원 고유값") private Long id; - @Column(name = "KAKAO_ID", unique = true) + @Column(name = "KAKAO_ID", unique = true, nullable = false) @Comment("카카오 ID") private Long kakaoId; diff --git a/src/main/java/com/example/hackathon/global/auth/dto/KakaoUserInfoDto.java b/src/main/java/com/example/hackathon/global/auth/dto/KakaoUserInfoDto.java index 13e7a3e..a6b3250 100644 --- a/src/main/java/com/example/hackathon/global/auth/dto/KakaoUserInfoDto.java +++ b/src/main/java/com/example/hackathon/global/auth/dto/KakaoUserInfoDto.java @@ -33,9 +33,10 @@ public KakaoUserInfoDto( public User toEntity() { return User.builder() - .id(id) + .kakaoId(id) .name(name) .oauthProvider(KAKAO) + .regId(String.valueOf(id)) .build(); } } From c4457f9b3b342062afffbaabb00e8d4bedc7ebef Mon Sep 17 00:00:00 2001 From: leejunnyeop Date: Sun, 18 May 2025 03:12:11 +0900 Subject: [PATCH 4/8] =?UTF-8?q?fix:=20Swagger=20500=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EB=B0=8F=20Security=20=ED=97=88=EC=9A=A9=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - springdoc-openapi-starter-webmvc-ui 2.2.0 적용으로 버전 충돌 해결 - Swagger JWT 인증 설정 및 보안 스키마 등록 - SecurityConfig에서 Swagger 관련 경로 permitAll 처리 - /v3/api-docs, /swagger-ui 등 접근 시 인증 없이 열람 가능하도록 수정 --- build.gradle | 3 +-- .../global/config/SecurityConfig.java | 3 +++ .../global/config/SwaggerConfig.java | 23 +++++++++++++++---- .../global/jwt/AuthUserArgumentResolver.java | 4 ++++ 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index 961170b..74e79fa 100644 --- a/build.gradle +++ b/build.gradle @@ -50,8 +50,7 @@ dependencies { // Test testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6' } tasks.named('test') { diff --git a/src/main/java/com/example/hackathon/global/config/SecurityConfig.java b/src/main/java/com/example/hackathon/global/config/SecurityConfig.java index c16d6b3..af464eb 100644 --- a/src/main/java/com/example/hackathon/global/config/SecurityConfig.java +++ b/src/main/java/com/example/hackathon/global/config/SecurityConfig.java @@ -34,6 +34,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // ✅ 경로별 접근 권한 설정 .authorizeHttpRequests(auth -> auth .requestMatchers( + "/swagger-ui/**", + "/swagger-ui.html", + "/v3/api-docs/**", "/auth/**", // 소셜 로그인 콜백 "/login", // 혹시 사용할 경우 "/health", // 헬스 체크 diff --git a/src/main/java/com/example/hackathon/global/config/SwaggerConfig.java b/src/main/java/com/example/hackathon/global/config/SwaggerConfig.java index a802682..578feac 100644 --- a/src/main/java/com/example/hackathon/global/config/SwaggerConfig.java +++ b/src/main/java/com/example/hackathon/global/config/SwaggerConfig.java @@ -1,19 +1,34 @@ package com.example.hackathon.global.config; import io.swagger.v3.oas.models.OpenAPI; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.servers.Server; - +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.Components; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { + + private static final String SECURITY_SCHEME_NAME = "JWT"; + @Bean public OpenAPI openAPI() { return new OpenAPI() .info(apiInfo()) - .addServersItem(new Server().url("/")); + .addServersItem(new Server().url("/")) + .components(new Components() + .addSecuritySchemes(SECURITY_SCHEME_NAME, + new SecurityScheme() + .name(SECURITY_SCHEME_NAME) + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + ) + ) + .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEME_NAME)); } private Info apiInfo() { diff --git a/src/main/java/com/example/hackathon/global/jwt/AuthUserArgumentResolver.java b/src/main/java/com/example/hackathon/global/jwt/AuthUserArgumentResolver.java index bae5a71..e5fb782 100644 --- a/src/main/java/com/example/hackathon/global/jwt/AuthUserArgumentResolver.java +++ b/src/main/java/com/example/hackathon/global/jwt/AuthUserArgumentResolver.java @@ -33,6 +33,10 @@ public Object resolveArgument( String token = ((HttpServletRequest) webRequest.getNativeRequest()) .getHeader("Authorization"); + if (token == null || token.isBlank()) { + return null; + } + // JWT 파싱 → userId 추출 return jwtUtil.getUserIdFromToken(token); } From 67e9553a76a8ddecca3dcf073b9f7d6302dc9224 Mon Sep 17 00:00:00 2001 From: leejunnyeop Date: Sun, 18 May 2025 03:20:58 +0900 Subject: [PATCH 5/8] =?UTF-8?q?fix=20:=20=EA=B9=83=20=EC=B6=A9=EB=8F=8C?= =?UTF-8?q?=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0558b6d..3df3047 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,7 +10,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: - ddl-auto: update + ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect From 17e529401622b93d3eb99c4ce14c76286aab7286 Mon Sep 17 00:00:00 2001 From: leejunnyeop Date: Sun, 18 May 2025 03:47:21 +0900 Subject: [PATCH 6/8] =?UTF-8?q?chore:=20=EB=A9=94=EC=9D=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=9D=B8=EC=A6=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 시큐리티에서 메인 화면 인증 없이 허용 --- .../java/com/example/hackathon/global/config/SecurityConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/example/hackathon/global/config/SecurityConfig.java b/src/main/java/com/example/hackathon/global/config/SecurityConfig.java index af464eb..5d61658 100644 --- a/src/main/java/com/example/hackathon/global/config/SecurityConfig.java +++ b/src/main/java/com/example/hackathon/global/config/SecurityConfig.java @@ -34,6 +34,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti // ✅ 경로별 접근 권한 설정 .authorizeHttpRequests(auth -> auth .requestMatchers( + "/", "/swagger-ui/**", "/swagger-ui.html", "/v3/api-docs/**", From 618eba8a97a8a652862ab825005e10714e328a48 Mon Sep 17 00:00:00 2001 From: parkmineum Date: Sun, 18 May 2025 03:53:40 +0900 Subject: [PATCH 7/8] =?UTF-8?q?[CHORE]=20.yml=20=EB=B3=80=EA=B2=BD,=20ngin?= =?UTF-8?q?x=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nginx/nginx.conf | 3 +-- src/main/resources/application.yml | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 9d73ea8..2ee9796 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -18,7 +18,6 @@ http { server { listen 80; return 301 https://api.neodinary.store$request_uri; - return ; } server { @@ -26,7 +25,7 @@ http { server_name api.neodinary.store; ssl_certificate /etc/letsencrypt/live/api.neodinary.store/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/liveapi.neodinary.store/privkey.pem; + ssl_certificate_key /etc/letsencrypt/live/api.neodinary.store/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0558b6d..563317b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,9 +4,9 @@ spring: server: port: 8080 datasource: - url: jdbc:mysql://${DEFAULT_URL}?serverTimezone=UTC - username: ${DB_USERNAME} - password: ${DB_PASSWORD} + url: jdbc:mysql://${PROD_DB_ENDPOINT}:3306/${PROD_DB_NAME}?serverTimezone=UTC + username: ${PROD_DB_USERNAME} + password: ${PROD_DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: From be4c0e7bd9e87c6f8cfc80a077bee90e48e9745a Mon Sep 17 00:00:00 2001 From: parkmineum <165489156+parkmineum@users.noreply.github.com> Date: Sun, 18 May 2025 03:56:26 +0900 Subject: [PATCH 8/8] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bd7a123..303a3b5 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ -# Be \ No newline at end of file +# Be + + + +### 아키텍처 +image