Skip to content

Commit b6bf9bd

Browse files
committed
2 parents 2383dbd + f2a7e96 commit b6bf9bd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2152
-708
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.example.log4u.common.config;
2+
3+
import java.util.concurrent.Executor;
4+
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.scheduling.annotation.EnableAsync;
8+
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
9+
10+
@Configuration
11+
@EnableAsync
12+
public class AsyncConfig {
13+
@Bean(name = "mediaTaskExecutor")
14+
public Executor mediaTaskExecutor() {
15+
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
16+
executor.setCorePoolSize(2);
17+
executor.setMaxPoolSize(5);
18+
executor.setQueueCapacity(100);
19+
executor.setThreadNamePrefix("media-async-");
20+
executor.initialize();
21+
return executor;
22+
}
23+
}

src/main/java/com/example/log4u/common/config/MySqlConfig.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"com.example.log4u.domain.reports",
2929
"com.example.log4u.domain.supports",
3030
"com.example.log4u.domain.user",
31-
"com.example.log4u.domain.subscription"
31+
"com.example.log4u.domain.subscription",
32+
"com.example.log4u.domain.hashtag"
3233
},
3334
entityManagerFactoryRef = "mysqlEntityManagerFactory",
3435
transactionManagerRef = "mysqlTransactionManager"
@@ -57,7 +58,8 @@ public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory() {
5758
"com.example.log4u.domain.reports",
5859
"com.example.log4u.domain.supports",
5960
"com.example.log4u.domain.user",
60-
"com.example.log4u.domain.subscription"
61+
"com.example.log4u.domain.subscription",
62+
"com.example.log4u.domain.hashtag"
6163
);
6264
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
6365
vendorAdapter.setShowSql(true);
Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
package com.example.log4u.domain.comment.dto.response;
22

3+
import java.time.LocalDateTime;
4+
35
import com.example.log4u.domain.comment.entity.Comment;
6+
import com.example.log4u.domain.user.entity.User;
47

58
public record CommentResponseDto(
69
Long commentId,
7-
String content
10+
Long userId,
11+
String userName,
12+
String userProfileImage,
13+
String content,
14+
LocalDateTime createdAt
815
) {
9-
public static CommentResponseDto of(Comment comment) {
16+
public static CommentResponseDto of(Comment comment, User user) {
1017
return new CommentResponseDto(
1118
comment.getCommentId(),
12-
comment.getContent()
19+
user.getUserId(),
20+
user.getName(),
21+
user.getProfileImage(),
22+
comment.getContent(),
23+
comment.getCreatedAt()
1324
);
1425
}
1526
}
27+

src/main/java/com/example/log4u/domain/comment/repository/CommentRepositoryCustom.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import org.springframework.data.domain.Pageable;
44
import org.springframework.data.domain.Slice;
55

6+
import com.example.log4u.domain.comment.dto.response.CommentResponseDto;
67
import com.example.log4u.domain.comment.entity.Comment;
78

89
public interface CommentRepositoryCustom {
910

10-
Slice<Comment> findByDiaryIdWithCursor(Long diaryId, Long cursorCommentId, Pageable pageable);
11+
Slice<CommentResponseDto> findWithUserByDiaryId(Long diaryId, Long cursorCommentId, Pageable pageable);
1112
}

src/main/java/com/example/log4u/domain/comment/repository/CommentRepositoryImpl.java

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
import org.springframework.data.domain.SliceImpl;
1010
import org.springframework.stereotype.Repository;
1111

12+
import com.example.log4u.domain.comment.dto.response.CommentResponseDto;
1213
import com.example.log4u.domain.comment.entity.Comment;
14+
import com.example.log4u.domain.comment.entity.QComment;
15+
import com.example.log4u.domain.user.entity.QUser;
16+
import com.example.log4u.domain.user.entity.User;
17+
import com.querydsl.core.Tuple;
1318
import com.querydsl.jpa.impl.JPAQueryFactory;
1419

1520
import lombok.RequiredArgsConstructor;
@@ -21,19 +26,31 @@ public class CommentRepositoryImpl implements CommentRepositoryCustom {
2126
private final JPAQueryFactory queryFactory;
2227

2328
@Override
24-
public Slice<Comment> findByDiaryIdWithCursor(Long diaryId, Long cursorCommentId, Pageable pageable) {
25-
List<Comment> result = queryFactory
26-
.selectFrom(comment)
29+
public Slice<CommentResponseDto> findWithUserByDiaryId(Long diaryId, Long cursorCommentId, Pageable pageable) {
30+
QComment comment = QComment.comment;
31+
QUser user = QUser.user;
32+
33+
List<Tuple> tuples = queryFactory
34+
.select(comment, user)
35+
.from(comment)
36+
.join(user).on(comment.userId.eq(user.userId))
2737
.where(
2838
comment.diaryId.eq(diaryId),
2939
cursorCommentId != null ? comment.commentId.lt(cursorCommentId) : null
3040
)
3141
.orderBy(comment.commentId.desc())
32-
.limit(pageable.getPageSize() + 1) // 커서 기반 페이징
42+
.limit(pageable.getPageSize() + 1)
3343
.fetch();
3444

35-
boolean hasNext = result.size() > pageable.getPageSize();
36-
List<Comment> content = hasNext ? result.subList(0, pageable.getPageSize()) : result;
45+
boolean hasNext = tuples.size() > pageable.getPageSize();
46+
List<CommentResponseDto> content = tuples.stream()
47+
.limit(pageable.getPageSize())
48+
.map(tuple -> {
49+
Comment c = tuple.get(comment);
50+
User u = tuple.get(user);
51+
return CommentResponseDto.of(c, u);
52+
})
53+
.toList();
3754

3855
return new SliceImpl<>(content, pageable, hasNext);
3956
}

src/main/java/com/example/log4u/domain/comment/service/CommentService.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,10 @@ private Comment getComment(Long commentId) {
6262
public PageResponse<CommentResponseDto> getCommentListByDiary(Long diaryId, Long cursorCommentId, int size) {
6363
checkDiaryExists(diaryId);
6464
Pageable pageable = PageRequest.of(0, size);
65-
Slice<Comment> slice = commentRepository.findByDiaryIdWithCursor(diaryId, cursorCommentId, pageable);
65+
Slice<CommentResponseDto> slice = commentRepository.findWithUserByDiaryId(diaryId, cursorCommentId, pageable);
6666

67-
List<CommentResponseDto> dtoList = slice.getContent().stream()
68-
.map(CommentResponseDto::of)
69-
.toList();
70-
71-
Long nextCursor = slice.hasNext() ? dtoList.getLast().commentId() : null;
72-
return PageResponse.of(new SliceImpl<>(dtoList, pageable, slice.hasNext()), nextCursor);
67+
Long nextCursor = slice.hasNext() ? slice.getContent().getLast().commentId() : null;
68+
return PageResponse.of(slice, nextCursor);
7369
}
70+
7471
}

src/main/java/com/example/log4u/domain/diary/controller/DiaryController.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import com.example.log4u.domain.diary.SortType;
1919
import com.example.log4u.domain.diary.dto.DiaryRequestDto;
2020
import com.example.log4u.domain.diary.dto.DiaryResponseDto;
21-
import com.example.log4u.domain.diary.service.DiaryService;
21+
import com.example.log4u.domain.diary.facade.DiaryFacade;
2222

2323
import jakarta.validation.Valid;
2424
import lombok.RequiredArgsConstructor;
@@ -30,7 +30,7 @@
3030
@Slf4j
3131
public class DiaryController {
3232

33-
private final DiaryService diaryService;
33+
private final DiaryFacade diaryFacade;
3434

3535
@GetMapping("/users/{userId}")
3636
public ResponseEntity<PageResponse<DiaryResponseDto>> getDiariesByUserId(
@@ -39,18 +39,30 @@ public ResponseEntity<PageResponse<DiaryResponseDto>> getDiariesByUserId(
3939
@RequestParam(required = false) Long cursorId,
4040
@RequestParam(defaultValue = "12") int size
4141
) {
42-
PageResponse<DiaryResponseDto> response = diaryService.getDiariesByCursor(customOAuth2User.getUserId(),
42+
PageResponse<DiaryResponseDto> response = diaryFacade.getDiariesByCursor(customOAuth2User.getUserId(),
4343
targetUserId, cursorId, size);
4444

4545
return ResponseEntity.ok(response);
4646
}
4747

48+
@GetMapping("/users/me")
49+
public ResponseEntity<PageResponse<DiaryResponseDto>> getMyDiaries(
50+
@AuthenticationPrincipal CustomOAuth2User customOAuth2User,
51+
@RequestParam(required = false) Long cursorId,
52+
@RequestParam(defaultValue = "12") int size
53+
) {
54+
PageResponse<DiaryResponseDto> response = diaryFacade.getDiariesByCursor(customOAuth2User.getUserId(),
55+
customOAuth2User.getUserId(), cursorId, size);
56+
57+
return ResponseEntity.ok(response);
58+
}
59+
4860
@PostMapping
4961
public ResponseEntity<Void> createDiary(
5062
@AuthenticationPrincipal CustomOAuth2User customOAuth2User,
5163
@Valid @RequestBody DiaryRequestDto request
5264
) {
53-
diaryService.saveDiary(customOAuth2User.getUserId(), request);
65+
diaryFacade.createDiary(customOAuth2User.getUserId(), request);
5466
return ResponseEntity.status(HttpStatus.CREATED).build();
5567
}
5668

@@ -60,10 +72,10 @@ public ResponseEntity<PageResponse<DiaryResponseDto>> searchDiaries(
6072
@RequestParam(required = false) String keyword,
6173
@RequestParam(defaultValue = "LATEST") SortType sort,
6274
@RequestParam(required = false) Long cursorId,
63-
@RequestParam(defaultValue = "6") int size
75+
@RequestParam(defaultValue = "12") int size
6476
) {
6577
return ResponseEntity.ok(
66-
diaryService.searchDiariesByCursor(keyword, sort, cursorId, size)
78+
diaryFacade.searchDiariesByCursor(keyword, sort, cursorId, size)
6779
);
6880
}
6981

@@ -72,7 +84,7 @@ public ResponseEntity<DiaryResponseDto> getDiary(
7284
@AuthenticationPrincipal CustomOAuth2User customOAuth2User,
7385
@PathVariable Long diaryId
7486
) {
75-
DiaryResponseDto diary = diaryService.getDiary(customOAuth2User.getUserId(), diaryId);
87+
DiaryResponseDto diary = diaryFacade.getDiary(customOAuth2User.getUserId(), diaryId);
7688
return ResponseEntity.ok(diary);
7789
}
7890

@@ -82,16 +94,16 @@ public ResponseEntity<Void> modifyDiary(
8294
@PathVariable Long diaryId,
8395
@Valid @RequestBody DiaryRequestDto request
8496
) {
85-
diaryService.updateDiary(customOAuth2User.getUserId(), diaryId, request);
97+
diaryFacade.updateDiary(customOAuth2User.getUserId(), diaryId, request);
8698
return ResponseEntity.ok().build();
8799
}
88100

89101
@DeleteMapping("/{diaryId}")
90-
public ResponseEntity<?> deleteDiary(
102+
public ResponseEntity<Void> deleteDiary(
91103
@AuthenticationPrincipal CustomOAuth2User customOAuth2User,
92104
@PathVariable Long diaryId
93105
) {
94-
diaryService.deleteDiary(customOAuth2User.getUserId(), diaryId);
106+
diaryFacade.deleteDiary(customOAuth2User.getUserId(), diaryId);
95107
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
96108
}
97-
}
109+
}

src/main/java/com/example/log4u/domain/diary/dto/DiaryRequestDto.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public record DiaryRequestDto(
3636
@NotNull(message = "미디어 첨부는 필수입니다.")
3737
@Size(min = 1, max = 10, message = "미디어는 최소 1개, 최대 10개까지만 업로드 가능합니다.")
3838
@Valid
39-
List<MediaRequestDto> mediaList
39+
List<MediaRequestDto> mediaList,
40+
41+
List<String> hashtagList
4042
) {
4143
public static Diary toEntity(Long userId, DiaryRequestDto diaryRequestDto, String thumbnailUrl) {
4244
return Diary.builder()

src/main/java/com/example/log4u/domain/diary/dto/DiaryResponseDto.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
import com.example.log4u.domain.map.dto.LocationDto;
88
import com.example.log4u.domain.media.dto.MediaResponseDto;
99
import com.example.log4u.domain.media.entity.Media;
10+
import com.example.log4u.domain.user.entity.User;
1011

1112
import lombok.Builder;
1213

1314
@Builder
1415
public record DiaryResponseDto(
1516
Long diaryId,
16-
Long userId,
17+
Long authorId,
18+
String authorNickname,
19+
String authorProfileImage,
1720
LocationDto location,
1821
String title,
1922
String content,
@@ -24,13 +27,23 @@ public record DiaryResponseDto(
2427
String thumbnailUrl,
2528
Long likeCount,
2629
List<MediaResponseDto> mediaList,
30+
List<String> hashtagList,
2731
boolean isLiked
2832
) {
29-
public static DiaryResponseDto of(Diary diary, List<Media> media, boolean isLiked) {
33+
// 단건 조회용 (isLiked + User)
34+
public static DiaryResponseDto of(
35+
Diary diary,
36+
List<Media> media,
37+
List<String> hashtagList,
38+
boolean isLiked,
39+
User author
40+
) {
3041
return DiaryResponseDto.builder()
3142
.diaryId(diary.getDiaryId())
32-
.userId(diary.getUserId())
33-
.location(LocationDto.of(diary.getLocation()))
43+
.authorId(diary.getUserId())
44+
.authorNickname(author.getNickname())
45+
.authorProfileImage(author.getProfileImage())
46+
.location(com.example.log4u.domain.map.dto.LocationDto.of(diary.getLocation()))
3447
.title(diary.getTitle())
3548
.content(diary.getContent())
3649
.weatherInfo(diary.getWeatherInfo().name())
@@ -41,12 +54,36 @@ public static DiaryResponseDto of(Diary diary, List<Media> media, boolean isLike
4154
.likeCount(diary.getLikeCount())
4255
.mediaList(media.stream()
4356
.map(MediaResponseDto::of).toList())
57+
.hashtagList(hashtagList)
4458
.isLiked(isLiked)
4559
.build();
4660
}
4761

48-
// 다이어리 목록 반환 시 사용 (isLiked false 기본값)
49-
public static DiaryResponseDto of(Diary diary, List<Media> media) {
50-
return DiaryResponseDto.of(diary, media, false);
62+
// 다이어리 목록 반환 시 사용 (isLiked false, User null 기본값)
63+
public static DiaryResponseDto of(
64+
Diary diary,
65+
List<Media> media,
66+
List<String> hashtagList
67+
) {
68+
return DiaryResponseDto.builder()
69+
.diaryId(diary.getDiaryId())
70+
.authorId(diary.getUserId())
71+
.authorNickname(null)
72+
.authorProfileImage(null)
73+
.location(com.example.log4u.domain.map.dto.LocationDto.of(diary.getLocation()))
74+
.title(diary.getTitle())
75+
.content(diary.getContent())
76+
.weatherInfo(diary.getWeatherInfo().name())
77+
.visibility(diary.getVisibility().name())
78+
.createdAt(diary.getCreatedAt())
79+
.updatedAt(diary.getUpdatedAt())
80+
.thumbnailUrl(diary.getThumbnailUrl())
81+
.likeCount(diary.getLikeCount())
82+
.mediaList(media.stream()
83+
.map(MediaResponseDto::of).toList())
84+
.hashtagList(hashtagList)
85+
.isLiked(false)
86+
.build();
5187
}
88+
5289
}

0 commit comments

Comments
 (0)