Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/com/example/FixLog/FixLogApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

//Create_At 어노테이션
@EnableJpaAuditing
@SpringBootApplication
public class FixLogApplication {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.example.FixLog.domain.member.Member;
import com.example.FixLog.dto.Response;
import com.example.FixLog.dto.WithdrawRequestDto;
import com.example.FixLog.dto.member.MemberInfoResponseDto;
import com.example.FixLog.dto.member.SignupRequestDto;
import com.example.FixLog.dto.member.DuplicateCheckResponseDto;
Expand Down Expand Up @@ -51,8 +52,11 @@ public ResponseEntity<Response<MemberInfoResponseDto>> getMyInfo(@Authentication
}

@DeleteMapping("/me")
public ResponseEntity<Response<Void>> withdraw(@AuthenticationPrincipal Member member) {
memberService.withdraw(member);
public ResponseEntity<Response<Void>> withdraw(
@AuthenticationPrincipal Member member,
@RequestBody WithdrawRequestDto request
) {
memberService.withdraw(member, request.getPassword());
return ResponseEntity.ok(Response.success("회원 탈퇴 성공", null));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.example.FixLog.controller;

import com.example.FixLog.dto.Response;
import com.example.FixLog.dto.member.edit.EditNicknameRequestDto;
import com.example.FixLog.dto.member.edit.EditPasswordRequestDto;
import com.example.FixLog.dto.member.edit.EditProfileImageRequestDto;
import com.example.FixLog.dto.member.edit.EditBioRequestDto;
import com.example.FixLog.service.MemberService;
import com.example.FixLog.domain.member.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/mypage")
public class MypageMemberController {

private final MemberService memberService;

@PatchMapping("/members/nickname")
public ResponseEntity<Response<String>> editNickname(
@RequestBody EditNicknameRequestDto requestDto
) {
Member member = memberService.getCurrentMemberInfo();
memberService.editNickname(member, requestDto.getNickname());
return ResponseEntity.ok(Response.success("닉네임 수정 성공", null));
}

@PatchMapping("/members/password")
public ResponseEntity<Response<Void>> editPassword(
@AuthenticationPrincipal UserDetails userDetails,
@RequestBody EditPasswordRequestDto requestDto
) {
Member member = memberService.getCurrentMemberInfo();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AuthenticationPrincipal UserDetails userDetails 이거랑 Member member = memberService.getCurrentMemberInfo(); 이거는 둘 중에 하나만 사용해도 되지 않나요?
저는 매개변수에 @AuthenticationPrincipal 사용은 안하고 서비스 단에서 member 객체 불러와서 사용하도록 했거든요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 인증 관련 처리를 컨트롤러에서 분리하고자 @AuthenticationPrincipal은 사용하지 않고, 서비스 단에서 SecurityContextHolder를 활용해 getCurrentMemberInfo()로 인증된 회원 정보를 가져오도록 통일했습니다. 확인 부탁드립니다!!

memberService.editPassword(member, requestDto);
return ResponseEntity.ok(Response.success("비밀번호 변경 성공", null));
}

@PatchMapping("/members/profile-image")
public ResponseEntity<Response<String>> editProfileImage(
@RequestBody EditProfileImageRequestDto requestDto
) {
Member member = memberService.getCurrentMemberInfo();
memberService.editProfileImage(member, requestDto.getProfileImageUrl());
return ResponseEntity.ok(Response.success("프로필 이미지 수정 성공", null));
}

@PatchMapping("/members/bio")
public ResponseEntity<Response<String>> editBio(
@RequestBody EditBioRequestDto requestDto
) {
Member member = memberService.getCurrentMemberInfo();
memberService.editBio(member, requestDto.getBio());
return ResponseEntity.ok(Response.success("소개글 수정 성공", null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ public ResponseEntity<Response<PageResponseDto<MyPostPageResponseDto>>> getMyPos
return ResponseEntity.ok(Response.success("내가 작성한 글 보기 성공", data));
}

// 내가 좋아요한 글
@GetMapping("/likes")
public ResponseEntity<Response<PageResponseDto<MyPostPageResponseDto>>> getLikedPosts(
@AuthenticationPrincipal UserDetails userDetails,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "4") int size,
@RequestParam(defaultValue = "0") int sort) {

String email = userDetails.getUsername();
PageResponseDto<MyPostPageResponseDto> result = mypagePostService.getLikedPosts(email, page, sort, size);
return ResponseEntity.ok(Response.success("내가 좋아요한 글 보기 성공", result));
}
// // 내가 좋아요한 글
// @GetMapping("/likes")
// public ResponseEntity<Response<PageResponseDto<MyPostPageResponseDto>>> getLikedPosts(
// @AuthenticationPrincipal UserDetails userDetails,
// @RequestParam(defaultValue = "0") int page,
// @RequestParam(defaultValue = "4") int size,
// @RequestParam(defaultValue = "0") int sort) {
//
// String email = userDetails.getUsername();
// PageResponseDto<MyPostPageResponseDto> result = mypagePostService.getLikedPosts(email, page, sort, size);
// return ResponseEntity.ok(Response.success("내가 좋아요한 글 보기 성공", result));
// }


}
11 changes: 6 additions & 5 deletions src/main/java/com/example/FixLog/domain/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
Expand All @@ -20,6 +21,7 @@

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EntityListeners(AuditingEntityListener.class)
public class Member implements UserDetails {
Expand Down Expand Up @@ -57,7 +59,7 @@ public void setIsDeleted(boolean isDeleted) {
@Column
private LocalDateTime updatedAt;

// 프로필 사진 url, 지금은 nullable 이지만 나중에 기본값 설정
// 프로필 사진 url
@Column
private String profileImageUrl;

Expand All @@ -84,13 +86,10 @@ public static Member of(String email, String password, String nickname, SocialTy
member.nickname = nickname;
member.socialType = socialType;
member.isDeleted = false;
member.profileImageUrl = "https://dummyimage.com/200x200/cccccc/ffffff&text=Profile"; // 기본 프로필 이미지(임시)
member.profileImageUrl = null; // 디폴트 이미지는 db에 null로 저장하고 프론트한테는 기본 이미지 링크로 반환하는 방향으로 통일
return member;
}

public void setProfileImageUrl(String profileImageUrl) {
this.profileImageUrl = profileImageUrl;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Expand Down Expand Up @@ -121,4 +120,6 @@ public boolean isCredentialsNonExpired() {
public boolean isEnabled() {
return !this.isDeleted; // 탈퇴 여부 기반 활성 상태
}


}
8 changes: 8 additions & 0 deletions src/main/java/com/example/FixLog/dto/WithdrawRequestDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.FixLog.dto;

import lombok.Getter;

@Getter
public class WithdrawRequestDto {
private String password;
}
14 changes: 14 additions & 0 deletions src/main/java/com/example/FixLog/dto/member/LoginResponseDto.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.example.FixLog.dto.member;

import com.example.FixLog.domain.member.Member;
import com.example.FixLog.util.DefaultImage;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -12,4 +14,16 @@ public class LoginResponseDto {
private String accessToken;
private String nickname;
private String profileImageUrl;

// 정적 팩토리 메서드
public static LoginResponseDto from(Member member, String accessToken) {
return new LoginResponseDto(
member.getUserId(),
accessToken,
member.getNickname(),
member.getProfileImageUrl() != null
? member.getProfileImageUrl()
: DefaultImage.PROFILE
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.example.FixLog.dto.member;

import com.example.FixLog.domain.member.Member;
import com.example.FixLog.domain.member.SocialType;
import com.example.FixLog.util.DefaultImage;
import com.example.FixLog.util.DefaultText;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -12,4 +15,18 @@ public class MemberInfoResponseDto {
private String profileImageUrl;
private String bio;
private SocialType socialType;

public static MemberInfoResponseDto from(Member member) {
return new MemberInfoResponseDto(
member.getEmail(),
member.getNickname(),
member.getProfileImageUrl() != null
? member.getProfileImageUrl()
: DefaultImage.PROFILE,
member.getBio() != null
? member.getBio()
: DefaultText.BIO,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분들은 서비스단에서 처리하는 게 더 좋지 않을까요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

말씀 주신 부분을 반영하여 해당 처리는 서비스 단에서 담당하도록 변경했습니다.
확인 부탁드립니다! :)

member.getSocialType()
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

팩토리 메서드 구현이 우수합니다.

null 값에 대한 기본값 처리가 올바르게 구현되었고, 유틸리티 상수를 사용하여 일관성을 유지하고 있습니다. 정적 팩토리 메서드 패턴을 잘 활용했습니다.

컨트롤러에서 팩토리 메서드 사용을 권장합니다.

MemberController.getMyInfo 메서드에서 이 새로운 팩토리 메서드를 사용하지 않고 있어 일관성이 부족합니다. 기본값 처리 로직의 중복을 피하기 위해 팩토리 메서드 사용을 고려해보세요.

다음과 같이 수정을 제안합니다:

// MemberController.java의 getMyInfo 메서드에서
-MemberInfoResponseDto responseDto = new MemberInfoResponseDto(
-        member.getEmail(),
-        member.getNickname(),
-        member.getProfileImageUrl(),
-        member.getBio(),
-        member.getSocialType()
-);
+MemberInfoResponseDto responseDto = MemberInfoResponseDto.from(member);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static MemberInfoResponseDto from(Member member) {
return new MemberInfoResponseDto(
member.getEmail(),
member.getNickname(),
member.getProfileImageUrl() != null
? member.getProfileImageUrl()
: DefaultImage.PROFILE,
member.getBio() != null
? member.getBio()
: DefaultText.BIO,
member.getSocialType()
);
}
// In MemberController.java, inside getMyInfo():
MemberInfoResponseDto responseDto = MemberInfoResponseDto.from(member);
🤖 Prompt for AI Agents
In src/main/java/com/example/FixLog/dto/member/MemberInfoResponseDto.java lines
19 to 31, the static factory method correctly handles null values with default
constants. To fix the issue, update the MemberController.getMyInfo method to use
this factory method when creating MemberInfoResponseDto instances. This will
ensure consistent default value handling and avoid duplication of null checks
across the codebase.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.FixLog.dto.member.edit;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setter는 객체 상태를 너무 쉽게 바꿀 수 있어서 setter 사용하면 불변성 유지가 어렵다고 알고있어요!
Setter 사용은 정말 꼭 필요하지 않으면 지양하는 게 좋다고 알고있는데, 혹시 다른 있으면 말씀해주세요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 필드에 대한 변경은 명시적인 메서드를 통해 처리하도록 Setter를 제거하고 로직을 수정했습니다! 확인 부탁드립니다~

@NoArgsConstructor
public class EditBioRequestDto {
private String bio;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.FixLog.dto.member.edit;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class EditNicknameRequestDto {
private String nickname;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example.FixLog.dto.member.edit;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class EditPasswordRequestDto {
private String currentPassword;
private String newPassword;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.FixLog.dto.member.edit;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@NoArgsConstructor
public class EditProfileImageRequestDto {
private String profileImageUrl;
}
3 changes: 2 additions & 1 deletion src/main/java/com/example/FixLog/exception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public enum ErrorCode {
SORT_NOT_EXIST(HttpStatus.BAD_REQUEST, "사용할 수 없는 정렬입니다."),
INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다."),
REQUIRED_TAGS_MISSING(HttpStatus.BAD_REQUEST, "태그를 선택해주세요."),
REQUIRED_CONTENT_MISSING(HttpStatus.BAD_REQUEST, "필수 본문이 입력되지 않았습니다.");
REQUIRED_CONTENT_MISSING(HttpStatus.BAD_REQUEST, "필수 본문이 입력되지 않았습니다."),
SAME_AS_OLD_PASSWORD(HttpStatus.BAD_REQUEST, "다른 비밀번호 입력 바랍니다.");

private final HttpStatus status;
private final String message;
Expand Down
16 changes: 3 additions & 13 deletions src/main/java/com/example/FixLog/service/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,7 @@ public LoginResponseDto login(LoginRequestDto requestDto) {

String token = jwtUtil.createToken(member.getUserId(), member.getEmail());

// 로그인 응답 시에도 null-safe하게 처리
String profileUrl = member.getProfileImageUrl() != null
? member.getProfileImageUrl()
: "https://dummyimage.com/200x200/cccccc/ffffff&text=Profile";

return new LoginResponseDto(
member.getUserId(),
token,
member.getNickname(),
member.getProfileImageUrl() != null
? member.getProfileImageUrl()
: "https://your-cdn.com/images/default-profile.png");
// 응답에서 null-safe하게 기본 이미지 처리 포함
return LoginResponseDto.from(member, token);
}
}
}
Loading