Skip to content

Commit 39144ef

Browse files
authored
Merge pull request #66 from POPCONG/develop
[ Deploy ] 프로필 편집 기능 작성
2 parents 5998df4 + db11ee3 commit 39144ef

8 files changed

Lines changed: 113 additions & 2 deletions

File tree

src/main/java/popcong/app/adapter/in/user/UserController.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
import org.springframework.web.bind.annotation.*;
99
import org.springframework.web.multipart.MultipartFile;
1010
import popcong.app.application.auth.port.in.GoogleDriveSubmitUseCase;
11+
import popcong.app.application.image.port.out.ProfileImageUploadPort;
12+
import popcong.app.application.image.service.ProfileImageService;
13+
import popcong.app.application.user.dto.response.MyProfileResponseDto;
1114
import popcong.app.application.user.dto.response.UserResponseDto;
15+
import popcong.app.application.user.port.in.GetMyProfileUseCase;
16+
import popcong.app.application.user.port.in.UpdateMyProfileUseCase;
1217
import popcong.app.application.user.port.in.UserInfoUseCase;
1318
import popcong.app.domain.user.model.DocumentType;
1419
import popcong.app.domain.user.model.SignUpUserType;
@@ -31,6 +36,11 @@ public class UserController {
3136
private final GoogleDriveSubmitUseCase googleDriveSubmitUseCase;
3237
private final UserInfoUseCase userInfoUseCase;
3338

39+
private final GetMyProfileUseCase getMyProfileUseCase;
40+
private final UpdateMyProfileUseCase updateMyProfileUseCase;
41+
private final ProfileImageService profileImageService;
42+
private final ProfileImageUploadPort profileImageUploadPort;
43+
3444

3545
/**
3646
* GUEST 파일 업로드 API
@@ -139,4 +149,41 @@ public ResponseDto<UserResponseDto> getUserInfo(@AuthenticationPrincipal User us
139149
result
140150
);
141151
}
152+
153+
// 내 프로필 조회
154+
@GetMapping("/mypage/me")
155+
public ResponseDto<MyProfileResponseDto> getMyProfile(@AuthenticationPrincipal User user) {
156+
if (user == null) throw new BusinessException(AuthErrorCode.UNAUTHORIZED);
157+
158+
MyProfileResponseDto dto = getMyProfileUseCase.get(user.userId());
159+
160+
return new ResponseDto<>(
161+
HttpStatus.OK.value(),
162+
"내 프로필 조회 성공",
163+
dto
164+
);
165+
}
166+
167+
//프로필 편집
168+
@PatchMapping(value = "/my/update-profile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
169+
public ResponseDto<Void> updateMyProfile(
170+
@AuthenticationPrincipal User user,
171+
@RequestPart(required = false) String name,
172+
@RequestPart(required = false) String introduction,
173+
@RequestPart(required = false) MultipartFile profileImage
174+
) {
175+
if (user == null) throw new BusinessException(AuthErrorCode.UNAUTHORIZED);
176+
177+
String profileImageUrl = null;
178+
if (profileImage != null && !profileImage.isEmpty()) {
179+
// S3 업로드 + IMAGE 테이블 반영 + USER.profile_image_url 동기화
180+
profileImageUrl = profileImageUploadPort.uploadProfileImage(user.userId(), profileImage);
181+
182+
}
183+
updateMyProfileUseCase.update(user.userId(), name, introduction, profileImageUrl);
184+
return new ResponseDto<>(
185+
HttpStatus.OK.value(),
186+
"프로필 편집 성공",
187+
null);
188+
}
142189
}

src/main/java/popcong/app/adapter/out/persistence/image/repository/ImageJpaRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ Optional<ImageJpaEntity> findByImageableTypeAndImageableIdAndSaveOrder(
1616
List<ImageJpaEntity> findByImageableIdAndImageableTypeOrderBySaveOrderAsc(
1717
Long imageableId, ImageableType imageableType
1818
);
19+
20+
void deleteByImageableTypeAndImageableId(ImageableType imageableType, Long imageableId);
1921
}

src/main/java/popcong/app/adapter/out/persistence/user/repository/UpdateUserAdapter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,5 @@ public void updateProfile(Long userId, String name, String introduction, String
2424
if (introduction != null) user.changeIntroduction(introduction);
2525
if (profileImageUrl != null) user.changeProfileImageUrl(profileImageUrl);
2626

27-
2827
}
2928
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package popcong.app.application.image.service;
2+
3+
4+
import lombok.RequiredArgsConstructor;
5+
import org.springframework.stereotype.Service;
6+
import org.springframework.transaction.annotation.Transactional;
7+
import popcong.app.adapter.out.persistence.image.entity.ImageJpaEntity;
8+
import popcong.app.adapter.out.persistence.image.repository.ImageJpaRepository;
9+
import popcong.app.domain.image.model.ImageableType;
10+
11+
@Service
12+
@RequiredArgsConstructor
13+
public class ProfileImageService {
14+
15+
private final ImageJpaRepository imageRepo;
16+
17+
/** 기존 PROFILE 이미지를 지우고 새 URL 1장으로 교체 (IMAGE 테이블만) */
18+
@Transactional
19+
public void replaceProfileImage(Long userId, String newUrl) {
20+
imageRepo.deleteByImageableTypeAndImageableId(ImageableType.PROFILE, userId);
21+
22+
ImageJpaEntity entity = ImageJpaEntity.builder()
23+
.imageUrl(newUrl)
24+
.saveOrder(0)
25+
.imageableId(userId)
26+
.imageableType(ImageableType.PROFILE)
27+
.build();
28+
29+
imageRepo.save(entity);
30+
}
31+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package popcong.app.application.user.port.in;
2+
3+
public interface ProfileImageRecordUseCase {
4+
void recordProfileImage(Long userId, String imageUrl);
5+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package popcong.app.application.user.port.out;
22

33
public interface UpdateUserPort {
4+
45
void updateProfile(Long userId, String name, String introduction, String profileImageUrl);
56
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//package popcong.app.application.user.service;
2+
//
3+
//import lombok.RequiredArgsConstructor;
4+
//import org.springframework.stereotype.Service;
5+
//import org.springframework.transaction.annotation.Transactional;
6+
//
7+
//@Service
8+
//@RequiredArgsConstructor
9+
//@Transactional
10+
//public class ProfileImageRecordService {
11+
//
12+
// private final SaveImagePort saveImagePort;
13+
//
14+
// @Override
15+
// public void recordProfileImage(Long userId, String imageUrl) {
16+
// saveImagePort.upsertProfileImage(userId, imageUrl, 1); // 프로필은 항상 1순위
17+
// }
18+
//}

src/main/java/popcong/app/application/user/service/UpdateMyProfileService.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import lombok.RequiredArgsConstructor;
44
import org.springframework.stereotype.Service;
55
import org.springframework.transaction.annotation.Transactional;
6+
import popcong.app.application.image.service.ProfileImageService;
67
import popcong.app.application.user.port.in.UpdateMyProfileUseCase;
78
import popcong.app.application.user.port.out.UpdateUserPort;
89

@@ -11,11 +12,18 @@
1112
public class UpdateMyProfileService implements UpdateMyProfileUseCase {
1213

1314
private final UpdateUserPort updateUserPort;
15+
private final ProfileImageService profileImageService;
1416

1517
/** name/introduction/profileImageUrl 각각 null 이면 “해당 항목은 변경 없음” 처리 */
16-
@Override
1718
@Transactional
19+
@Override
1820
public void update(Long userId, String name, String introduction, String profileImageUrl) {
21+
// 이름/소개만 업데이트
1922
updateUserPort.updateProfile(userId, name, introduction, profileImageUrl);
23+
24+
// 프로필 이미지는 ProfileImageService로 위임
25+
if (profileImageUrl != null) {
26+
profileImageService.replaceProfileImage(userId, profileImageUrl);
27+
}
2028
}
2129
}

0 commit comments

Comments
 (0)