Skip to content

Commit e7b4229

Browse files
authored
Merge pull request #43 from prgrms-web-devcourse-final-project/develop
Chore[infra]: 배포
2 parents ff4d23b + c465d5c commit e7b4229

File tree

15 files changed

+269
-215
lines changed

15 files changed

+269
-215
lines changed

.github/workflows/CI-CD_Pipeline.yml

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ jobs:
126126
run: |
127127
cat > .env << 'EOF'
128128
# JWT Configuration Properties 바인딩용 (빌드 시 필요)
129-
CUSTOM_JWT_SECRET_KEY=build-dummy-key-for-configuration-properties-binding
129+
CUSTOM_JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
130130
CUSTOM_JWT_ACCESS_TOKEN_EXPIRATION_SECONDS=3600
131131
EOF
132132
@@ -178,7 +178,29 @@ jobs:
178178
file: backend/Dockerfile
179179
push: true
180180
tags: |
181-
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:${{ github.sha }}
182-
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/backend:latest
181+
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/balaw:${{ github.sha }}
182+
${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}/balaw:latest
183183
cache-from: type=gha
184184
cache-to: type=gha,mode=max
185+
deploy:
186+
needs: docker-build
187+
runs-on: ubuntu-latest
188+
env:
189+
DOCKER_IMAGE_NAME: balaw
190+
steps:
191+
- name: AWS SSM Send-Command
192+
uses: peterkimzz/aws-ssm-send-command@master
193+
id: ssm
194+
with:
195+
aws-region: ${{ secrets.AWS_REGION }}
196+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
197+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
198+
instance-ids: "i-0b903187bca01a1c4"
199+
working-directory: /
200+
comment: Deploy
201+
command: |
202+
docker pull ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
203+
docker stop app1 2>/dev/null
204+
docker rm app1 2>/dev/null
205+
docker run -d --name app1 -p 8080:8080 ghcr.io/doohyojeong/${{ env.DOCKER_IMAGE_NAME }}:latest
206+
docker rmi $(docker images -f "dangling=true" -q)

.github/workflows/deploy.yml

Lines changed: 0 additions & 92 deletions
This file was deleted.

backend/Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ COPY settings.gradle .
1212
RUN gradle dependencies --no-daemon
1313

1414
# 소스 코드 복사
15-
COPY .env .
1615
COPY src src
1716

1817
# 애플리케이션 빌드

backend/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ dependencies {
3737
implementation 'org.apache.commons:commons-lang3:3.18.0'
3838
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.9'
3939

40+
// JWT (JSON Web Token)
41+
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
42+
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
43+
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
44+
4045
// Database (데이터베이스)
4146
runtimeOnly 'com.h2database:h2'
4247
runtimeOnly 'com.mysql:mysql-connector-j'

backend/src/main/java/com/ai/lawyer/domain/member/controller/MemberController.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public class MemberController {
3535
@ApiResponse(responseCode = "400", description = "잘못된 요청 (중복 이메일/닉네임, 유효성 검증 실패)")
3636
})
3737
public ResponseEntity<MemberResponse> signup(@Valid @RequestBody MemberSignupRequest request) {
38-
log.info("회원가입 요청: email={}, nickname={}", request.getLoginId(), request.getNickname());
38+
log.info("회원가입 요청: email={}, name={}", request.getLoginId(), request.getName());
3939

4040
try {
4141
MemberResponse response = memberService.signup(request);
@@ -72,11 +72,19 @@ public ResponseEntity<MemberResponse> login(@Valid @RequestBody MemberLoginReque
7272
@ApiResponses({
7373
@ApiResponse(responseCode = "200", description = "로그아웃 성공")
7474
})
75-
public ResponseEntity<Void> logout(HttpServletResponse response) {
75+
public ResponseEntity<Void> logout(Authentication authentication, HttpServletResponse response) {
7676
log.info("로그아웃 요청");
7777

78-
memberService.logout(response);
79-
log.info("로그아웃 완료");
78+
if (authentication != null && authentication.getName() != null) {
79+
String loginId = authentication.getName();
80+
memberService.logout(loginId, response);
81+
log.info("로그아웃 완료: email={}", loginId);
82+
} else {
83+
// 인증 정보가 없어도 쿠키는 클리어
84+
memberService.logout("", response);
85+
log.info("인증 정보 없이 로그아웃 완료");
86+
}
87+
8088
return ResponseEntity.ok().build();
8189
}
8290

@@ -128,7 +136,7 @@ public ResponseEntity<Void> withdraw(Authentication authentication, HttpServletR
128136
// loginId로 Member를 조회하여 실제 memberId 사용
129137
Member member = memberService.findByLoginId(loginId);
130138
memberService.withdraw(member.getMemberId());
131-
memberService.logout(response); // 탈퇴 후 로그아웃 처리
139+
memberService.logout(loginId, response); // 탈퇴 후 로그아웃 처리
132140
log.info("회원탈퇴 성공: email={}, memberId={}", loginId, member.getMemberId());
133141
return ResponseEntity.ok().build();
134142
} catch (IllegalArgumentException e) {

backend/src/main/java/com/ai/lawyer/domain/member/dto/MemberResponse.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ public class MemberResponse {
1414

1515
private Long memberId;
1616
private String loginId;
17-
private String nickname;
1817
private Integer age;
1918
private Member.Gender gender;
2019
private Member.Role role;
@@ -26,7 +25,6 @@ public static MemberResponse from(Member member) {
2625
return MemberResponse.builder()
2726
.memberId(member.getMemberId())
2827
.loginId(member.getLoginId())
29-
.nickname(member.getNickname())
3028
.age(member.getAge())
3129
.gender(member.getGender())
3230
.role(member.getRole())

backend/src/main/java/com/ai/lawyer/domain/member/dto/MemberSignupRequest.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,8 @@ public class MemberSignupRequest {
1616
private String loginId;
1717

1818
@NotBlank(message = "비밀번호는 필수입니다")
19-
@Size(min = 8, message = "비밀번호는 최소 8자 이상이어야 합니다")
2019
private String password;
2120

22-
@NotBlank(message = "닉네임은 필수입니다")
23-
@Size(max = 50, message = "닉네임은 50자 이하여야 합니다")
24-
private String nickname;
25-
2621
@NotNull(message = "나이는 필수입니다")
2722
@Min(value = 14, message = "최소 14세 이상이어야 합니다")
2823
private Integer age;

backend/src/main/java/com/ai/lawyer/domain/member/entity/Member.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ public class Member {
3636
@NotBlank(message = "비밀번호는 필수입니다")
3737
private String password;
3838

39-
@Column(name = "nickname", nullable = false, length = 50)
40-
@NotBlank(message = "닉네임은 필수입니다")
41-
private String nickname;
42-
4339
@Column(name = "age", nullable = false)
4440
@NotNull(message = "나이는 필수입니다")
4541
@Min(value = 14, message = "최소 14세 이상이어야 합니다")

backend/src/main/java/com/ai/lawyer/domain/member/repositories/MemberRepository.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,4 @@ public interface MemberRepository extends JpaRepository<Member, Long> {
1212
Optional<Member> findByLoginId(String loginId);
1313

1414
boolean existsByLoginId(String loginId);
15-
16-
boolean existsByNickname(String nickname);
1715
}

backend/src/main/java/com/ai/lawyer/domain/member/service/MemberService.java

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ public class MemberService {
2424
@Transactional
2525
public MemberResponse signup(MemberSignupRequest request) {
2626
validateDuplicateLoginId(request.getLoginId());
27-
validateDuplicateNickname(request.getNickname());
2827

2928
Member member = Member.builder()
3029
.loginId(request.getLoginId())
3130
.password(passwordEncoder.encode(request.getPassword()))
32-
.nickname(request.getNickname())
3331
.age(request.getAge())
3432
.gender(request.getGender())
3533
.name(request.getName())
@@ -58,34 +56,40 @@ public MemberResponse login(MemberLoginRequest request, HttpServletResponse resp
5856
return MemberResponse.from(member);
5957
}
6058

61-
public void logout(HttpServletResponse response) {
59+
public void logout(String loginId, HttpServletResponse response) {
60+
// Redis에서 리프레시 토큰 삭제
61+
tokenProvider.deleteRefreshToken(loginId);
62+
6263
// 쿠키 삭제
6364
cookieUtil.clearTokenCookies(response);
64-
65-
// TODO: 추후 레디스에서 토큰 무효화
6665
}
6766

6867
public MemberResponse refreshToken(String refreshToken, HttpServletResponse response) {
69-
// 리프레시 토큰 유효성 검증
70-
if (!tokenProvider.validateToken(refreshToken)) {
68+
// Redis에서 리프레시 토큰으로 사용자를 찾기 (Redis 키 패턴: refresh_token:loginId)
69+
String username = tokenProvider.findUsernameByRefreshToken(refreshToken);
70+
if (username == null) {
71+
throw new IllegalArgumentException("유효하지 않은 리프레시 토큰입니다.");
72+
}
73+
74+
// Redis에서 리프레시 토큰 유효성 검증
75+
if (!tokenProvider.validateRefreshToken(username, refreshToken)) {
7176
throw new IllegalArgumentException("유효하지 않은 리프레시 토큰입니다.");
7277
}
7378

74-
// TODO: 추후 레디스에서 리프레시 토큰과 매핑된 회원 정보 조회
75-
// 현재는 임시로 토큰에서 사용자명 추출 후 DB 조회
76-
String username = tokenProvider.getUsernameFromToken(refreshToken);
79+
// 회원 정보 조회
7780
Member member = memberRepository.findByLoginId(username)
7881
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회원입니다."));
7982

83+
// 기존 리프레시 토큰 Redis에서 삭제 (RTR 패턴)
84+
tokenProvider.deleteRefreshToken(username);
85+
8086
// 새로운 액세스 토큰과 리프레시 토큰 생성
8187
String newAccessToken = tokenProvider.generateAccessToken(member);
8288
String newRefreshToken = tokenProvider.generateRefreshToken(member);
8389

8490
// 새로운 토큰들을 쿠키로 설정
8591
cookieUtil.setTokenCookies(response, newAccessToken, newRefreshToken);
8692

87-
// TODO: 추후 레디스에서 기존 토큰 무효화 및 새 토큰 저장
88-
8993
return MemberResponse.from(member);
9094
}
9195

@@ -114,10 +118,4 @@ private void validateDuplicateLoginId(String loginId) {
114118
throw new IllegalArgumentException("이미 존재하는 이메일입니다.");
115119
}
116120
}
117-
118-
private void validateDuplicateNickname(String nickname) {
119-
if (memberRepository.existsByNickname(nickname)) {
120-
throw new IllegalArgumentException("이미 존재하는 닉네임입니다.");
121-
}
122-
}
123121
}

0 commit comments

Comments
 (0)