diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml index 6817cd44f..5d1edbf8f 100644 --- a/.github/workflows/build-deploy.yml +++ b/.github/workflows/build-deploy.yml @@ -3,7 +3,7 @@ run-name: Running on: push: branches: - - deploy # deploy 브런치로 푸쉬했을 때 실행 + - deploy pull_request: branches: - deploy diff --git a/appspec.yml b/appspec.yml index 0d70f3c05..37c70a455 100644 --- a/appspec.yml +++ b/appspec.yml @@ -5,6 +5,8 @@ files: - source: / destination: /home/ec2-user/cicd overwrite: yes + exclude: + - /home/ec2-user/cicd/src/main/resources/application-prod.yml file_exists_behavior: OVERWRITE @@ -31,6 +33,11 @@ permissions: - file hooks: + BeforeInstall: + - location: scripts/backup.sh + timeout: 60 + runas: ec2-user + ApplicationStop: - location: scripts/stop.sh timeout: 60 @@ -40,3 +47,8 @@ hooks: - location: scripts/deploy.sh timeout: 600 runas: ec2-user + + AfterInstall: + - location: scripts/restore.sh + timeout: 60 + runas: ec2-user diff --git a/docker-compose.yml b/docker-compose.yml index b02717a1a..821829592 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,8 +21,6 @@ services: - app3 - prometheus - grafana - networks: - - server-network app1: image: "yeachan05/application:latest" @@ -34,8 +32,9 @@ services: - redis volumes: - /home/ec2-user/application-prod.yml:/config/application-prod.yml - networks: - - server-network + environment: + - TZ=Asia/Seoul + - spring.application.name=app1 app2: image: "yeachan05/application:latest" @@ -47,8 +46,9 @@ services: - redis volumes: - /home/ec2-user/application-prod.yml:/config/application-prod.yml - networks: - - server-network + environment: + - TZ=Asia/Seoul + - spring.application.name=app2 app3: image: "yeachan05/application:latest" @@ -60,8 +60,9 @@ services: - redis volumes: - /home/ec2-user/application-prod.yml:/config/application-prod.yml - networks: - - server-network + environment: + - TZ=Asia/Seoul + - spring.application.name=app3 redis: container_name: redis @@ -71,8 +72,6 @@ services: - "6379:6379" volumes: - redis-data:/data - networks: - - server-network prometheus: image: prom/prometheus @@ -85,21 +84,18 @@ services: - "9090:9090" extra_hosts: - "host.docker.internal:host-gateway" - networks: - - server-network grafana: image: grafana/grafana container_name: grafana restart: always + user: "472" ports: - "3009:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD} volumes: - grafana-storage:/var/lib/grafana - networks: - - server-network mysqld_exporter: image: quay.io/prometheus/mysqld-exporter @@ -111,14 +107,7 @@ services: - "9104:9104" volumes: - /home/ec2-user/my.cnf:/etc/mysql/my.cnf - networks: - - server-network - volumes: grafana-storage: prometheus-data: - redis-data: - -networks: - server-network: - driver: bridge + redis-data: \ No newline at end of file diff --git a/nginx.conf b/nginx.conf index 2b86cee7e..b8f9c3cb4 100644 --- a/nginx.conf +++ b/nginx.conf @@ -49,6 +49,11 @@ http { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; + + # 프록시 버퍼 확장 + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; } location = /favicon.ico { return 204; diff --git a/prometheus.yml b/prometheus.yml index abb0d6183..5a067c96f 100644 --- a/prometheus.yml +++ b/prometheus.yml @@ -8,7 +8,7 @@ scrape_configs: - job_name: 'spring-boot-apps' static_configs: - - targets: ['app1:8080', 'app2:8080', 'app3:8080'] + - targets: ['host.docker.internal:8081', 'host.docker.internal:8082', 'host.docker.internal:8083'] metrics_path: '/actuator/prometheus' - job_name: 'mysql' diff --git a/scripts/backup.sh b/scripts/backup.sh new file mode 100644 index 000000000..143a569eb --- /dev/null +++ b/scripts/backup.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +mkdir -p /home/ec2-user/cicd/backup +cp /home/ec2-user/cicd/src/main/resources/application-prod.yml /home/ec2-user/cicd/backup/ diff --git a/scripts/restore.sh b/scripts/restore.sh new file mode 100644 index 000000000..3e6652a8f --- /dev/null +++ b/scripts/restore.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +if [ -f /home/ec2-user/cicd/backup/application-prod.yml ]; then + cp /home/ec2-user/cicd/backup/application-prod.yml /home/ec2-user/cicd/src/main/resources/application-prod.yml +fi diff --git a/src/main/java/org/kakaoshare/backend/domain/member/controller/OAuthController.java b/src/main/java/org/kakaoshare/backend/domain/member/controller/OAuthController.java index f38b0138c..7f6a6b21b 100644 --- a/src/main/java/org/kakaoshare/backend/domain/member/controller/OAuthController.java +++ b/src/main/java/org/kakaoshare/backend/domain/member/controller/OAuthController.java @@ -4,6 +4,7 @@ import lombok.RequiredArgsConstructor; import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginRequest; import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResponse; +import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResult; import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueRequest; import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResponse; import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResult; @@ -29,11 +30,11 @@ public class OAuthController { @PostMapping("/login") public ResponseEntity login(@RequestBody @Valid final OAuthLoginRequest oAuthLoginRequest) { - final OAuthLoginResponse loginResponse = oAuthService.login(oAuthLoginRequest); - final ResponseCookie cookie = refreshTokenCookieProvider.createCookie(loginResponse.refreshToken()); + final OAuthLoginResult oAuthLoginResult = oAuthService.login(oAuthLoginRequest); + final ResponseCookie cookie = refreshTokenCookieProvider.createCookie(oAuthLoginResult.refreshToken()); return ResponseEntity.ok() .header(HttpHeaders.SET_COOKIE, cookie.toString()) - .body(loginResponse); + .body(OAuthLoginResponse.from(oAuthLoginResult)); } @PostMapping("/logout") diff --git a/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginRequest.java b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginRequest.java index f8858d597..dac5dcec3 100644 --- a/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginRequest.java +++ b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginRequest.java @@ -5,4 +5,5 @@ public record OAuthLoginRequest( @NotNull(message = "소셜 이름은 필수입니다.") String provider, @NotNull(message = "소셜 리프레시 토큰은 필수입니다.") String socialAccessToken -) {} \ No newline at end of file +) { +} \ No newline at end of file diff --git a/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResponse.java b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResponse.java index 8a5e1052f..b7744f8dc 100644 --- a/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResponse.java +++ b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResponse.java @@ -1,15 +1,7 @@ package org.kakaoshare.backend.domain.member.dto.oauth.authenticate; -import lombok.Builder; -import org.kakaoshare.backend.domain.member.dto.oauth.profile.OAuthProfile; -import org.kakaoshare.backend.domain.member.dto.oauth.token.RefreshTokenDto; -import org.kakaoshare.backend.domain.member.entity.token.RefreshToken; - -@Builder -public record OAuthLoginResponse(String accessToken, RefreshTokenDto refreshToken, OAuthLoginMemberResponse member) { - public static OAuthLoginResponse of(final String accessToken, - final RefreshToken refreshToken, - final OAuthProfile oAuthProfile) { - return new OAuthLoginResponse(accessToken, RefreshTokenDto.from(refreshToken), OAuthLoginMemberResponse.from(oAuthProfile)); +public record OAuthLoginResponse(String accessToken, OAuthLoginMemberResponse member) { + public static OAuthLoginResponse from(final OAuthLoginResult oAuthLoginResult) { + return new OAuthLoginResponse(oAuthLoginResult.accessToken(), oAuthLoginResult.member()); } -} \ No newline at end of file +} diff --git a/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResult.java b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResult.java new file mode 100644 index 000000000..360b3c150 --- /dev/null +++ b/src/main/java/org/kakaoshare/backend/domain/member/dto/oauth/authenticate/OAuthLoginResult.java @@ -0,0 +1,15 @@ +package org.kakaoshare.backend.domain.member.dto.oauth.authenticate; + +import lombok.Builder; +import org.kakaoshare.backend.domain.member.dto.oauth.profile.OAuthProfile; +import org.kakaoshare.backend.domain.member.dto.oauth.token.RefreshTokenDto; +import org.kakaoshare.backend.domain.member.entity.token.RefreshToken; + +@Builder +public record OAuthLoginResult(String accessToken, RefreshTokenDto refreshToken, OAuthLoginMemberResponse member) { + public static OAuthLoginResult of(final String accessToken, + final RefreshToken refreshToken, + final OAuthProfile oAuthProfile) { + return new OAuthLoginResult(accessToken, RefreshTokenDto.from(refreshToken), OAuthLoginMemberResponse.from(oAuthProfile)); + } +} \ No newline at end of file diff --git a/src/main/java/org/kakaoshare/backend/domain/member/repository/MemberRepository.java b/src/main/java/org/kakaoshare/backend/domain/member/repository/MemberRepository.java index 4ce2683ae..63180519d 100644 --- a/src/main/java/org/kakaoshare/backend/domain/member/repository/MemberRepository.java +++ b/src/main/java/org/kakaoshare/backend/domain/member/repository/MemberRepository.java @@ -1,15 +1,16 @@ package org.kakaoshare.backend.domain.member.repository; -import java.util.List; import org.kakaoshare.backend.domain.member.entity.Member; import org.kakaoshare.backend.domain.member.repository.query.MemberRepositoryCustom; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; -import org.springframework.data.jpa.repository.Query; public interface MemberRepository extends JpaRepository, MemberRepositoryCustom { Optional findMemberByProviderId(String providerId); @Query("SELECT m FROM Member m WHERE m.providerId IN :providerIds") - List findByProviderIds(List providerIds); + List findByProviderIds(@Param("providerIds") List providerIds); } diff --git a/src/main/java/org/kakaoshare/backend/domain/member/service/oauth/OAuthService.java b/src/main/java/org/kakaoshare/backend/domain/member/service/oauth/OAuthService.java index 924ddbd69..838108363 100644 --- a/src/main/java/org/kakaoshare/backend/domain/member/service/oauth/OAuthService.java +++ b/src/main/java/org/kakaoshare/backend/domain/member/service/oauth/OAuthService.java @@ -2,7 +2,7 @@ import lombok.RequiredArgsConstructor; import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginRequest; -import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResponse; +import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResult; import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueRequest; import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueResponse; import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResult; @@ -42,7 +42,7 @@ public class OAuthService { private final OAuthWebClientService webClientService; @Transactional - public OAuthLoginResponse login(final OAuthLoginRequest oAuthLoginRequest) { + public OAuthLoginResult login(final OAuthLoginRequest oAuthLoginRequest) { final ClientRegistration registration = clientRegistrationRepository.findByRegistrationId(oAuthLoginRequest.provider()); final OAuthProfile oAuthProfile = getProfile(oAuthLoginRequest, registration); final UserDetails userDetails = addOrFindByProfile(oAuthProfile); @@ -50,7 +50,7 @@ public OAuthLoginResponse login(final OAuthLoginRequest oAuthLoginRequest) { final RefreshToken refreshToken = refreshTokenProvider.createToken(userDetails.getUsername()); refreshTokenRepository.save(refreshToken); - return OAuthLoginResponse.of(accessToken, refreshToken, oAuthProfile); + return OAuthLoginResult.of(accessToken, refreshToken, oAuthProfile); } @Transactional diff --git a/src/main/resources/db/migration/V11__add_receipt_option_date_column.sql b/src/main/resources/db/migration/V11__add_receipt_option_date_column.sql new file mode 100644 index 000000000..280a3e491 --- /dev/null +++ b/src/main/resources/db/migration/V11__add_receipt_option_date_column.sql @@ -0,0 +1,3 @@ +ALTER TABLE receipt_option + ADD COLUMN created_at datetime(6) null, + ADD COLUMN updated_at datetime(6) null; \ No newline at end of file diff --git a/src/test/java/org/kakaoshare/backend/domain/member/service/OAuthServiceTest.java b/src/test/java/org/kakaoshare/backend/domain/member/service/OAuthServiceTest.java index b2f37869d..2cb0ed669 100644 --- a/src/test/java/org/kakaoshare/backend/domain/member/service/OAuthServiceTest.java +++ b/src/test/java/org/kakaoshare/backend/domain/member/service/OAuthServiceTest.java @@ -5,7 +5,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginRequest; -import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResponse; +import org.kakaoshare.backend.domain.member.dto.oauth.authenticate.OAuthLoginResult; import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueRequest; import org.kakaoshare.backend.domain.member.dto.oauth.issue.OAuthReissueResponse; import org.kakaoshare.backend.domain.member.dto.oauth.issue.ReissueResult; @@ -101,8 +101,8 @@ public void authenticateWhenNewMember() throws Exception { doReturn(refreshToken).when(refreshTokenProvider).createToken(userDetails.getUsername()); doReturn(refreshToken).when(refreshTokenRepository).save(any()); - final OAuthLoginResponse expect = OAuthLoginResponse.of(accessToken, refreshToken, oAuthProfile); - final OAuthLoginResponse actual = oAuthService.login(request); + final OAuthLoginResult expect = OAuthLoginResult.of(accessToken, refreshToken, oAuthProfile); + final OAuthLoginResult actual = oAuthService.login(request); assertThat(expect).isEqualTo(actual); } @@ -122,8 +122,8 @@ public void authenticateWhenExistingMember() throws Exception { doReturn(refreshToken).when(refreshTokenProvider).createToken(userDetails.getUsername()); doReturn(refreshToken).when(refreshTokenRepository).save(any()); - final OAuthLoginResponse expect = OAuthLoginResponse.of(accessToken, refreshToken, oAuthProfile); - final OAuthLoginResponse actual = oAuthService.login(request); + final OAuthLoginResult expect = OAuthLoginResult.of(accessToken, refreshToken, oAuthProfile); + final OAuthLoginResult actual = oAuthService.login(request); assertThat(expect).isEqualTo(actual); }