From 821c7bf524b78ecd9a6fd79dd1db9762132de3c1 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Tue, 12 Dec 2023 13:56:48 +0900
Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=EC=8A=A4=ED=82=A4=EB=A7=88=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20baseEntity=20=EB=B6=84?=
 =?UTF-8?q?=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../nextstep/courses/domain/BaseEntity.java   |   9 ++
 .../java/nextstep/courses/domain/Course.java  |   6 +-
 .../java/nextstep/courses/domain/Session.java |   4 +-
 src/main/resources/schema.sql                 | 102 ++++++++++++------
 .../nextstep/courses/domain/SessionTest.java  |  10 +-
 5 files changed, 90 insertions(+), 41 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/domain/BaseEntity.java

diff --git a/src/main/java/nextstep/courses/domain/BaseEntity.java b/src/main/java/nextstep/courses/domain/BaseEntity.java
new file mode 100644
index 000000000..6b61a1487
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/BaseEntity.java
@@ -0,0 +1,9 @@
+package nextstep.courses.domain;
+
+import java.time.LocalDateTime;
+
+public class BaseEntity {
+    LocalDateTime createdAt;
+
+    LocalDateTime updatedAt;
+}
diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java
index 0f6971604..68e5cf935 100644
--- a/src/main/java/nextstep/courses/domain/Course.java
+++ b/src/main/java/nextstep/courses/domain/Course.java
@@ -2,17 +2,13 @@
 
 import java.time.LocalDateTime;
 
-public class Course {
+public class Course extends BaseEntity{
     private Long id;
 
     private String title;
 
     private Long creatorId;
 
-    private LocalDateTime createdAt;
-
-    private LocalDateTime updatedAt;
-
     public Course() {
     }
 
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 99e79af17..b37ef5975 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -8,7 +8,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public abstract class Session {
+public abstract class Session extends BaseEntity{
     final Long id;
     final Course course;
     final SessionCover sessionCover;
@@ -21,6 +21,8 @@ public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
         this.course = course;
+        this.createdAt = LocalDateTime.now();
+        this.updatedAt = LocalDateTime.now();
     }
 
     public abstract void enroll(NsUser participant, Long amount);
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 8d5a988c8..cc25ed776 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -1,50 +1,92 @@
-create table course (
-    id bigint generated by default as identity,
-    title varchar(255) not null,
-    creator_id bigint not null,
-    created_at timestamp not null,
+create table course
+(
+    id         bigint generated by default as identity,
+    title      varchar(255) not null,
+    creator_id bigint       not null,
+    created_at timestamp    not null,
     updated_at timestamp,
     primary key (id)
 );
 
-create table ns_user (
-    id bigint generated by default as identity,
-    user_id varchar(20) not null,
-    password varchar(20) not null,
-    name varchar(20) not null,
-    email varchar(50),
-    created_at timestamp not null,
+create table session
+(
+    id              bigint generated by default as identity,
+    begin_dt        timestamp,
+    end_dt          timestamp,
+    session_status  varchar(10),
+    capacity        bigint,
+    price           bigint,
+    course_id       bigint not null,
+    registration_id bigint,
+    created_at      timestamp,
+    updated_at      timestamp,
+    primary key (id)
+);
+
+create table registration
+(
+    id         bigint generated by default as identity,
+    session_id bigint not null,
+    ns_user_id bigint,
+    amount     bigint,
+    created_at timestamp,
     updated_at timestamp,
     primary key (id)
 );
 
-create table question (
-    id bigint generated by default as identity,
-    created_at timestamp not null,
+create table session_cover
+(
+    id         bigint generated by default as identity,
+    session_id bigint not null,
+    image      blob,
+    created_at timestamp,
     updated_at timestamp,
-    contents clob,
-    deleted boolean not null,
-    title varchar(100) not null,
-    writer_id bigint,
     primary key (id)
 );
 
-create table answer (
-    id bigint generated by default as identity,
-    created_at timestamp not null,
+
+create table ns_user
+(
+    id         bigint generated by default as identity,
+    user_id    varchar(20) not null,
+    password   varchar(20) not null,
+    name       varchar(20) not null,
+    email      varchar(50),
+    created_at timestamp   not null,
     updated_at timestamp,
-    contents clob,
-    deleted boolean not null,
+    primary key (id)
+);
+
+create table question
+(
+    id         bigint generated by default as identity,
+    created_at timestamp    not null,
+    updated_at timestamp,
+    contents   clob,
+    deleted    boolean      not null,
+    title      varchar(100) not null,
+    writer_id  bigint,
+    primary key (id)
+);
+
+create table answer
+(
+    id          bigint generated by default as identity,
+    created_at  timestamp not null,
+    updated_at  timestamp,
+    contents    clob,
+    deleted     boolean   not null,
     question_id bigint,
-    writer_id bigint,
+    writer_id   bigint,
     primary key (id)
 );
 
-create table delete_history (
-    id bigint not null,
-    content_id bigint,
-    content_type varchar(255),
-    created_date timestamp,
+create table delete_history
+(
+    id            bigint not null,
+    content_id    bigint,
+    content_type  varchar(255),
+    created_date  timestamp,
     deleted_by_id bigint,
     primary key (id)
 );
diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java
index c3ad572ca..77c452e22 100644
--- a/src/test/java/nextstep/courses/domain/SessionTest.java
+++ b/src/test/java/nextstep/courses/domain/SessionTest.java
@@ -13,7 +13,7 @@ class SessionTest {
 
     @Test
     void 무료강의생성() {
-        Session freeSession = new FreeSession(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, null), new Course());
+        Session freeSession = new FreeSession(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
         assertThat(freeSession.id).isEqualTo(1L);
     }
 
@@ -23,13 +23,13 @@ class SessionTest {
         int sessionCapacity = 100;
 
         Session paidSession = new PaidSession(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, null), new Course(), sessionCapacity, sessionPrice);
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), sessionCapacity, sessionPrice);
         assertThat(paidSession.id).isEqualTo(2L);
     }
 
     @Test
     void 수강신청상태_exception() {
-        Session session = new FreeSession(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, null), new Course());
+        Session session = new FreeSession(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
         assertThatExceptionOfType(BusinessInvalidValueException.class)
                 .isThrownBy(() -> session.enroll(new NsUser(), 0L))
                 .withMessage("수강신청 가능한 상태가 아닙니다.");
@@ -38,7 +38,7 @@ class SessionTest {
     @Test
     void 최대수강인원_exception() {
         Session paidSession = new PaidSession(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, null), new Course(), 0, 1_000_000L);
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 0, 1_000_000L);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)
@@ -49,7 +49,7 @@ class SessionTest {
     @Test
     void 가격비교_exception() {
         Session paidSession = new PaidSession(4L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, null), new Course(), 10, 1_000_000L);
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10, 1_000_000L);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)

From 53740e30814598632b446b83d49f7cd3b89e7502 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Tue, 12 Dec 2023 14:00:05 +0900
Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=EA=B8=B0=EC=88=98=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

---
 .../courses/domain/{Symester.java => Semester.java}      | 4 ++--
 src/main/resources/schema.sql                            | 9 +++++++++
 2 files changed, 11 insertions(+), 2 deletions(-)
 rename src/main/java/nextstep/courses/domain/{Symester.java => Semester.java} (63%)

diff --git a/src/main/java/nextstep/courses/domain/Symester.java b/src/main/java/nextstep/courses/domain/Semester.java
similarity index 63%
rename from src/main/java/nextstep/courses/domain/Symester.java
rename to src/main/java/nextstep/courses/domain/Semester.java
index e9963f91f..1a3f71c48 100644
--- a/src/main/java/nextstep/courses/domain/Symester.java
+++ b/src/main/java/nextstep/courses/domain/Semester.java
@@ -1,9 +1,9 @@
 package nextstep.courses.domain;
 
-public class Symester {
+public class Semester {
     private final Course course;
 
-    public Symester(Course course) {
+    public Semester(Course course) {
         this.course = course;
     }
 }
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index cc25ed776..71c2b7a2c 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -8,6 +8,15 @@ create table course
     primary key (id)
 );
 
+create table semester
+(
+    id         bigint generated by default as identity,
+    course_id  bigint not null,
+    created_at timestamp not null,
+    updated_at timestamp,
+    primary key (id)
+);
+
 create table session
 (
     id              bigint generated by default as identity,

From b83b6cad7ff41d685dc63487a197e6f060d70eff Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Tue, 12 Dec 2023 14:00:55 +0900
Subject: [PATCH 03/15] =?UTF-8?q?feat:=20baseEntity=20=EC=83=81=EC=86=8D?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/nextstep/courses/domain/Semester.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/nextstep/courses/domain/Semester.java b/src/main/java/nextstep/courses/domain/Semester.java
index 1a3f71c48..a8dbd85e2 100644
--- a/src/main/java/nextstep/courses/domain/Semester.java
+++ b/src/main/java/nextstep/courses/domain/Semester.java
@@ -1,6 +1,6 @@
 package nextstep.courses.domain;
 
-public class Semester {
+public class Semester extends BaseEntity{
     private final Course course;
 
     public Semester(Course course) {

From cb25131962d016bbdeb5f41623f2a41e9b3f368d Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Tue, 12 Dec 2023 15:17:22 +0900
Subject: [PATCH 04/15] =?UTF-8?q?feat:=20=EC=83=81=EC=86=8D=20=EC=9B=90?=
 =?UTF-8?q?=EB=B3=B5=20=EB=B0=8F=20session=20=ED=81=B4=EB=9E=98=EC=8A=A4?=
 =?UTF-8?q?=20=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../nextstep/courses/domain/Capacity.java     | 22 ++++++++
 .../nextstep/courses/domain/FreeSession.java  | 18 -------
 .../nextstep/courses/domain/PaidSession.java  | 45 -----------------
 .../java/nextstep/courses/domain/Price.java   | 21 ++++++++
 .../java/nextstep/courses/domain/Session.java | 50 ++++++++++++++-----
 .../nextstep/courses/domain/SessionTest.java  | 20 ++++----
 6 files changed, 91 insertions(+), 85 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/domain/Capacity.java
 delete mode 100644 src/main/java/nextstep/courses/domain/FreeSession.java
 delete mode 100644 src/main/java/nextstep/courses/domain/PaidSession.java
 create mode 100644 src/main/java/nextstep/courses/domain/Price.java

diff --git a/src/main/java/nextstep/courses/domain/Capacity.java b/src/main/java/nextstep/courses/domain/Capacity.java
new file mode 100644
index 000000000..0cc606ab2
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/Capacity.java
@@ -0,0 +1,22 @@
+package nextstep.courses.domain;
+
+import nextstep.courses.exception.BusinessInvalidValueException;
+
+public class Capacity {
+    private final int capacity;
+
+    public Capacity(int capacity) {
+        this.capacity = capacity;
+    }
+
+    public void validateCapacity(int count) {
+        if (count >= capacity) {
+            throw new BusinessInvalidValueException("최대수강인원을 초과했습니다.");
+        }
+    }
+
+    public int capacity() {
+         return capacity;
+    }
+}
+
diff --git a/src/main/java/nextstep/courses/domain/FreeSession.java b/src/main/java/nextstep/courses/domain/FreeSession.java
deleted file mode 100644
index 8ae90c460..000000000
--- a/src/main/java/nextstep/courses/domain/FreeSession.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package nextstep.courses.domain;
-
-import nextstep.users.domain.NsUser;
-
-import java.time.LocalDateTime;
-
-public class FreeSession extends Session {
-
-    public FreeSession(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
-        super(id, beginDt, endDt, sessionCover, course);
-    }
-
-    @Override
-    public void enroll(NsUser participant, Long amount) {
-        validateStatus();
-        this.participants.add(participant);
-    }
-}
diff --git a/src/main/java/nextstep/courses/domain/PaidSession.java b/src/main/java/nextstep/courses/domain/PaidSession.java
deleted file mode 100644
index 195b646f5..000000000
--- a/src/main/java/nextstep/courses/domain/PaidSession.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package nextstep.courses.domain;
-
-import nextstep.courses.exception.BusinessInvalidValueException;
-import nextstep.users.domain.NsUser;
-
-import java.time.LocalDateTime;
-
-public class PaidSession extends Session {
-    private final int capacity;
-    private final long price;
-
-    public PaidSession(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, int capacity, long price) {
-        super(id, beginDt, endDt, sessionCover, course);
-        this.capacity = capacity;
-        this.price = price;
-    }
-
-    @Override
-    public void enroll(NsUser participant, Long amount) {
-        validateCapacity();
-        validatePrice(amount);
-        validateStatus();
-        this.participants.add(participant);
-    }
-
-    private void validateCapacity() {
-        if (this.participants.size() >= capacity) {
-            throw new BusinessInvalidValueException("최대수강인원을 초과했습니다.");
-        }
-    }
-
-    private void validatePrice(long price) {
-        if (this.price != price) {
-            throw new BusinessInvalidValueException("강의 가격이 변동되었습니다.");
-        }
-    }
-
-    public long price() {
-        return price;
-    }
-
-    public int capacity() {
-        return capacity;
-    }
-}
diff --git a/src/main/java/nextstep/courses/domain/Price.java b/src/main/java/nextstep/courses/domain/Price.java
new file mode 100644
index 000000000..c87140dd0
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/Price.java
@@ -0,0 +1,21 @@
+package nextstep.courses.domain;
+
+import nextstep.courses.exception.BusinessInvalidValueException;
+
+public class Price {
+    private final long price;
+
+    public Price(long price) {
+        this.price = price;
+    }
+
+    public void validatePrice(long price) {
+        if (this.price != price) {
+            throw new BusinessInvalidValueException("강의 가격이 변동되었습니다.");
+        }
+    }
+
+    public long price() {
+        return price;
+    }
+}
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index b37ef5975..92c7c2824 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -8,24 +8,35 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public abstract class Session extends BaseEntity{
-    final Long id;
-    final Course course;
-    final SessionCover sessionCover;
-    final Period period;
-    SessionStatus status = SessionStatus.PREPARE;
-    final List<NsUser> participants = new ArrayList<>();
-
-    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
+public class Session extends BaseEntity{
+    public static long FREE_PRICE = 0L;
+    public static int MAX_CAPACITY = Integer.MAX_VALUE;
+    private final Long id;
+    private final Course course;
+    private final SessionCover sessionCover;
+    private final Period period;
+    private final Capacity capacity;
+    private final Price price;
+
+    private SessionStatus status = SessionStatus.PREPARE;
+    private final List<NsUser> participants = new ArrayList<>();
+
+    private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
         this.course = course;
-        this.createdAt = LocalDateTime.now();
-        this.updatedAt = LocalDateTime.now();
+        this.capacity = capacity;
+        this.price = price;
+    }
+
+    public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
+        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(MAX_CAPACITY), new Price(FREE_PRICE));
     }
 
-    public abstract void enroll(NsUser participant, Long amount);
+    public static Session ofPaid(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Long price, Integer capacity) {
+        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(capacity), new Price(price));
+    }
 
     public void startEnrollment() {
         this.status = SessionStatus.ENROLL;
@@ -37,6 +48,21 @@ public void validateStatus() {
         }
     }
 
+    public void enroll(NsUser participant, Long amount) {
+        capacity.validateCapacity(participants.size());
+        price.validatePrice(amount);
+        validateStatus();
+        this.participants.add(participant);
+    }
+
+    public Price price() {
+        return price;
+    }
+
+    public Capacity capacity() {
+        return capacity;
+    }
+
     public Long id() {
         return id;
     }
diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java
index 77c452e22..47f04dd38 100644
--- a/src/test/java/nextstep/courses/domain/SessionTest.java
+++ b/src/test/java/nextstep/courses/domain/SessionTest.java
@@ -13,8 +13,8 @@ class SessionTest {
 
     @Test
     void 무료강의생성() {
-        Session freeSession = new FreeSession(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
-        assertThat(freeSession.id).isEqualTo(1L);
+        Session freeSession = Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
+        assertThat(freeSession.id()).isEqualTo(1L);
     }
 
     @Test
@@ -22,14 +22,14 @@ class SessionTest {
         long sessionPrice = 1_000_000L;
         int sessionCapacity = 100;
 
-        Session paidSession = new PaidSession(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), sessionCapacity, sessionPrice);
-        assertThat(paidSession.id).isEqualTo(2L);
+        Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), sessionPrice, sessionCapacity);
+        assertThat(paidSession.id()).isEqualTo(2L);
     }
 
     @Test
     void 수강신청상태_exception() {
-        Session session = new FreeSession(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
+        Session session = Session.ofFree(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
         assertThatExceptionOfType(BusinessInvalidValueException.class)
                 .isThrownBy(() -> session.enroll(new NsUser(), 0L))
                 .withMessage("수강신청 가능한 상태가 아닙니다.");
@@ -37,8 +37,8 @@ class SessionTest {
 
     @Test
     void 최대수강인원_exception() {
-        Session paidSession = new PaidSession(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 0, 1_000_000L);
+        Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10000L, 0);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)
@@ -48,8 +48,8 @@ class SessionTest {
 
     @Test
     void 가격비교_exception() {
-        Session paidSession = new PaidSession(4L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10, 1_000_000L);
+        Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
+                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10000L, 1);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)

From 40b28a57a6af151f9b967b34cdea38fe3b92b047 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Wed, 13 Dec 2023 14:03:27 +0900
Subject: [PATCH 05/15] =?UTF-8?q?feat:=20db=20=EB=A7=A4=ED=95=91=EC=9D=84?=
 =?UTF-8?q?=20=EC=9C=84=ED=95=9C=20=EC=A4=80=EB=B9=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/nextstep/courses/domain/Course.java  |  4 +++
 .../java/nextstep/courses/domain/Period.java  |  8 +++++
 .../java/nextstep/courses/domain/Session.java | 30 +++++++++++++++++--
 .../nextstep/courses/domain/SessionCover.java | 13 +++++++-
 .../java/nextstep/courses/utils/DateUtil.java | 13 ++++++++
 .../courses/utils/RasterProcessor.java        |  2 +-
 .../courses/utils/VectorProcessor.java        |  2 +-
 .../nextstep/courses/domain/SessionTest.java  | 10 +++----
 8 files changed, 72 insertions(+), 10 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/utils/DateUtil.java

diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java
index 68e5cf935..8ea1be510 100644
--- a/src/main/java/nextstep/courses/domain/Course.java
+++ b/src/main/java/nextstep/courses/domain/Course.java
@@ -24,6 +24,10 @@ public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, Lo
         this.updatedAt = updatedAt;
     }
 
+    public Long id() {
+        return id;
+    }
+
     public String getTitle() {
         return title;
     }
diff --git a/src/main/java/nextstep/courses/domain/Period.java b/src/main/java/nextstep/courses/domain/Period.java
index 4a24dacf9..219b3c412 100644
--- a/src/main/java/nextstep/courses/domain/Period.java
+++ b/src/main/java/nextstep/courses/domain/Period.java
@@ -10,4 +10,12 @@ public Period(LocalDateTime beginDt, LocalDateTime endDt) {
         this.beginDt = beginDt;
         this.endDt = endDt;
     }
+
+    public LocalDateTime getBeginDt() {
+        return beginDt;
+    }
+
+    public LocalDateTime getEndDt() {
+        return endDt;
+    }
 }
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 92c7c2824..8e46a7cd6 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -8,7 +8,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-public class Session extends BaseEntity{
+public class Session extends BaseEntity {
     public static long FREE_PRICE = 0L;
     public static int MAX_CAPACITY = Integer.MAX_VALUE;
     private final Long id;
@@ -21,7 +21,7 @@ public class Session extends BaseEntity{
     private SessionStatus status = SessionStatus.PREPARE;
     private final List<NsUser> participants = new ArrayList<>();
 
-    private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
+    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
@@ -30,6 +30,16 @@ private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCove
         this.price = price;
     }
 
+    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, SessionCover sessionCover, Capacity capacity, Price price, Course course) {
+        this.id = id;
+        this.period = new Period(beginDt, endDt);
+        this.status = status;
+        this.sessionCover = sessionCover;
+        this.course = course;
+        this.capacity = capacity;
+        this.price = price;
+    }
+
     public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
         return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(MAX_CAPACITY), new Price(FREE_PRICE));
     }
@@ -66,4 +76,20 @@ public Capacity capacity() {
     public Long id() {
         return id;
     }
+
+    public Period period() {
+        return period;
+    }
+
+    public Course course() {
+        return course;
+    }
+
+    public SessionCover sessionCover() {
+        return sessionCover;
+    }
+
+    public String status() {
+        return this.status.name();
+    }
 }
diff --git a/src/main/java/nextstep/courses/domain/SessionCover.java b/src/main/java/nextstep/courses/domain/SessionCover.java
index 3f2822d5e..a919a4ef0 100644
--- a/src/main/java/nextstep/courses/domain/SessionCover.java
+++ b/src/main/java/nextstep/courses/domain/SessionCover.java
@@ -2,9 +2,16 @@
 
 public class SessionCover {
     public static final double RATIO = (double) 3 / 2;
+
+    private Long id;
     private final byte[] image;
 
-    public SessionCover(int width, int height, long size, byte[] image) {
+    public SessionCover(Long id, byte[] image) {
+        this.id = id;
+        this.image = image;
+    }
+
+    public SessionCover(long id, int width, int height, long size, byte[] image) {
         validateSize(size);
         validatePixel(width, height);
         validateRatio(width, height);
@@ -35,4 +42,8 @@ private static void validateRatio(int width, int height) {
     public byte[] image() {
         return image;
     }
+
+    public Long id() {
+        return id;
+    }
 }
diff --git a/src/main/java/nextstep/courses/utils/DateUtil.java b/src/main/java/nextstep/courses/utils/DateUtil.java
new file mode 100644
index 000000000..0d5b91174
--- /dev/null
+++ b/src/main/java/nextstep/courses/utils/DateUtil.java
@@ -0,0 +1,13 @@
+package nextstep.courses.utils;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+
+public class DateUtil {
+    public static LocalDateTime toLocalDateTime(Timestamp timestamp) {
+        if (timestamp == null) {
+            return null;
+        }
+        return timestamp.toLocalDateTime();
+    }
+}
diff --git a/src/main/java/nextstep/courses/utils/RasterProcessor.java b/src/main/java/nextstep/courses/utils/RasterProcessor.java
index 7462317cb..4373d6fa2 100644
--- a/src/main/java/nextstep/courses/utils/RasterProcessor.java
+++ b/src/main/java/nextstep/courses/utils/RasterProcessor.java
@@ -18,7 +18,7 @@ public SessionCover processImage(File file) throws IOException {
             throw new FileNotFoundException("Invalid image file.");
         }
 
-        return new SessionCover(image.getWidth(), image.getHeight(), file.length(), writeRasterImage(image));
+        return new SessionCover(2L, image.getWidth(), image.getHeight(), file.length(), writeRasterImage(image));
     }
 
     private static byte[] writeRasterImage(BufferedImage image) throws IOException {
diff --git a/src/main/java/nextstep/courses/utils/VectorProcessor.java b/src/main/java/nextstep/courses/utils/VectorProcessor.java
index 855b896ff..a447b4e0a 100644
--- a/src/main/java/nextstep/courses/utils/VectorProcessor.java
+++ b/src/main/java/nextstep/courses/utils/VectorProcessor.java
@@ -17,7 +17,7 @@ public class VectorProcessor implements ImageProcessor {
     @Override
     public SessionCover processImage(File file) throws IOException {
         Element svgRoot = parseXML(file);
-        return new SessionCover(parseInt(svgRoot.getAttribute("width")), parseInt(svgRoot.getAttribute("height")), file.length(), writeVectorImage(file));
+        return new SessionCover(1L, parseInt(svgRoot.getAttribute("width")), parseInt(svgRoot.getAttribute("height")), file.length(), writeVectorImage(file));
     }
 
     private int parseInt(String pixel) {
diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java
index 47f04dd38..a474250c7 100644
--- a/src/test/java/nextstep/courses/domain/SessionTest.java
+++ b/src/test/java/nextstep/courses/domain/SessionTest.java
@@ -13,7 +13,7 @@ class SessionTest {
 
     @Test
     void 무료강의생성() {
-        Session freeSession = Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
+        Session freeSession = Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(3L, 300, 200, 1024, new byte[100]), new Course());
         assertThat(freeSession.id()).isEqualTo(1L);
     }
 
@@ -23,13 +23,13 @@ class SessionTest {
         int sessionCapacity = 100;
 
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), sessionPrice, sessionCapacity);
+                new SessionCover(4L, 300, 200, 1024, new byte[100]), new Course(), sessionPrice, sessionCapacity);
         assertThat(paidSession.id()).isEqualTo(2L);
     }
 
     @Test
     void 수강신청상태_exception() {
-        Session session = Session.ofFree(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(300, 200, 1024, new byte[100]), new Course());
+        Session session = Session.ofFree(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(5L, 300, 200, 1024, new byte[100]), new Course());
         assertThatExceptionOfType(BusinessInvalidValueException.class)
                 .isThrownBy(() -> session.enroll(new NsUser(), 0L))
                 .withMessage("수강신청 가능한 상태가 아닙니다.");
@@ -38,7 +38,7 @@ class SessionTest {
     @Test
     void 최대수강인원_exception() {
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10000L, 0);
+                new SessionCover(6L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 0);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)
@@ -49,7 +49,7 @@ class SessionTest {
     @Test
     void 가격비교_exception() {
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(300, 200, 1024, new byte[100]), new Course(), 10000L, 1);
+                new SessionCover(7L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 1);
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)

From e6385aa23581db75b6a7208de5cc0af21679d22d Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Wed, 13 Dec 2023 15:01:00 +0900
Subject: [PATCH 06/15] =?UTF-8?q?feat:=20session=5Fcover=20DB=20=EC=97=B0?=
 =?UTF-8?q?=EA=B2=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../nextstep/courses/domain/BaseEntity.java   |  8 ++++
 .../nextstep/courses/domain/SessionCover.java | 13 ++++++-
 .../domain/SessionCoverRepository.java        |  7 ++++
 .../JdbcSessionCoverRepository.java           | 38 +++++++++++++++++++
 src/main/resources/schema.sql                 | 24 ++++++------
 .../SessionCoverRepositoryTest.java           | 22 +++++++++++
 6 files changed, 98 insertions(+), 14 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/domain/SessionCoverRepository.java
 create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
 create mode 100644 src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java

diff --git a/src/main/java/nextstep/courses/domain/BaseEntity.java b/src/main/java/nextstep/courses/domain/BaseEntity.java
index 6b61a1487..74f2b215d 100644
--- a/src/main/java/nextstep/courses/domain/BaseEntity.java
+++ b/src/main/java/nextstep/courses/domain/BaseEntity.java
@@ -6,4 +6,12 @@ public class BaseEntity {
     LocalDateTime createdAt;
 
     LocalDateTime updatedAt;
+
+    public LocalDateTime createdAt() {
+        return createdAt;
+    }
+
+    public LocalDateTime updatedAt() {
+        return updatedAt;
+    }
 }
diff --git a/src/main/java/nextstep/courses/domain/SessionCover.java b/src/main/java/nextstep/courses/domain/SessionCover.java
index a919a4ef0..e473a18f3 100644
--- a/src/main/java/nextstep/courses/domain/SessionCover.java
+++ b/src/main/java/nextstep/courses/domain/SessionCover.java
@@ -1,14 +1,23 @@
 package nextstep.courses.domain;
 
-public class SessionCover {
+import java.time.LocalDateTime;
+
+public class SessionCover extends BaseEntity{
     public static final double RATIO = (double) 3 / 2;
 
     private Long id;
     private final byte[] image;
 
-    public SessionCover(Long id, byte[] image) {
+
+    public SessionCover(byte[] image) {
+        this.image = image;
+    }
+
+    public SessionCover(Long id, byte[] image, LocalDateTime createdAt, LocalDateTime updatedAt) {
         this.id = id;
         this.image = image;
+        this.createdAt = createdAt;
+        this.updatedAt = updatedAt;
     }
 
     public SessionCover(long id, int width, int height, long size, byte[] image) {
diff --git a/src/main/java/nextstep/courses/domain/SessionCoverRepository.java b/src/main/java/nextstep/courses/domain/SessionCoverRepository.java
new file mode 100644
index 000000000..777fff932
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/SessionCoverRepository.java
@@ -0,0 +1,7 @@
+package nextstep.courses.domain;
+
+public interface SessionCoverRepository {
+    int save(SessionCover sessionCover);
+
+    SessionCover findById(Long id);
+}
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
new file mode 100644
index 000000000..f96d0a70a
--- /dev/null
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
@@ -0,0 +1,38 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.SessionCover;
+import nextstep.courses.domain.SessionCoverRepository;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+
+import static nextstep.courses.utils.DateUtil.toLocalDateTime;
+
+@Repository("sessionCoverRepository")
+public class JdbcSessionCoverRepository implements SessionCoverRepository {
+    private final JdbcOperations jdbcTemplate;
+
+    public JdbcSessionCoverRepository(JdbcOperations jdbcTemplate) {
+        this.jdbcTemplate = jdbcTemplate;
+    }
+
+    @Override
+    public int save(SessionCover sessionCover) {
+        String sql = "insert into session_cover (image, created_at, updated_at) values(?,?,?)";
+        return jdbcTemplate.update(sql, sessionCover.image(), LocalDateTime.now(), LocalDateTime.now());
+    }
+
+    @Override
+    public SessionCover findById(Long id) {
+        String sql = "select id, image, created_at, updated_at from session_cover where id = ?";
+        RowMapper<SessionCover> rowMapper = (rs, rowNum) -> new SessionCover(
+                rs.getLong(1),
+                rs.getBytes(2),
+                toLocalDateTime(rs.getTimestamp(3)),
+                toLocalDateTime(rs.getTimestamp(4)));
+
+        return jdbcTemplate.queryForObject(sql, rowMapper, id);
+    }
+}
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 71c2b7a2c..4d602af00 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -11,7 +11,7 @@ create table course
 create table semester
 (
     id         bigint generated by default as identity,
-    course_id  bigint not null,
+    course_id  bigint    not null,
     created_at timestamp not null,
     updated_at timestamp,
     primary key (id)
@@ -19,16 +19,17 @@ create table semester
 
 create table session
 (
-    id              bigint generated by default as identity,
-    begin_dt        timestamp,
-    end_dt          timestamp,
-    session_status  varchar(10),
-    capacity        bigint,
-    price           bigint,
-    course_id       bigint not null,
-    registration_id bigint,
-    created_at      timestamp,
-    updated_at      timestamp,
+    id               bigint generated by default as identity,
+    begin_dt         timestamp,
+    end_dt           timestamp,
+    session_status   varchar(10),
+    capacity         bigint,
+    price            bigint,
+    course_id        bigint not null,
+    registration_id  bigint,
+    session_cover_id bigint,
+    created_at       timestamp,
+    updated_at       timestamp,
     primary key (id)
 );
 
@@ -46,7 +47,6 @@ create table registration
 create table session_cover
 (
     id         bigint generated by default as identity,
-    session_id bigint not null,
     image      blob,
     created_at timestamp,
     updated_at timestamp,
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
new file mode 100644
index 000000000..54f0cff8f
--- /dev/null
+++ b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
@@ -0,0 +1,22 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.SessionCover;
+import nextstep.courses.domain.SessionCoverRepository;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+@SpringBootTest
+class SessionCoverRepositoryTest {
+    @Autowired
+    private SessionCoverRepository sessionCoverRepository;
+
+    @Test
+    void save_and_findById() {
+        int id = sessionCoverRepository.save(new SessionCover(new byte[100]));
+        SessionCover sessionCover = sessionCoverRepository.findById((long) id);
+        assertThat(sessionCover.id()).isEqualTo(id);
+    }
+}
\ No newline at end of file

From 48a48dbc576bfc350dc4203817d5217b4061d149 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Wed, 13 Dec 2023 15:03:18 +0900
Subject: [PATCH 07/15] =?UTF-8?q?refactor:=20toLocalDateTime=20=EB=B6=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../courses/infrastructure/JdbcCourseRepository.java      | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
index f9122cbe3..b63c96f50 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
@@ -9,6 +9,8 @@
 import java.sql.Timestamp;
 import java.time.LocalDateTime;
 
+import static nextstep.courses.utils.DateUtil.toLocalDateTime;
+
 @Repository("courseRepository")
 public class JdbcCourseRepository implements CourseRepository {
     private JdbcOperations jdbcTemplate;
@@ -35,10 +37,4 @@ public Course findById(Long id) {
         return jdbcTemplate.queryForObject(sql, rowMapper, id);
     }
 
-    private LocalDateTime toLocalDateTime(Timestamp timestamp) {
-        if (timestamp == null) {
-            return null;
-        }
-        return timestamp.toLocalDateTime();
-    }
 }

From e6c0821e663402b5de5626ab6076b27808eefffd Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Wed, 13 Dec 2023 22:22:43 +0900
Subject: [PATCH 08/15] =?UTF-8?q?feat:=20session=20db=20=EC=97=B0=EA=B2=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../nextstep/courses/domain/Registration.java | 35 +++++++++++-
 .../domain/RegistrationRepository.java        | 10 ++++
 .../java/nextstep/courses/domain/Session.java | 17 +++++-
 .../courses/domain/SessionRepository.java     |  7 +++
 .../JdbcRegistrationRepository.java           | 52 +++++++++++++++++
 .../infrastructure/JdbcSessionRepository.java | 57 +++++++++++++++++++
 .../payments/service/PaymentService.java      |  4 +-
 src/main/resources/data.sql                   |  6 ++
 src/main/resources/schema.sql                 |  3 +-
 .../RegistrationRepositoryTest.java           | 24 ++++++++
 10 files changed, 207 insertions(+), 8 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/domain/RegistrationRepository.java
 create mode 100644 src/main/java/nextstep/courses/domain/SessionRepository.java
 create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
 create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
 create mode 100644 src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java

diff --git a/src/main/java/nextstep/courses/domain/Registration.java b/src/main/java/nextstep/courses/domain/Registration.java
index 4d0b22577..df157f8ac 100644
--- a/src/main/java/nextstep/courses/domain/Registration.java
+++ b/src/main/java/nextstep/courses/domain/Registration.java
@@ -4,10 +4,41 @@
 
 public class Registration {
 
-    public Registration() {
+    private Long id = null;
+    private final NsUser user;
+    private final Session session;
+    private final Long amount;
+
+    public Registration(Long id, NsUser user, Session session, Long amount) {
+        this.id = id;
+        this.user = user;
+        this.session = session;
+        this.amount = amount;
+    }
+
+    public Registration(NsUser user, Session session, Long amount) {
+        this.user = user;
+        this.session = session;
+        this.amount = amount;
     }
 
-    public void register(NsUser user, Session session, Long amount) {
+    public void register() {
         session.enroll(user, amount);
     }
+
+    public Long id() {
+        return id;
+    }
+
+    public NsUser nsUser() {
+        return user;
+    }
+
+    public Session session() {
+        return session;
+    }
+
+    public Long amount() {
+        return amount;
+    }
 }
diff --git a/src/main/java/nextstep/courses/domain/RegistrationRepository.java b/src/main/java/nextstep/courses/domain/RegistrationRepository.java
new file mode 100644
index 000000000..64045a29a
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/RegistrationRepository.java
@@ -0,0 +1,10 @@
+package nextstep.courses.domain;
+
+import nextstep.users.domain.NsUser;
+
+import java.util.List;
+
+public interface RegistrationRepository {
+    int save(Registration registration);
+    List<NsUser> findParticipantsBySessionId(Long sessionId);
+}
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 8e46a7cd6..03a70ee8f 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -19,7 +19,7 @@ public class Session extends BaseEntity {
     private final Price price;
 
     private SessionStatus status = SessionStatus.PREPARE;
-    private final List<NsUser> participants = new ArrayList<>();
+    private List<NsUser> participants = new ArrayList<>();
 
     public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
@@ -30,7 +30,7 @@ public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover
         this.price = price;
     }
 
-    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, SessionCover sessionCover, Capacity capacity, Price price, Course course) {
+    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt, List<NsUser> participants) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.status = status;
@@ -38,6 +38,19 @@ public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatu
         this.course = course;
         this.capacity = capacity;
         this.price = price;
+        this.createdAt = createdAt;
+        this.updatedAt = updatedAt;
+        this.participants = participants;
+    }
+
+    public Session(long id, Period period, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt) {
+        this.id = id;
+        this.period = period;
+        this.status = status;
+        this.sessionCover = sessionCover;
+        this.course = course;
+        this.capacity = capacity;
+        this.price = price;
     }
 
     public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
diff --git a/src/main/java/nextstep/courses/domain/SessionRepository.java b/src/main/java/nextstep/courses/domain/SessionRepository.java
new file mode 100644
index 000000000..ebf96c581
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/SessionRepository.java
@@ -0,0 +1,7 @@
+package nextstep.courses.domain;
+
+public interface SessionRepository {
+    int save(Session session);
+
+    Session findById(Long id);
+}
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
new file mode 100644
index 000000000..10d65433e
--- /dev/null
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
@@ -0,0 +1,52 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.Course;
+import nextstep.courses.domain.Registration;
+import nextstep.courses.domain.RegistrationRepository;
+import nextstep.users.domain.NsUser;
+import nextstep.users.domain.UserRepository;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static nextstep.courses.utils.DateUtil.toLocalDateTime;
+
+@Repository("registrationRepository")
+public class JdbcRegistrationRepository implements RegistrationRepository {
+    private JdbcOperations jdbcTemplate;
+    private final UserRepository userRepository;
+
+    public JdbcRegistrationRepository(JdbcOperations jdbcTemplate, UserRepository userRepository) {
+        this.jdbcTemplate = jdbcTemplate;
+        this.userRepository = userRepository;
+    }
+
+    @Override
+    public int save(Registration registration) {
+        String sql = "insert into registration (ns_user_id, session_id, amount created_at) values(?, ?, ?, ?)";
+        return jdbcTemplate.update(sql, registration.nsUser().getId(), registration.session().id(), registration.amount(), LocalDateTime.now());
+    }
+
+    @Override
+    public List<NsUser> findParticipantsBySessionId(Long sessionId) {
+        String sql = "select u.id, u.user_id, u.password, u.name, u.email, u.created_at, u.updated_at  " +
+                "from registration r " +
+                "join session s on r.session_id = s.id " +
+                "join ns_user u on u.id = r.ns_user_id " +
+                "where session_id = ?";
+
+        RowMapper<NsUser> rowMapper = (rs, rowNum) -> new NsUser(
+                rs.getLong(1),
+                rs.getString(2),
+                rs.getString(3),
+                rs.getString(4),
+                rs.getString(5),
+                toLocalDateTime(rs.getTimestamp(6)),
+                toLocalDateTime(rs.getTimestamp(7)));
+
+        return jdbcTemplate.query(sql, rowMapper, sessionId);
+    }
+}
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
new file mode 100644
index 000000000..b2f7b09d3
--- /dev/null
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
@@ -0,0 +1,57 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.*;
+import nextstep.courses.enums.SessionStatus;
+import org.springframework.jdbc.core.JdbcOperations;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.stereotype.Repository;
+
+import java.time.LocalDateTime;
+
+import static nextstep.courses.utils.DateUtil.toLocalDateTime;
+
+@Repository("sessionRepository")
+public class JdbcSessionRepository implements SessionRepository {
+
+    private final CourseRepository courseRepository;
+    private final SessionCoverRepository sessionCoverRepository;
+    private final RegistrationRepository registrationRepository;
+    private JdbcOperations jdbcTemplate;
+
+    public JdbcSessionRepository(CourseRepository courseRepository, SessionCoverRepository sessionCoverRepository, RegistrationRepository registrationRepository, JdbcOperations jdbcTemplate) {
+        this.courseRepository = courseRepository;
+        this.sessionCoverRepository = sessionCoverRepository;
+        this.registrationRepository = registrationRepository;
+        this.jdbcTemplate = jdbcTemplate;
+    }
+
+    @Override
+    public int save(Session session) {
+        String sql = "insert into session (begin_dt, end_dt, session_status, capacity, price, course_id, session_cover_id, created_at, updated_at) values(?, ?, ?, ?, ?, ?, ?, ? ,?)";
+        return jdbcTemplate.update(sql, session.period().getBeginDt(), session.period().getBeginDt(), session.status(), session.capacity().capacity(),
+                session.price().price(), session.course().id(), session.sessionCover().id(), LocalDateTime.now(), LocalDateTime.now());
+    }
+
+    @Override
+    public Session findById(Long id) {
+        String sql = "select s.id, s.begin_dt, s.nd_dt, s.session_status, s.capacity, s.price, " +
+                "s.course_id, s.session_cover_id, s.created_at, s.updated_at" +
+                "from session s where s.id = ?";
+
+        RowMapper<Session> rowMapper = (rs, rowNum) -> new Session(
+                rs.getLong(1),
+                toLocalDateTime(rs.getTimestamp(2)),
+                toLocalDateTime(rs.getTimestamp(3)),
+                SessionStatus.valueOf(rs.getString(4)),
+                new Capacity(rs.getInt(5)),
+                new Price(rs.getInt(6)),
+                courseRepository.findById(rs.getLong(7)),
+                sessionCoverRepository.findById(rs.getLong(8)),
+                toLocalDateTime(rs.getTimestamp(9)),
+                toLocalDateTime(rs.getTimestamp(10)),
+                registrationRepository.findParticipantsBySessionId(rs.getLong(1))
+        );
+
+        return jdbcTemplate.queryForObject(sql, rowMapper, id);
+    }
+}
diff --git a/src/main/java/nextstep/payments/service/PaymentService.java b/src/main/java/nextstep/payments/service/PaymentService.java
index 7bfc4d357..fe7844c7f 100644
--- a/src/main/java/nextstep/payments/service/PaymentService.java
+++ b/src/main/java/nextstep/payments/service/PaymentService.java
@@ -7,8 +7,8 @@
 
 public class PaymentService {
     public Payment payment(NsUser user, Session session, Long amount) {
-        Registration registration = new Registration();
-        registration.register(user, session, amount);
+        Registration registration = new Registration(user, session, amount);
+        registration.register();
         return new Payment(session.id());
     }
 }
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
index 4a6bc5a66..50a20049f 100644
--- a/src/main/resources/data.sql
+++ b/src/main/resources/data.sql
@@ -8,3 +8,9 @@ INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUE
 INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUES (2, '언더스코어 강력 추천드려요. 다만 최신 버전을 공부하는 것보다는 0.10.0 버전부터 보는게 더 좋더군요. 코드의 변천사도 알 수 있고, 최적화되지 않은 코드들이 기능은 그대로 두고 최적화되어 가는 걸 보면 재미가 있습니다 :)', CURRENT_TIMESTAMP(), 1, false);
 
 INSERT INTO question (id, writer_id, title, contents, created_at, deleted) VALUES (2, 2, 'runtime 에 reflect 발동 주체 객체가 뭔지 알 방법이 있을까요?', '설계를 희한하게 하는 바람에 꼬인 문제같긴 합니다만. 여쭙습니다. 상황은 mybatis select 실행될 시에 return object 의 getter 가 호출되면서인데요. getter 안에 다른 property 에 의존중인 코드가 삽입되어 있어서, 만약 다른 mybatis select 구문에 해당 property 가 없다면 exception 이 발생하게 됩니다.', CURRENT_TIMESTAMP(), false);
+
+
+INSERT INTO course (id, title, creator_id, created_at) values (1L, '제목', 1L, CURRENT_TIMESTAMP());
+INSERT INTO session (id, begin_dt, end_dt, session_status, capacity, price, course_id, session_cover_id, created_at, updated_at)
+values (100L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), 1, 100,  20000, 1L, 1L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
+INSERT INTO registration (id, session_id, ns_user_id, amount) values (100L, 100L, 1L, 20000);
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 4d602af00..34427dad0 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -26,7 +26,6 @@ create table session
     capacity         bigint,
     price            bigint,
     course_id        bigint not null,
-    registration_id  bigint,
     session_cover_id bigint,
     created_at       timestamp,
     updated_at       timestamp,
@@ -37,7 +36,7 @@ create table registration
 (
     id         bigint generated by default as identity,
     session_id bigint not null,
-    ns_user_id bigint,
+    ns_user_id bigint not null,
     amount     bigint,
     created_at timestamp,
     updated_at timestamp,
diff --git a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
new file mode 100644
index 000000000..06e3c0154
--- /dev/null
+++ b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
@@ -0,0 +1,24 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.RegistrationRepository;
+import nextstep.users.domain.NsUser;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.List;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+
+@SpringBootTest
+class RegistrationRepositoryTest {
+    @Autowired
+    private RegistrationRepository registrationRepository;
+
+    @Test
+    void findParticipants() {
+        List<NsUser> userList = registrationRepository.findParticipantsBySessionId(100L);
+        assertThat(userList.get(0).getId()).isEqualTo(1L);
+    }
+}
\ No newline at end of file

From 386422ce3163c0cd3e9b20922e306e1eff982c92 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Wed, 13 Dec 2023 23:05:38 +0900
Subject: [PATCH 09/15] =?UTF-8?q?fix:=20testcase=20=EC=B6=94=EA=B0=80=20?=
 =?UTF-8?q?=EB=B0=8F=20=EB=B2=84=EA=B7=B8=20=ED=94=BD=EC=8A=A4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/nextstep/courses/domain/Course.java  |  4 +++
 .../java/nextstep/courses/domain/Session.java |  2 +-
 .../nextstep/courses/domain/SessionCover.java |  1 +
 .../JdbcRegistrationRepository.java           |  3 +--
 .../infrastructure/JdbcSessionRepository.java |  6 ++---
 src/main/resources/data.sql                   |  3 ++-
 .../RegistrationRepositoryTest.java           |  8 ++++--
 .../SessionCoverRepositoryTest.java           |  2 +-
 .../infrastructure/SessionRepositoryTest.java | 27 +++++++++++++++++++
 9 files changed, 46 insertions(+), 10 deletions(-)
 create mode 100644 src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java

diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java
index 8ea1be510..efd996fea 100644
--- a/src/main/java/nextstep/courses/domain/Course.java
+++ b/src/main/java/nextstep/courses/domain/Course.java
@@ -16,6 +16,10 @@ public Course(String title, Long creatorId) {
         this(0L, title, creatorId, LocalDateTime.now(), null);
     }
 
+    public Course(Long id, String title, Long creatorId) {
+        this(id, title, creatorId, LocalDateTime.now(), null);
+    }
+
     public Course(Long id, String title, Long creatorId, LocalDateTime createdAt, LocalDateTime updatedAt) {
         this.id = id;
         this.title = title;
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 03a70ee8f..c05617231 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -21,7 +21,7 @@ public class Session extends BaseEntity {
     private SessionStatus status = SessionStatus.PREPARE;
     private List<NsUser> participants = new ArrayList<>();
 
-    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
+    public  Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
diff --git a/src/main/java/nextstep/courses/domain/SessionCover.java b/src/main/java/nextstep/courses/domain/SessionCover.java
index e473a18f3..cc019c896 100644
--- a/src/main/java/nextstep/courses/domain/SessionCover.java
+++ b/src/main/java/nextstep/courses/domain/SessionCover.java
@@ -28,6 +28,7 @@ public SessionCover(long id, int width, int height, long size, byte[] image) {
             throw new IllegalArgumentException("이미지 값이 없습니다.");
         }
         this.image = image;
+        this.id = id;
     }
 
     private static void validateSize(long size) {
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
index 10d65433e..9be9c84de 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
@@ -1,6 +1,5 @@
 package nextstep.courses.infrastructure;
 
-import nextstep.courses.domain.Course;
 import nextstep.courses.domain.Registration;
 import nextstep.courses.domain.RegistrationRepository;
 import nextstep.users.domain.NsUser;
@@ -26,7 +25,7 @@ public JdbcRegistrationRepository(JdbcOperations jdbcTemplate, UserRepository us
 
     @Override
     public int save(Registration registration) {
-        String sql = "insert into registration (ns_user_id, session_id, amount created_at) values(?, ?, ?, ?)";
+        String sql = "insert into registration (ns_user_id, session_id, amount, created_at) values(?, ?, ?, ?)";
         return jdbcTemplate.update(sql, registration.nsUser().getId(), registration.session().id(), registration.amount(), LocalDateTime.now());
     }
 
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
index b2f7b09d3..2826c0528 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
@@ -34,9 +34,9 @@ public int save(Session session) {
 
     @Override
     public Session findById(Long id) {
-        String sql = "select s.id, s.begin_dt, s.nd_dt, s.session_status, s.capacity, s.price, " +
-                "s.course_id, s.session_cover_id, s.created_at, s.updated_at" +
-                "from session s where s.id = ?";
+        String sql = "select id, begin_dt, end_dt, session_status, capacity, price, " +
+                "course_id, session_cover_id, created_at, updated_at " +
+                "from session where id = ?";
 
         RowMapper<Session> rowMapper = (rs, rowNum) -> new Session(
                 rs.getLong(1),
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
index 50a20049f..9a750c8c8 100644
--- a/src/main/resources/data.sql
+++ b/src/main/resources/data.sql
@@ -10,7 +10,8 @@ INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUE
 INSERT INTO question (id, writer_id, title, contents, created_at, deleted) VALUES (2, 2, 'runtime 에 reflect 발동 주체 객체가 뭔지 알 방법이 있을까요?', '설계를 희한하게 하는 바람에 꼬인 문제같긴 합니다만. 여쭙습니다. 상황은 mybatis select 실행될 시에 return object 의 getter 가 호출되면서인데요. getter 안에 다른 property 에 의존중인 코드가 삽입되어 있어서, 만약 다른 mybatis select 구문에 해당 property 가 없다면 exception 이 발생하게 됩니다.', CURRENT_TIMESTAMP(), false);
 
 
-INSERT INTO course (id, title, creator_id, created_at) values (1L, '제목', 1L, CURRENT_TIMESTAMP());
+INSERT INTO course (id, title, creator_id, created_at) values (100L, '제목', 1L, CURRENT_TIMESTAMP());
+INSERT INTO session_cover (id, image, created_at, updated_at) values (100L, '제목', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
 INSERT INTO session (id, begin_dt, end_dt, session_status, capacity, price, course_id, session_cover_id, created_at, updated_at)
 values (100L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), 1, 100,  20000, 1L, 1L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
 INSERT INTO registration (id, session_id, ns_user_id, amount) values (100L, 100L, 1L, 20000);
diff --git a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
index 06e3c0154..97677aa49 100644
--- a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
@@ -1,11 +1,12 @@
 package nextstep.courses.infrastructure;
 
-import nextstep.courses.domain.RegistrationRepository;
+import nextstep.courses.domain.*;
 import nextstep.users.domain.NsUser;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
+import java.time.LocalDateTime;
 import java.util.List;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -17,7 +18,10 @@ class RegistrationRepositoryTest {
     private RegistrationRepository registrationRepository;
 
     @Test
-    void findParticipants() {
+    void crud() {
+        int id = registrationRepository.save(new Registration(new NsUser(1L, "1", "2", "3", "4")
+                , Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course())
+                , 100000L));
         List<NsUser> userList = registrationRepository.findParticipantsBySessionId(100L);
         assertThat(userList.get(0).getId()).isEqualTo(1L);
     }
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
index 54f0cff8f..7d046f226 100644
--- a/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
@@ -14,7 +14,7 @@ class SessionCoverRepositoryTest {
     private SessionCoverRepository sessionCoverRepository;
 
     @Test
-    void save_and_findById() {
+    void crud() {
         int id = sessionCoverRepository.save(new SessionCover(new byte[100]));
         SessionCover sessionCover = sessionCoverRepository.findById((long) id);
         assertThat(sessionCover.id()).isEqualTo(id);
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
new file mode 100644
index 000000000..95308dcde
--- /dev/null
+++ b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
@@ -0,0 +1,27 @@
+package nextstep.courses.infrastructure;
+
+import nextstep.courses.domain.Course;
+import nextstep.courses.domain.Session;
+import nextstep.courses.domain.SessionCover;
+import nextstep.courses.domain.SessionRepository;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.time.LocalDateTime;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+@SpringBootTest
+class SessionRepositoryTest {
+
+    @Autowired
+    private SessionRepository sessionRepository;
+
+    @Test
+    void crud() {
+        int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L,"제목", 3L)));
+        Session session = sessionRepository.findById((long) id);
+        assertThat(session.id()).isEqualTo(id);
+    }
+}
\ No newline at end of file

From 51a96020a19c0a0c20b4c8a8ce89ca42a2518478 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Thu, 14 Dec 2023 14:57:24 +0900
Subject: [PATCH 10/15] =?UTF-8?q?refactor:=20baseEntity=20=ED=8C=A8?=
 =?UTF-8?q?=ED=82=A4=EC=A7=80=EC=9D=B4=EB=8F=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/main/java/nextstep/courses/domain/Course.java           | 4 +++-
 src/main/java/nextstep/courses/domain/Semester.java         | 4 +++-
 src/main/java/nextstep/courses/domain/Session.java          | 1 +
 src/main/java/nextstep/courses/domain/SessionCover.java     | 4 +++-
 .../java/nextstep/courses/{domain => utils}/BaseEntity.java | 6 +++---
 5 files changed, 13 insertions(+), 6 deletions(-)
 rename src/main/java/nextstep/courses/{domain => utils}/BaseEntity.java (66%)

diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java
index efd996fea..da2f5e3c3 100644
--- a/src/main/java/nextstep/courses/domain/Course.java
+++ b/src/main/java/nextstep/courses/domain/Course.java
@@ -1,8 +1,10 @@
 package nextstep.courses.domain;
 
+import nextstep.courses.utils.BaseEntity;
+
 import java.time.LocalDateTime;
 
-public class Course extends BaseEntity{
+public class Course extends BaseEntity {
     private Long id;
 
     private String title;
diff --git a/src/main/java/nextstep/courses/domain/Semester.java b/src/main/java/nextstep/courses/domain/Semester.java
index a8dbd85e2..082e64053 100644
--- a/src/main/java/nextstep/courses/domain/Semester.java
+++ b/src/main/java/nextstep/courses/domain/Semester.java
@@ -1,6 +1,8 @@
 package nextstep.courses.domain;
 
-public class Semester extends BaseEntity{
+import nextstep.courses.utils.BaseEntity;
+
+public class Semester extends BaseEntity {
     private final Course course;
 
     public Semester(Course course) {
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index c05617231..e380bb26e 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -2,6 +2,7 @@
 
 import nextstep.courses.enums.SessionStatus;
 import nextstep.courses.exception.BusinessInvalidValueException;
+import nextstep.courses.utils.BaseEntity;
 import nextstep.users.domain.NsUser;
 
 import java.time.LocalDateTime;
diff --git a/src/main/java/nextstep/courses/domain/SessionCover.java b/src/main/java/nextstep/courses/domain/SessionCover.java
index cc019c896..cac622039 100644
--- a/src/main/java/nextstep/courses/domain/SessionCover.java
+++ b/src/main/java/nextstep/courses/domain/SessionCover.java
@@ -1,8 +1,10 @@
 package nextstep.courses.domain;
 
+import nextstep.courses.utils.BaseEntity;
+
 import java.time.LocalDateTime;
 
-public class SessionCover extends BaseEntity{
+public class SessionCover extends BaseEntity {
     public static final double RATIO = (double) 3 / 2;
 
     private Long id;
diff --git a/src/main/java/nextstep/courses/domain/BaseEntity.java b/src/main/java/nextstep/courses/utils/BaseEntity.java
similarity index 66%
rename from src/main/java/nextstep/courses/domain/BaseEntity.java
rename to src/main/java/nextstep/courses/utils/BaseEntity.java
index 74f2b215d..56420fad1 100644
--- a/src/main/java/nextstep/courses/domain/BaseEntity.java
+++ b/src/main/java/nextstep/courses/utils/BaseEntity.java
@@ -1,11 +1,11 @@
-package nextstep.courses.domain;
+package nextstep.courses.utils;
 
 import java.time.LocalDateTime;
 
 public class BaseEntity {
-    LocalDateTime createdAt;
+    public LocalDateTime createdAt;
 
-    LocalDateTime updatedAt;
+    public LocalDateTime updatedAt;
 
     public LocalDateTime createdAt() {
         return createdAt;

From 7028a0bb248628f8e2b3e55b899cb37770703ad9 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Thu, 14 Dec 2023 15:05:14 +0900
Subject: [PATCH 11/15] =?UTF-8?q?feat:=20registration=20save=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

---
 .../java/nextstep/courses/domain/Registration.java | 10 ++++++++--
 .../nextstep/payments/service/PaymentService.java  | 14 +++++++++++---
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/main/java/nextstep/courses/domain/Registration.java b/src/main/java/nextstep/courses/domain/Registration.java
index df157f8ac..31b12fbc5 100644
--- a/src/main/java/nextstep/courses/domain/Registration.java
+++ b/src/main/java/nextstep/courses/domain/Registration.java
@@ -9,19 +9,25 @@ public class Registration {
     private final Session session;
     private final Long amount;
 
-    public Registration(Long id, NsUser user, Session session, Long amount) {
+    private Registration(Long id, NsUser user, Session session, Long amount) {
         this.id = id;
         this.user = user;
         this.session = session;
         this.amount = amount;
     }
 
-    public Registration(NsUser user, Session session, Long amount) {
+    private Registration(NsUser user, Session session, Long amount) {
         this.user = user;
         this.session = session;
         this.amount = amount;
     }
 
+    public static Registration register(NsUser user, Session session, Long amount) {
+        Registration registration = new Registration(user, session, amount);
+        session.enroll(user, amount);
+        return registration;
+    }
+
     public void register() {
         session.enroll(user, amount);
     }
diff --git a/src/main/java/nextstep/payments/service/PaymentService.java b/src/main/java/nextstep/payments/service/PaymentService.java
index fe7844c7f..50e3ace9b 100644
--- a/src/main/java/nextstep/payments/service/PaymentService.java
+++ b/src/main/java/nextstep/payments/service/PaymentService.java
@@ -2,13 +2,21 @@
 
 import nextstep.courses.domain.Registration;
 import nextstep.courses.domain.Session;
+import nextstep.courses.infrastructure.JdbcRegistrationRepository;
 import nextstep.payments.domain.Payment;
 import nextstep.users.domain.NsUser;
+import org.springframework.stereotype.Service;
 
+@Service
 public class PaymentService {
-    public Payment payment(NsUser user, Session session, Long amount) {
-        Registration registration = new Registration(user, session, amount);
-        registration.register();
+    private final JdbcRegistrationRepository jdbcRegistrationRepository;
+
+    public PaymentService(JdbcRegistrationRepository jdbcRegistrationRepository) {
+        this.jdbcRegistrationRepository = jdbcRegistrationRepository;
+    }
+
+    public Payment payment(NsUser user, Session session, Long amount) {;
+        jdbcRegistrationRepository.save(Registration.register(user, session, amount));
         return new Payment(session.id());
     }
 }

From c3a906e468975dc499d0aecdb7e2b7f0eb8f75a7 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Fri, 15 Dec 2023 15:27:36 +0900
Subject: [PATCH 12/15] =?UTF-8?q?refactor:=20repository=EA=B0=84=20?=
 =?UTF-8?q?=EC=9D=98=EC=A1=B4=20=EC=A0=9C=EA=B1=B0=20=EB=B0=8F=20Registrat?=
 =?UTF-8?q?ion=EC=97=90=EC=84=9C=20NsUser=20=EB=8F=84=EB=A9=94=EC=9D=B8=20?=
 =?UTF-8?q?=EC=9D=98=EC=A1=B4=20=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/nextstep/courses/domain/Course.java  |  4 +++
 .../nextstep/courses/domain/Registration.java | 14 ++++----
 .../domain/RegistrationRepository.java        | 10 ------
 .../java/nextstep/courses/domain/Session.java | 29 +++++++----------
 .../nextstep/courses/domain/SessionCover.java |  5 ++-
 .../{ => repository}/CourseRepository.java    |  4 ++-
 .../repository/RegistrationRepository.java    | 11 +++++++
 .../SessionCoverRepository.java               |  4 ++-
 .../{ => repository}/SessionRepository.java   |  4 ++-
 .../infrastructure/JdbcCourseRepository.java  |  5 +--
 .../JdbcRegistrationRepository.java           | 32 ++++++++-----------
 .../JdbcSessionCoverRepository.java           |  2 +-
 .../infrastructure/JdbcSessionRepository.java | 16 +++-------
 .../java/nextstep/users/domain/NsUser.java    |  4 +++
 src/main/resources/data.sql                   |  7 ----
 src/main/resources/schema.sql                 |  2 +-
 .../infrastructure/CourseRepositoryTest.java  |  2 +-
 .../RegistrationRepositoryTest.java           | 12 ++++---
 .../SessionCoverRepositoryTest.java           |  2 +-
 .../infrastructure/SessionRepositoryTest.java |  4 +--
 20 files changed, 83 insertions(+), 90 deletions(-)
 delete mode 100644 src/main/java/nextstep/courses/domain/RegistrationRepository.java
 rename src/main/java/nextstep/courses/domain/{ => repository}/CourseRepository.java (54%)
 create mode 100644 src/main/java/nextstep/courses/domain/repository/RegistrationRepository.java
 rename src/main/java/nextstep/courses/domain/{ => repository}/SessionCoverRepository.java (57%)
 rename src/main/java/nextstep/courses/domain/{ => repository}/SessionRepository.java (54%)

diff --git a/src/main/java/nextstep/courses/domain/Course.java b/src/main/java/nextstep/courses/domain/Course.java
index da2f5e3c3..f76223d3a 100644
--- a/src/main/java/nextstep/courses/domain/Course.java
+++ b/src/main/java/nextstep/courses/domain/Course.java
@@ -14,6 +14,10 @@ public class Course extends BaseEntity {
     public Course() {
     }
 
+    public Course(Long id) {
+        this.id = id;
+    }
+
     public Course(String title, Long creatorId) {
         this(0L, title, creatorId, LocalDateTime.now(), null);
     }
diff --git a/src/main/java/nextstep/courses/domain/Registration.java b/src/main/java/nextstep/courses/domain/Registration.java
index 31b12fbc5..95e200cb6 100644
--- a/src/main/java/nextstep/courses/domain/Registration.java
+++ b/src/main/java/nextstep/courses/domain/Registration.java
@@ -1,22 +1,26 @@
 package nextstep.courses.domain;
 
+import nextstep.courses.utils.BaseEntity;
 import nextstep.users.domain.NsUser;
 
-public class Registration {
+import java.time.LocalDateTime;
 
+public class Registration extends BaseEntity {
     private Long id = null;
     private final NsUser user;
     private final Session session;
     private final Long amount;
 
-    private Registration(Long id, NsUser user, Session session, Long amount) {
+    public Registration(Long id, NsUser user, Session session, Long amount, LocalDateTime createdAt, LocalDateTime updatedAt) {
         this.id = id;
         this.user = user;
         this.session = session;
         this.amount = amount;
+        this.createdAt = createdAt;
+        this.updatedAt = updatedAt;
     }
 
-    private Registration(NsUser user, Session session, Long amount) {
+    public Registration(NsUser user, Session session, Long amount) {
         this.user = user;
         this.session = session;
         this.amount = amount;
@@ -28,10 +32,6 @@ public static Registration register(NsUser user, Session session, Long amount) {
         return registration;
     }
 
-    public void register() {
-        session.enroll(user, amount);
-    }
-
     public Long id() {
         return id;
     }
diff --git a/src/main/java/nextstep/courses/domain/RegistrationRepository.java b/src/main/java/nextstep/courses/domain/RegistrationRepository.java
deleted file mode 100644
index 64045a29a..000000000
--- a/src/main/java/nextstep/courses/domain/RegistrationRepository.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package nextstep.courses.domain;
-
-import nextstep.users.domain.NsUser;
-
-import java.util.List;
-
-public interface RegistrationRepository {
-    int save(Registration registration);
-    List<NsUser> findParticipantsBySessionId(Long sessionId);
-}
diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index e380bb26e..54232a08f 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -13,45 +13,38 @@ public class Session extends BaseEntity {
     public static long FREE_PRICE = 0L;
     public static int MAX_CAPACITY = Integer.MAX_VALUE;
     private final Long id;
-    private final Course course;
-    private final SessionCover sessionCover;
-    private final Period period;
-    private final Capacity capacity;
-    private final Price price;
+    private Course course;
+    private SessionCover sessionCover;
+    private Period period;
+    private Capacity capacity;
+    private Price price;
 
     private SessionStatus status = SessionStatus.PREPARE;
     private List<NsUser> participants = new ArrayList<>();
 
-    public  Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
+    public Session(Long id) {
         this.id = id;
-        this.period = new Period(beginDt, endDt);
-        this.sessionCover = sessionCover;
-        this.course = course;
-        this.capacity = capacity;
-        this.price = price;
     }
 
-    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt, List<NsUser> participants) {
+    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
-        this.status = status;
         this.sessionCover = sessionCover;
         this.course = course;
         this.capacity = capacity;
         this.price = price;
-        this.createdAt = createdAt;
-        this.updatedAt = updatedAt;
-        this.participants = participants;
     }
 
-    public Session(long id, Period period, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt) {
+    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt) {
         this.id = id;
-        this.period = period;
+        this.period = new Period(beginDt, endDt);
         this.status = status;
         this.sessionCover = sessionCover;
         this.course = course;
         this.capacity = capacity;
         this.price = price;
+        this.createdAt = createdAt;
+        this.updatedAt = updatedAt;
     }
 
     public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
diff --git a/src/main/java/nextstep/courses/domain/SessionCover.java b/src/main/java/nextstep/courses/domain/SessionCover.java
index cac622039..c9843c4f7 100644
--- a/src/main/java/nextstep/courses/domain/SessionCover.java
+++ b/src/main/java/nextstep/courses/domain/SessionCover.java
@@ -8,8 +8,11 @@ public class SessionCover extends BaseEntity {
     public static final double RATIO = (double) 3 / 2;
 
     private Long id;
-    private final byte[] image;
+    private byte[] image;
 
+    public SessionCover(Long id) {
+        this.id = id;
+    }
 
     public SessionCover(byte[] image) {
         this.image = image;
diff --git a/src/main/java/nextstep/courses/domain/CourseRepository.java b/src/main/java/nextstep/courses/domain/repository/CourseRepository.java
similarity index 54%
rename from src/main/java/nextstep/courses/domain/CourseRepository.java
rename to src/main/java/nextstep/courses/domain/repository/CourseRepository.java
index 6aaeb638d..675e42f31 100644
--- a/src/main/java/nextstep/courses/domain/CourseRepository.java
+++ b/src/main/java/nextstep/courses/domain/repository/CourseRepository.java
@@ -1,4 +1,6 @@
-package nextstep.courses.domain;
+package nextstep.courses.domain.repository;
+
+import nextstep.courses.domain.Course;
 
 public interface CourseRepository {
     int save(Course course);
diff --git a/src/main/java/nextstep/courses/domain/repository/RegistrationRepository.java b/src/main/java/nextstep/courses/domain/repository/RegistrationRepository.java
new file mode 100644
index 000000000..9dab72269
--- /dev/null
+++ b/src/main/java/nextstep/courses/domain/repository/RegistrationRepository.java
@@ -0,0 +1,11 @@
+package nextstep.courses.domain.repository;
+
+import nextstep.courses.domain.Registration;
+
+import java.util.List;
+
+public interface RegistrationRepository {
+    int save(Registration registration);
+
+    List<Registration> findAllBySessionId(Long sessionId);
+}
diff --git a/src/main/java/nextstep/courses/domain/SessionCoverRepository.java b/src/main/java/nextstep/courses/domain/repository/SessionCoverRepository.java
similarity index 57%
rename from src/main/java/nextstep/courses/domain/SessionCoverRepository.java
rename to src/main/java/nextstep/courses/domain/repository/SessionCoverRepository.java
index 777fff932..582ea641f 100644
--- a/src/main/java/nextstep/courses/domain/SessionCoverRepository.java
+++ b/src/main/java/nextstep/courses/domain/repository/SessionCoverRepository.java
@@ -1,4 +1,6 @@
-package nextstep.courses.domain;
+package nextstep.courses.domain.repository;
+
+import nextstep.courses.domain.SessionCover;
 
 public interface SessionCoverRepository {
     int save(SessionCover sessionCover);
diff --git a/src/main/java/nextstep/courses/domain/SessionRepository.java b/src/main/java/nextstep/courses/domain/repository/SessionRepository.java
similarity index 54%
rename from src/main/java/nextstep/courses/domain/SessionRepository.java
rename to src/main/java/nextstep/courses/domain/repository/SessionRepository.java
index ebf96c581..9dca1bb59 100644
--- a/src/main/java/nextstep/courses/domain/SessionRepository.java
+++ b/src/main/java/nextstep/courses/domain/repository/SessionRepository.java
@@ -1,4 +1,6 @@
-package nextstep.courses.domain;
+package nextstep.courses.domain.repository;
+
+import nextstep.courses.domain.Session;
 
 public interface SessionRepository {
     int save(Session session);
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
index b63c96f50..99c8b5922 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcCourseRepository.java
@@ -1,14 +1,11 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.Course;
-import nextstep.courses.domain.CourseRepository;
+import nextstep.courses.domain.repository.CourseRepository;
 import org.springframework.jdbc.core.JdbcOperations;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Repository;
 
-import java.sql.Timestamp;
-import java.time.LocalDateTime;
-
 import static nextstep.courses.utils.DateUtil.toLocalDateTime;
 
 @Repository("courseRepository")
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
index 9be9c84de..61b5c01ff 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcRegistrationRepository.java
@@ -1,9 +1,9 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.Registration;
-import nextstep.courses.domain.RegistrationRepository;
+import nextstep.courses.domain.Session;
+import nextstep.courses.domain.repository.RegistrationRepository;
 import nextstep.users.domain.NsUser;
-import nextstep.users.domain.UserRepository;
 import org.springframework.jdbc.core.JdbcOperations;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Repository;
@@ -16,11 +16,9 @@
 @Repository("registrationRepository")
 public class JdbcRegistrationRepository implements RegistrationRepository {
     private JdbcOperations jdbcTemplate;
-    private final UserRepository userRepository;
 
-    public JdbcRegistrationRepository(JdbcOperations jdbcTemplate, UserRepository userRepository) {
+    public JdbcRegistrationRepository(JdbcOperations jdbcTemplate) {
         this.jdbcTemplate = jdbcTemplate;
-        this.userRepository = userRepository;
     }
 
     @Override
@@ -30,21 +28,17 @@ public int save(Registration registration) {
     }
 
     @Override
-    public List<NsUser> findParticipantsBySessionId(Long sessionId) {
-        String sql = "select u.id, u.user_id, u.password, u.name, u.email, u.created_at, u.updated_at  " +
-                "from registration r " +
-                "join session s on r.session_id = s.id " +
-                "join ns_user u on u.id = r.ns_user_id " +
-                "where session_id = ?";
-
-        RowMapper<NsUser> rowMapper = (rs, rowNum) -> new NsUser(
+    public List<Registration> findAllBySessionId(Long sessionId) {
+        String sql = "select id, session_id, ns_user_id, amount, created_at, updated_at " +
+                "from registration r where session_id = ?";
+
+        RowMapper<Registration> rowMapper = (rs, rowNum) -> new Registration(
                 rs.getLong(1),
-                rs.getString(2),
-                rs.getString(3),
-                rs.getString(4),
-                rs.getString(5),
-                toLocalDateTime(rs.getTimestamp(6)),
-                toLocalDateTime(rs.getTimestamp(7)));
+                new NsUser(rs.getLong(2)),
+                new Session(rs.getLong(3)),
+                rs.getLong(4),
+                toLocalDateTime(rs.getTimestamp(5)),
+                toLocalDateTime(rs.getTimestamp(6)));
 
         return jdbcTemplate.query(sql, rowMapper, sessionId);
     }
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
index f96d0a70a..bc1de599c 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionCoverRepository.java
@@ -1,7 +1,7 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.SessionCover;
-import nextstep.courses.domain.SessionCoverRepository;
+import nextstep.courses.domain.repository.SessionCoverRepository;
 import org.springframework.jdbc.core.JdbcOperations;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.stereotype.Repository;
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
index 2826c0528..59d6c29b2 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
@@ -1,6 +1,7 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.*;
+import nextstep.courses.domain.repository.SessionRepository;
 import nextstep.courses.enums.SessionStatus;
 import org.springframework.jdbc.core.JdbcOperations;
 import org.springframework.jdbc.core.RowMapper;
@@ -13,15 +14,9 @@
 @Repository("sessionRepository")
 public class JdbcSessionRepository implements SessionRepository {
 
-    private final CourseRepository courseRepository;
-    private final SessionCoverRepository sessionCoverRepository;
-    private final RegistrationRepository registrationRepository;
     private JdbcOperations jdbcTemplate;
 
-    public JdbcSessionRepository(CourseRepository courseRepository, SessionCoverRepository sessionCoverRepository, RegistrationRepository registrationRepository, JdbcOperations jdbcTemplate) {
-        this.courseRepository = courseRepository;
-        this.sessionCoverRepository = sessionCoverRepository;
-        this.registrationRepository = registrationRepository;
+    public JdbcSessionRepository(JdbcOperations jdbcTemplate) {
         this.jdbcTemplate = jdbcTemplate;
     }
 
@@ -45,11 +40,10 @@ public Session findById(Long id) {
                 SessionStatus.valueOf(rs.getString(4)),
                 new Capacity(rs.getInt(5)),
                 new Price(rs.getInt(6)),
-                courseRepository.findById(rs.getLong(7)),
-                sessionCoverRepository.findById(rs.getLong(8)),
+                new Course(rs.getLong(7)),
+                new SessionCover(rs.getLong(8)),
                 toLocalDateTime(rs.getTimestamp(9)),
-                toLocalDateTime(rs.getTimestamp(10)),
-                registrationRepository.findParticipantsBySessionId(rs.getLong(1))
+                toLocalDateTime(rs.getTimestamp(10))
         );
 
         return jdbcTemplate.queryForObject(sql, rowMapper, id);
diff --git a/src/main/java/nextstep/users/domain/NsUser.java b/src/main/java/nextstep/users/domain/NsUser.java
index 62ec5138c..01ab7fc85 100755
--- a/src/main/java/nextstep/users/domain/NsUser.java
+++ b/src/main/java/nextstep/users/domain/NsUser.java
@@ -25,6 +25,10 @@ public class NsUser {
     public NsUser() {
     }
 
+    public NsUser(Long id) {
+        this.id = id;
+    }
+
     public NsUser(Long id, String userId, String password, String name, String email) {
         this(id, userId, password, name, email, LocalDateTime.now(), null);
     }
diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql
index 9a750c8c8..4a6bc5a66 100644
--- a/src/main/resources/data.sql
+++ b/src/main/resources/data.sql
@@ -8,10 +8,3 @@ INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUE
 INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUES (2, '언더스코어 강력 추천드려요. 다만 최신 버전을 공부하는 것보다는 0.10.0 버전부터 보는게 더 좋더군요. 코드의 변천사도 알 수 있고, 최적화되지 않은 코드들이 기능은 그대로 두고 최적화되어 가는 걸 보면 재미가 있습니다 :)', CURRENT_TIMESTAMP(), 1, false);
 
 INSERT INTO question (id, writer_id, title, contents, created_at, deleted) VALUES (2, 2, 'runtime 에 reflect 발동 주체 객체가 뭔지 알 방법이 있을까요?', '설계를 희한하게 하는 바람에 꼬인 문제같긴 합니다만. 여쭙습니다. 상황은 mybatis select 실행될 시에 return object 의 getter 가 호출되면서인데요. getter 안에 다른 property 에 의존중인 코드가 삽입되어 있어서, 만약 다른 mybatis select 구문에 해당 property 가 없다면 exception 이 발생하게 됩니다.', CURRENT_TIMESTAMP(), false);
-
-
-INSERT INTO course (id, title, creator_id, created_at) values (100L, '제목', 1L, CURRENT_TIMESTAMP());
-INSERT INTO session_cover (id, image, created_at, updated_at) values (100L, '제목', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
-INSERT INTO session (id, begin_dt, end_dt, session_status, capacity, price, course_id, session_cover_id, created_at, updated_at)
-values (100L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP(), 1, 100,  20000, 1L, 1L, CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
-INSERT INTO registration (id, session_id, ns_user_id, amount) values (100L, 100L, 1L, 20000);
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 34427dad0..9763759b4 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -35,8 +35,8 @@ create table session
 create table registration
 (
     id         bigint generated by default as identity,
-    session_id bigint not null,
     ns_user_id bigint not null,
+    session_id bigint not null,
     amount     bigint,
     created_at timestamp,
     updated_at timestamp,
diff --git a/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java
index f087fc0ad..5b7987c4f 100644
--- a/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/CourseRepositoryTest.java
@@ -1,7 +1,7 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.Course;
-import nextstep.courses.domain.CourseRepository;
+import nextstep.courses.domain.repository.CourseRepository;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
diff --git a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
index 97677aa49..f3ef2e57d 100644
--- a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
@@ -1,6 +1,10 @@
 package nextstep.courses.infrastructure;
 
-import nextstep.courses.domain.*;
+import nextstep.courses.domain.Course;
+import nextstep.courses.domain.Registration;
+import nextstep.courses.domain.Session;
+import nextstep.courses.domain.SessionCover;
+import nextstep.courses.domain.repository.RegistrationRepository;
 import nextstep.users.domain.NsUser;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,9 +24,9 @@ class RegistrationRepositoryTest {
     @Test
     void crud() {
         int id = registrationRepository.save(new Registration(new NsUser(1L, "1", "2", "3", "4")
-                , Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course())
+                , Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(1L, 300, 200, 1024, new byte[100]), new Course())
                 , 100000L));
-        List<NsUser> userList = registrationRepository.findParticipantsBySessionId(100L);
-        assertThat(userList.get(0).getId()).isEqualTo(1L);
+        List<Registration> registrations = registrationRepository.findAllBySessionId(1L);
+        assertThat(registrations.get(0).nsUser().getId()).isEqualTo(1L);
     }
 }
\ No newline at end of file
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
index 7d046f226..f0c0b1bed 100644
--- a/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/SessionCoverRepositoryTest.java
@@ -1,7 +1,7 @@
 package nextstep.courses.infrastructure;
 
 import nextstep.courses.domain.SessionCover;
-import nextstep.courses.domain.SessionCoverRepository;
+import nextstep.courses.domain.repository.SessionCoverRepository;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
index 95308dcde..1a76e7087 100644
--- a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
@@ -3,7 +3,7 @@
 import nextstep.courses.domain.Course;
 import nextstep.courses.domain.Session;
 import nextstep.courses.domain.SessionCover;
-import nextstep.courses.domain.SessionRepository;
+import nextstep.courses.domain.repository.SessionRepository;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
@@ -20,7 +20,7 @@ class SessionRepositoryTest {
 
     @Test
     void crud() {
-        int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L,"제목", 3L)));
+        int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L, "제목", 3L)));
         Session session = sessionRepository.findById((long) id);
         assertThat(session.id()).isEqualTo(id);
     }

From be7549b85a03eb2532bea6ff17b859d4a5212978 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Fri, 15 Dec 2023 16:34:22 +0900
Subject: [PATCH 13/15] =?UTF-8?q?feat:=20=EC=88=98=EA=B0=95=EC=8B=A0?=
 =?UTF-8?q?=EC=B2=AD=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=83=9D=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../domain/repository/SessionRepository.java  |  4 ++-
 .../infrastructure/JdbcSessionRepository.java |  5 ++--
 .../courses/service/SessionService.java       | 28 +++++++++++++++++++
 .../payments/service/PaymentService.java      | 10 +------
 .../infrastructure/SessionRepositoryTest.java |  2 +-
 5 files changed, 36 insertions(+), 13 deletions(-)
 create mode 100644 src/main/java/nextstep/courses/service/SessionService.java

diff --git a/src/main/java/nextstep/courses/domain/repository/SessionRepository.java b/src/main/java/nextstep/courses/domain/repository/SessionRepository.java
index 9dca1bb59..535cf1062 100644
--- a/src/main/java/nextstep/courses/domain/repository/SessionRepository.java
+++ b/src/main/java/nextstep/courses/domain/repository/SessionRepository.java
@@ -2,8 +2,10 @@
 
 import nextstep.courses.domain.Session;
 
+import java.util.Optional;
+
 public interface SessionRepository {
     int save(Session session);
 
-    Session findById(Long id);
+    Optional<Session> findById(Long id);
 }
diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
index 59d6c29b2..c10eb3a94 100644
--- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
+++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java
@@ -8,6 +8,7 @@
 import org.springframework.stereotype.Repository;
 
 import java.time.LocalDateTime;
+import java.util.Optional;
 
 import static nextstep.courses.utils.DateUtil.toLocalDateTime;
 
@@ -28,7 +29,7 @@ public int save(Session session) {
     }
 
     @Override
-    public Session findById(Long id) {
+    public Optional<Session> findById(Long id) {
         String sql = "select id, begin_dt, end_dt, session_status, capacity, price, " +
                 "course_id, session_cover_id, created_at, updated_at " +
                 "from session where id = ?";
@@ -46,6 +47,6 @@ public Session findById(Long id) {
                 toLocalDateTime(rs.getTimestamp(10))
         );
 
-        return jdbcTemplate.queryForObject(sql, rowMapper, id);
+        return Optional.of(jdbcTemplate.queryForObject(sql, rowMapper, id));
     }
 }
diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java
new file mode 100644
index 000000000..ea058aab9
--- /dev/null
+++ b/src/main/java/nextstep/courses/service/SessionService.java
@@ -0,0 +1,28 @@
+package nextstep.courses.service;
+
+import nextstep.courses.domain.Registration;
+import nextstep.courses.domain.Session;
+import nextstep.courses.domain.repository.RegistrationRepository;
+import nextstep.courses.domain.repository.SessionRepository;
+import nextstep.users.domain.NsUser;
+import nextstep.users.domain.UserRepository;
+
+
+public class SessionService {
+    private final RegistrationRepository registrationRepository;
+    private final SessionRepository sessionRepository;
+    private final UserRepository userRepository;
+
+    public SessionService(RegistrationRepository registrationRepository, SessionRepository sessionRepository, UserRepository userRepository) {
+        this.registrationRepository = registrationRepository;
+        this.sessionRepository = sessionRepository;
+        this.userRepository = userRepository;
+    }
+
+    public void registerSession(String userId, Long sessionId, Long amount) {
+        NsUser user = userRepository.findByUserId(userId).orElseThrow(() -> new IllegalArgumentException("유효한 userId가 아닙니다."));
+        Session session = sessionRepository.findById(sessionId).orElseThrow(() -> new IllegalArgumentException("유효한 sessionId가 아닙니다."));;
+
+        registrationRepository.save(Registration.register(user, session, amount));
+    }
+}
diff --git a/src/main/java/nextstep/payments/service/PaymentService.java b/src/main/java/nextstep/payments/service/PaymentService.java
index 50e3ace9b..e43203c2d 100644
--- a/src/main/java/nextstep/payments/service/PaymentService.java
+++ b/src/main/java/nextstep/payments/service/PaymentService.java
@@ -1,22 +1,14 @@
 package nextstep.payments.service;
 
-import nextstep.courses.domain.Registration;
 import nextstep.courses.domain.Session;
-import nextstep.courses.infrastructure.JdbcRegistrationRepository;
 import nextstep.payments.domain.Payment;
 import nextstep.users.domain.NsUser;
 import org.springframework.stereotype.Service;
 
 @Service
 public class PaymentService {
-    private final JdbcRegistrationRepository jdbcRegistrationRepository;
 
-    public PaymentService(JdbcRegistrationRepository jdbcRegistrationRepository) {
-        this.jdbcRegistrationRepository = jdbcRegistrationRepository;
-    }
-
-    public Payment payment(NsUser user, Session session, Long amount) {;
-        jdbcRegistrationRepository.save(Registration.register(user, session, amount));
+    public Payment payment(NsUser user, Session session, Long amount) {
         return new Payment(session.id());
     }
 }
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
index 1a76e7087..1fc5dffe8 100644
--- a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
@@ -21,7 +21,7 @@ class SessionRepositoryTest {
     @Test
     void crud() {
         int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L, "제목", 3L)));
-        Session session = sessionRepository.findById((long) id);
+        Session session = sessionRepository.findById((long) id).orElseThrow(() -> new IllegalArgumentException("유효하지 않은 id입니다."));
         assertThat(session.id()).isEqualTo(id);
     }
 }
\ No newline at end of file

From 766f65ba140bb398f7fc653142b2ca935319c27c Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Fri, 15 Dec 2023 17:21:07 +0900
Subject: [PATCH 14/15] =?UTF-8?q?feat:=20=EC=88=98=EA=B0=95=EC=8B=A0?=
 =?UTF-8?q?=EC=B2=AD=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=83=9D=EC=84=B1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../java/nextstep/courses/domain/Session.java | 30 +++++++++++++-----
 .../courses/service/SessionService.java       | 31 +++++++++++++++++--
 .../nextstep/users/domain/UserRepository.java |  3 ++
 .../infrastructure/JdbcUserRepository.java    | 25 +++++++++++++++
 4 files changed, 80 insertions(+), 9 deletions(-)

diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 54232a08f..3f9092ae7 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -26,7 +26,7 @@ public Session(Long id) {
         this.id = id;
     }
 
-    public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
+    private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
@@ -47,6 +47,14 @@ public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatu
         this.updatedAt = updatedAt;
     }
 
+    public static Session fromSessionForFree(Session session, SessionCover sessionCover, Course course) {
+        return Session.ofFree(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course);
+    }
+
+    public static Session fromSessionForPaid(Session session, SessionCover sessionCover, Course course) {
+        return Session.ofPaid(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course, session.price.price(), session.capacity.capacity());
+    }
+
     public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
         return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(MAX_CAPACITY), new Price(FREE_PRICE));
     }
@@ -55,14 +63,15 @@ public static Session ofPaid(Long id, LocalDateTime beginDt, LocalDateTime endDt
         return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(capacity), new Price(price));
     }
 
-    public void startEnrollment() {
-        this.status = SessionStatus.ENROLL;
+    public static Session fromSession(Session session, SessionCover sessionCover, Course course) {
+        if (session.price.equals(0L)) {
+            return fromSessionForFree(session, sessionCover, course);
+        }
+        return fromSessionForPaid(session, sessionCover, course);
     }
 
-    public void validateStatus() {
-        if (SessionStatus.ENROLL != this.status) {
-            throw new BusinessInvalidValueException("수강신청 가능한 상태가 아닙니다.");
-        }
+    public void startEnrollment() {
+        this.status = SessionStatus.ENROLL;
     }
 
     public void enroll(NsUser participant, Long amount) {
@@ -72,6 +81,13 @@ public void enroll(NsUser participant, Long amount) {
         this.participants.add(participant);
     }
 
+
+    private void validateStatus() {
+        if (SessionStatus.ENROLL != this.status) {
+            throw new BusinessInvalidValueException("수강신청 가능한 상태가 아닙니다.");
+        }
+    }
+
     public Price price() {
         return price;
     }
diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java
index ea058aab9..cdf78d10d 100644
--- a/src/main/java/nextstep/courses/service/SessionService.java
+++ b/src/main/java/nextstep/courses/service/SessionService.java
@@ -1,28 +1,55 @@
 package nextstep.courses.service;
 
+import nextstep.courses.domain.Course;
 import nextstep.courses.domain.Registration;
 import nextstep.courses.domain.Session;
+import nextstep.courses.domain.SessionCover;
+import nextstep.courses.domain.repository.CourseRepository;
 import nextstep.courses.domain.repository.RegistrationRepository;
+import nextstep.courses.domain.repository.SessionCoverRepository;
 import nextstep.courses.domain.repository.SessionRepository;
 import nextstep.users.domain.NsUser;
 import nextstep.users.domain.UserRepository;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
+import java.util.List;
+import java.util.stream.Collectors;
 
+@Service
 public class SessionService {
+    private final CourseRepository courseRepository;
     private final RegistrationRepository registrationRepository;
     private final SessionRepository sessionRepository;
     private final UserRepository userRepository;
+    private final SessionCoverRepository sessionCoverRepository;
 
-    public SessionService(RegistrationRepository registrationRepository, SessionRepository sessionRepository, UserRepository userRepository) {
+    public SessionService(CourseRepository courseRepository, RegistrationRepository registrationRepository, SessionRepository sessionRepository, UserRepository userRepository, SessionCoverRepository sessionCoverRepository) {
+        this.courseRepository = courseRepository;
         this.registrationRepository = registrationRepository;
         this.sessionRepository = sessionRepository;
         this.userRepository = userRepository;
+        this.sessionCoverRepository = sessionCoverRepository;
     }
 
+    @Transactional
     public void registerSession(String userId, Long sessionId, Long amount) {
         NsUser user = userRepository.findByUserId(userId).orElseThrow(() -> new IllegalArgumentException("유효한 userId가 아닙니다."));
-        Session session = sessionRepository.findById(sessionId).orElseThrow(() -> new IllegalArgumentException("유효한 sessionId가 아닙니다."));;
+        Session session = retrieveSession(sessionId);
 
         registrationRepository.save(Registration.register(user, session, amount));
     }
+
+    private Session retrieveSession(Long sessionId) {
+        Session session = sessionRepository.findById(sessionId).orElseThrow(() -> new IllegalArgumentException("유효한 sessionId가 아닙니다."));
+
+        Course course = courseRepository.findById(session.course().id());
+        SessionCover sessionCover = sessionCoverRepository.findById(session.sessionCover().id());
+        List<Registration> registrations = registrationRepository.findAllBySessionId(sessionId);
+        List<NsUser> users = userRepository.findAllByIds(registrations.stream().map(r -> r.nsUser().getId()).collect(Collectors.toList()));
+
+        return Session.fromSession(session, sessionCover, course);
+    }
+
+
 }
diff --git a/src/main/java/nextstep/users/domain/UserRepository.java b/src/main/java/nextstep/users/domain/UserRepository.java
index 745a85dc1..b0618c3b7 100755
--- a/src/main/java/nextstep/users/domain/UserRepository.java
+++ b/src/main/java/nextstep/users/domain/UserRepository.java
@@ -1,7 +1,10 @@
 package nextstep.users.domain;
 
+import java.util.List;
 import java.util.Optional;
 
 public interface UserRepository {
     Optional<NsUser> findByUserId(String userId);
+
+    List<NsUser> findAllByIds(List<Long> ids);
 }
diff --git a/src/main/java/nextstep/users/infrastructure/JdbcUserRepository.java b/src/main/java/nextstep/users/infrastructure/JdbcUserRepository.java
index 005f04fc5..2c42cb12e 100644
--- a/src/main/java/nextstep/users/infrastructure/JdbcUserRepository.java
+++ b/src/main/java/nextstep/users/infrastructure/JdbcUserRepository.java
@@ -4,10 +4,14 @@
 import nextstep.users.domain.UserRepository;
 import org.springframework.jdbc.core.JdbcOperations;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 import org.springframework.stereotype.Repository;
 
 import java.sql.Timestamp;
 import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 @Repository("userRepository")
@@ -32,6 +36,27 @@ public Optional<NsUser> findByUserId(String userId) {
         return Optional.of(jdbcTemplate.queryForObject(sql, rowMapper, userId));
     }
 
+    @Override
+    public List<NsUser> findAllByIds(List<Long> ids) {
+        NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
+
+        String sql = "SELECT id, user_id, password, name, email, created_at, updated_at FROM ns_user WHERE id IN (:ids)";
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("ids", ids);
+
+        RowMapper<NsUser> rowMapper = (rs, rowNum) -> new NsUser(
+                rs.getLong("id"),
+                rs.getString("user_id"),
+                rs.getString("password"),
+                rs.getString("name"),
+                rs.getString("email"),
+                toLocalDateTime(rs.getTimestamp("created_at")),
+                toLocalDateTime(rs.getTimestamp("updated_at")));
+
+        return namedParameterJdbcTemplate.query(sql, params, rowMapper);
+    }
+
     private LocalDateTime toLocalDateTime(Timestamp timestamp) {
         if (timestamp == null) {
             return null;

From f1362b6188c9cb4254b9afe396fb016f84ee4494 Mon Sep 17 00:00:00 2001
From: Hyesooo <hyesookim95@gmail.com>
Date: Fri, 15 Dec 2023 17:44:48 +0900
Subject: [PATCH 15/15] =?UTF-8?q?fix:=20=EC=88=98=EA=B0=95=EC=8B=A0?=
 =?UTF-8?q?=EC=B2=AD=20=EC=84=9C=EB=B9=84=EC=8A=A4=20Session=20=EC=A1=B0?=
 =?UTF-8?q?=ED=9A=8C=EC=8B=9C=20=EC=88=98=EA=B0=95=EC=83=9D(nsUser)=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=98=EC=97=AC=20=EB=93=B1=EB=A1=9D?=
 =?UTF-8?q?=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

---
 .../java/nextstep/courses/domain/Session.java | 28 +++++++++----------
 .../courses/service/SessionService.java       |  4 ++-
 .../nextstep/courses/domain/SessionTest.java  | 11 ++++----
 .../RegistrationRepositoryTest.java           |  3 +-
 .../infrastructure/SessionRepositoryTest.java |  3 +-
 5 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java
index 3f9092ae7..32e4d66b2 100644
--- a/src/main/java/nextstep/courses/domain/Session.java
+++ b/src/main/java/nextstep/courses/domain/Session.java
@@ -6,7 +6,6 @@
 import nextstep.users.domain.NsUser;
 
 import java.time.LocalDateTime;
-import java.util.ArrayList;
 import java.util.List;
 
 public class Session extends BaseEntity {
@@ -20,19 +19,20 @@ public class Session extends BaseEntity {
     private Price price;
 
     private SessionStatus status = SessionStatus.PREPARE;
-    private List<NsUser> participants = new ArrayList<>();
+    private List<NsUser> participants;
 
     public Session(Long id) {
         this.id = id;
     }
 
-    private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price) {
+    private Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Capacity capacity, Price price, List<NsUser> participants) {
         this.id = id;
         this.period = new Period(beginDt, endDt);
         this.sessionCover = sessionCover;
         this.course = course;
         this.capacity = capacity;
         this.price = price;
+        this.participants = participants;
     }
 
     public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatus status, Capacity capacity, Price price, Course course, SessionCover sessionCover, LocalDateTime createdAt, LocalDateTime updatedAt) {
@@ -47,27 +47,27 @@ public Session(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionStatu
         this.updatedAt = updatedAt;
     }
 
-    public static Session fromSessionForFree(Session session, SessionCover sessionCover, Course course) {
-        return Session.ofFree(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course);
+    public static Session fromSessionForFree(Session session, SessionCover sessionCover, Course course, List<NsUser> participants) {
+        return Session.ofFree(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course, participants);
     }
 
-    public static Session fromSessionForPaid(Session session, SessionCover sessionCover, Course course) {
-        return Session.ofPaid(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course, session.price.price(), session.capacity.capacity());
+    public static Session fromSessionForPaid(Session session, SessionCover sessionCover, Course course, List<NsUser> participants) {
+        return Session.ofPaid(session.id, session.period.getBeginDt(), session.period.getEndDt(), sessionCover, course, session.price.price(), session.capacity.capacity(), participants);
     }
 
-    public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course) {
-        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(MAX_CAPACITY), new Price(FREE_PRICE));
+    public static Session ofFree(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, List<NsUser> participants) {
+        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(MAX_CAPACITY), new Price(FREE_PRICE), participants);
     }
 
-    public static Session ofPaid(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Long price, Integer capacity) {
-        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(capacity), new Price(price));
+    public static Session ofPaid(Long id, LocalDateTime beginDt, LocalDateTime endDt, SessionCover sessionCover, Course course, Long price, Integer capacity, List<NsUser> participants) {
+        return new Session(id, beginDt, endDt, sessionCover, course, new Capacity(capacity), new Price(price), participants);
     }
 
-    public static Session fromSession(Session session, SessionCover sessionCover, Course course) {
+    public static Session fromSession(Session session, SessionCover sessionCover, Course course, List<NsUser> participants) {
         if (session.price.equals(0L)) {
-            return fromSessionForFree(session, sessionCover, course);
+            return fromSessionForFree(session, sessionCover, course, participants);
         }
-        return fromSessionForPaid(session, sessionCover, course);
+        return fromSessionForPaid(session, sessionCover, course, participants);
     }
 
     public void startEnrollment() {
diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java
index cdf78d10d..b69a191fe 100644
--- a/src/main/java/nextstep/courses/service/SessionService.java
+++ b/src/main/java/nextstep/courses/service/SessionService.java
@@ -44,11 +44,13 @@ private Session retrieveSession(Long sessionId) {
         Session session = sessionRepository.findById(sessionId).orElseThrow(() -> new IllegalArgumentException("유효한 sessionId가 아닙니다."));
 
         Course course = courseRepository.findById(session.course().id());
+
         SessionCover sessionCover = sessionCoverRepository.findById(session.sessionCover().id());
+
         List<Registration> registrations = registrationRepository.findAllBySessionId(sessionId);
         List<NsUser> users = userRepository.findAllByIds(registrations.stream().map(r -> r.nsUser().getId()).collect(Collectors.toList()));
 
-        return Session.fromSession(session, sessionCover, course);
+        return Session.fromSession(session, sessionCover, course, users);
     }
 
 
diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java
index a474250c7..6a36f4d25 100644
--- a/src/test/java/nextstep/courses/domain/SessionTest.java
+++ b/src/test/java/nextstep/courses/domain/SessionTest.java
@@ -5,6 +5,7 @@
 import org.junit.jupiter.api.Test;
 
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 
 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -13,7 +14,7 @@ class SessionTest {
 
     @Test
     void 무료강의생성() {
-        Session freeSession = Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(3L, 300, 200, 1024, new byte[100]), new Course());
+        Session freeSession = Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(3L, 300, 200, 1024, new byte[100]), new Course(), new ArrayList<>());
         assertThat(freeSession.id()).isEqualTo(1L);
     }
 
@@ -23,13 +24,13 @@ class SessionTest {
         int sessionCapacity = 100;
 
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(4L, 300, 200, 1024, new byte[100]), new Course(), sessionPrice, sessionCapacity);
+                new SessionCover(4L, 300, 200, 1024, new byte[100]), new Course(), sessionPrice, sessionCapacity, new ArrayList<>());
         assertThat(paidSession.id()).isEqualTo(2L);
     }
 
     @Test
     void 수강신청상태_exception() {
-        Session session = Session.ofFree(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(5L, 300, 200, 1024, new byte[100]), new Course());
+        Session session = Session.ofFree(5L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(5L, 300, 200, 1024, new byte[100]), new Course(), new ArrayList<>());
         assertThatExceptionOfType(BusinessInvalidValueException.class)
                 .isThrownBy(() -> session.enroll(new NsUser(), 0L))
                 .withMessage("수강신청 가능한 상태가 아닙니다.");
@@ -38,7 +39,7 @@ class SessionTest {
     @Test
     void 최대수강인원_exception() {
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(6L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 0);
+                new SessionCover(6L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 0, new ArrayList<>());
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)
@@ -49,7 +50,7 @@ class SessionTest {
     @Test
     void 가격비교_exception() {
         Session paidSession = Session.ofPaid(2L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1),
-                new SessionCover(7L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 1);
+                new SessionCover(7L, 300, 200, 1024, new byte[100]), new Course(), 10000L, 1, new ArrayList<>());
         paidSession.startEnrollment();
 
         assertThatExceptionOfType(BusinessInvalidValueException.class)
diff --git a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
index f3ef2e57d..9fdd6198a 100644
--- a/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/RegistrationRepositoryTest.java
@@ -11,6 +11,7 @@
 import org.springframework.boot.test.context.SpringBootTest;
 
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
@@ -24,7 +25,7 @@ class RegistrationRepositoryTest {
     @Test
     void crud() {
         int id = registrationRepository.save(new Registration(new NsUser(1L, "1", "2", "3", "4")
-                , Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(1L, 300, 200, 1024, new byte[100]), new Course())
+                , Session.ofFree(1L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(1L, 300, 200, 1024, new byte[100]), new Course(), new ArrayList<>())
                 , 100000L));
         List<Registration> registrations = registrationRepository.findAllBySessionId(1L);
         assertThat(registrations.get(0).nsUser().getId()).isEqualTo(1L);
diff --git a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
index 1fc5dffe8..dc357724e 100644
--- a/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
+++ b/src/test/java/nextstep/courses/infrastructure/SessionRepositoryTest.java
@@ -9,6 +9,7 @@
 import org.springframework.boot.test.context.SpringBootTest;
 
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 
 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 
@@ -20,7 +21,7 @@ class SessionRepositoryTest {
 
     @Test
     void crud() {
-        int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L, "제목", 3L)));
+        int id = sessionRepository.save(Session.ofFree(3L, LocalDateTime.now(), LocalDateTime.now().plusMonths(1), new SessionCover(100L, 300, 200, 1024, new byte[100]), new Course(100L, "제목", 3L), new ArrayList<>()));
         Session session = sessionRepository.findById((long) id).orElseThrow(() -> new IllegalArgumentException("유효하지 않은 id입니다."));
         assertThat(session.id()).isEqualTo(id);
     }