Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
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));
// }


}
4 changes: 2 additions & 2 deletions src/main/java/com/example/FixLog/domain/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void setIsDeleted(boolean isDeleted) {
@Column
private LocalDateTime updatedAt;

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

Expand All @@ -84,7 +84,7 @@ 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;
}

Expand Down
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.

}
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);
}
}
}
21 changes: 11 additions & 10 deletions src/main/java/com/example/FixLog/service/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,20 @@ public void signup(SignupRequestDto request) {
throw new CustomException(ErrorCode.NICKNAME_DUPLICATED);
}

// 문제 없으면 저장
// 회원 객체 생성 (profileImageUrl = null)
Member member = Member.of(
request.getEmail(),
passwordEncoder.encode(request.getPassword()),
request.getNickname(),
SocialType.EMAIL
);
// 기본 프로필 이미지 URL 생성
member.setProfileImageUrl("https://dummyimage.com/200x200/cccccc/ffffff&text=Profile");
// 먼저 회원 정보 저장

// 회원 저장
memberRepository.save(member);

// 기본 폴더 생성
BookmarkFolder newFolder = new BookmarkFolder(member);
bookmarkFolderRepository.save(newFolder);

}

public boolean isEmailDuplicated(String email) {
Expand All @@ -58,19 +56,22 @@ public boolean isEmailDuplicated(String email) {
public boolean isNicknameDuplicated(String nickname) {
return memberRepository.findByNickname(nickname).isPresent();
}

// 현재 로그인한 사용자 정보 member 객체로 반환
public Member getCurrentMemberInfo(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String userEmail = authentication.getName();
return memberRepository.findByEmail(userEmail)
.orElseThrow(() -> new CustomException(ErrorCode.USER_EMAIL_NOT_FOUND));
}

// 회원탈퇴
public void withdraw(Member member) {
public void withdraw(Member member, String password) {
if (!passwordEncoder.matches(password, member.getPassword())) {
throw new CustomException(ErrorCode.INVALID_PASSWORD);
}

member.setIsDeleted(true);
memberRepository.save(member);
}
}

}
33 changes: 1 addition & 32 deletions src/main/java/com/example/FixLog/service/MypagePostService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.example.FixLog.service;

import com.example.FixLog.domain.like.PostLike;
import com.example.FixLog.domain.member.Member;
import com.example.FixLog.domain.post.Post;
import com.example.FixLog.dto.PageResponseDto;
Expand All @@ -9,7 +8,6 @@
import com.example.FixLog.exception.ErrorCode;
import com.example.FixLog.repository.MemberRepository;
import com.example.FixLog.repository.fork.ForkRepository;
import com.example.FixLog.repository.like.PostLikeRepository;
import com.example.FixLog.repository.post.PostRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand All @@ -27,13 +25,11 @@ public class MypagePostService {
private final PostRepository postRepository;
private final MemberRepository memberRepository;
private final ForkRepository forkRepository;
private final PostLikeRepository postLikeRepository;

public MypagePostService(PostRepository postRepository, MemberRepository memberRepository, ForkRepository forkRepository, PostLikeRepository postLikeRepository) {
public MypagePostService(PostRepository postRepository, MemberRepository memberRepository, ForkRepository forkRepository) {
this.postRepository = postRepository;
this.memberRepository = memberRepository;
this.forkRepository = forkRepository;
this.postLikeRepository = postLikeRepository;
}

// 내가 쓴 글 보기
Expand Down Expand Up @@ -61,31 +57,4 @@ public PageResponseDto<MyPostPageResponseDto> getMyPosts(String email, int page,
)
);
}

// 내가 좋아요한 글 보기
public PageResponseDto<MyPostPageResponseDto> getLikedPosts(String email, int page, int sort, int size) {
Member member = memberRepository.findByEmail(email)
.orElseThrow(() -> new CustomException(ErrorCode.USER_EMAIL_NOT_FOUND));

// 1: 오래된순, 0: 최신순
Sort.Direction direction = (sort == 1) ? Sort.Direction.ASC : Sort.Direction.DESC;
Pageable pageable = PageRequest.of(page, size, Sort.by(direction, "postId.createdAt"));

Page<PostLike> postLikePage = postLikeRepository.findByUserId(member, pageable);
List<Post> likedPosts = postLikePage.map(PostLike::getPostId).getContent();

// fork count 한번에 조회
List<Object[]> forkCounts = forkRepository.countForksByOriginalPosts(likedPosts);
Map<Long, Integer> forkCountMap = forkCounts.stream()
.collect(Collectors.toMap(
row -> (Long) row[0],
row -> ((Long) row[1]).intValue()
));

return PageResponseDto.from(postLikePage.map(PostLike::getPostId), post ->
MyPostPageResponseDto.from(post, forkCountMap.getOrDefault(post.getPostId(), 0))
);
}


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

public class DefaultImage {
public static final String PROFILE = "https://dummyimage.com/200x200/cccccc/ffffff&text=Profile"; // 임시 기본 프로필 이미지
}
5 changes: 5 additions & 0 deletions src/main/java/com/example/FixLog/util/DefaultText.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.FixLog.util;

public class DefaultText {
public static final String BIO = "오늘도 에러 없는 하루 보내세요!";
}
41 changes: 20 additions & 21 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
spring.application.name=FixLog

//# DB setting
//spring.h2.console.enabled=true
# DB setting
spring.h2.console.enabled=true
''spring.h2.console.path=/h2-console

//# DataBase Info
//spring.datasource.url=jdbc:h2:tcp://localhost/~/fixlog
//spring.datasource.driver-class-name=org.h2.Driver
//spring.datasource.username=sa
//spring.datasource.password=
# DataBase Info
spring.datasource.url=jdbc:h2:tcp://localhost/~/fixlog
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

//spring.jpa.show-sql=true
//spring.jpa.hibernate.ddl-auto=update
//spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

구성 오류: H2 콘솔 경로 설정 구문 오류
''spring.h2.console.path=/h2-console에 불필요한 작은따옴표('')가 포함되어 있어 적용되지 않습니다. 아래와 같이 오탈자를 수정해야 합니다.

- ''spring.h2.console.path=/h2-console
+ spring.h2.console.path=/h2-console
📝 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
# DB setting
spring.h2.console.enabled=true
''spring.h2.console.path=/h2-console
//# DataBase Info
//spring.datasource.url=jdbc:h2:tcp://localhost/~/fixlog
//spring.datasource.driver-class-name=org.h2.Driver
//spring.datasource.username=sa
//spring.datasource.password=
# DataBase Info
spring.datasource.url=jdbc:h2:tcp://localhost/~/fixlog
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
//spring.jpa.show-sql=true
//spring.jpa.hibernate.ddl-auto=update
//spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
# DB setting
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# DataBase Info
spring.datasource.url=jdbc:h2:tcp://localhost/~/fixlog
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
🤖 Prompt for AI Agents
In src/main/resources/application.properties around lines 2 to 14, the H2
console path setting has incorrect syntax due to unnecessary single quotes
before the property key. Remove the leading two single quotes from the line
`''spring.h2.console.path=/h2-console` so it reads
`spring.h2.console.path=/h2-console` to fix the configuration error.


//# JWT
//jwt.secret=fixlogfixlogfixlogfixlogfixlog1234
//jwt.expiration-time=86400000

##### dev #####
server.port=8083

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=${mysql_url}
spring.datasource.username=${mysql_username}
spring.datasource.password=${mysql_password}

spring.jpa.hibernate.ddl-auto=create
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
#server.port=8083
#
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.url=${mysql_url}
#spring.datasource.username=${mysql_username}
#spring.datasource.password=${mysql_password}
#
#spring.jpa.hibernate.ddl-auto=create
#spring.jpa.properties.hibernate.format_sql=true
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

##### jwt #####
spring.jwt.secret=${jwt_key}