Skip to content

Commit

Permalink
[Refactor] user refactor (#111)
Browse files Browse the repository at this point in the history
* feat(User): User의 Id에 private getter 제거

* feat(Url): Url의 pattern 변경과 상수로 미리 compile해 두도록 변경

* feat(UserQueryRepository): User 에그리거트에 하나의 repository만 만들어 사용하도록 변경

* docs(Readme): 리드미 일부 수정

* refactor(Notice): 생성자의 파라미터에 개행 추가
  • Loading branch information
zbqmgldjfh authored Jan 12, 2024
1 parent fd554a0 commit 96e30c2
Show file tree
Hide file tree
Showing 11 changed files with 101 additions and 32 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,12 @@ JPA 프로그래밍의 저자, 김영한 선생님의 의견을 빌리자면 다
다음 글의 3번 “양방향 연관관계 주의점”을 보면 이해할 수 있다.
https://blogshine.tistory.com/345

아예 User에서 UserCategory를 삭제하는 편이 더 좋을것 같다. 양방향 연관관계가 필수적인 포인트가 아니기 때문이다! → **User에서 제거!**
아예 User에서 UserCategory를 삭제하는 편이 더 좋을것 같다. 양방향 연관관계가 필수적인 포인트가 아니기 때문이다! → **User에서 제거!**

<img width="483" alt="image" src="https://github.com/ku-ring/ku-ring-backend-web/assets/60593969/74154306-43ad-42d3-a523-7803823b9227">

테이블 구조에 변화는 없기에 적용가능

---

## 3. 공지 Scrap작업 multi-threading 처리로 시간 개선하기
Expand Down Expand Up @@ -419,6 +422,9 @@ Querydsl 도입으로 다음과 같은 이점을 얻었습니다.
----
## 2. Flyway
<img width="300" src="https://github.com/ku-ring/ku-ring-backend-web/assets/60593969/c6df0ca7-48a5-4b32-9e19-4298b9a64313">
dev, local 환경에서는 단순히 ddl을 create-drop 또는 update 옵션을 사용하고 있었기에 DB에 대해 고민할 필요가 없었습니다.
하지만 운영환경에서는 ddl을 validate 또는 none 옵션을 사용해야하기 때문에 초기에는 DB script를 뽑아서 별도로 관리를 했습니다.
이후 기능이 추가되면서 script가 변경되는 일이 빈번해졌고, 매번 일일이 스크립트를 관리하는 것이 번거로울 뿐 아니라 실수하기 딱 좋은 부분이라 Flyway를 도입하여 데이터베이스 형상관리를 진행했습니다.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
package com.kustacks.kuring.admin.common.dto;

import com.kustacks.kuring.user.domain.Feedback;
import com.querydsl.core.annotations.QueryProjection;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class FeedbackDto {

private String contents;
private Long userId;
private LocalDateTime createdAt;

public static FeedbackDto from(Feedback feedback) {
return new FeedbackDto(feedback.getContent(), feedback.getUserId(), feedback.getCreatedAt());
@QueryProjection
public FeedbackDto(String contents, Long userId, LocalDateTime createdAt) {
this.contents = contents;
this.userId = userId;
this.createdAt = createdAt;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ public class DepartmentNotice extends Notice {
private DepartmentName departmentName;

@Builder
public DepartmentNotice(String articleId, String postedDate, String updatedDate, String subject, CategoryName categoryName, Boolean important, String fullUrl, DepartmentName departmentName) {
public DepartmentNotice(String articleId, String postedDate, String updatedDate,
String subject, CategoryName categoryName, Boolean important,
String fullUrl, DepartmentName departmentName)
{
super(articleId, postedDate, updatedDate, subject, categoryName, important, fullUrl);
this.departmentName = departmentName;
}
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/kustacks/kuring/notice/domain/Notice.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ public class Notice {
@Column(name = "category_name", nullable = false)
private CategoryName categoryName;

public Notice(String articleId, String postedDate, String updatedDate, String subject, CategoryName categoryName, Boolean important, String fullUrl) {
public Notice(String articleId, String postedDate, String updatedDate,
String subject, CategoryName categoryName, Boolean important,
String fullUrl)
{
this.articleId = articleId;
this.postedDate = postedDate;
this.updatedDate = updatedDate;
Expand Down
39 changes: 35 additions & 4 deletions src/main/java/com/kustacks/kuring/notice/domain/Url.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,38 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Url {

private static final String REGEX_PATTERN = "^((http|https)://)?([a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?)$";
/**
* Regular Expression by RFC 3986 for URI Validation
* @link https://datatracker.ietf.org/doc/html/rfc3986#appendix-B
* @author jiwoo
*/
private static final String REGEX_SCHEME = "[A-Za-z][+-.\\w^_]*:";

// Example: "//".
private static final String REGEX_AUTHORATIVE_DECLARATION = "/{2}";

// Optional component. Example: "suzie:abc123@". The use of the format "user:password" is deprecated.
private static final String REGEX_USERINFO = "(?:\\S+(?::\\S*)?@)?";

// Examples: "fitbit.com", "22.231.113.64".
private static final String REGEX_HOST = "(?:" + // @Author = http://www.regular-expressions.info/examples.html
// IP address
"(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" +
"|" + // host name
"(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" + // domain name
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" + // TLD identifier must have >= 2 characters
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))";

// Example: ":8042".
private static final String REGEX_PORT = "(?::\\d{2,5})?";

//Example: "/user/heartrate?foo=bar#element1".
private static final String REGEX_RESOURCE_PATH = "(?:/\\S*)?";

private static final String REGEX_URL = "^(?:(?:" + REGEX_SCHEME + REGEX_AUTHORATIVE_DECLARATION + ")?" +
REGEX_USERINFO + REGEX_HOST + REGEX_PORT + REGEX_RESOURCE_PATH + ")$";

private static final Pattern compiledUrlPattern = Pattern.compile(REGEX_URL);

@Column(name = "url", length = 256, nullable = false)
private String value;
Expand All @@ -30,11 +61,11 @@ public Url(String fullUrl) {
}

private boolean isValidUrl(String fullUrl) {
return !Objects.isNull(fullUrl) && patternMatches(fullUrl, REGEX_PATTERN);
return !Objects.isNull(fullUrl) && patternMatches(fullUrl);
}

private boolean patternMatches(String targetUrl, String regexPattern) {
return Pattern.compile(regexPattern)
private boolean patternMatches(String targetUrl) {
return compiledUrlPattern
.matcher(targetUrl)
.matches();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package com.kustacks.kuring.user.business;

import com.kustacks.kuring.admin.common.dto.FeedbackDto;
import com.kustacks.kuring.common.exception.code.ErrorCode;
import com.kustacks.kuring.common.exception.NotFoundException;
import com.kustacks.kuring.user.domain.FeedbackRepository;
import com.kustacks.kuring.common.exception.code.ErrorCode;
import com.kustacks.kuring.message.firebase.FirebaseService;
import com.kustacks.kuring.message.firebase.ServerProperties;
import com.kustacks.kuring.user.domain.User;
import com.kustacks.kuring.user.domain.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.kustacks.kuring.message.firebase.FirebaseService.ALL_DEVICE_SUBSCRIBED_TOPIC;

Expand All @@ -26,7 +23,6 @@
public class FeedbackService {

private final UserRepository userRepository;
private final FeedbackRepository feedbackRepository;
private final FirebaseService firebaseService;
private final ServerProperties serverProperties;

Expand All @@ -37,17 +33,15 @@ public void saveFeedback(String token, String content) {
firebaseService.subscribe(token, serverProperties.ifDevThenAddSuffix(ALL_DEVICE_SUBSCRIBED_TOPIC));
}

User findUser = optionalUser.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));
User findUser = optionalUser
.orElseThrow(() -> new NotFoundException(ErrorCode.USER_NOT_FOUND));

findUser.addFeedback(content);
}

@Transactional(readOnly = true)
public List<FeedbackDto> lookupFeedbacks(int page, int size) {
PageRequest pageRequest = PageRequest.of(page, size, Sort.Direction.DESC, "createdAt");

return feedbackRepository.findAll(pageRequest)
.stream()
.map(FeedbackDto::from)
.collect(Collectors.toList());
PageRequest pageRequest = PageRequest.of(page, size);
return userRepository.findAllFeedbackByPageRequest(pageRequest);
}
}

This file was deleted.

1 change: 0 additions & 1 deletion src/main/java/com/kustacks/kuring/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
public class User implements Serializable {

@Id
@Getter(AccessLevel.PRIVATE)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.kustacks.kuring.user.domain;

import com.kustacks.kuring.admin.common.dto.FeedbackDto;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface UserQueryRepository {

List<FeedbackDto> findAllFeedbackByPageRequest(Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.kustacks.kuring.user.domain;

import com.kustacks.kuring.admin.common.dto.FeedbackDto;
import com.kustacks.kuring.admin.common.dto.QFeedbackDto;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;

import java.util.List;

import static com.kustacks.kuring.user.domain.QFeedback.feedback;

@RequiredArgsConstructor
public class UserQueryRepositoryImpl implements UserQueryRepository {

private final JPAQueryFactory queryFactory;

@Override
public List<FeedbackDto> findAllFeedbackByPageRequest(Pageable pageable) {
return queryFactory.select(new QFeedbackDto(feedback.content.value, feedback.user.id, feedback.createdAt))
.from(feedback)
.orderBy(feedback.createdAt.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import java.util.List;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {
public interface UserRepository extends JpaRepository<User, Long>, UserQueryRepository {
Optional<User> findByToken(String token);

@Query("SELECT u.token FROM User u")
Expand Down

0 comments on commit 96e30c2

Please sign in to comment.