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 diff --git a/build.gradle b/build.gradle index c1f58c0..74e79fa 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' @@ -52,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/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/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..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,24 +26,23 @@ public class User extends BaseEntity { @Comment("회원 고유값") private Long id; + @Column(name = "KAKAO_ID", unique = true, nullable = false) + @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/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(); } } 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/config/SecurityConfig.java b/src/main/java/com/example/hackathon/global/config/SecurityConfig.java index c16d6b3..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,10 @@ 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); } 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 0558b6d..90e5294 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -4,13 +4,13 @@ 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: - ddl-auto: update + ddl-auto: create properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect