diff --git a/.ebextensions/build-dev.config b/.ebextensions/build-dev.config index 31c03be..437e7d4 100644 --- a/.ebextensions/build-dev.config +++ b/.ebextensions/build-dev.config @@ -9,4 +9,4 @@ files: # run app killall java - java -Dspring.profiles.active=dev -Dfile.encoding=UTF-8 -jar $JAR_PATH + java -Dspring.profiles.active=dev -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Seoul -jar $JAR_PATH diff --git a/.ebextensions/build-prod.config b/.ebextensions/build-prod.config index 1db6d11..e133044 100644 --- a/.ebextensions/build-prod.config +++ b/.ebextensions/build-prod.config @@ -9,4 +9,4 @@ files: # run app killall java - java -Dspring.profiles.active=prod -Dfile.encoding=UTF-8 -jar $JAR_PATH + java -Dspring.profiles.active=prod -Dfile.encoding=UTF-8 -Duser.timezone=Asia/Seoul -jar $JAR_PATH diff --git a/build.gradle b/build.gradle index 7b557c5..9564d15 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ dependencies { implementation 'io.jsonwebtoken:jjwt-api:0.12.3' implementation platform('software.amazon.awssdk:bom:2.21.27') implementation("software.amazon.awssdk:s3") + implementation "org.jboss.logging:jboss-logging:3.5.3.Final" implementation 'software.amazon.awssdk:sts' implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.3' diff --git a/src/main/java/com/strcat/controller/BoardController.java b/src/main/java/com/strcat/controller/BoardController.java index 8ab7dc0..f45b843 100644 --- a/src/main/java/com/strcat/controller/BoardController.java +++ b/src/main/java/com/strcat/controller/BoardController.java @@ -1,11 +1,13 @@ package com.strcat.controller; +import com.strcat.domain.Board; import com.strcat.domain.User; import com.strcat.dto.CreateBoardReqDto; import com.strcat.dto.CreateContentReqDto; import com.strcat.dto.DeleteContentReqDto; import com.strcat.dto.ReadBoardResDto; import com.strcat.dto.ReadBoardSummaryResDto; +import com.strcat.dto.ReadPublicBoardResDto; import com.strcat.service.BoardService; import com.strcat.service.ContentService; import io.swagger.v3.oas.annotations.Operation; @@ -15,7 +17,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.Optional; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatusCode; import org.springframework.security.core.Authentication; @@ -102,7 +104,7 @@ public ReadBoardSummaryResDto readSummary(@PathVariable(name = "boardId") String @ApiResponse(responseCode = "401", description = "인증 실패", content = { @Content(examples = {@ExampleObject("인증 실패")})}) public ReadBoardResDto deleteContents(@PathVariable(name = "boardId") String encryptedBoardId, @RequestBody - DeleteContentReqDto dto, Authentication authentication) { + DeleteContentReqDto dto, Authentication authentication) { if (authentication == null) { throw new ResponseStatusException(HttpStatusCode.valueOf(401)); } @@ -111,4 +113,9 @@ public ReadBoardResDto deleteContents(@PathVariable(name = "boardId") String enc return contentService.deleteContent(encryptedBoardId, dto, user); } + + @GetMapping("/public") + public List readPublicBoards() { + return boardService.readPublicBoard().stream().map(Board::toReadPublicBoardResDto).toList(); + } } diff --git a/src/main/java/com/strcat/domain/Board.java b/src/main/java/com/strcat/domain/Board.java index ace58d7..f4a79d4 100644 --- a/src/main/java/com/strcat/domain/Board.java +++ b/src/main/java/com/strcat/domain/Board.java @@ -5,6 +5,7 @@ import com.strcat.dto.ReadBoardResDto; import com.strcat.dto.ReadBoardSummaryResDto; import com.strcat.dto.ReadMyInfoResDto; +import com.strcat.dto.ReadPublicBoardResDto; import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -20,7 +21,6 @@ import java.util.List; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.ToString; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -46,6 +46,9 @@ public class Board { @Column(name = "encrypted_id", columnDefinition = "TEXT", unique = true) private String encryptedId; + @Column(name = "is_public", nullable = false, columnDefinition = "bit(1) default 0") + private Boolean isPublic = false; + @JsonIgnore @ManyToOne @JoinColumn(name = "user_id", nullable = false) // 외래키 컬럼 지정 @@ -58,10 +61,11 @@ public class Board { @OneToMany(mappedBy = "board", cascade = CascadeType.ALL) private List history; - public Board(String title, String theme, User user) { + public Board(String title, String theme, User user, Boolean isPublic) { this.title = title; this.theme = theme; this.user = user; + this.isPublic = isPublic; } public Long calculateTotalContentLength() { @@ -70,8 +74,19 @@ public Long calculateTotalContentLength() { .sum(); } + public LocalDateTime findLastContentCreatedTime() { + if (!contents.isEmpty()) { + return contents.stream() + .map(Content::getCreatedAt) + .max(LocalDateTime::compareTo) + .orElse(null); + } else { + return createdAt; + } + } + private BoardResponse toBoardResponse() { - return new BoardResponse(encryptedId, title, theme, contents); + return new BoardResponse(encryptedId, title, theme, isPublic, contents); } public ReadBoardResDto toReadBoardResDto(Boolean isOwner) { @@ -83,6 +98,11 @@ public ReadBoardSummaryResDto toReadBoardSummaryDto() { } public ReadMyInfoResDto toReadMyInfoResDto() { - return new ReadMyInfoResDto(encryptedId, title); + return new ReadMyInfoResDto(encryptedId, title, isPublic); + } + + public ReadPublicBoardResDto toReadPublicBoardResDto() { + return new ReadPublicBoardResDto(encryptedId, title, theme, findLastContentCreatedTime(), contents.size(), + calculateTotalContentLength()); } } diff --git a/src/main/java/com/strcat/domain/History.java b/src/main/java/com/strcat/domain/History.java index a7a67de..1cb6770 100644 --- a/src/main/java/com/strcat/domain/History.java +++ b/src/main/java/com/strcat/domain/History.java @@ -1,9 +1,7 @@ package com.strcat.domain; import com.fasterxml.jackson.annotation.JsonIgnore; -import com.strcat.dto.HistoryDto; import com.strcat.dto.HistoryItem; -import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EntityListeners; @@ -12,16 +10,10 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; -import jakarta.persistence.OneToMany; import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.List; import lombok.Data; -import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.ToString; -import org.apache.commons.lang3.builder.HashCodeExclude; -import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @Entity @@ -55,6 +47,6 @@ public History(User user, Board board, LocalDateTime visitedAt) { } public HistoryItem toDto() { - return new HistoryItem(board.getEncryptedId(), board.getTitle(), visitedAt); + return new HistoryItem(board.getEncryptedId(), board.getTitle(), board.getIsPublic(), visitedAt); } } diff --git a/src/main/java/com/strcat/dto/BoardResponse.java b/src/main/java/com/strcat/dto/BoardResponse.java index a63fa37..5188b98 100644 --- a/src/main/java/com/strcat/dto/BoardResponse.java +++ b/src/main/java/com/strcat/dto/BoardResponse.java @@ -1,5 +1,6 @@ package com.strcat.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import com.strcat.domain.Content; import java.util.List; import lombok.EqualsAndHashCode; @@ -15,5 +16,7 @@ public class BoardResponse { private final String id; private final String title; private final String theme; + @JsonProperty("public") + private final Boolean isPublic; private final List contents; } diff --git a/src/main/java/com/strcat/dto/CreateBoardReqDto.java b/src/main/java/com/strcat/dto/CreateBoardReqDto.java index 536c917..b231145 100644 --- a/src/main/java/com/strcat/dto/CreateBoardReqDto.java +++ b/src/main/java/com/strcat/dto/CreateBoardReqDto.java @@ -1,5 +1,6 @@ package com.strcat.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -8,4 +9,6 @@ public class CreateBoardReqDto { private final String title; private final String theme; + @JsonProperty("public") + private final Boolean isPublic; } diff --git a/src/main/java/com/strcat/dto/HistoryItem.java b/src/main/java/com/strcat/dto/HistoryItem.java index 3ce6eb5..e70badb 100644 --- a/src/main/java/com/strcat/dto/HistoryItem.java +++ b/src/main/java/com/strcat/dto/HistoryItem.java @@ -1,6 +1,7 @@ package com.strcat.dto; import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import java.time.LocalDateTime; @@ -11,7 +12,7 @@ "visitTime": "2024-02-07 07:54:54" } """) -public record HistoryItem(String encryptedBoardId, String title, +public record HistoryItem(String encryptedBoardId, String title, @JsonProperty("public") Boolean isPublic, @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") LocalDateTime visitTime) { } diff --git a/src/main/java/com/strcat/dto/ReadBoardResDto.java b/src/main/java/com/strcat/dto/ReadBoardResDto.java index 7314976..6a01328 100644 --- a/src/main/java/com/strcat/dto/ReadBoardResDto.java +++ b/src/main/java/com/strcat/dto/ReadBoardResDto.java @@ -1,6 +1,5 @@ package com.strcat.dto; -import com.strcat.domain.Board; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/strcat/dto/ReadMyInfoResDto.java b/src/main/java/com/strcat/dto/ReadMyInfoResDto.java index 5b37736..7e2eae3 100644 --- a/src/main/java/com/strcat/dto/ReadMyInfoResDto.java +++ b/src/main/java/com/strcat/dto/ReadMyInfoResDto.java @@ -1,5 +1,6 @@ package com.strcat.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -8,4 +9,6 @@ public class ReadMyInfoResDto { private final String id; private final String title; + @JsonProperty("public") + private final Boolean isPublic; } diff --git a/src/main/java/com/strcat/dto/ReadPublicBoardResDto.java b/src/main/java/com/strcat/dto/ReadPublicBoardResDto.java new file mode 100644 index 0000000..230309b --- /dev/null +++ b/src/main/java/com/strcat/dto/ReadPublicBoardResDto.java @@ -0,0 +1,22 @@ +package com.strcat.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import java.time.LocalDateTime; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.ToString; + +@RequiredArgsConstructor +@Getter +@EqualsAndHashCode +@ToString +public class ReadPublicBoardResDto { + private final String id; + private final String title; + private final String theme; + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Seoul") + private final LocalDateTime lastContentCreatedAt; + private final Integer contentCount; + private final Long contentTextCount; +} diff --git a/src/main/java/com/strcat/repository/BoardRepository.java b/src/main/java/com/strcat/repository/BoardRepository.java index da5da87..13f206c 100644 --- a/src/main/java/com/strcat/repository/BoardRepository.java +++ b/src/main/java/com/strcat/repository/BoardRepository.java @@ -9,4 +9,5 @@ @Repository public interface BoardRepository extends JpaRepository { Optional findByEncryptedId(String encryptedId); + List findByIsPublicTrue(); } diff --git a/src/main/java/com/strcat/service/BoardService.java b/src/main/java/com/strcat/service/BoardService.java index a39ac40..ce26823 100644 --- a/src/main/java/com/strcat/service/BoardService.java +++ b/src/main/java/com/strcat/service/BoardService.java @@ -27,7 +27,7 @@ public class BoardService { public String createBoard(CreateBoardReqDto dto, Long userId) { Board board; User user = userRepository.findById(userId).orElseThrow(() -> new NotAcceptableException("유저가 존재하지 않습니다.")); - board = new Board(dto.getTitle(), dto.getTheme(), user); + board = new Board(dto.getTitle(), dto.getTheme(), user, dto.getIsPublic()); board = boardRepository.save(board); String encryptedBoardId = secureDataUtils.encrypt(board.getId()); @@ -41,7 +41,8 @@ public ReadBoardResDto readBoard(String encryptedBoardId, Long userId) { .orElseThrow(() -> new NotAcceptableException("존재하지 않는 보드입니다.")); if (userId != null) { recordHistoryUseCase.write(userId, - List.of(new HistoryItem(encryptedBoardId, board.getTitle(), LocalDateTime.now()))); + List.of(new HistoryItem(encryptedBoardId, board.getTitle(), board.getIsPublic(), + LocalDateTime.now()))); Boolean isOwner = userId.equals(board.getUser().getId()); return board.toReadBoardResDto(isOwner); @@ -55,5 +56,7 @@ public ReadBoardSummaryResDto readSummary(String encryptedBoardId) { .toReadBoardSummaryDto(); } - + public List readPublicBoard() { + return boardRepository.findByIsPublicTrue(); + } } diff --git a/src/main/java/com/strcat/service/UserService.java b/src/main/java/com/strcat/service/UserService.java index 858e340..1622f1b 100644 --- a/src/main/java/com/strcat/service/UserService.java +++ b/src/main/java/com/strcat/service/UserService.java @@ -15,7 +15,6 @@ import jakarta.transaction.Transactional; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -65,7 +64,7 @@ public List readMyBoardInfo(Long userId) { List boards = user.getBoards(); return boards.stream() .map(Board::toReadMyInfoResDto) - .collect(Collectors.toList()); + .toList(); } @@ -82,6 +81,7 @@ public HistoryDto postMyBoardHistory(Long userId, HistoryDto dto) { return new HistoryDto(result.stream() .map((history -> new HistoryItem(history.getBoard().getEncryptedId(), history.getBoard().getTitle(), + history.getBoard().getIsPublic(), history.getVisitedAt()))).toList()); } } \ No newline at end of file diff --git a/src/test/java/com/strcat/board/BoardServiceTest.java b/src/test/java/com/strcat/board/BoardServiceTest.java index 7669562..60f9c49 100644 --- a/src/test/java/com/strcat/board/BoardServiceTest.java +++ b/src/test/java/com/strcat/board/BoardServiceTest.java @@ -16,6 +16,7 @@ import com.strcat.usecase.RecordHistoryUseCase; import com.strcat.util.JwtUtils; import com.strcat.util.SecureDataUtils; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -45,7 +46,8 @@ public BoardServiceTest(BoardRepository boardRepository, UserRepository userRepo this.contentRepository = contentRepository; JwtUtils jwtUtils = new JwtUtils("testtesttesttesttesttesttesttesttesttest"); this.secureDataUtils = new SecureDataUtils("MyTestCode-32CharacterTestAPIKey"); - this.boardService = new BoardService(boardRepository, secureDataUtils, userRepository, new RecordHistoryUseCase(userRepository, boardRepository, historyRepository)); + this.boardService = new BoardService(boardRepository, secureDataUtils, userRepository, + new RecordHistoryUseCase(userRepository, boardRepository, historyRepository)); } @BeforeEach @@ -59,7 +61,7 @@ class 성공 { @Test public void 생성() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); //when String encryptedUrl = boardService.createBoard(dto, user.getId()); @@ -72,11 +74,12 @@ class 성공 { @Test public void 보드주인일때조회() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); String encryptedUrl = boardService.createBoard(dto, user.getId()); Board board = boardRepository.findAll().get(0); ReadBoardResDto expect = new ReadBoardResDto(true, - new BoardResponse(board.getEncryptedId(), board.getTitle(), board.getTheme(), board.getContents())); + new BoardResponse(board.getEncryptedId(), board.getTitle(), board.getTheme(), false, + board.getContents())); //when ReadBoardResDto result = boardService.readBoard(encryptedUrl, user.getId()); @@ -88,14 +91,15 @@ class 성공 { @Test public void 보드주인아닌조회() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); String encryptedUrl = boardService.createBoard(dto, user.getId()); Board board = boardRepository.findAll().get(0); User user2 = new User(); userRepository.save(user2); ReadBoardResDto expect = new ReadBoardResDto(false, - new BoardResponse(board.getEncryptedId(), board.getTitle(), board.getTheme(), board.getContents())); + new BoardResponse(board.getEncryptedId(), board.getTitle(), board.getTheme(), false, + board.getContents())); //when ReadBoardResDto result = boardService.readBoard(encryptedUrl, user2.getId()); @@ -107,7 +111,7 @@ class 성공 { @Test public void 컨텐츠없는요약() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); String encryptedUrl = boardService.createBoard(dto, user.getId()); ReadBoardSummaryResDto expect = new ReadBoardSummaryResDto("가나다", "Green", 0, 0L); @@ -121,7 +125,7 @@ class 성공 { @Test public void 컨텐츠존재요약() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); String encryptedUrl = boardService.createBoard(dto, user.getId()); ReadBoardResDto boardRes = boardService.readBoard(encryptedUrl, user.getId()); Board board = boardRepository.findByEncryptedId(encryptedUrl).orElseThrow(); @@ -136,6 +140,23 @@ class 성공 { //then Assertions.assertEquals(expect, result); } + + @Test + public void 공개보드조회() { + //given + CreateBoardReqDto publicDto = new CreateBoardReqDto("공개", "Green", false); + CreateBoardReqDto privateDto = new CreateBoardReqDto("비공개", "Green", true); + boardService.createBoard(publicDto, user.getId()); + boardService.createBoard(privateDto, user.getId()); + + //when + List result = boardService.readPublicBoard(); + List expect = boardRepository.findAll().stream().filter((board) -> board.getIsPublic().equals(true)) + .toList(); + + //then + Assertions.assertEquals(expect, result); + } } @Nested @@ -143,7 +164,7 @@ class 실패 { @Test public void 제목길이30자이상보드생성() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다가나다가나다가나다가나다가나다가나다가나다가나다가나다가", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다가나다가나다가나다가나다가나다가나다가나다가나다가나다가", "Green", false); //when Throwable thrown = Assertions.assertThrows(DataIntegrityViolationException.class, () -> @@ -156,7 +177,7 @@ class 실패 { @Test public void 존재하지않는보드조회() { //given - CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green"); + CreateBoardReqDto dto = new CreateBoardReqDto("가나다", "Green", false); boardService.createBoard(dto, user.getId()); String validNotExistUrl = secureDataUtils.encrypt(Long.MAX_VALUE); diff --git a/src/test/java/com/strcat/board/ContentServiceTest.java b/src/test/java/com/strcat/board/ContentServiceTest.java index 94c208e..d245e41 100644 --- a/src/test/java/com/strcat/board/ContentServiceTest.java +++ b/src/test/java/com/strcat/board/ContentServiceTest.java @@ -52,7 +52,7 @@ public void beforeEach() { userRepository.deleteAll(); User user = new User(); userRepository.save(user); - boardRepository.save(new Board("홍길동", "dsfds", user)); + boardRepository.save(new Board("홍길동", "dsfds", user, false)); } @Test @@ -93,7 +93,7 @@ public void beforeEach() { public void content_삭제_성공() { //given User user = userRepository.findAll().get(0); - Board board = boardRepository.save(new Board("asd", "asd", user)); + Board board = boardRepository.save(new Board("asd", "asd", user, false)); String encryptedBoardId = secureDataUtils.encrypt(board.getId()); CreateContentReqDto dto = new CreateContentReqDto( "12345", "안녕! 만나서 반가워. 행복하길 바래~", "photo"); diff --git a/src/test/java/com/strcat/user/UserServiceTest.java b/src/test/java/com/strcat/user/UserServiceTest.java index 28f4314..db309c2 100644 --- a/src/test/java/com/strcat/user/UserServiceTest.java +++ b/src/test/java/com/strcat/user/UserServiceTest.java @@ -30,7 +30,6 @@ public class UserServiceTest { private final UserService userService; private final UserRepository userRepository; private final BoardRepository boardRepository; - private final HistoryRepository historyRepository; private final SecureDataUtils secureDataUtils; private User me; private List boards; @@ -40,7 +39,6 @@ public UserServiceTest(UserRepository userRepository, BoardRepository boardRepos HistoryRepository historyRepository) { this.boardRepository = boardRepository; this.userRepository = userRepository; - this.historyRepository = historyRepository; this.secureDataUtils = new SecureDataUtils("testtesttesttesttesttesttesttest"); JwtUtils jwtUtils = new JwtUtils("testtesttesttesttesttesttesttesttesttest"); this.userService = new UserService(userRepository, boardRepository, historyRepository, jwtUtils); @@ -55,7 +53,7 @@ public void beforeEach() { userRepository.save(other); for (int i = 1; i <= 10; ++i) { - boardRepository.save(new Board("test_board" + i, "green", other)); + boardRepository.save(new Board("test_board" + i, "green", other, false)); } this.boards = boardRepository.findAll(); @@ -70,7 +68,8 @@ public void beforeEach() { public void 최근기록저장_성공() { //given List history = boards.stream() - .map((board) -> new HistoryItem(board.getEncryptedId(), board.getTitle(), LocalDateTime.now())) + .map((board) -> new HistoryItem(board.getEncryptedId(), board.getTitle(), board.getIsPublic(), + LocalDateTime.now())) .toList(); HistoryDto historyDto = new HistoryDto(history); @@ -87,7 +86,8 @@ public void beforeEach() { User user = userRepository.findById(me.getId()).orElseThrow(); LocalDateTime now = LocalDateTime.now(); List history = boards.stream() - .map((board) -> new HistoryItem(board.getEncryptedId(), board.getTitle(), now)).toList(); + .map((board) -> new HistoryItem(board.getEncryptedId(), board.getTitle(), board.getIsPublic(), now)) + .toList(); HistoryDto historyDto = new HistoryDto(history); user.setHistories(boards.stream().map((board) -> new History(user, board, now)).toList()); userService.postMyBoardHistory(user.getId(), historyDto);