Skip to content

Commit 6c392e7

Browse files
committed
♻️Refactor: 사용자 정보 조회 구현 및 캐시 무효화
1 parent cfd286e commit 6c392e7

File tree

5 files changed

+116
-7
lines changed

5 files changed

+116
-7
lines changed

src/main/java/com/be/sportizebe/domain/user/controller/UserController.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
66
import com.be.sportizebe.domain.user.dto.response.SignUpResponse;
77
import com.be.sportizebe.domain.user.dto.response.UpdateProfileResponse;
8+
import com.be.sportizebe.domain.user.dto.response.UserInfoResponse;
89
import com.be.sportizebe.domain.user.service.UserServiceImpl;
910
import com.be.sportizebe.global.response.BaseResponse;
1011
import com.be.sportizebe.global.cache.dto.UserAuthInfo;
@@ -54,4 +55,13 @@ public ResponseEntity<BaseResponse<UpdateProfileResponse>> updateProfile(
5455
UpdateProfileResponse response = userService.updateProfile(userAuthInfo.getId(), request);
5556
return ResponseEntity.ok(BaseResponse.success("프로필 수정 성공", response));
5657
}
58+
59+
@GetMapping("/me")
60+
@Operation(summary = "내 정보 조회", description = "현재 로그인한 사용자의 정보를 조회합니다.")
61+
public ResponseEntity<BaseResponse<UserInfoResponse>> getMyInfo(
62+
@AuthenticationPrincipal UserAuthInfo userAuthInfo
63+
) {
64+
UserInfoResponse response = userService.getUserInfo(userAuthInfo.getId());
65+
return ResponseEntity.ok(BaseResponse.success("사용자 정보 조회 성공", response));
66+
}
5767
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.be.sportizebe.domain.user.dto.response;
2+
3+
import com.be.sportizebe.domain.user.entity.Gender;
4+
import com.be.sportizebe.domain.user.entity.SportType;
5+
import com.be.sportizebe.domain.user.entity.User;
6+
import com.be.sportizebe.global.cache.dto.UserAuthInfo;
7+
import io.swagger.v3.oas.annotations.media.Schema;
8+
import lombok.Builder;
9+
10+
import java.util.List;
11+
12+
@Builder
13+
@Schema(title = "UserInfoResponse DTO", description = "사용자 정보 조회 응답")
14+
public record UserInfoResponse(
15+
@Schema(description = "사용자 ID", example = "1")
16+
Long userId,
17+
18+
@Schema(description = "이메일(아이디)", example = "test@example.com")
19+
String username,
20+
21+
@Schema(description = "닉네임", example = "축구왕")
22+
String nickname,
23+
24+
@Schema(description = "한줄 소개", example = "안녕하세요!")
25+
String introduce,
26+
27+
@Schema(description = "프로필 이미지 URL")
28+
String profileImage,
29+
30+
@Schema(description = "성별", example = "MALE")
31+
Gender gender,
32+
33+
@Schema(description = "전화번호", example = "010-1234-5678")
34+
String phoneNumber,
35+
36+
@Schema(description = "관심 종목")
37+
List<SportType> interestType
38+
) {
39+
public static UserInfoResponse from(User user) { // DB 조회
40+
return UserInfoResponse.builder()
41+
.userId(user.getId())
42+
.username(user.getUsername())
43+
.nickname(user.getNickname())
44+
.introduce(user.getIntroduce())
45+
.profileImage(user.getProfileImage())
46+
.gender(user.getGender())
47+
.phoneNumber(user.getPhoneNumber())
48+
.interestType(user.getInterestType())
49+
.build();
50+
}
51+
52+
public static UserInfoResponse from(UserAuthInfo userAuthInfo) { // 캐시메모리 조회
53+
return UserInfoResponse.builder()
54+
.userId(userAuthInfo.getId())
55+
.username(userAuthInfo.getUsername())
56+
.nickname(userAuthInfo.getNickname())
57+
.introduce(userAuthInfo.getIntroduce())
58+
.profileImage(userAuthInfo.getProfileImage())
59+
.gender(userAuthInfo.getGender())
60+
.phoneNumber(userAuthInfo.getPhoneNumber())
61+
.interestType(userAuthInfo.getInterestType())
62+
.build();
63+
}
64+
}

src/main/java/com/be/sportizebe/domain/user/service/UserService.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
66
import com.be.sportizebe.domain.user.dto.response.SignUpResponse;
77
import com.be.sportizebe.domain.user.dto.response.UpdateProfileResponse;
8+
import com.be.sportizebe.domain.user.dto.response.UserInfoResponse;
89
import org.springframework.web.multipart.MultipartFile;
910

1011
public interface UserService {
@@ -17,4 +18,7 @@ public interface UserService {
1718

1819
// 프로필 수정 (닉네임, 한줄소개)
1920
UpdateProfileResponse updateProfile(Long userId, UpdateProfileRequest request);
21+
22+
// 사용자 정보 조회
23+
UserInfoResponse getUserInfo(Long userId);
2024
}

src/main/java/com/be/sportizebe/domain/user/service/UserServiceImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.be.sportizebe.domain.user.dto.response.ProfileImageResponse;
66
import com.be.sportizebe.domain.user.dto.response.SignUpResponse;
77
import com.be.sportizebe.domain.user.dto.response.UpdateProfileResponse;
8+
import com.be.sportizebe.domain.user.dto.response.UserInfoResponse;
89
import com.be.sportizebe.domain.user.entity.Role;
910
import com.be.sportizebe.domain.user.entity.User;
1011
import com.be.sportizebe.domain.user.exception.UserErrorCode;
@@ -78,6 +79,9 @@ public ProfileImageResponse uploadProfileImage(Long userId, MultipartFile file)
7879
// 사용자 프로필 이미지 URL 업데이트
7980
user.updateProfileImage(profileImageUrl);
8081

82+
// 프로필 이미지가 캐시에 포함되어 있으므로 캐시 무효화
83+
userCacheService.evictUserAuthInfo(userId);
84+
8185
log.info("사용자 프로필 이미지 업로드 완료: userId={}, url={}", userId, profileImageUrl);
8286

8387
return ProfileImageResponse.from(profileImageUrl);
@@ -104,4 +108,15 @@ public UpdateProfileResponse updateProfile(Long userId, UpdateProfileRequest req
104108

105109
return UpdateProfileResponse.from(user);
106110
}
111+
112+
@Override
113+
public UserInfoResponse getUserInfo(Long userId) {
114+
// 캐시에서 사용자 정보 조회 (캐시 미스 시 DB 조회 후 캐싱)
115+
var userAuthInfo = userCacheService.findUserAuthInfoById(userId);
116+
if (userAuthInfo == null) {
117+
throw new CustomException(UserErrorCode.USER_NOT_FOUND);
118+
}
119+
120+
return UserInfoResponse.from(userAuthInfo);
121+
}
107122
}
Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,48 @@
11
package com.be.sportizebe.global.cache.dto;
22

3+
import com.be.sportizebe.domain.user.entity.Gender;
34
import com.be.sportizebe.domain.user.entity.Role;
5+
import com.be.sportizebe.domain.user.entity.SportType;
46
import com.be.sportizebe.domain.user.entity.User;
57
import lombok.AllArgsConstructor;
8+
import lombok.Builder;
69
import lombok.Getter;
710
import lombok.NoArgsConstructor;
811

912
import java.io.Serializable;
13+
import java.util.List;
1014

1115
/**
1216
* JWT 인증 필터에서 사용할 캐시용 사용자 정보 DTO
1317
* User 엔티티의 연관관계(posts 등)로 인한 직렬화 문제를 방지
18+
* 민감정보(password, refreshToken) 제외
1419
*/
1520
@Getter
21+
@Builder
1622
@NoArgsConstructor
1723
@AllArgsConstructor
18-
public class UserAuthInfo implements Serializable { // Serializable : 직렬화 가능하다라는 마커 표시
24+
public class UserAuthInfo implements Serializable {
1925
private Long id;
2026
private String username;
2127
private String nickname;
2228
private Role role;
29+
private String profileImage;
30+
private String introduce;
31+
private Gender gender;
32+
private String phoneNumber;
33+
private List<SportType> interestType;
2334

2435
public static UserAuthInfo from(User user) {
25-
return new UserAuthInfo(
26-
user.getId(),
27-
user.getUsername(),
28-
user.getNickname(),
29-
user.getRole()
30-
);
36+
return UserAuthInfo.builder()
37+
.id(user.getId())
38+
.username(user.getUsername())
39+
.nickname(user.getNickname())
40+
.role(user.getRole())
41+
.profileImage(user.getProfileImage())
42+
.introduce(user.getIntroduce())
43+
.gender(user.getGender())
44+
.phoneNumber(user.getPhoneNumber())
45+
.interestType(user.getInterestType())
46+
.build();
3147
}
3248
}

0 commit comments

Comments
 (0)