diff --git a/build.gradle.kts b/build.gradle.kts index f6a6aec9..ba51abb1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -48,11 +48,20 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-data-redis") implementation("org.springframework.session:spring-session-data-redis") + // AWS S3 + implementation("io.awspring.cloud:spring-cloud-aws-starter-s3:3.4.0") + runtimeOnly("com.h2database:h2") runtimeOnly("com.mysql:mysql-connector-j") annotationProcessor("org.projectlombok:lombok") + //json + implementation("io.jsonwebtoken:jjwt-api:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5") + runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5") +// json 파싱용 + //Spring AI implementation(platform("org.springframework.ai:spring-ai-bom:1.0.0-M4")) diff --git a/cookies.txt b/cookies.txt new file mode 100644 index 00000000..c31d9899 --- /dev/null +++ b/cookies.txt @@ -0,0 +1,4 @@ +# Netscape HTTP Cookie File +# https://curl.se/docs/http-cookies.html +# This file was generated by libcurl! Edit at your own risk. + diff --git a/src/main/java/com/back/domain/cocktail/comment/entity/CocktailComment.java b/src/main/java/com/back/domain/cocktail/comment/entity/CocktailComment.java index 782df0b0..4676c0c7 100644 --- a/src/main/java/com/back/domain/cocktail/comment/entity/CocktailComment.java +++ b/src/main/java/com/back/domain/cocktail/comment/entity/CocktailComment.java @@ -16,7 +16,6 @@ @Entity @Getter -@Table(name = "cocktailcomment") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor diff --git a/src/main/java/com/back/domain/post/category/entity/Category.java b/src/main/java/com/back/domain/post/category/entity/Category.java index 6dda2f13..33879404 100644 --- a/src/main/java/com/back/domain/post/category/entity/Category.java +++ b/src/main/java/com/back/domain/post/category/entity/Category.java @@ -1,23 +1,12 @@ package com.back.domain.post.category.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import jakarta.persistence.*; +import lombok.*; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @Entity @Getter @Setter -@Table(name = "category") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor diff --git a/src/main/java/com/back/domain/post/comment/entity/Comment.java b/src/main/java/com/back/domain/post/comment/entity/Comment.java index 64e7f870..b8164b27 100644 --- a/src/main/java/com/back/domain/post/comment/entity/Comment.java +++ b/src/main/java/com/back/domain/post/comment/entity/Comment.java @@ -2,21 +2,8 @@ import com.back.domain.post.comment.enums.CommentStatus; import com.back.domain.post.post.entity.Post; -import com.back.domain.post.post.enums.PostStatus; import com.back.domain.user.entity.User; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import java.time.LocalDateTime; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -25,9 +12,10 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; + @Entity @Getter -@Table(name = "comment") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor diff --git a/src/main/java/com/back/domain/post/post/entity/Post.java b/src/main/java/com/back/domain/post/post/entity/Post.java index da602d18..a7198225 100644 --- a/src/main/java/com/back/domain/post/post/entity/Post.java +++ b/src/main/java/com/back/domain/post/post/entity/Post.java @@ -3,23 +3,7 @@ import com.back.domain.post.category.entity.Category; import com.back.domain.post.post.enums.PostStatus; import com.back.domain.user.entity.User; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -28,9 +12,12 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + @Entity @Getter -@Table(name = "post") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor diff --git a/src/main/java/com/back/domain/post/post/entity/PostLike.java b/src/main/java/com/back/domain/post/post/entity/PostLike.java index 86b1ec3d..d9cbf58b 100644 --- a/src/main/java/com/back/domain/post/post/entity/PostLike.java +++ b/src/main/java/com/back/domain/post/post/entity/PostLike.java @@ -2,32 +2,17 @@ import com.back.domain.post.post.enums.PostLikeStatus; import com.back.domain.user.entity.User; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import jakarta.persistence.UniqueConstraint; -import java.time.LocalDateTime; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import jakarta.persistence.*; +import lombok.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import java.time.LocalDateTime; + @Entity @Getter // 같은 사용자(user_id)가 같은 게시글(post_id)을 중복 추천하지 못하도록 DB 레벨에서 보장. -@Table(name = "post_like", uniqueConstraints = { +@Table(uniqueConstraints = { @UniqueConstraint(columnNames = {"post_id", "user_id"}) }) @EntityListeners(AuditingEntityListener.class) diff --git a/src/main/java/com/back/domain/post/post/entity/PostTag.java b/src/main/java/com/back/domain/post/post/entity/PostTag.java index 9a09a924..f753c846 100644 --- a/src/main/java/com/back/domain/post/post/entity/PostTag.java +++ b/src/main/java/com/back/domain/post/post/entity/PostTag.java @@ -1,15 +1,6 @@ package com.back.domain.post.post.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -18,7 +9,6 @@ @Entity @Getter -@Table(name = "post_tag") @EntityListeners(AuditingEntityListener.class) @NoArgsConstructor(access = AccessLevel.PROTECTED) public class PostTag { diff --git a/src/main/java/com/back/domain/post/post/entity/Tag.java b/src/main/java/com/back/domain/post/post/entity/Tag.java index d215e43d..91900228 100644 --- a/src/main/java/com/back/domain/post/post/entity/Tag.java +++ b/src/main/java/com/back/domain/post/post/entity/Tag.java @@ -4,16 +4,10 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; @Entity @Getter -@Table(name = "tag") @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder diff --git a/src/main/java/com/back/domain/user/controller/UserAuthController.java b/src/main/java/com/back/domain/user/controller/UserAuthController.java index cf3e00cd..c0442d96 100644 --- a/src/main/java/com/back/domain/user/controller/UserAuthController.java +++ b/src/main/java/com/back/domain/user/controller/UserAuthController.java @@ -34,10 +34,10 @@ public class UserAuthController { }) @PostMapping("/refresh") public RsData refreshToken(HttpServletRequest request, HttpServletResponse response) { - RefreshTokenResDto refreshToken = userAuthService.refreshTokens(request, response); + RefreshTokenResDto refreshTokenData = userAuthService.refreshTokens(request, response); - if (refreshToken != null) { - return RsData.of(200, "토큰이 갱신 성공.", refreshToken); + if (refreshTokenData != null) { + return RsData.of(200, "토큰이 갱신 성공.", refreshTokenData); } else { return RsData.of(401, "토큰 갱신에 실패했습니다. 다시 로그인해주세요."); } diff --git a/src/main/java/com/back/domain/user/service/UserAuthService.java b/src/main/java/com/back/domain/user/service/UserAuthService.java index 72b5bc72..e655c94c 100644 --- a/src/main/java/com/back/domain/user/service/UserAuthService.java +++ b/src/main/java/com/back/domain/user/service/UserAuthService.java @@ -93,7 +93,7 @@ public User joinSocial(String oauthId, String email, String nickname){ String uniqueNickname = generateNickname(nickname); User user = User.builder() - .email(email) + .email(email != null ? email : "") .nickname(uniqueNickname) .abvDegree(0.0) .createdAt(LocalDateTime.now()) @@ -112,7 +112,8 @@ public RsData findOrCreateOAuthUser(String oauthId, String email, String n if (existingUser.isPresent()) { // 기존 사용자 업데이트 (이메일만 업데이트) User user = existingUser.get(); - user.setEmail(email); + // null 체크 후 빈 문자열로 대체 + user.setEmail(email != null ? email : ""); return RsData.of(200, "회원 정보가 업데이트 되었습니다", user); //더티체킹 } else { User newUser = joinSocial(oauthId, email, nickname); @@ -137,6 +138,8 @@ public void issueTokens(HttpServletResponse response, Long userId, String email, String accessToken = jwtUtil.generateAccessToken(userId, email, nickname); String refreshToken = refreshTokenService.generateRefreshToken(userId); + log.debug("토큰 발급 완료 - userId: {}, accessToken: {}, refreshToken: {}", userId, accessToken, refreshToken); + jwtUtil.addAccessTokenToCookie(response, accessToken); jwtUtil.addRefreshTokenToCookie(response, refreshToken); } @@ -144,8 +147,15 @@ public void issueTokens(HttpServletResponse response, Long userId, String email, public RefreshTokenResDto refreshTokens(HttpServletRequest request, HttpServletResponse response) { try { String oldRefreshToken = jwtUtil.getRefreshTokenFromCookie(request); + log.debug("토큰 갱신 시도 - 받은 RefreshToken: {}", oldRefreshToken); + + if (oldRefreshToken == null) { + log.error("RefreshToken이 쿠키에서 발견되지 않음"); + return null; + } - if (oldRefreshToken == null || !refreshTokenService.validateToken(oldRefreshToken)) { + if (!refreshTokenService.validateToken(oldRefreshToken)) { + log.error("RefreshToken 검증 실패: {}", oldRefreshToken); return null; } diff --git a/src/main/java/com/back/global/controller/HomeController.java b/src/main/java/com/back/global/controller/HomeController.java deleted file mode 100644 index e7a2f936..00000000 --- a/src/main/java/com/back/global/controller/HomeController.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.back.global.controller; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class HomeController { - - @Value("${custom.site.frontUrl}") - private String frontUrl; - - @Value("${spring.profiles.active}") - private String activeProfile; - - @GetMapping("/") - public String redirect() { - if("prod".equals(activeProfile)){ - return "redirect:" + frontUrl; - } - return "redirect:/swagger-ui/index.html"; - } -} \ No newline at end of file diff --git a/src/main/java/com/back/global/file/FileController.java b/src/main/java/com/back/global/file/FileController.java new file mode 100644 index 00000000..44d7c666 --- /dev/null +++ b/src/main/java/com/back/global/file/FileController.java @@ -0,0 +1,40 @@ +package com.back.global.file; + +import com.back.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.Bucket; + +import java.util.List; +import java.util.stream.Collectors; + + +@Tag(name = "File", description = "file API") +@RestController +@RequestMapping("/file") +@RequiredArgsConstructor +public class FileController { + private final S3Client s3Client; + + @Operation(summary = "S3 버킷 목록 조회", description = "모든 버킷 목록을 조회") + @GetMapping("/buckets") + public RsData> listBuckets() { + + return RsData.of( + 200, + "버킷 목록 조회", + s3Client + .listBuckets() + .buckets() + .stream() + .map(Bucket::name) + .collect(Collectors.toList()) + ); + + } +} diff --git a/src/main/java/com/back/global/globalExceptionHandler/GlobalExceptionHandler.java b/src/main/java/com/back/global/globalExceptionHandler/GlobalExceptionHandler.java index edc77bfa..9bd6468f 100644 --- a/src/main/java/com/back/global/globalExceptionHandler/GlobalExceptionHandler.java +++ b/src/main/java/com/back/global/globalExceptionHandler/GlobalExceptionHandler.java @@ -5,9 +5,12 @@ import com.back.global.rsData.RsData; import com.fasterxml.jackson.core.JsonProcessingException; import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.dao.DataAccessException; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.transaction.TransactionException; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingRequestHeaderException; @@ -30,6 +33,7 @@ * 500: Internal Server Error */ +@Slf4j @RestControllerAdvice public class GlobalExceptionHandler { diff --git a/src/main/java/com/back/global/jwt/JwtUtil.java b/src/main/java/com/back/global/jwt/JwtUtil.java index 36c19201..bc725f2e 100644 --- a/src/main/java/com/back/global/jwt/JwtUtil.java +++ b/src/main/java/com/back/global/jwt/JwtUtil.java @@ -19,13 +19,16 @@ public class JwtUtil { private final SecretKey secretKey; private final long accessTokenExpiration; + private final String cookieDomain; private static final String ACCESS_TOKEN_COOKIE_NAME = "accessToken"; private static final String REFRESH_TOKEN_COOKIE_NAME = "refreshToken"; public JwtUtil(@Value("${custom.jwt.secretKey}") String secretKey, - @Value("${custom.accessToken.expirationSeconds}") long accessTokenExpiration) { + @Value("${custom.accessToken.expirationSeconds}") long accessTokenExpiration, + @Value("${custom.site.cookieDomain}") String cookieDomain) { this.secretKey = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); this.accessTokenExpiration = accessTokenExpiration * 1000; + this.cookieDomain = cookieDomain; } public String generateAccessToken(Long userId, String email, String nickname) { @@ -33,12 +36,12 @@ public String generateAccessToken(Long userId, String email, String nickname) { Date expiration = new Date(now.getTime() + accessTokenExpiration); return Jwts.builder() - .subject(String.valueOf(userId)) + .setSubject(String.valueOf(userId)) .claim("email", email) .claim("nickname", nickname) - .issuedAt(now) - .expiration(expiration) - .signWith(secretKey) + .setIssuedAt(now) + .setExpiration(expiration) + .signWith(secretKey) // javax.crypto.SecretKey 타입 .compact(); } @@ -48,6 +51,7 @@ public void addAccessTokenToCookie(HttpServletResponse response, String accessTo cookie.setHttpOnly(true); cookie.setSecure(false); // 개발환경에서는 false, 프로덕션에서는 true cookie.setPath("/"); + cookie.setDomain(cookieDomain); cookie.setMaxAge((int) (accessTokenExpiration / 1000)); response.addCookie(cookie); } @@ -58,16 +62,17 @@ public void removeAccessTokenCookie(HttpServletResponse response) { cookie.setHttpOnly(true); cookie.setSecure(false); cookie.setPath("/"); + cookie.setDomain(cookieDomain); cookie.setMaxAge(0); response.addCookie(cookie); } public boolean validateAccessToken(String token) { try { - Jwts.parser() - .verifyWith(secretKey) + Jwts.parserBuilder() + .setSigningKey(secretKey) .build() - .parseSignedClaims(token); + .parseClaimsJws(token); return true; } catch (SecurityException | MalformedJwtException e) { log.error("Invalid JWT signature: {}", e.getMessage()); @@ -90,15 +95,15 @@ public String getEmailFromToken(String token) { } public String getNicknameFromToken(String token) { - return parseToken(token).get("nickname", String.class); + return parseToken(token).get("nickname").toString(); } private Claims parseToken(String token) { - return Jwts.parser() - .verifyWith(secretKey) + return Jwts.parserBuilder() + .setSigningKey(secretKey) .build() - .parseSignedClaims(token) - .getPayload(); + .parseClaimsJws(token) + .getBody(); } public void addRefreshTokenToCookie(HttpServletResponse response, String refreshToken) { @@ -106,19 +111,25 @@ public void addRefreshTokenToCookie(HttpServletResponse response, String refresh cookie.setHttpOnly(true); cookie.setSecure(false); cookie.setPath("/"); + cookie.setDomain(cookieDomain); cookie.setMaxAge(60 * 60 * 24 * 30); response.addCookie(cookie); } public String getRefreshTokenFromCookie(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); + log.debug("받은 쿠키 개수: {}", cookies != null ? cookies.length : 0); + if (cookies != null) { for (Cookie cookie : cookies) { + log.debug("쿠키 확인 - 이름: {}, 값: {}", cookie.getName(), cookie.getValue()); if (REFRESH_TOKEN_COOKIE_NAME.equals(cookie.getName())) { + log.debug("RefreshToken 쿠키 발견: {}", cookie.getValue()); return cookie.getValue(); } } } + log.debug("RefreshToken 쿠키를 찾을 수 없음"); return null; } @@ -127,6 +138,7 @@ public void removeRefreshTokenCookie(HttpServletResponse response) { cookie.setHttpOnly(true); cookie.setSecure(false); cookie.setPath("/"); + cookie.setDomain(cookieDomain); cookie.setMaxAge(0); response.addCookie(cookie); } diff --git a/src/main/java/com/back/global/rq/Rq.java b/src/main/java/com/back/global/rq/Rq.java index cf10341a..72f02868 100644 --- a/src/main/java/com/back/global/rq/Rq.java +++ b/src/main/java/com/back/global/rq/Rq.java @@ -25,9 +25,13 @@ public class Rq { private final HttpServletResponse resp; private final UserService userService; - @Value("${custom.cookie.secure:false}") + @Value("${custom.cookie.secure}") private boolean cookieSecure; + @Value("${custom.cookie.same}") + private String cookieSameSite; + + public User getActor() { return Optional.ofNullable( SecurityContextHolder @@ -90,7 +94,7 @@ public void setCrossDomainCookie(String name, String value, int maxAge) { .path("/") .maxAge(maxAge) .secure(cookieSecure) - .sameSite("None") + .sameSite(cookieSameSite) .httpOnly(true) .build(); resp.addHeader("Set-Cookie", cookie.toString()); diff --git a/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java b/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java index f7ea019b..18269f8f 100644 --- a/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java +++ b/src/main/java/com/back/global/security/CustomOAuth2LoginSuccessHandler.java @@ -28,11 +28,16 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo // Access Token과 Refresh Token 발급 userAuthService.issueTokens(response, securityUser.getId(), securityUser.getEmail(), securityUser.getNickname()); - if (securityUser.isFirstLogin()) { + boolean isFirstLogin = securityUser.isFirstLogin(); + + if (isFirstLogin) { + // DB에서 isFirstLogin을 false로 업데이트 userAuthService.setFirstLoginFalse(securityUser.getId()); - response.sendRedirect(frontendUrl + "/login/first-user"); + // 첫 로그인이므로 first-user 페이지로 리다이렉트 + response.sendRedirect(frontendUrl + "/login/user/first-user"); } else { - response.sendRedirect(frontendUrl + "/login/success"); + // 기존 사용자는 success 페이지로 리다이렉트 + response.sendRedirect(frontendUrl + "/login/user/success"); } } } \ No newline at end of file diff --git a/src/main/java/com/back/global/security/SecurityUser.java b/src/main/java/com/back/global/security/SecurityUser.java index 81aafb2b..ae0b9adb 100644 --- a/src/main/java/com/back/global/security/SecurityUser.java +++ b/src/main/java/com/back/global/security/SecurityUser.java @@ -32,7 +32,13 @@ public SecurityUser( Collection authorities, Map attributes ) { - super(email, "", authorities); // OAuth2에서는 빈 패스워드 + super( + (email != null && !email.isBlank()) ? email : String.valueOf(id), // ★★★ 핵심 수정 + "", + authorities + ); + + this.id = id; this.nickname = nickname; this.email = email; diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 875f3ea1..6d73afc5 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -41,7 +41,8 @@ logging: # 쿠키 보안 설정 (HTTP 환경용) custom: cookie: - secure: false + secure: true + same: "Lax" # # AI 설정 # ai: diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index a65bc4f8..db71b28c 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -19,7 +19,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: - ddl-auto: create-drop + ddl-auto: create # 삭제 재성성 과정에서 외래키 제약발생. create 변경 후 배포 테스트 properties: hibernate: show_sql: false @@ -37,6 +37,7 @@ logging: custom: cookie: secure: true + same: "None" domain: ${custom.prod.cookieDomain} site: frontUrl: "${custom.prod.frontUrl}" diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 10a0200d..e2ac5c23 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -8,8 +8,7 @@ spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration - - org.springframework.boot.autoconfigure.session.SessionAutoConfiguration - - + application: name: back diff --git a/terraform/main.tf b/terraform/main.tf index cf62dcd5..2e43504c 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -184,6 +184,41 @@ resource "aws_iam_instance_profile" "instance_profile_1" { } } +# S3 버킷 설정 추가 +resource "aws_s3_bucket" "app_bucket" { + bucket = "${var.prefix}-${var.s3_bucket_name}" + + tags = { + Name = "${var.prefix}-${var.s3_bucket_name}" + } +} + +resource "aws_s3_bucket_public_access_block" "app_bucket_pab" { + bucket = aws_s3_bucket.app_bucket.id + + block_public_acls = false + block_public_policy = false + ignore_public_acls = false + restrict_public_buckets = false +} + +resource "aws_s3_bucket_policy" "app_bucket_policy" { + bucket = aws_s3_bucket.app_bucket.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = "*" + Action = "s3:GetObject" + Resource = "${aws_s3_bucket.app_bucket.arn}/*" + } + ] + }) +} + + locals { ec2_user_data_base = <<-END_OF_FILE #!/bin/bash diff --git a/terraform/variables.tf b/terraform/variables.tf index 06a4546e..65582eed 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -18,5 +18,15 @@ variable "prefix" { variable "app_1_domain" { description = "app_1 domain" default = "api.ssoul.o-r.kr" +} + +variable "s3_bucket_name" { + description = "S3 bucket name for file storage" + default = "app-s3-bucket" +} +variable "s3_public_read" { + description = "Enable public read access for S3 bucket" + type = bool + default = true } \ No newline at end of file