From 6f7fdb6893400319f48a0d3905af9dcffe3a18dd Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:13:29 +0900 Subject: [PATCH 01/66] =?UTF-8?q?Feat=20:=20Comment,=20News=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=20=EC=9E=91=EC=84=B1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/comment/entity/Comment.java | 39 ++++++++++++++++++ .../back/domain/news/news/entity/News.java | 40 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 back/src/main/java/com/back/domain/news/comment/entity/Comment.java create mode 100644 back/src/main/java/com/back/domain/news/news/entity/News.java diff --git a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java new file mode 100644 index 00000000..ee7dd1ee --- /dev/null +++ b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java @@ -0,0 +1,39 @@ +package com.back.domain.news.comment.entity; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.news.news.entity.News; +import com.back.global.jpa.BaseEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Comment extends BaseEntity { + @ManyToOne + private Member member; + @ManyToOne + @JoinColumn + private News news; + private String content; + + @Builder(access = AccessLevel.PRIVATE) + private Comment(Member member, News news, String content) { + this.member = member; + this.news = news; + this.content = content; + } + + public static Comment create(Member member, News news, String content) { + return Comment.builder() + .member(member) + .news(news) + .content(content) + .build(); + } +} diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java new file mode 100644 index 00000000..249c931a --- /dev/null +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -0,0 +1,40 @@ +package com.back.domain.news.news.entity; + +import com.back.domain.news.comment.entity.Comment; +import com.back.global.jpa.BaseEntity; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.OneToMany; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class News extends BaseEntity { + private String title; + //todo: video entity 생성 후 통합 필요 +// @OneToOne +// private Video video; + private String content; + @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) + private List comment; + + @Builder(access = AccessLevel.PRIVATE) + private News(String title, String content, List comment) { + this.title = title; + this.content = content; + this.comment = comment; + } + + public static News create(String title, String content) { + return News.builder() + .title(title) + .content(content) + .build(); + } +} From 6be1cd9fc00c17c7319448807052d9cdf422e724 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:27:38 +0900 Subject: [PATCH 02/66] =?UTF-8?q?Feat=20:=20likes=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/back/domain/news/news/entity/News.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index 249c931a..f17c2d5f 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -23,18 +23,20 @@ public class News extends BaseEntity { private String content; @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) private List comment; + private Integer likes = 0; @Builder(access = AccessLevel.PRIVATE) - private News(String title, String content, List comment) { + private News(String title, String content, Integer likes) { this.title = title; this.content = content; - this.comment = comment; + this.likes = likes; } public static News create(String title, String content) { return News.builder() .title(title) .content(content) + .likes(0) .build(); } } From 01a559103c1bd06fde9253e35431ff77c6ba424d Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:32:25 +0900 Subject: [PATCH 03/66] =?UTF-8?q?Feat=20:=20Video=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20News=20=EC=99=80=20=EC=97=B0=EA=B4=80=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EB=A7=A4=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/file/entity/Video.java | 56 +++++++++++++++++++ .../back/domain/news/news/entity/News.java | 13 +++-- 2 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 back/src/main/java/com/back/domain/file/entity/Video.java diff --git a/back/src/main/java/com/back/domain/file/entity/Video.java b/back/src/main/java/com/back/domain/file/entity/Video.java new file mode 100644 index 00000000..6479594f --- /dev/null +++ b/back/src/main/java/com/back/domain/file/entity/Video.java @@ -0,0 +1,56 @@ +package com.back.domain.file.entity; + +import com.back.global.jpa.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.JdbcTypeCode; +import org.hibernate.type.SqlTypes; + +@Getter +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Video extends BaseEntity { + @Column(unique = true) + private String uuid; + + @JdbcTypeCode(SqlTypes.JSON) + @Column(name = "transcoding_results") + private String transcodingResults; + + private String originalPath; + + private Integer views; + + private String originalFileName; + + private Integer duration; + + private Long fileSize; + + @Builder(access = AccessLevel.PRIVATE) + private Video(String uuid, String transcodingResults, String originalPath, Integer views, String originalFileName, Integer duration, Long fileSize) { + this.uuid = uuid; + this.transcodingResults = transcodingResults; + this.originalPath = originalPath; + this.views = views; + this.originalFileName = originalFileName; + this.duration = duration; + this.fileSize = fileSize; + } + + public static Video create(String uuid, String transcodingResults, String originalPath, String originalFileName, Integer duration, Long fileSize) { + return Video.builder() + .uuid(uuid) + .transcodingResults(transcodingResults) + .originalPath(originalPath) + .views(0) + .originalFileName(originalFileName) + .duration(duration) + .fileSize(fileSize) + .build(); + } +} diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index f17c2d5f..543cb191 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -1,10 +1,12 @@ package com.back.domain.news.news.entity; +import com.back.domain.file.entity.Video; import com.back.domain.news.comment.entity.Comment; import com.back.global.jpa.BaseEntity; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -17,24 +19,25 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class News extends BaseEntity { private String title; - //todo: video entity 생성 후 통합 필요 -// @OneToOne -// private Video video; + @OneToOne + private Video video; private String content; @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) private List comment; private Integer likes = 0; @Builder(access = AccessLevel.PRIVATE) - private News(String title, String content, Integer likes) { + private News(String title, Video video, String content, Integer likes) { this.title = title; + this.video = video; this.content = content; this.likes = likes; } - public static News create(String title, String content) { + public static News create(String title, Video video, String content) { return News.builder() .title(title) + .video(video) .content(content) .likes(0) .build(); From 75eb051821915056420313112fc677cb8acb09de Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:44:24 +0900 Subject: [PATCH 04/66] =?UTF-8?q?Feat=20:=20=EB=B9=84=EB=94=94=EC=98=A4=20?= =?UTF-8?q?=ED=94=BD=EC=8A=A4=EC=B3=90=20=EB=A9=94=EC=86=8C=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/fixture/VideoFixture.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 back/src/test/java/com/back/domain/fixture/VideoFixture.java diff --git a/back/src/test/java/com/back/domain/fixture/VideoFixture.java b/back/src/test/java/com/back/domain/fixture/VideoFixture.java new file mode 100644 index 00000000..08053734 --- /dev/null +++ b/back/src/test/java/com/back/domain/fixture/VideoFixture.java @@ -0,0 +1,63 @@ +package com.back.domain.fixture; + +import com.back.domain.file.entity.Video; + +import java.util.UUID; + +public class VideoFixture { + private String uuid = UUID.randomUUID().toString(); + private String transcodingResults = "{\"resolutions\": [\"360p\", \"720p\"]}"; + private String originalPath = "/videos/original.mp4"; + private String originalFileName = "original.mp4"; + private Integer duration = 120; + private Long fileSize = 1024L * 1024L * 10; // 10MB + + private static VideoFixture builder() { + return new VideoFixture(); + } + + public static Video createDefault() { + return builder().build(); + } + + public VideoFixture withUuid(String uuid) { + this.uuid = uuid; + return this; + } + + public VideoFixture withTranscodingResults(String transcodingResults) { + this.transcodingResults = transcodingResults; + return this; + } + + public VideoFixture withOriginalPath(String originalPath) { + this.originalPath = originalPath; + return this; + } + + public VideoFixture withOriginalFileName(String originalFileName) { + this.originalFileName = originalFileName; + return this; + } + + public VideoFixture withDuration(Integer duration) { + this.duration = duration; + return this; + } + + public VideoFixture withFileSize(Long fileSize) { + this.fileSize = fileSize; + return this; + } + + public Video build() { + return Video.create( + uuid, + transcodingResults, + originalPath, + originalFileName, + duration, + fileSize + ); + } +} \ No newline at end of file From 69583cb122ea9d864d7bf8f22226f3f128d5dc2a Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:44:47 +0900 Subject: [PATCH 05/66] =?UTF-8?q?Test=20:=20News=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/entity/NewsTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 back/src/test/java/com/back/domain/news/news/entity/NewsTest.java diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java new file mode 100644 index 00000000..1143c68a --- /dev/null +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -0,0 +1,26 @@ +package com.back.domain.news.news.entity; + +import com.back.domain.file.entity.Video; +import com.back.domain.fixture.VideoFixture; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class NewsTest { + @Test + @DisplayName("제목과 영상,내용으로 뉴스 객체 생성") + void newsCreationTestWithTitleAndContent() { + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + + News news = News.create(title, video, content); + + assertThat(news).isNotNull(); + assertThat(news.getTitle()).isEqualTo(title); + assertThat(news.getVideo()).isEqualTo(video); + assertThat(news.getContent()).isEqualTo(content); + } + +} \ No newline at end of file From 76a8e17dd8e41c110394866a477881829f134356 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 11:46:32 +0900 Subject: [PATCH 06/66] =?UTF-8?q?Refactor=20:=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=EB=A5=BC=20=ED=86=B5=ED=95=B4=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main/java/com/back/domain/news/news/entity/News.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index 543cb191..a81d022d 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -24,7 +24,7 @@ public class News extends BaseEntity { private String content; @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) private List comment; - private Integer likes = 0; + private Integer likes; @Builder(access = AccessLevel.PRIVATE) private News(String title, Video video, String content, Integer likes) { From 5e5dfcb701c2abbd095cb38e70364fdd15e0bf89 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:01:03 +0900 Subject: [PATCH 07/66] =?UTF-8?q?Feat=20:=20News=EC=9D=98=20=EC=9C=A0?= =?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/back/domain/news/news/entity/News.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index a81d022d..35475e8a 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -35,6 +35,15 @@ private News(String title, Video video, String content, Integer likes) { } public static News create(String title, Video video, String content) { + if (title == null || title.isBlank()) { + throw new IllegalArgumentException("Title cannot be null or empty"); + } + if (video == null) { + throw new IllegalArgumentException("Video cannot be null"); + } + if (content == null || content.isBlank()) { + throw new IllegalArgumentException("Content cannot be null or empty"); + } return News.builder() .title(title) .video(video) From 74fbd3dade37ae8fcda211a6d21fdc28700c5717 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:02:26 +0900 Subject: [PATCH 08/66] =?UTF-8?q?Test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/entity/NewsTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index 1143c68a..3dc60b90 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -21,6 +21,58 @@ void newsCreationTestWithTitleAndContent() { assertThat(news.getTitle()).isEqualTo(title); assertThat(news.getVideo()).isEqualTo(video); assertThat(news.getContent()).isEqualTo(content); + assertThat(news.getLikes()).isEqualTo(0); + } + + @Test + @DisplayName("제목이 null 혹은 공백인 경우 예외를 반환한다.") + void newsCreationTestWithInvalidTitle() { + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + + try { + News.create(null, video, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + News.create("", video, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("영상이 null인 경우 예외를 반환한다.") + void newsCreationTestWithInvalidVideo() { + String title = "Sample News Title"; + String content = "This is a sample news content."; + + try { + News.create(title, null, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("내용이 null 혹은 공백인 경우 예외를 반환한다.") + void newsCreationTestWithInvalidContent() { + String title = "Sample News Title"; + Video video = VideoFixture.createDefault(); + + try { + News.create(title, video, null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + News.create(title, video, ""); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } } } \ No newline at end of file From 22c8e39d7f0c248236b43fbc827eb93dd88ef931 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:06:23 +0900 Subject: [PATCH 09/66] =?UTF-8?q?Test=20:=20=EC=83=9D=EC=84=B1=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EA=B0=80=20=EC=BD=94=EB=A9=98=ED=8A=B8=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=81=AC=EA=B8=B0=EB=A5=BC=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/test/java/com/back/domain/news/news/entity/NewsTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index 3dc60b90..ff4e068c 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -21,6 +21,7 @@ void newsCreationTestWithTitleAndContent() { assertThat(news.getTitle()).isEqualTo(title); assertThat(news.getVideo()).isEqualTo(video); assertThat(news.getContent()).isEqualTo(content); + assertThat(news.getComment().size()).isEqualTo(0); assertThat(news.getLikes()).isEqualTo(0); } From e6e9571a420d01f0a827cf5d5790c2c23e62573c Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:08:22 +0900 Subject: [PATCH 10/66] =?UTF-8?q?Fix=20:=20=EC=83=9D=EC=84=B1=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=B4=20=EC=BD=94=EB=A9=98=ED=8A=B8=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=B4=88=EA=B8=B0?= =?UTF-8?q?=ED=99=94=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/back/domain/news/news/entity/News.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index 35475e8a..cab11477 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -12,6 +12,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.ArrayList; import java.util.List; @Getter @@ -27,10 +28,11 @@ public class News extends BaseEntity { private Integer likes; @Builder(access = AccessLevel.PRIVATE) - private News(String title, Video video, String content, Integer likes) { + private News(String title, Video video, String content, List comment, Integer likes) { this.title = title; this.video = video; this.content = content; + this.comment = comment; this.likes = likes; } @@ -48,6 +50,7 @@ public static News create(String title, Video video, String content) { .title(title) .video(video) .content(content) + .comment(new ArrayList<>()) .likes(0) .build(); } From 56930e7fe93de5438641714edd59b9502dc3238a Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:18:00 +0900 Subject: [PATCH 11/66] =?UTF-8?q?Feat=20:=20News=EC=99=80=20Member?= =?UTF-8?q?=EA=B0=80=20=EC=97=B0=EA=B4=80=EA=B4=80=EA=B3=84=EB=A5=BC=20?= =?UTF-8?q?=EB=A7=BA=EB=8F=84=EB=A1=9D=20=EB=A7=A4=ED=95=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/news/news/entity/News.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index cab11477..864c45e8 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -1,12 +1,10 @@ package com.back.domain.news.news.entity; import com.back.domain.file.entity.Video; +import com.back.domain.member.member.entity.Member; import com.back.domain.news.comment.entity.Comment; import com.back.global.jpa.BaseEntity; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Entity; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -19,6 +17,8 @@ @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) public class News extends BaseEntity { + @ManyToOne(fetch = FetchType.LAZY) + private Member member; private String title; @OneToOne private Video video; @@ -28,15 +28,20 @@ public class News extends BaseEntity { private Integer likes; @Builder(access = AccessLevel.PRIVATE) - private News(String title, Video video, String content, List comment, Integer likes) { + private News(Member member, String title, Video video, String content, List comment, Integer likes) { + this.member = member; this.title = title; this.video = video; this.content = content; this.comment = comment; + this.likes = likes; } - public static News create(String title, Video video, String content) { + public static News create(Member member, String title, Video video, String content) { + if (member == null) { + throw new IllegalArgumentException("Member cannot be null"); + } if (title == null || title.isBlank()) { throw new IllegalArgumentException("Title cannot be null or empty"); } @@ -47,6 +52,7 @@ public static News create(String title, Video video, String content) { throw new IllegalArgumentException("Content cannot be null or empty"); } return News.builder() + .member(member) .title(title) .video(video) .content(content) From 9ab5c6bf6888ddae978f5eb48d32e3a1002904f4 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:22:54 +0900 Subject: [PATCH 12/66] =?UTF-8?q?Feat=20:=20Member=20=ED=94=BD=EC=8A=A4?= =?UTF-8?q?=EC=B3=90=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/fixture/MemberFixture.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 back/src/test/java/com/back/domain/fixture/MemberFixture.java diff --git a/back/src/test/java/com/back/domain/fixture/MemberFixture.java b/back/src/test/java/com/back/domain/fixture/MemberFixture.java new file mode 100644 index 00000000..983de55a --- /dev/null +++ b/back/src/test/java/com/back/domain/fixture/MemberFixture.java @@ -0,0 +1,51 @@ +package com.back.domain.fixture; + +import com.back.domain.member.member.entity.Member; + +public class MemberFixture { + private String email = "test@example.com"; + private String password = "password123"; + private String name = "Test User"; + private Member.Role role = Member.Role.MENTEE; + private Integer id = null; + + private static MemberFixture builder() { + return new MemberFixture(); + } + + public static Member createDefault() { + return builder().build(); + } + + public MemberFixture withEmail(String email) { + this.email = email; + return this; + } + + public MemberFixture withPassword(String password) { + this.password = password; + return this; + } + + public MemberFixture withName(String name) { + this.name = name; + return this; + } + + public MemberFixture withRole(Member.Role role) { + this.role = role; + return this; + } + + public MemberFixture withId(Integer id) { + this.id = id; + return this; + } + + public Member build() { + if (id != null) { + return new Member(id, email, name); + } + return new Member(email, password, name, role); + } +} From 5591ed1f399f9f7a032ceec3e154e07e1c0e9274 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:24:03 +0900 Subject: [PATCH 13/66] =?UTF-8?q?Test=20:=20Member=20=EC=97=B0=EA=B4=80?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=EB=A7=A4=ED=95=91=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BC=80=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/entity/NewsTest.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index ff4e068c..87b86291 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -1,7 +1,9 @@ package com.back.domain.news.news.entity; import com.back.domain.file.entity.Video; +import com.back.domain.fixture.MemberFixture; import com.back.domain.fixture.VideoFixture; +import com.back.domain.member.member.entity.Member; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -14,10 +16,11 @@ void newsCreationTestWithTitleAndContent() { String title = "Sample News Title"; String content = "This is a sample news content."; Video video = VideoFixture.createDefault(); - - News news = News.create(title, video, content); + Member member = MemberFixture.createDefault(); + News news = News.create(member, title, video, content); assertThat(news).isNotNull(); + assertThat(news.getMember()).isEqualTo(member); assertThat(news.getTitle()).isEqualTo(title); assertThat(news.getVideo()).isEqualTo(video); assertThat(news.getContent()).isEqualTo(content); @@ -25,20 +28,35 @@ void newsCreationTestWithTitleAndContent() { assertThat(news.getLikes()).isEqualTo(0); } + @Test + @DisplayName("멤버가 null인 경우 예외를 반환한다.") + void newsCreationTestWithInvalidMember() { + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + + try { + News.create(null, title, video, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + @Test @DisplayName("제목이 null 혹은 공백인 경우 예외를 반환한다.") void newsCreationTestWithInvalidTitle() { + Member member = MemberFixture.createDefault(); String content = "This is a sample news content."; Video video = VideoFixture.createDefault(); try { - News.create(null, video, content); + News.create(member, null, video, content); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class); } try { - News.create("", video, content); + News.create(member, "", video, content); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class); } @@ -47,11 +65,12 @@ void newsCreationTestWithInvalidTitle() { @Test @DisplayName("영상이 null인 경우 예외를 반환한다.") void newsCreationTestWithInvalidVideo() { + Member member = MemberFixture.createDefault(); String title = "Sample News Title"; String content = "This is a sample news content."; try { - News.create(title, null, content); + News.create(member, title, null, content); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class); } @@ -60,20 +79,20 @@ void newsCreationTestWithInvalidVideo() { @Test @DisplayName("내용이 null 혹은 공백인 경우 예외를 반환한다.") void newsCreationTestWithInvalidContent() { + Member member = MemberFixture.createDefault(); String title = "Sample News Title"; Video video = VideoFixture.createDefault(); try { - News.create(title, video, null); + News.create(member, title, video, null); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class); } try { - News.create(title, video, ""); + News.create(member, title, video, ""); } catch (Exception e) { assertThat(e).isInstanceOf(IllegalArgumentException.class); } } - } \ No newline at end of file From 3dce02e4454acec6777e1db9255624d39e0d0117 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:24:45 +0900 Subject: [PATCH 14/66] =?UTF-8?q?Feat=20:=20News=20=ED=94=BD=EC=8A=A4?= =?UTF-8?q?=EC=B3=90=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/fixture/NewsFixture.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 back/src/test/java/com/back/domain/fixture/NewsFixture.java diff --git a/back/src/test/java/com/back/domain/fixture/NewsFixture.java b/back/src/test/java/com/back/domain/fixture/NewsFixture.java new file mode 100644 index 00000000..f21ba022 --- /dev/null +++ b/back/src/test/java/com/back/domain/fixture/NewsFixture.java @@ -0,0 +1,62 @@ +package com.back.domain.fixture; + +import com.back.domain.file.entity.Video; +import com.back.domain.member.member.entity.Member; +import com.back.domain.news.comment.entity.Comment; +import com.back.domain.news.news.entity.News; + +import java.util.ArrayList; +import java.util.List; + +public class NewsFixture { + private Member member = MemberFixture.createDefault(); + private String title = "Sample News Title"; + private Video video = VideoFixture.createDefault(); + private String content = "This is a sample news content."; + private List comments = new ArrayList<>(); + private Integer likes = 0; + + private static NewsFixture builder() { + return new NewsFixture(); + } + + public static News createDefault() { + return builder().build(); + } + + public NewsFixture withMember(Member member) { + this.member = member; + return this; + } + + public NewsFixture withTitle(String title) { + this.title = title; + return this; + } + + public NewsFixture withVideo(Video video) { + this.video = video; + return this; + } + + public NewsFixture withContent(String content) { + this.content = content; + return this; + } + + public NewsFixture withLikes(Integer likes) { + this.likes = likes; + return this; + } + + public NewsFixture withComments(List comments) { + this.comments = comments; + return this; + } + + public News build() { + News news = News.create(member, title, video, content); + news.getComment().addAll(comments); + return news; + } +} From cbf817fae115d5bc659d30567352eda81e03df44 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:25:49 +0900 Subject: [PATCH 15/66] =?UTF-8?q?Feat=20:=20Comment=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/news/comment/entity/Comment.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java index ee7dd1ee..0eef3394 100644 --- a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java +++ b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java @@ -24,6 +24,15 @@ public class Comment extends BaseEntity { @Builder(access = AccessLevel.PRIVATE) private Comment(Member member, News news, String content) { + if (member == null) { + throw new IllegalArgumentException("Member cannot be null"); + } + if (news == null) { + throw new IllegalArgumentException("News cannot be null"); + } + if (content == null || content.isBlank()) { + throw new IllegalArgumentException("Content cannot be null or empty"); + } this.member = member; this.news = news; this.content = content; From 4526c33996f41afcd2b95c9d9d7324360fd670c0 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:30:17 +0900 Subject: [PATCH 16/66] =?UTF-8?q?Test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/comment/entity/CommentTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java diff --git a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java new file mode 100644 index 00000000..095f6c10 --- /dev/null +++ b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java @@ -0,0 +1,72 @@ +package com.back.domain.news.comment.entity; + + +import com.back.domain.fixture.MemberFixture; +import com.back.domain.fixture.NewsFixture; +import com.back.domain.member.member.entity.Member; +import com.back.domain.news.news.entity.News; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class CommentTest { + @Test + @DisplayName("사용자, 뉴스, 내용으로 댓글 객체 생성") + void commentCreationTest() { + Member member = MemberFixture.createDefault(); + News news = NewsFixture.createDefault(); + String content = "This is a sample comment content."; + Comment comment = Comment.create(member, news, content); + + assertThat(comment).isNotNull(); + assertThat(comment.getMember()).isEqualTo(member); + assertThat(comment.getNews()).isEqualTo(news); + assertThat(comment.getContent()).isEqualTo(content); + } + + @Test + @DisplayName("멤버가 null인 경우 예외를 반환한다.") + void commentCreationTestWithInvalidMember() { + News news = NewsFixture.createDefault(); + String content = "This is a sample comment content."; + + try { + Comment.create(null, news, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("뉴스가 null인 경우 예외를 반환한다.") + void commentCreationTestWithInvalidNews() { + Member member = MemberFixture.createDefault(); + String content = "This is a sample comment content."; + + try { + Comment.create(member, null, content); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("내용이 null 혹은 공백인 경우 예외를 반환한다.") + void commentCreationTestWithInvalidContent() { + Member member = MemberFixture.createDefault(); + News news = NewsFixture.createDefault(); + + try { + Comment.create(member, news, null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + Comment.create(member, news, ""); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } +} \ No newline at end of file From b73f3ec37b21b7df947d718fd31131c572e69121 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:39:32 +0900 Subject: [PATCH 17/66] =?UTF-8?q?Feat=20:=20Video=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/back/domain/file/entity/Video.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/back/src/main/java/com/back/domain/file/entity/Video.java b/back/src/main/java/com/back/domain/file/entity/Video.java index 6479594f..d4557dfe 100644 --- a/back/src/main/java/com/back/domain/file/entity/Video.java +++ b/back/src/main/java/com/back/domain/file/entity/Video.java @@ -43,6 +43,16 @@ private Video(String uuid, String transcodingResults, String originalPath, Integ } public static Video create(String uuid, String transcodingResults, String originalPath, String originalFileName, Integer duration, Long fileSize) { + if (uuid == null || uuid.isBlank()) { + throw new IllegalArgumentException("uuid cannot be null or empty"); + } + if (originalPath == null || originalPath.isBlank()) { + throw new IllegalArgumentException("originalPath cannot be null or empty"); + } + if (originalFileName == null || originalFileName.isBlank()) { + throw new IllegalArgumentException("originalFileName cannot be null or empty"); + } + return Video.builder() .uuid(uuid) .transcodingResults(transcodingResults) From a2571e9a315501f5f503f36b1f431810db0ae562 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:39:54 +0900 Subject: [PATCH 18/66] =?UTF-8?q?Chore=20:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/back/domain/news/comment/entity/CommentTest.java | 4 ++-- .../test/java/com/back/domain/news/news/entity/NewsTest.java | 4 ++-- .../java/com/back/{domain => }/fixture/MemberFixture.java | 2 +- .../test/java/com/back/{domain => }/fixture/NewsFixture.java | 2 +- .../test/java/com/back/{domain => }/fixture/VideoFixture.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename back/src/test/java/com/back/{domain => }/fixture/MemberFixture.java (97%) rename back/src/test/java/com/back/{domain => }/fixture/NewsFixture.java (97%) rename back/src/test/java/com/back/{domain => }/fixture/VideoFixture.java (98%) diff --git a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java index 095f6c10..ab9e89ef 100644 --- a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java +++ b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java @@ -1,8 +1,8 @@ package com.back.domain.news.comment.entity; -import com.back.domain.fixture.MemberFixture; -import com.back.domain.fixture.NewsFixture; +import com.back.fixture.MemberFixture; +import com.back.fixture.NewsFixture; import com.back.domain.member.member.entity.Member; import com.back.domain.news.news.entity.News; import org.junit.jupiter.api.DisplayName; diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index 87b86291..340b83e7 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -1,8 +1,8 @@ package com.back.domain.news.news.entity; import com.back.domain.file.entity.Video; -import com.back.domain.fixture.MemberFixture; -import com.back.domain.fixture.VideoFixture; +import com.back.fixture.MemberFixture; +import com.back.fixture.VideoFixture; import com.back.domain.member.member.entity.Member; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/back/src/test/java/com/back/domain/fixture/MemberFixture.java b/back/src/test/java/com/back/fixture/MemberFixture.java similarity index 97% rename from back/src/test/java/com/back/domain/fixture/MemberFixture.java rename to back/src/test/java/com/back/fixture/MemberFixture.java index 983de55a..ef11bb26 100644 --- a/back/src/test/java/com/back/domain/fixture/MemberFixture.java +++ b/back/src/test/java/com/back/fixture/MemberFixture.java @@ -1,4 +1,4 @@ -package com.back.domain.fixture; +package com.back.fixture; import com.back.domain.member.member.entity.Member; diff --git a/back/src/test/java/com/back/domain/fixture/NewsFixture.java b/back/src/test/java/com/back/fixture/NewsFixture.java similarity index 97% rename from back/src/test/java/com/back/domain/fixture/NewsFixture.java rename to back/src/test/java/com/back/fixture/NewsFixture.java index f21ba022..cf6ccffe 100644 --- a/back/src/test/java/com/back/domain/fixture/NewsFixture.java +++ b/back/src/test/java/com/back/fixture/NewsFixture.java @@ -1,4 +1,4 @@ -package com.back.domain.fixture; +package com.back.fixture; import com.back.domain.file.entity.Video; import com.back.domain.member.member.entity.Member; diff --git a/back/src/test/java/com/back/domain/fixture/VideoFixture.java b/back/src/test/java/com/back/fixture/VideoFixture.java similarity index 98% rename from back/src/test/java/com/back/domain/fixture/VideoFixture.java rename to back/src/test/java/com/back/fixture/VideoFixture.java index 08053734..2f6a8398 100644 --- a/back/src/test/java/com/back/domain/fixture/VideoFixture.java +++ b/back/src/test/java/com/back/fixture/VideoFixture.java @@ -1,4 +1,4 @@ -package com.back.domain.fixture; +package com.back.fixture; import com.back.domain.file.entity.Video; From cb6fb24d06e59dae83d2c4c807b5403696d4d6ba Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 12:50:32 +0900 Subject: [PATCH 19/66] =?UTF-8?q?Test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/file/entity/VideoTest.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 back/src/test/java/com/back/domain/file/entity/VideoTest.java diff --git a/back/src/test/java/com/back/domain/file/entity/VideoTest.java b/back/src/test/java/com/back/domain/file/entity/VideoTest.java new file mode 100644 index 00000000..b2abf596 --- /dev/null +++ b/back/src/test/java/com/back/domain/file/entity/VideoTest.java @@ -0,0 +1,91 @@ +package com.back.domain.file.entity; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class VideoTest { + + @Test + @DisplayName("uuid, transcodingResults, originalPath, originalFileName, duration, fileSize로 Video 객체 생성") + void videoCreationTest() { + String uuid = "sample-uuid"; + String transcodingResults = "{\"status\":\"done\"}"; + String originalPath = "/videos/sample.mp4"; + String originalFileName = "sample.mp4"; + Integer duration = 120; + Long fileSize = 1024L; + + Video video = Video.create(uuid, transcodingResults, originalPath, originalFileName, duration, fileSize); + + assertThat(video).isNotNull(); + assertThat(video.getUuid()).isEqualTo(uuid); + assertThat(video.getTranscodingResults()).isEqualTo(transcodingResults); + assertThat(video.getOriginalPath()).isEqualTo(originalPath); + assertThat(video.getViews()).isEqualTo(0); // 기본값 확인 + assertThat(video.getOriginalFileName()).isEqualTo(originalFileName); + assertThat(video.getDuration()).isEqualTo(duration); + assertThat(video.getFileSize()).isEqualTo(fileSize); + } + + @Test + @DisplayName("uuid가 null 또는 공백일 경우 예외를 반환한다.") + void videoCreationTestWithInvalidUuid() { + String transcodingResults = "{}"; + String originalPath = "/videos/sample.mp4"; + String originalFileName = "sample.mp4"; + + try { + Video.create(null, transcodingResults, originalPath, originalFileName, 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + Video.create("", transcodingResults, originalPath, originalFileName, 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("originalPath가 null 또는 공백일 경우 예외를 반환한다.") + void videoCreationTestWithInvalidOriginalPath() { + String uuid = "sample-uuid"; + String transcodingResults = "{}"; + String originalFileName = "sample.mp4"; + + try { + Video.create(uuid, transcodingResults, null, originalFileName, 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + Video.create(uuid, transcodingResults, "", originalFileName, 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("originalFileName이 null 또는 공백일 경우 예외를 반환한다.") + void videoCreationTestWithInvalidOriginalFileName() { + String uuid = "sample-uuid"; + String transcodingResults = "{}"; + String originalPath = "/videos/sample.mp4"; + + try { + Video.create(uuid, transcodingResults, originalPath, null, 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + Video.create(uuid, transcodingResults, originalPath, "", 100, 1000L); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } +} From c3eda5c4a7634af06e57a8d523d55a12f060f9c4 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 14:06:22 +0900 Subject: [PATCH 20/66] =?UTF-8?q?Feat=20:=20News=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20Repository,=20Service=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/repository/NewsRepository.java | 9 +++++++++ .../back/domain/news/news/service/NewsService.java | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 back/src/main/java/com/back/domain/news/news/repository/NewsRepository.java create mode 100644 back/src/main/java/com/back/domain/news/news/service/NewsService.java diff --git a/back/src/main/java/com/back/domain/news/news/repository/NewsRepository.java b/back/src/main/java/com/back/domain/news/news/repository/NewsRepository.java new file mode 100644 index 00000000..af85d4e2 --- /dev/null +++ b/back/src/main/java/com/back/domain/news/news/repository/NewsRepository.java @@ -0,0 +1,9 @@ +package com.back.domain.news.news.repository; + +import com.back.domain.news.news.entity.News; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface NewsRepository extends JpaRepository { +} diff --git a/back/src/main/java/com/back/domain/news/news/service/NewsService.java b/back/src/main/java/com/back/domain/news/news/service/NewsService.java new file mode 100644 index 00000000..3ae0c2f9 --- /dev/null +++ b/back/src/main/java/com/back/domain/news/news/service/NewsService.java @@ -0,0 +1,12 @@ +package com.back.domain.news.news.service; + + +import com.back.domain.news.news.repository.NewsRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class NewsService { + private final NewsRepository newsRepository; +} From 7f907342cde1f8bdce6e35f14decf78fd52d5cc2 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 14:41:57 +0900 Subject: [PATCH 21/66] =?UTF-8?q?Feat=20:=20Like=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/news/like/entity/Like.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 back/src/main/java/com/back/domain/news/like/entity/Like.java diff --git a/back/src/main/java/com/back/domain/news/like/entity/Like.java b/back/src/main/java/com/back/domain/news/like/entity/Like.java new file mode 100644 index 00000000..1a398e76 --- /dev/null +++ b/back/src/main/java/com/back/domain/news/like/entity/Like.java @@ -0,0 +1,50 @@ +package com.back.domain.news.like.entity; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.news.news.entity.News; +import com.back.global.jpa.BaseEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@Table(name = "news_like", uniqueConstraints = { + @UniqueConstraint(columnNames = {"member_id", "news_id"}) +}) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Like extends BaseEntity { + + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + private News news; + + @Builder(access = AccessLevel.PRIVATE) + private Like(Member member, News news) { + this.member = member; + this.news = news; + } + + public static Like create(Member member, News news) { + if (member == null) { + throw new IllegalArgumentException("Member cannot be null"); + } + if (news == null) { + throw new IllegalArgumentException("News cannot be null"); + } + Like like = Like.builder() + .member(member) + .news(news) + .build(); + news.getLikes().add(like); + return like; + } +} From 05f6696797faabc726b571b5e6f3db8b1c8dcf47 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 14:42:43 +0900 Subject: [PATCH 22/66] =?UTF-8?q?Feat=20:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=A7=91=EA=B3=84=EB=A5=BC=20=EC=A0=95=EC=88=98=EA=B0=80=20?= =?UTF-8?q?=EC=95=84=EB=8B=8C=20Like=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/news/news/entity/News.java | 52 +++++++++++++++++-- .../domain/news/news/entity/NewsTest.java | 2 +- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index 864c45e8..4afb7e5a 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -3,6 +3,7 @@ import com.back.domain.file.entity.Video; import com.back.domain.member.member.entity.Member; import com.back.domain.news.comment.entity.Comment; +import com.back.domain.news.like.entity.Like; import com.back.global.jpa.BaseEntity; import jakarta.persistence.*; import lombok.AccessLevel; @@ -25,16 +26,16 @@ public class News extends BaseEntity { private String content; @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) private List comment; - private Integer likes; + @OneToMany(mappedBy = "news", cascade = CascadeType.ALL, orphanRemoval = true) + private List likes = new ArrayList<>(); @Builder(access = AccessLevel.PRIVATE) - private News(Member member, String title, Video video, String content, List comment, Integer likes) { + private News(Member member, String title, Video video, String content, List comment, List likes) { this.member = member; this.title = title; this.video = video; this.content = content; this.comment = comment; - this.likes = likes; } @@ -57,7 +58,50 @@ public static News create(Member member, String title, Video video, String conte .video(video) .content(content) .comment(new ArrayList<>()) - .likes(0) + .likes(new ArrayList<>()) .build(); } + + public void like(Like like) { + if (this.likes.contains(like)) { + throw new IllegalStateException("이미 좋아요를 누른 뉴스입니다."); + } + this.likes.add(like); + } + + public void unLike(Like like) { + if (!this.likes.contains(like)) { + throw new IllegalStateException("좋아요를 누르지 않은 뉴스입니다."); + } + this.likes.remove(like); + } + + public void addComment(Comment comment) { + if (comment == null) { + throw new IllegalArgumentException("Comment cannot be null"); + } + this.comment.add(comment); + } + + public void removeComment(Comment comment) { + if (comment == null) { + throw new IllegalArgumentException("Comment cannot be null"); + } + this.comment.remove(comment); + } + + public void update(String title, Video video, String content) { + if (title == null || title.isBlank()) { + throw new IllegalArgumentException("Title cannot be null or empty"); + } + if (video == null) { + throw new IllegalArgumentException("Video cannot be null"); + } + if (content == null || content.isBlank()) { + throw new IllegalArgumentException("Content cannot be null or empty"); + } + this.title = title; + this.video = video; + this.content = content; + } } diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index 340b83e7..1fe98ded 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -25,7 +25,7 @@ void newsCreationTestWithTitleAndContent() { assertThat(news.getVideo()).isEqualTo(video); assertThat(news.getContent()).isEqualTo(content); assertThat(news.getComment().size()).isEqualTo(0); - assertThat(news.getLikes()).isEqualTo(0); + assertThat(news.getLikes().size()).isEqualTo(0); } @Test From 2abbb551436dd7d9a05346961d394233c528303b Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 14:42:54 +0900 Subject: [PATCH 23/66] =?UTF-8?q?Feat=20:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/comment/entity/Comment.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java index 0eef3394..adc0d3c6 100644 --- a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java +++ b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java @@ -39,10 +39,25 @@ private Comment(Member member, News news, String content) { } public static Comment create(Member member, News news, String content) { - return Comment.builder() + Comment comment = Comment.builder() .member(member) .news(news) .content(content) .build(); + news.addComment(comment); + + return comment; + } + + public Comment update(String content) { + if (content == null || content.isBlank()) { + throw new IllegalArgumentException("Content cannot be null or empty"); + } + this.content = content; + return this; + } + + public void remove() { + this.news.removeComment(this); } } From 1e758ef245d3ac4fb221a2c030f454328ecb29c8 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 14:51:23 +0900 Subject: [PATCH 24/66] =?UTF-8?q?Fix=20:=20News=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main/java/com/back/domain/news/like/entity/Like.java | 1 - 1 file changed, 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/news/like/entity/Like.java b/back/src/main/java/com/back/domain/news/like/entity/Like.java index 1a398e76..4658afbb 100644 --- a/back/src/main/java/com/back/domain/news/like/entity/Like.java +++ b/back/src/main/java/com/back/domain/news/like/entity/Like.java @@ -44,7 +44,6 @@ public static Like create(Member member, News news) { .member(member) .news(news) .build(); - news.getLikes().add(like); return like; } } From ace6d2dece9ec7c4eb1aee5862aa407d958fc03a Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:17:15 +0900 Subject: [PATCH 25/66] =?UTF-8?q?Fix=20:=20News=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/back/domain/news/comment/entity/Comment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java index adc0d3c6..9c123f98 100644 --- a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java +++ b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java @@ -44,7 +44,6 @@ public static Comment create(Member member, News news, String content) { .news(news) .content(content) .build(); - news.addComment(comment); return comment; } From 1e1150dd2b432c436fce3c92c8ab972dfca6df8b Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:18:56 +0900 Subject: [PATCH 26/66] =?UTF-8?q?Chore=20:=20=EB=A9=94=EB=AA=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main/java/com/back/domain/news/news/entity/News.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/back/src/main/java/com/back/domain/news/news/entity/News.java b/back/src/main/java/com/back/domain/news/news/entity/News.java index 4afb7e5a..23c8c02f 100644 --- a/back/src/main/java/com/back/domain/news/news/entity/News.java +++ b/back/src/main/java/com/back/domain/news/news/entity/News.java @@ -69,6 +69,10 @@ public void like(Like like) { this.likes.add(like); } + /** + * 좋아요를 취소할 수 있게 해야할까요? + */ + @Deprecated(forRemoval = true) public void unLike(Like like) { if (!this.likes.contains(like)) { throw new IllegalStateException("좋아요를 누르지 않은 뉴스입니다."); From 469bb0dd551a5e7a4045b3334a458ae5c983fd6d Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:19:13 +0900 Subject: [PATCH 27/66] =?UTF-8?q?Test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/entity/NewsTest.java | 196 ++++++++++++++++++ 1 file changed, 196 insertions(+) diff --git a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java index 1fe98ded..a29e2c10 100644 --- a/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java +++ b/back/src/test/java/com/back/domain/news/news/entity/NewsTest.java @@ -1,6 +1,8 @@ package com.back.domain.news.news.entity; import com.back.domain.file.entity.Video; +import com.back.domain.news.comment.entity.Comment; +import com.back.domain.news.like.entity.Like; import com.back.fixture.MemberFixture; import com.back.fixture.VideoFixture; import com.back.domain.member.member.entity.Member; @@ -95,4 +97,198 @@ void newsCreationTestWithInvalidContent() { assertThat(e).isInstanceOf(IllegalArgumentException.class); } } + + @Test + @DisplayName("사용자는 뉴스에 좋아요를 누를 수 있다.") + void likeNewsTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + Like like = Like.create(member, news); + news.like(like); + + assertThat(news.getLikes().size()).isEqualTo(1); + assertThat(news.getLikes()).contains(like); + } + + @Test + @DisplayName("사용자는 이미 좋아요를 누른 뉴스에 다시 좋아요를 누를 수 없다.") + void likeNewsAlreadyLikedTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + Like like = Like.create(member, news); + news.like(like); + + try { + news.like(like); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalStateException.class); + } + + assertThat(news.getLikes().size()).isEqualTo(1); + } + + @Test + @DisplayName("뉴스의 제목, 영상, 내용을 수정할 수 있다.") + void updateNewsTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + String newTitle = "Updated News Title"; + String newContent = "This is the updated news content."; + Video newVideo = VideoFixture.createDefault(); + + news.update(newTitle, newVideo, newContent); + + assertThat(news.getTitle()).isEqualTo(newTitle); + assertThat(news.getContent()).isEqualTo(newContent); + assertThat(news.getVideo()).isEqualTo(newVideo); + } + + @Test + @DisplayName("업데이트시 제목이 null 혹은 공백인 경우 예외를 반환한다.") + void updateNewsTestWithInvalidTitle() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + String newContent = "This is the updated news content."; + Video newVideo = VideoFixture.createDefault(); + + try { + news.update(null, newVideo, newContent); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + news.update("", newVideo, newContent); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("업데이트시 영상이 null인 경우 예외를 반환한다.") + void updateNewsTestWithInvalidVideo() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + String newTitle = "Updated News Title"; + String newContent = "This is the updated news content."; + + try { + news.update(newTitle, null, newContent); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("업데이트시 내용이 null 혹은 공백인 경우 예외를 반환한다.") + void updateNewsTestWithInvalidContent() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + String newTitle = "Updated News Title"; + Video newVideo = VideoFixture.createDefault(); + + try { + news.update(newTitle, newVideo, null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + news.update(newTitle, newVideo, ""); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } + + @Test + @DisplayName("뉴스에 댓글을 추가할 수 있다.") + void addCommentTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + Comment comment = Comment.create(member, news, "This is a comment."); + news.addComment(comment); + + assertThat(news.getComment().size()).isEqualTo(1); + assertThat(news.getComment()).contains(comment); + } + + @Test + @DisplayName("뉴스에 null 댓글을 추가하려 하면 예외를 반환한다.") + void addNullCommentTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + try { + news.addComment(null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + assertThat(news.getComment().size()).isEqualTo(0); + } + + @Test + @DisplayName("뉴스의 댓글을 제거할 수 있다.") + void removeCommentTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + Comment comment = Comment.create(member, news, "This is a comment."); + news.addComment(comment); + assertThat(news.getComment().size()).isEqualTo(1); + + news.removeComment(comment); + assertThat(news.getComment().size()).isEqualTo(0); + } + @Test + @DisplayName("뉴스의 null 댓글을 제거하려하면 예외를 반환한다.") + void removeNullCommentTest() { + Member member = MemberFixture.createDefault(); + String title = "Sample News Title"; + String content = "This is a sample news content."; + Video video = VideoFixture.createDefault(); + News news = News.create(member, title, video, content); + + try { + news.removeComment(null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + assertThat(news.getComment().size()).isEqualTo(0); + } } \ No newline at end of file From c61a7d745979602ce52b28dd85cd5fac8a017494 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:22:37 +0900 Subject: [PATCH 28/66] =?UTF-8?q?Fix=20:=20News=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EB=A5=BC=20=ED=86=B5=ED=95=B4=20=EC=82=AD=EC=A0=9C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/back/domain/news/comment/entity/Comment.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java index 9c123f98..647255d6 100644 --- a/back/src/main/java/com/back/domain/news/comment/entity/Comment.java +++ b/back/src/main/java/com/back/domain/news/comment/entity/Comment.java @@ -55,8 +55,4 @@ public Comment update(String content) { this.content = content; return this; } - - public void remove() { - this.news.removeComment(this); - } } From a7e10d2d789546b9f8f07b21fa8c16f6bafbfbdc Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:22:59 +0900 Subject: [PATCH 29/66] =?UTF-8?q?Test=20:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/comment/entity/CommentTest.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java index ab9e89ef..24706b3a 100644 --- a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java +++ b/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java @@ -69,4 +69,39 @@ void commentCreationTestWithInvalidContent() { assertThat(e).isInstanceOf(IllegalArgumentException.class); } } + + @Test + @DisplayName("댓글 내용을 수정할 수 있다.") + void commentUpdateTest() { + Member member = MemberFixture.createDefault(); + News news = NewsFixture.createDefault(); + String content = "This is a sample comment content."; + Comment comment = Comment.create(member, news, content); + + String newContent = "This is the updated comment content."; + comment.update(newContent); + + assertThat(comment.getContent()).isEqualTo(newContent); + } + + @Test + @DisplayName("댓글 수정 시 내용이 null 혹은 공백인 경우 예외를 반환한다.") + void commentUpdateTestWithInvalidContent() { + Member member = MemberFixture.createDefault(); + News news = NewsFixture.createDefault(); + String content = "This is a sample comment content."; + Comment comment = Comment.create(member, news, content); + + try { + comment.update(null); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + + try { + comment.update(""); + } catch (Exception e) { + assertThat(e).isInstanceOf(IllegalArgumentException.class); + } + } } \ No newline at end of file From dafa8c741ec486865f3f6d08efae519eb6b4f343 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:24:52 +0900 Subject: [PATCH 30/66] =?UTF-8?q?Feat=20:=20file=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20Service,=20Repository=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/file/repository/VideoRepository.java | 7 +++++++ .../com/back/domain/file/service/VideoService.java | 11 +++++++++++ 2 files changed, 18 insertions(+) create mode 100644 back/src/main/java/com/back/domain/file/repository/VideoRepository.java create mode 100644 back/src/main/java/com/back/domain/file/service/VideoService.java diff --git a/back/src/main/java/com/back/domain/file/repository/VideoRepository.java b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java new file mode 100644 index 00000000..56c2eac8 --- /dev/null +++ b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java @@ -0,0 +1,7 @@ +package com.back.domain.file.repository; + +import org.springframework.stereotype.Repository; + +@Repository +public interface VideoRepository { +} diff --git a/back/src/main/java/com/back/domain/file/service/VideoService.java b/back/src/main/java/com/back/domain/file/service/VideoService.java new file mode 100644 index 00000000..2fc45cc9 --- /dev/null +++ b/back/src/main/java/com/back/domain/file/service/VideoService.java @@ -0,0 +1,11 @@ +package com.back.domain.file.service; + +import com.back.domain.file.repository.VideoRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class VideoService { + private final VideoRepository videoRepository; +} From f330c672360b76496472c1b94d5b9527b7540c41 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:26:14 +0900 Subject: [PATCH 31/66] =?UTF-8?q?Feat=20:=20comment=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20Service,=20Repository=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/comment/repository/CommentRepository.java | 7 +++++++ .../domain/news/comment/service/CommentService.java | 10 ++++++++++ 2 files changed, 17 insertions(+) create mode 100644 back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java create mode 100644 back/src/main/java/com/back/domain/news/comment/service/CommentService.java diff --git a/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java b/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java new file mode 100644 index 00000000..2b64b71b --- /dev/null +++ b/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java @@ -0,0 +1,7 @@ +package com.back.domain.news.comment.repository; + +import org.springframework.stereotype.Repository; + +@Repository +public interface CommentRepository { +} diff --git a/back/src/main/java/com/back/domain/news/comment/service/CommentService.java b/back/src/main/java/com/back/domain/news/comment/service/CommentService.java new file mode 100644 index 00000000..aa377645 --- /dev/null +++ b/back/src/main/java/com/back/domain/news/comment/service/CommentService.java @@ -0,0 +1,10 @@ +package com.back.domain.news.comment.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CommentService { + +} From d46cc1309b8444545d5bb2ae89ae11af616ef5c1 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:27:26 +0900 Subject: [PATCH 32/66] =?UTF-8?q?Feat=20:=20Like=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20Service,=20Repository=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../back/domain/news/like/repository/LikeRepository.java | 7 +++++++ .../com/back/domain/news/like/service/LikeService.java | 9 +++++++++ 2 files changed, 16 insertions(+) create mode 100644 back/src/main/java/com/back/domain/news/like/repository/LikeRepository.java create mode 100644 back/src/main/java/com/back/domain/news/like/service/LikeService.java diff --git a/back/src/main/java/com/back/domain/news/like/repository/LikeRepository.java b/back/src/main/java/com/back/domain/news/like/repository/LikeRepository.java new file mode 100644 index 00000000..2bfbae8a --- /dev/null +++ b/back/src/main/java/com/back/domain/news/like/repository/LikeRepository.java @@ -0,0 +1,7 @@ +package com.back.domain.news.like.repository; + +import org.springframework.stereotype.Repository; + +@Repository +public interface LikeRepository { +} diff --git a/back/src/main/java/com/back/domain/news/like/service/LikeService.java b/back/src/main/java/com/back/domain/news/like/service/LikeService.java new file mode 100644 index 00000000..36a41186 --- /dev/null +++ b/back/src/main/java/com/back/domain/news/like/service/LikeService.java @@ -0,0 +1,9 @@ +package com.back.domain.news.like.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LikeService { +} From 3aa9157e41430c09f3befdb09f0947a7aed0fead Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:37:29 +0900 Subject: [PATCH 33/66] =?UTF-8?q?Feat=20:=20NewsService=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/news/service/NewsService.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/back/src/main/java/com/back/domain/news/news/service/NewsService.java b/back/src/main/java/com/back/domain/news/news/service/NewsService.java index 3ae0c2f9..2080cbad 100644 --- a/back/src/main/java/com/back/domain/news/news/service/NewsService.java +++ b/back/src/main/java/com/back/domain/news/news/service/NewsService.java @@ -1,12 +1,42 @@ package com.back.domain.news.news.service; +import com.back.domain.file.entity.Video; +import com.back.domain.member.member.entity.Member; +import com.back.domain.news.news.entity.News; import com.back.domain.news.news.repository.NewsRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class NewsService { private final NewsRepository newsRepository; + + public News createNews(Member member, String title, Video video, String content) { + News news = News.create(member, title, video, content); + return newsRepository.save(news); + } + + public Page getNewsByPage(int page, int size) { + Pageable pageable = PageRequest.of(page, size, Sort.by("createDate").descending()); + return newsRepository.findAll(pageable); + } + + public News getNewsById(Integer id) { + return newsRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("뉴스를 찾을 수 없습니다.")); + } + + public void updateNews(News news, String title, Video video, String content) { + news.update(title, video, content); + newsRepository.save(news); + } + + public void deleteNews(News news) { + newsRepository.delete(news); + } } From 48abe96d014df835662f4256fabb65f431f569e4 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 15:48:03 +0900 Subject: [PATCH 34/66] =?UTF-8?q?Feat=20:=20News=EB=A1=9C=EB=B6=80?= =?UTF-8?q?=ED=84=B0=20Comment=EC=A0=91=EA=B7=BC=20=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=98=EA=B8=B0=EB=96=84=EB=AC=B8=EC=97=90=20=EA=B5=B3?= =?UTF-8?q?=EC=9D=B4=20=EC=9E=91=EC=84=B1=20=EC=95=88=ED=95=B4=EB=8F=84=20?= =?UTF-8?q?=EB=90=A0=20=EA=B2=83=20=EA=B0=99=EB=8B=A4,=20=EB=8B=A4?= =?UTF-8?q?=EB=A7=8C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=EB=8A=94=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=ED=95=98=EB=8A=94=EA=B2=83=EC=9D=B4=20?= =?UTF-8?q?=EC=A2=8B=EB=8B=A4=EB=8A=94=20=EA=B0=95=EC=82=AC=EB=8B=98=20?= =?UTF-8?q?=EC=9D=98=EA=B2=AC=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/comment/repository/CommentRepository.java | 7 ------- .../domain/news/comment/service/CommentService.java | 10 ---------- 2 files changed, 17 deletions(-) delete mode 100644 back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java delete mode 100644 back/src/main/java/com/back/domain/news/comment/service/CommentService.java diff --git a/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java b/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java deleted file mode 100644 index 2b64b71b..00000000 --- a/back/src/main/java/com/back/domain/news/comment/repository/CommentRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.back.domain.news.comment.repository; - -import org.springframework.stereotype.Repository; - -@Repository -public interface CommentRepository { -} diff --git a/back/src/main/java/com/back/domain/news/comment/service/CommentService.java b/back/src/main/java/com/back/domain/news/comment/service/CommentService.java deleted file mode 100644 index aa377645..00000000 --- a/back/src/main/java/com/back/domain/news/comment/service/CommentService.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.back.domain.news.comment.service; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class CommentService { - -} From 003d85c647c2f8adcdf610aa995edef15bf16c65 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 16:04:26 +0900 Subject: [PATCH 35/66] =?UTF-8?q?Feat=20:=20JpaRepository=20=EC=83=81?= =?UTF-8?q?=EC=86=8D=EB=B0=9B=EB=8F=84=EB=A1=9D=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/back/domain/file/repository/VideoRepository.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/back/src/main/java/com/back/domain/file/repository/VideoRepository.java b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java index 56c2eac8..9fa9df8e 100644 --- a/back/src/main/java/com/back/domain/file/repository/VideoRepository.java +++ b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java @@ -1,7 +1,9 @@ package com.back.domain.file.repository; +import com.back.domain.file.entity.Video; +import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository -public interface VideoRepository { +public interface VideoRepository extends JpaRepository { } From 68b8c59a856cfc6dc86710e3cf47ba0941750fbd Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 17:11:14 +0900 Subject: [PATCH 36/66] =?UTF-8?q?Feat=20:=20S3=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=EC=A0=84=20=EB=AA=A8=ED=82=B9=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?MiniO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..80a2439a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.8" + +services: + minio: + image: quay.io/minio/minio:latest + container_name: minio + ports: + - "9000:9000" # S3 API + - "9001:9001" # Web Console + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + volumes: + - minio-data:/data + command: server /data --console-address ":9001" + +volumes: + minio-data: From 6d3e75d0847a199d7eb6620466353bac0e21bea8 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Fri, 19 Sep 2025 17:22:58 +0900 Subject: [PATCH 37/66] =?UTF-8?q?Feat=20:=20=ED=8C=8C=EC=9D=BC=20=EB=8B=A4?= =?UTF-8?q?=EC=9A=B4=EB=A1=9C=EB=93=9C=EB=A5=BC=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B0=8F=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/build.gradle.kts | 2 + .../domain/file/service/VideoService.java | 37 +++++++++++++++++++ .../java/com/back/global/app/S3Config.java | 25 +++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 back/src/main/java/com/back/global/app/S3Config.java diff --git a/back/build.gradle.kts b/back/build.gradle.kts index 7796c035..bb9030b8 100644 --- a/back/build.gradle.kts +++ b/back/build.gradle.kts @@ -43,6 +43,8 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.springframework.security:spring-security-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + implementation ("software.amazon.awssdk:s3:2.25.0") } tasks.withType { diff --git a/back/src/main/java/com/back/domain/file/service/VideoService.java b/back/src/main/java/com/back/domain/file/service/VideoService.java index 2fc45cc9..ed07f5d5 100644 --- a/back/src/main/java/com/back/domain/file/service/VideoService.java +++ b/back/src/main/java/com/back/domain/file/service/VideoService.java @@ -3,9 +3,46 @@ import com.back.domain.file.repository.VideoRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; +import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; +import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest; + +import java.net.URL; +import java.time.Duration; @Service @RequiredArgsConstructor public class VideoService { private final VideoRepository videoRepository; + private final S3Presigner presigner; + + public URL generateUploadUrl(String bucket, String objectKey) { + PutObjectRequest request = PutObjectRequest.builder() + .bucket(bucket) + .key(objectKey) + .build(); + + PresignedPutObjectRequest presignedRequest = + presigner.presignPutObject(builder -> builder + .signatureDuration(Duration.ofMinutes(5)) + .putObjectRequest(request)); + + return presignedRequest.url(); + } + + public URL generateDownloadUrl(String bucket, String objectKey) { + GetObjectRequest request = GetObjectRequest.builder() + .bucket(bucket) + .key(objectKey) + .build(); + + PresignedGetObjectRequest presignedRequest = + presigner.presignGetObject(builder -> builder + .signatureDuration(Duration.ofMinutes(5)) + .getObjectRequest(request)); + + return presignedRequest.url(); + } } diff --git a/back/src/main/java/com/back/global/app/S3Config.java b/back/src/main/java/com/back/global/app/S3Config.java new file mode 100644 index 00000000..20e0257c --- /dev/null +++ b/back/src/main/java/com/back/global/app/S3Config.java @@ -0,0 +1,25 @@ +package com.back.global.app; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.presigner.S3Presigner; + +@Configuration +public class S3Config { + + @Bean + public S3Presigner s3Presigner() { + return S3Presigner.builder() + .credentialsProvider( + StaticCredentialsProvider.create( + AwsBasicCredentials.create("minioadmin", "minioadmin") // FIXME : MinIO 아이디, 비밀번호 이후 변경 + ) + ) + .endpointOverride(java.net.URI.create("http://localhost:9000")) // FIXME : MinIO 엔드포인트 이후 변경 + .region(Region.AP_SOUTHEAST_1) // FIXME : 이후 리전따라 변경 + .build(); + } +} From 20726d1a47c0c4eb9fded970099b3e0a56e27e61 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Sat, 20 Sep 2025 16:26:46 +0900 Subject: [PATCH 38/66] =?UTF-8?q?Feat=20:=20=EB=A9=94=ED=83=80=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=A0=80=EC=9E=A5=ED=95=A0=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20createVideo,=20Dash=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=EC=9A=A9=20=EB=A9=94=EC=84=9C=EB=93=9C=20gen?= =?UTF-8?q?erateDashUrls()=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/file/service/VideoService.java | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/back/src/main/java/com/back/domain/file/service/VideoService.java b/back/src/main/java/com/back/domain/file/service/VideoService.java index ed07f5d5..a1d804a8 100644 --- a/back/src/main/java/com/back/domain/file/service/VideoService.java +++ b/back/src/main/java/com/back/domain/file/service/VideoService.java @@ -1,5 +1,6 @@ package com.back.domain.file.service; +import com.back.domain.file.entity.Video; import com.back.domain.file.repository.VideoRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -11,6 +12,10 @@ import java.net.URL; import java.time.Duration; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -18,6 +23,12 @@ public class VideoService { private final VideoRepository videoRepository; private final S3Presigner presigner; + public Video createVideo(String transcodingStatus, String originalPath, String originalFilename, Integer duration, Long fileSize) { + String uuid = UUID.randomUUID().toString(); + Video video = Video.create(uuid, transcodingStatus, originalPath, originalFilename, duration, fileSize); + return videoRepository.save(video); + } + public URL generateUploadUrl(String bucket, String objectKey) { PutObjectRequest request = PutObjectRequest.builder() .bucket(bucket) @@ -26,7 +37,7 @@ public URL generateUploadUrl(String bucket, String objectKey) { PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(builder -> builder - .signatureDuration(Duration.ofMinutes(5)) + .signatureDuration(Duration.ofMinutes(30)) .putObjectRequest(request)); return presignedRequest.url(); @@ -40,9 +51,23 @@ public URL generateDownloadUrl(String bucket, String objectKey) { PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(builder -> builder - .signatureDuration(Duration.ofMinutes(5)) + .signatureDuration(Duration.ofHours(1)) // 스트리밍 중 끊기지 않게 충분히 .getObjectRequest(request)); return presignedRequest.url(); } + + // DASH용 인덱스 + 세그먼트 URL 발급 + public Map generateDashUrls(String bucket, String mpdFile, List segmentFiles) { + // MPD 파일 URL + URL mpdUrl = generateDownloadUrl(bucket, mpdFile); + + // 각 세그먼트 파일 URL + Map segmentUrls = segmentFiles.stream() + .collect(Collectors.toMap(f -> f, f -> generateDownloadUrl(bucket, f))); + + // MPD 포함 합쳐서 반환 + segmentUrls.put("mpd", mpdUrl); + return segmentUrls; + } } From 48e2fc441931c7df371e99862b0c1b78eb859d58 Mon Sep 17 00:00:00 2001 From: jiseopshin Date: Sat, 20 Sep 2025 17:05:07 +0900 Subject: [PATCH 39/66] =?UTF-8?q?Feat=20:=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/domain/file/repository/VideoRepository.java | 3 +++ .../main/java/com/back/domain/file/service/VideoService.java | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/back/src/main/java/com/back/domain/file/repository/VideoRepository.java b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java index 9fa9df8e..02e6431e 100644 --- a/back/src/main/java/com/back/domain/file/repository/VideoRepository.java +++ b/back/src/main/java/com/back/domain/file/repository/VideoRepository.java @@ -4,6 +4,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.Optional; + @Repository public interface VideoRepository extends JpaRepository { + Optional