diff --git a/1 WEEK/core/1 week.md b/1 WEEK/core/1 week.md
index 283a343d..e016776a 100644
--- a/1 WEEK/core/1 week.md
+++ b/1 WEEK/core/1 week.md
@@ -445,6 +445,9 @@ class OrderServiceTest {
}
```
## HOME WORK
-1. 위 코드의 핵심은 무엇일까요?
-2. 위 코드의 문제점은 무엇일까요?
-3. 그 해결 방법은 무엇일까요?
+1. 위 코드의 핵심은 무엇일까요?
+ -- 관심사 분리, 추상화 클래스에 의존이 핵심이라 생각됩니다.
+2. 위 코드의 문제점은 무엇일까요?
+ -- 할인 정책이나, 데이터 저장 부분이 바뀌었을 때, 그와 관련된 모든 코드를 수정해야한다는 점과 Order 클래스가 2개 이상의 책임을 지고 있는것이 문제점입니다.
+3. 그 해결 방법은 무엇일까요?
+ -- 의존성을 주입해주는 클래스를 따로 만들어주고, Order 클래스는 책임을 1가지만 지도록 calculatePrice() 메서드를 빼주는 것으로 해결해야 합니다.
diff --git a/10 WEEK/students/.gitignore b/10 WEEK/students/.gitignore
new file mode 100644
index 00000000..c2065bc2
--- /dev/null
+++ b/10 WEEK/students/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/10 WEEK/students/build.gradle b/10 WEEK/students/build.gradle
new file mode 100644
index 00000000..59323230
--- /dev/null
+++ b/10 WEEK/students/build.gradle
@@ -0,0 +1,34 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.2.2'
+ id 'io.spring.dependency-management' version '1.1.4'
+}
+
+group = 'yebin'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/10 WEEK/students/gradle/wrapper/gradle-wrapper.jar b/10 WEEK/students/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..d64cd491
Binary files /dev/null and b/10 WEEK/students/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/10 WEEK/students/gradle/wrapper/gradle-wrapper.properties b/10 WEEK/students/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1af9e093
--- /dev/null
+++ b/10 WEEK/students/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/10 WEEK/students/gradlew b/10 WEEK/students/gradlew
new file mode 100644
index 00000000..1aa94a42
--- /dev/null
+++ b/10 WEEK/students/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/10 WEEK/students/gradlew.bat b/10 WEEK/students/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/10 WEEK/students/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/10 WEEK/students/settings.gradle b/10 WEEK/students/settings.gradle
new file mode 100644
index 00000000..6193f06f
--- /dev/null
+++ b/10 WEEK/students/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'students'
diff --git a/10 WEEK/students/src/main/java/yebin/students/StudentRepository.java b/10 WEEK/students/src/main/java/yebin/students/StudentRepository.java
new file mode 100644
index 00000000..f48bc309
--- /dev/null
+++ b/10 WEEK/students/src/main/java/yebin/students/StudentRepository.java
@@ -0,0 +1,47 @@
+package yebin.students;
+
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class StudentRepository {
+ private static final Map store = new HashMap<>();
+
+
+ public Students save(Students student){
+ store.put(student.getId(), student);
+ return student;
+ }
+
+ public Students findById(Long id){
+ return store.get(id);
+ }
+
+ public List findAll(){
+ return new ArrayList<>(store.values());
+ }
+
+ public void update(Long id, Students updateStudent){
+ //DB 에서 회원 정보를 찾는다 [ 이미 별도 메서드로 구분 되어 있음 ] 추상화 레벨 2
+ Students findStudent = store.get(id);
+ //Entity 정보를 수정한다. : 추상화 레벨 2
+ findStudent.setName(updateStudent.getName());
+ findStudent.setGrade(updateStudent.getGrade());
+ findStudent.setMajor(updateStudent.getMajor());
+ //DB 에 새로운 정보를 저장한다. : [ 이미 별도 메서드로 구분 되어 있음 ] 추상화 레벨 2
+ save(findStudent);
+ }
+
+
+ public void delete(Long id){
+ store.remove(id);
+ }
+
+ public void clearStore(){
+ store.clear();
+ }
+}
diff --git a/10 WEEK/students/src/main/java/yebin/students/StudentService.java b/10 WEEK/students/src/main/java/yebin/students/StudentService.java
new file mode 100644
index 00000000..00e40cfa
--- /dev/null
+++ b/10 WEEK/students/src/main/java/yebin/students/StudentService.java
@@ -0,0 +1,11 @@
+package yebin.students;
+
+import java.util.List;
+
+public interface StudentService {
+ public void join(Students student);
+ public Students showStudentInForById(Long studentId);
+ public void deleteStudentInFortById(Long studentId);
+ public void updateStudentInForById(Long studentId, Students updateStudent);
+ public boolean multiDeleteStudentInForById(List studentId);
+}
diff --git a/10 WEEK/students/src/main/java/yebin/students/StudentServiceImpl.java b/10 WEEK/students/src/main/java/yebin/students/StudentServiceImpl.java
new file mode 100644
index 00000000..2eb68070
--- /dev/null
+++ b/10 WEEK/students/src/main/java/yebin/students/StudentServiceImpl.java
@@ -0,0 +1,40 @@
+package yebin.students;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+@RequiredArgsConstructor
+public class StudentServiceImpl implements StudentService{
+ private final StudentRepository studentRepository;
+ @Override
+ public void join(Students student) {
+ studentRepository.save(student);
+ }
+
+ @Override
+ public Students showStudentInForById(Long studentId) {
+ return studentRepository.findById(studentId);
+ }
+
+ @Override
+ public void deleteStudentInFortById(Long studentId) {
+ studentRepository.delete(studentId);
+ }
+
+ @Override
+ public void updateStudentInForById(Long studentId, Students updateStudent) {
+ studentRepository.update(studentId, updateStudent);
+ }
+
+ @Override
+ public boolean multiDeleteStudentInForById(List studentId){
+ for (Long id : studentId) {
+ studentRepository.delete(id);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/10 WEEK/students/src/main/java/yebin/students/Students.java b/10 WEEK/students/src/main/java/yebin/students/Students.java
new file mode 100644
index 00000000..206d6785
--- /dev/null
+++ b/10 WEEK/students/src/main/java/yebin/students/Students.java
@@ -0,0 +1,21 @@
+package yebin.students;
+
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Students {
+ private String name;
+ private Long id;
+ private Integer grade;
+ private String major;
+
+ public Students(String name, Long id,Integer grade, String major){
+ this.name = name;
+ this.id = id;
+ this.grade = grade;
+ this.major = major;
+ }
+}
diff --git a/10 WEEK/students/src/main/java/yebin/students/StudentsApplication.java b/10 WEEK/students/src/main/java/yebin/students/StudentsApplication.java
new file mode 100644
index 00000000..87fd4b25
--- /dev/null
+++ b/10 WEEK/students/src/main/java/yebin/students/StudentsApplication.java
@@ -0,0 +1,13 @@
+package yebin.students;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class StudentsApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StudentsApplication.class, args);
+ }
+
+}
diff --git a/10 WEEK/students/src/main/resources/application.properties b/10 WEEK/students/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/10 WEEK/students/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/10 WEEK/students/src/test/java/yebin/students/StudentRepositoryTest.java b/10 WEEK/students/src/test/java/yebin/students/StudentRepositoryTest.java
new file mode 100644
index 00000000..137a3926
--- /dev/null
+++ b/10 WEEK/students/src/test/java/yebin/students/StudentRepositoryTest.java
@@ -0,0 +1,70 @@
+package yebin.students;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+public class StudentRepositoryTest {
+ StudentRepository studentRepository = new StudentRepository();
+
+ @AfterEach
+ void afterEach(){
+ studentRepository.clearStore();
+ }
+
+ @Test
+ void save(){
+ //given
+ Students student = new Students("yebin", 4, "소프트웨어학과");
+ //when
+ Students saveStudent = studentRepository.save(student);
+ //then
+ Students findStudent = studentRepository.findById(student.getId());
+ Assertions.assertThat(findStudent).isEqualTo(saveStudent);
+ }
+
+ @Test
+ void findAll(){
+ //given
+ Students student1 = new Students("yebin", 4, "소프트웨어학과");
+ Students student2 = new Students("son", 4, "소프트웨어학과");
+ studentRepository.save(student1);
+ studentRepository.save(student2);
+ //when
+ List students = studentRepository.findAll();
+ //then
+ Assertions.assertThat(students.size()).isEqualTo(2);
+ Assertions.assertThat(students).contains(student1,student2);
+ }
+
+ @Test
+ void update(){
+ //given
+ Students student = new Students("yebin", 4, "소프트웨어학과");
+ Students savedStudent = studentRepository.save(student);
+ Long studentId = savedStudent.getId();
+ //when
+ Students updateStudent = new Students("son", 2, "전자공학과");
+ studentRepository.update(studentId,updateStudent);
+ Students findStudent = studentRepository.findById(studentId);
+ //then
+ Assertions.assertThat(findStudent.getName()).isEqualTo(updateStudent.getName());
+ Assertions.assertThat(findStudent.getGrade()).isEqualTo(updateStudent.getGrade());
+ Assertions.assertThat(findStudent.getMajor()).isEqualTo(updateStudent.getMajor());
+ }
+
+ @Test
+ void delete(){
+ //given
+ Students student = new Students("yebin", 4, "소프트웨어학과");
+ Students savedStudent = studentRepository.save(student);
+ Long studentId = savedStudent.getId();
+ //when
+ studentRepository.delete(studentId);
+ List students = studentRepository.findAll();
+ //then
+ Assertions.assertThat(students.size()).isEqualTo(0);
+ }
+}
diff --git a/10 WEEK/students/src/test/java/yebin/students/StudentsApplicationTests.java b/10 WEEK/students/src/test/java/yebin/students/StudentsApplicationTests.java
new file mode 100644
index 00000000..4dd4e763
--- /dev/null
+++ b/10 WEEK/students/src/test/java/yebin/students/StudentsApplicationTests.java
@@ -0,0 +1,13 @@
+package yebin.students;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class StudentsApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/12 WEEK/student/student/.gitignore b/12 WEEK/student/student/.gitignore
new file mode 100644
index 00000000..c2065bc2
--- /dev/null
+++ b/12 WEEK/student/student/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/12 WEEK/student/student/build.gradle b/12 WEEK/student/student/build.gradle
new file mode 100644
index 00000000..c7415fe4
--- /dev/null
+++ b/12 WEEK/student/student/build.gradle
@@ -0,0 +1,34 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.2.2'
+ id 'io.spring.dependency-management' version '1.1.4'
+}
+
+group = 'student'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.jar b/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..d64cd491
Binary files /dev/null and b/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.properties b/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1af9e093
--- /dev/null
+++ b/12 WEEK/student/student/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/12 WEEK/student/student/gradlew b/12 WEEK/student/student/gradlew
new file mode 100644
index 00000000..1aa94a42
--- /dev/null
+++ b/12 WEEK/student/student/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/12 WEEK/student/student/gradlew.bat b/12 WEEK/student/student/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/12 WEEK/student/student/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/12 WEEK/student/student/settings.gradle b/12 WEEK/student/student/settings.gradle
new file mode 100644
index 00000000..d3e43d80
--- /dev/null
+++ b/12 WEEK/student/student/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'student'
diff --git a/12 WEEK/student/student/src/main/java/student/student/ENUM/Grade.java b/12 WEEK/student/student/src/main/java/student/student/ENUM/Grade.java
new file mode 100644
index 00000000..c29e2777
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/ENUM/Grade.java
@@ -0,0 +1,5 @@
+package student.student.ENUM;
+
+public enum Grade {
+ freshman, sophomore, junior, senior, the_5th
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/ENUM/Major.java b/12 WEEK/student/student/src/main/java/student/student/ENUM/Major.java
new file mode 100644
index 00000000..d6f36211
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/ENUM/Major.java
@@ -0,0 +1,5 @@
+package student.student.ENUM;
+
+public enum Major {
+ 소프트웨어학과, 컴퓨터공학과, 산업디자인학과
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/ENUM/Semester.java b/12 WEEK/student/student/src/main/java/student/student/ENUM/Semester.java
new file mode 100644
index 00000000..cfa92bea
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/ENUM/Semester.java
@@ -0,0 +1,5 @@
+package student.student.ENUM;
+
+public enum Semester {
+ first, second
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/Student.java b/12 WEEK/student/student/src/main/java/student/student/Student.java
new file mode 100644
index 00000000..4e20127c
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/Student.java
@@ -0,0 +1,50 @@
+package student.student;
+
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import student.student.ENUM.Grade;
+import student.student.ENUM.Major;
+import student.student.ENUM.Semester;
+
+@Getter
+@Setter
+public class Student {
+ private Long id;
+ private Grade grade;
+ private String name;
+ private String brith;
+ private Integer birthYear;
+ private Integer birthMonth;
+ private Integer birthMonthOfDay;
+ private Major major;
+ private Semester semester;
+ private String address;
+
+ public Student(Long id, Grade grade, String name, String brith, Integer birthYear, Integer birthMonth, Integer birthMonthOfDay, Major major, Semester semester, String address) {
+ this.id = id;
+ this.grade = grade;
+ this.name = name;
+ this.brith = brith;
+ this.birthYear = birthYear;
+ this.birthMonth = birthMonth;
+ this.birthMonthOfDay = birthMonthOfDay;
+ this.major = major;
+ this.semester = semester;
+ this.address = address;
+ }
+
+ public void signUpFormData(Long id, String name, String birth, Semester semester, String address, Grade grade){
+ this.id = id;
+ this.name = name;
+ this.brith = birth;
+ this.semester = semester;
+ this.address = address;
+ this.grade = grade;
+ }
+
+ public void updateFormData(String name, String address){
+ this.name = name;
+ this.address = address;
+ }
+}
\ No newline at end of file
diff --git a/12 WEEK/student/student/src/main/java/student/student/StudentApplication.java b/12 WEEK/student/student/src/main/java/student/student/StudentApplication.java
new file mode 100644
index 00000000..f764084d
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/StudentApplication.java
@@ -0,0 +1,13 @@
+package student.student;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class StudentApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StudentApplication.class, args);
+ }
+
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/controller/StudentController.java b/12 WEEK/student/student/src/main/java/student/student/controller/StudentController.java
new file mode 100644
index 00000000..80717069
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/controller/StudentController.java
@@ -0,0 +1,45 @@
+package student.student.controller;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+import student.student.Student;
+import student.student.service.StudentService;
+
+import java.util.List;
+
+@Controller
+@RequiredArgsConstructor
+@RequestMapping("/student")
+public class StudentController {
+ private final StudentService studentService;
+
+ @PostMapping
+ public String addStudent(@ModelAttribute Student student){
+ Object saveStudentData = studentService.saveStudent(student);
+ return "/addStudentForm";
+ }
+
+ @GetMapping("/{studentId}")
+ public String showStudentByStudentId(@PathVariable Long studentId, Model model){
+ Object findStudent = studentService.showStudentByStudentId(studentId);
+ model.addAttribute("findStudent",findStudent);
+ return "/findStudentForm";
+ }
+
+ @GetMapping
+ public String showAllStudents(Model model){
+ List students = studentService.showAllStudents();
+ model.addAttribute("findAllStudents",students);
+ return "/findStudentForm";
+ }
+
+ @PatchMapping("/{studentId}")
+ public String updateStudentByStudentId(@PathVariable Long studentId, @ModelAttribute Student updateStudent){
+ studentService.updateStudentByStudentId(studentId, updateStudent);
+ return "/updateStudentForm";
+ }
+
+
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/repository/StudentRepository.java b/12 WEEK/student/student/src/main/java/student/student/repository/StudentRepository.java
new file mode 100644
index 00000000..33b47f59
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/repository/StudentRepository.java
@@ -0,0 +1,39 @@
+package student.student.repository;
+
+import org.springframework.stereotype.Repository;
+import student.student.Student;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class StudentRepository {
+ private static final Map store = new HashMap<>();
+
+ public Student save(Student student){
+ store.put(student.getId(), student);
+ return student;
+ }
+
+ public Student findById(Long studentId){
+ return store.get(studentId);
+ }
+
+ public List findAll(){
+ return new ArrayList<>(store.values());
+ }
+
+ public void update(Long studentId, Student updateStudent){
+ Student findStudent = findById(studentId);
+ updateStudentInformation(findStudent,updateStudent);
+ save(findStudent);
+ }
+
+ private void updateStudentInformation(Student findStudent, Student updateStudent){
+ findStudent.setName(updateStudent.getName());
+ findStudent.setAddress(updateStudent.getAddress());
+ }
+}
+
diff --git a/12 WEEK/student/student/src/main/java/student/student/service/StudentService.java b/12 WEEK/student/student/src/main/java/student/student/service/StudentService.java
new file mode 100644
index 00000000..11adbcf3
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/service/StudentService.java
@@ -0,0 +1,12 @@
+package student.student.service;
+
+import student.student.Student;
+
+import java.util.List;
+
+public interface StudentService {
+ Object saveStudent(Student student);
+ Student showStudentByStudentId(Long studentId);
+ List showAllStudents();
+ Object updateStudentByStudentId(Long studentId, Student updateStudent);
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/service/StudentServiceImpl.java b/12 WEEK/student/student/src/main/java/student/student/service/StudentServiceImpl.java
new file mode 100644
index 00000000..513a0619
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/service/StudentServiceImpl.java
@@ -0,0 +1,84 @@
+package student.student.service;
+
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import student.student.Student;
+import student.student.repository.StudentRepository;
+import student.student.validation.ValidateStudent;
+
+import java.util.List;
+import java.util.Objects;
+
+@Service
+@RequiredArgsConstructor
+public class StudentServiceImpl implements StudentService{
+ private StudentRepository studentRepository;
+ private ValidateStudent validateStudent;
+ @Override
+ public Object saveStudent(Student student) {
+ Student findStudent = studentRepository.findById(student.getId());
+ // 저장하려는 학생 정보가 이미 있다면 해당 학생 정보 반환
+ if (!Objects.isNull(findStudent)){
+ return findStudent;
+ }
+ // 저장하려는 학생의 학번이 요구사항을 충족하지 못했다면 학번 반환
+ if(!validateStudent.validateStudentId(student.getId())){
+ return student.getId();
+ }
+ // 저장하려는 학생의 이름이 요구사항을 충족하지 못했다면 이름 반환
+ if(!validateStudent.validateStudentName(student.getName())){
+ return student.getName();
+ }
+ // 저장하려는 학생의 학과가 요구사항을 충족하지 못했다면 학과 반환
+ if(!validateStudent.validateMajor(student.getMajor())){
+ return student.getMajor();
+ }
+ // 저장하려는 학생의 학기가 요구사항을 충족하지 못했다면 학기 반환
+ if(!validateStudent.validateSemester(student.getSemester())){
+ return student.getSemester();
+ }
+ // 저장하려는 학생의 학년이 요구사항을 충족하지 못했다면 학년 반환
+ if(!validateStudent.validateGrade(student.getGrade())){
+ return student.getGrade();
+ }
+
+ return studentRepository.save(student);
+ }
+
+ @Override
+ public Student showStudentByStudentId(Long studentId) {
+ Student findStudent = studentRepository.findById(studentId);
+ // 찾으려는 학생의 정보가 없다면 null 반환?
+ if(Objects.isNull(findStudent)){
+ return null;
+ }
+
+ return findStudent;
+ }
+
+ @Override
+ public List showAllStudents() {
+ List students = studentRepository.findAll();
+ // 찾으려는 학생의 정보가 없다면 null 반환
+ if (Objects.isNull(students)){
+ return null;
+ }
+
+ return studentRepository.findAll();
+ }
+
+ @Override
+ public Object updateStudentByStudentId(Long studentId, Student updateStudent) {
+ Student findStudent = studentRepository.findById(studentId);
+ if(Objects.isNull(findStudent)){
+ return null;
+ }
+ // 수정하려는 학생의 이름이 요구사항을 충족하지 못했다면 이름 반환
+ if(validateStudent.validateStudentName(updateStudent.getName())){
+ return updateStudent.getName();
+ }
+
+ studentRepository.update(studentId,updateStudent);
+ return updateStudent;
+ }
+}
diff --git a/12 WEEK/student/student/src/main/java/student/student/validation/ValidateStudent.java b/12 WEEK/student/student/src/main/java/student/student/validation/ValidateStudent.java
new file mode 100644
index 00000000..a4871851
--- /dev/null
+++ b/12 WEEK/student/student/src/main/java/student/student/validation/ValidateStudent.java
@@ -0,0 +1,55 @@
+package student.student.validation;
+
+import student.student.ENUM.Grade;
+import student.student.ENUM.Major;
+import student.student.ENUM.Semester;
+import student.student.Student;
+
+import java.util.regex.Pattern;
+
+public class ValidateStudent {
+ public boolean validateStudentId(Long studentId){
+ if(studentId.SIZE != 7){
+ return false;
+ }
+ if(!Pattern.matches("[0-9+]",String.valueOf(studentId))){
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean validateStudentName(String studentName){
+ if(!Pattern.matches("^[ㄱ-ㅎ가-힣]*$",studentName)){
+ return false;
+ }
+ if(studentName.length() >= 2 && studentName.length() <= 7){
+ return false;
+ }
+ return true;
+ }
+
+ public boolean validateMajor(Major studentMajor){
+ // [ 소프트웨어, 컴퓨터공학, 산업디자인학과 외 금지 ] 이 의도를 표현하고 싶었으나 이렇게 하는건 아닌것 같은데..
+ if (studentMajor != Major.산업디자인학과 || studentMajor != Major.컴퓨터공학과 || studentMajor != Major.소프트웨어학과){
+ return false;
+ }
+ return true;
+ }
+
+ public boolean validateSemester(Semester studentSemester){
+ // 위와 동일,,
+ if(studentSemester != Semester.first || studentSemester != Semester.second){
+ return false;
+ }
+ return true;
+ }
+
+ public boolean validateGrade(Grade studentGrade){
+ // 위와 동일,,
+ if(studentGrade != Grade.freshman || studentGrade != Grade.sophomore || studentGrade != Grade.junior || studentGrade != Grade.senior || studentGrade !=Grade.the_5th){
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/12 WEEK/student/student/src/main/resources/application.properties b/12 WEEK/student/student/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/12 WEEK/student/student/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/12 WEEK/student/student/src/test/java/student/student/StudentApplicationTests.java b/12 WEEK/student/student/src/test/java/student/student/StudentApplicationTests.java
new file mode 100644
index 00000000..cace9524
--- /dev/null
+++ b/12 WEEK/student/student/src/test/java/student/student/StudentApplicationTests.java
@@ -0,0 +1,13 @@
+package student.student;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class StudentApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/2 WEEK/SON/ANSWER.md b/2 WEEK/SON/ANSWER.md
index 066e2c2a..1cf0c1b1 100644
--- a/2 WEEK/SON/ANSWER.md
+++ b/2 WEEK/SON/ANSWER.md
@@ -44,16 +44,37 @@ https://agilemanifesto.org/iso/ko/manifesto.html
---
## 주요 이론 요약
-
-Please provide a summary of your main theory here.
+Object Oriented Programming 설계 원칙
+
+OOP의 5원칙 ( SOLID )
+SRP ( Single Responsibility Prindiple ) : 한 클래스는 하나의 책임만 가져야 한다.
+OCP ( Open-Closed Prindiple ) : 확장에는 열려있으나, 변경에는 닫혀있어야한다.
+LSP ( Liskov's Substitution Principle ) : 하위객체는 상위객체와 교체할 수 있어야한다.
+ISP ( Interface Segregation Principle ) : 관심사에 맞게 인터페이스를 분리해야한다.
+DIP ( Dependency Inversion Principle ) : 구체화에 의존하지말고 추상화에 의존해야한다.
+
+OOP의 4가지 특징
+1. 캡슐화 2. 상속 3. 추상화 4. 다형성
## ISSUE
-Please enter your issue details here.
-
+SRP 위반 ---
+ Order 클래스 - calculatedPrice() 메서드가 Order 클래스내에 있으면 Order 클래스가 여러개의 책임을 갖으므로 SRP위반이라 생각됩니다.
+OCP 위반 ---
+ OrderServiceImpl 클래스 - memeberRepository와 discountPolicy를 직접 생성해주면 나중에 정책이 바뀌었을 때,
+ 이러한 변수를 선언한 코드들을 모두 수정해주어야하므로 OCP위반이라 생각됩니다.
+LSP 위반 ---
+
+ISP 위반 ---
+
+DIP 위반 ---
+
## Solution
-Please describe your solution in detail here.
+SRP 위반 ---
+ Order 클래스 - calculatedPrice()를 Order 클래스에서 빼내어 OrderService 클래스로 옮겨 책임을 한가지만 갖도록 해줍니다.
+OCP 위반 ---
+ OrderServiceImplt 클래스 - 의존성을 주입해주는 클래스를 새로 만들어 정책이 바뀌었을 시, 그 클래스만 수정하면 되도록 만들어줍니다.
## About
diff --git a/2 WEEK/SON/yebin/.gitignore b/2 WEEK/SON/yebin/.gitignore
new file mode 100644
index 00000000..c2065bc2
--- /dev/null
+++ b/2 WEEK/SON/yebin/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/2 WEEK/SON/yebin/build.gradle b/2 WEEK/SON/yebin/build.gradle
new file mode 100644
index 00000000..13d739db
--- /dev/null
+++ b/2 WEEK/SON/yebin/build.gradle
@@ -0,0 +1,38 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '2.7.17'
+ id 'io.spring.dependency-management' version '1.0.15.RELEASE'
+}
+
+group = 'com.yebin'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '11'
+}
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('bootBuildImage') {
+ builder = 'paketobuildpacks/builder-jammy-base:latest'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.jar b/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..7f93135c
Binary files /dev/null and b/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.properties b/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..3fa8f862
--- /dev/null
+++ b/2 WEEK/SON/yebin/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/2 WEEK/SON/yebin/gradlew b/2 WEEK/SON/yebin/gradlew
new file mode 100644
index 00000000..1aa94a42
--- /dev/null
+++ b/2 WEEK/SON/yebin/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/2 WEEK/SON/yebin/gradlew.bat b/2 WEEK/SON/yebin/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/2 WEEK/SON/yebin/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/2 WEEK/SON/yebin/settings.gradle b/2 WEEK/SON/yebin/settings.gradle
new file mode 100644
index 00000000..2e756485
--- /dev/null
+++ b/2 WEEK/SON/yebin/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'yebin'
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/MemberApp.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/MemberApp.java
new file mode 100644
index 00000000..d08a0e36
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/MemberApp.java
@@ -0,0 +1,25 @@
+package com.yebin.yebin;
+
+import com.yebin.yebin.dependency.AppConfig;
+import com.yebin.yebin.member.Grade;
+import com.yebin.yebin.member.Member;
+import com.yebin.yebin.member.MemberService;
+import com.yebin.yebin.member.MemberServiceImpl;
+
+public class MemberApp {
+ public static void main(String[] args) {
+ AppConfig appConfig = new AppConfig();
+ MemberService memberService =appConfig.memberService();
+
+ Member member = new Member("memberA", Grade.VIP);
+
+ memberService.join(member);
+
+ Member findMember = memberService.findMember(1L);
+
+ System.out.println("member = " + member.getName());
+ System.out.println("findMember = " + findMember.getName());
+
+
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/OrderApp.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/OrderApp.java
new file mode 100644
index 00000000..dfba847c
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/OrderApp.java
@@ -0,0 +1,26 @@
+package com.yebin.yebin;
+
+import com.yebin.yebin.dependency.AppConfig;
+import com.yebin.yebin.member.Grade;
+import com.yebin.yebin.member.Member;
+import com.yebin.yebin.member.MemberService;
+import com.yebin.yebin.member.MemberServiceImpl;
+import com.yebin.yebin.order.Order;
+import com.yebin.yebin.order.OrderService;
+import com.yebin.yebin.order.OrderServiceImpl;
+
+public class OrderApp {
+ public static void main(String[] args) {
+ AppConfig appConfig = new AppConfig();
+ MemberService memberService = appConfig.memberService();
+ OrderService orderService = appConfig.orderService();
+
+ Member member = new Member("memberA", Grade.VIP);
+ memberService.join(member);
+
+ Order order = orderService.createOrder(member.getId(),"itemA",10000);
+
+ System.out.println("order = " + order);
+
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/YebinApplication.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/YebinApplication.java
new file mode 100644
index 00000000..c14d586d
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/YebinApplication.java
@@ -0,0 +1,13 @@
+package com.yebin.yebin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class YebinApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(YebinApplication.class, args);
+ }
+
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/dependency/AppConfig.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/dependency/AppConfig.java
new file mode 100644
index 00000000..220170b0
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/dependency/AppConfig.java
@@ -0,0 +1,37 @@
+package com.yebin.yebin.dependency;
+
+import com.yebin.yebin.discount.DiscountPolicy;
+import com.yebin.yebin.discount.RateDiscountPolicy;
+import com.yebin.yebin.member.MemberRepository;
+import com.yebin.yebin.member.MemberService;
+import com.yebin.yebin.member.MemberServiceImpl;
+import com.yebin.yebin.member.MemoryMemberRepository;
+import com.yebin.yebin.order.OrderService;
+import com.yebin.yebin.order.OrderServiceImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AppConfig {
+ @Bean
+ public DiscountPolicy discountPolicy(){
+ // 할인 정책이 바뀌면 이 부분만 바꿔주면 된다.
+ return new RateDiscountPolicy();
+ }
+
+ @Bean
+ public MemberRepository memberRepository(){
+ // DB 연결하면 이 부분만 바꿔주면 된다.
+ return new MemoryMemberRepository();
+ }
+
+ @Bean
+ public MemberService memberService(){
+ return new MemberServiceImpl(memberRepository());
+ }
+
+ @Bean
+ public OrderService orderService(){
+ return new OrderServiceImpl(memberRepository(),discountPolicy());
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/DiscountPolicy.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/DiscountPolicy.java
new file mode 100644
index 00000000..ed10ed1b
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/DiscountPolicy.java
@@ -0,0 +1,7 @@
+package com.yebin.yebin.discount;
+
+import com.yebin.yebin.member.Member;
+
+public interface DiscountPolicy {
+ float discount(Member member, int price);
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/FixDiscountPolicy.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/FixDiscountPolicy.java
new file mode 100644
index 00000000..5c2d3118
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/FixDiscountPolicy.java
@@ -0,0 +1,19 @@
+package com.yebin.yebin.discount;
+
+import com.yebin.yebin.member.Grade;
+import com.yebin.yebin.member.Member;
+
+public class FixDiscountPolicy implements DiscountPolicy{
+ private int discountFixAmount = 1000;
+
+ @Override
+ public float discount(Member member, int price) {
+
+ if (member.getGrade() == Grade.VIP) {
+ return discountFixAmount;
+ }else {
+ return 0;
+ }
+
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/RateDiscountPolicy.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/RateDiscountPolicy.java
new file mode 100644
index 00000000..3a89ab08
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/discount/RateDiscountPolicy.java
@@ -0,0 +1,18 @@
+package com.yebin.yebin.discount;
+
+import com.yebin.yebin.member.Grade;
+import com.yebin.yebin.member.Member;
+import org.springframework.stereotype.Component;
+
+
+public class RateDiscountPolicy implements DiscountPolicy{
+ private float discountRate = 10;
+ @Override
+ public float discount(Member member, int price) {
+ if (member.getGrade() == Grade.VIP){
+ return price * (discountRate/100);
+ }
+
+ return 0;
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Grade.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Grade.java
new file mode 100644
index 00000000..d35ba28c
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Grade.java
@@ -0,0 +1,6 @@
+package com.yebin.yebin.member;
+
+public enum Grade {
+ BASIC,
+ VIP
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Member.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Member.java
new file mode 100644
index 00000000..85db9daa
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/Member.java
@@ -0,0 +1,20 @@
+package com.yebin.yebin.member;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Member {
+ private Long id;
+ private String name;
+ private Grade grade;
+
+ public Member( String name, Grade grade) {
+ this.name = name;
+ this.grade = grade;
+ }
+
+
+
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberRepository.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberRepository.java
new file mode 100644
index 00000000..bb51ae85
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberRepository.java
@@ -0,0 +1,7 @@
+package com.yebin.yebin.member;
+
+public interface MemberRepository {
+ void save(Member member);
+
+ Member findById(Long memberId);
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberService.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberService.java
new file mode 100644
index 00000000..49a89ab7
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberService.java
@@ -0,0 +1,7 @@
+package com.yebin.yebin.member;
+
+public interface MemberService {
+ void join(Member member);
+
+ Member findMember(Long memberId);
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberServiceImpl.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberServiceImpl.java
new file mode 100644
index 00000000..de7db79f
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemberServiceImpl.java
@@ -0,0 +1,27 @@
+package com.yebin.yebin.member;
+
+import com.yebin.yebin.dependency.AppConfig;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+
+public class MemberServiceImpl implements MemberService{
+
+ private final MemberRepository memberRepository;
+
+
+ public MemberServiceImpl(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+
+ @Override
+ public void join(Member member) {
+ memberRepository.save(member);
+ }
+
+ @Override
+ public Member findMember(Long memberId) {
+ return memberRepository.findById(memberId);
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemoryMemberRepository.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemoryMemberRepository.java
new file mode 100644
index 00000000..7689a99f
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/member/MemoryMemberRepository.java
@@ -0,0 +1,22 @@
+package com.yebin.yebin.member;
+
+import org.springframework.stereotype.Repository;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MemoryMemberRepository implements MemberRepository{
+ private static Map store = new HashMap<>();
+ private static long SEQUENCE = 0L;
+
+ @Override
+ public void save(Member member) {
+ member.setId(++SEQUENCE);
+ store.put(member.getId(),member);
+ }
+
+ @Override
+ public Member findById(Long memberId) {
+ return store.get(memberId);
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/Order.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/Order.java
new file mode 100644
index 00000000..735931ef
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/Order.java
@@ -0,0 +1,29 @@
+package com.yebin.yebin.order;
+
+public class Order {
+ private Long memberId;
+ private String itemName;
+ private int itemPrice;
+ private float discountPrice;
+
+ public Order(Long memberId, String itemName, int itemPrice, float discountPrice){
+ this.memberId = memberId;
+ this.itemName = itemName;
+ this.itemPrice = itemPrice;
+ this.discountPrice = discountPrice;
+ }
+
+ public float getDiscountPrice(){
+ return discountPrice;
+ }
+
+ @Override
+ public String toString() {
+ return "Order{" +
+ "memberId=" + memberId +
+ ", itemName='" + itemName + '\'' +
+ ", itemPrice=" + itemPrice +
+ ", discountPrice=" + discountPrice +
+ '}';
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderService.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderService.java
new file mode 100644
index 00000000..bd7ebbb5
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderService.java
@@ -0,0 +1,6 @@
+package com.yebin.yebin.order;
+
+public interface OrderService {
+ Order createOrder(Long memberId, String itemName, int itemPrice);
+ float calculatePrice(int itemPrice, float discountPrice);
+}
diff --git a/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderServiceImpl.java b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderServiceImpl.java
new file mode 100644
index 00000000..d56f6f6e
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/java/com/yebin/yebin/order/OrderServiceImpl.java
@@ -0,0 +1,32 @@
+package com.yebin.yebin.order;
+
+import com.yebin.yebin.dependency.AppConfig;
+import com.yebin.yebin.discount.DiscountPolicy;
+import com.yebin.yebin.member.Member;
+import com.yebin.yebin.member.MemberRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+public class OrderServiceImpl implements OrderService{
+ private final MemberRepository memberRepository;
+ private final DiscountPolicy discountPolicy;
+
+
+ public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy){
+ this.memberRepository = memberRepository;
+ this.discountPolicy = discountPolicy;
+ }
+
+ @Override
+ public Order createOrder(Long memberId, String itemName, int itemPrice) {
+ Member member = memberRepository.findById(memberId);
+ float discountPrice = discountPolicy.discount(member,itemPrice);
+ return new Order(memberId, itemName, itemPrice, discountPrice);
+ }
+
+ @Override
+ public float calculatePrice(int itemPrice, float discountPrice) {
+ return itemPrice - discountPrice;
+ }
+}
diff --git a/2 WEEK/SON/yebin/src/main/resources/application.properties b/2 WEEK/SON/yebin/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/2 WEEK/SON/yebin/src/test/java/com/yebin/yebin/YebinApplicationTests.java b/2 WEEK/SON/yebin/src/test/java/com/yebin/yebin/YebinApplicationTests.java
new file mode 100644
index 00000000..99fb928e
--- /dev/null
+++ b/2 WEEK/SON/yebin/src/test/java/com/yebin/yebin/YebinApplicationTests.java
@@ -0,0 +1,13 @@
+package com.yebin.yebin;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class YebinApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/4 WEEK/item-service/.gitignore b/4 WEEK/item-service/.gitignore
new file mode 100644
index 00000000..c2065bc2
--- /dev/null
+++ b/4 WEEK/item-service/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/4 WEEK/item-service/build.gradle b/4 WEEK/item-service/build.gradle
new file mode 100644
index 00000000..34550a7d
--- /dev/null
+++ b/4 WEEK/item-service/build.gradle
@@ -0,0 +1,38 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.1.6'
+ id 'io.spring.dependency-management' version '1.1.4'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('bootBuildImage') {
+ builder = 'paketobuildpacks/builder-jammy-base:latest'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.jar b/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..7f93135c
Binary files /dev/null and b/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.properties b/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..3fa8f862
--- /dev/null
+++ b/4 WEEK/item-service/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/4 WEEK/item-service/gradlew b/4 WEEK/item-service/gradlew
new file mode 100644
index 00000000..1aa94a42
--- /dev/null
+++ b/4 WEEK/item-service/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/4 WEEK/item-service/gradlew.bat b/4 WEEK/item-service/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/4 WEEK/item-service/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/4 WEEK/item-service/item-service/.gitignore b/4 WEEK/item-service/item-service/.gitignore
new file mode 100644
index 00000000..c2065bc2
--- /dev/null
+++ b/4 WEEK/item-service/item-service/.gitignore
@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/4 WEEK/item-service/item-service/build.gradle b/4 WEEK/item-service/item-service/build.gradle
new file mode 100644
index 00000000..34550a7d
--- /dev/null
+++ b/4 WEEK/item-service/item-service/build.gradle
@@ -0,0 +1,38 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.1.6'
+ id 'io.spring.dependency-management' version '1.1.4'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('bootBuildImage') {
+ builder = 'paketobuildpacks/builder-jammy-base:latest'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git a/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..7f93135c
Binary files /dev/null and b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..3fa8f862
--- /dev/null
+++ b/4 WEEK/item-service/item-service/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/4 WEEK/item-service/item-service/gradlew b/4 WEEK/item-service/item-service/gradlew
new file mode 100644
index 00000000..1aa94a42
--- /dev/null
+++ b/4 WEEK/item-service/item-service/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/4 WEEK/item-service/item-service/gradlew.bat b/4 WEEK/item-service/item-service/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/4 WEEK/item-service/item-service/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/4 WEEK/item-service/item-service/settings.gradle b/4 WEEK/item-service/item-service/settings.gradle
new file mode 100644
index 00000000..df5bd80b
--- /dev/null
+++ b/4 WEEK/item-service/item-service/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'item-service'
diff --git a/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java
new file mode 100644
index 00000000..1311934b
--- /dev/null
+++ b/4 WEEK/item-service/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java
@@ -0,0 +1,13 @@
+package hello.itemservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ItemServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ItemServiceApplication.class, args);
+ }
+
+}
diff --git a/4 WEEK/item-service/item-service/src/main/resources/application.properties b/4 WEEK/item-service/item-service/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/4 WEEK/item-service/item-service/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java b/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java
new file mode 100644
index 00000000..e2ded1be
--- /dev/null
+++ b/4 WEEK/item-service/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java
@@ -0,0 +1,13 @@
+package hello.itemservice;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ItemServiceApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/4 WEEK/item-service/settings.gradle b/4 WEEK/item-service/settings.gradle
new file mode 100644
index 00000000..df5bd80b
--- /dev/null
+++ b/4 WEEK/item-service/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'item-service'
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java b/4 WEEK/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java
new file mode 100644
index 00000000..1311934b
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/ItemServiceApplication.java
@@ -0,0 +1,13 @@
+package hello.itemservice;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ItemServiceApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ItemServiceApplication.class, args);
+ }
+
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/Item.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/Item.java
new file mode 100644
index 00000000..78b4c9a2
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/Item.java
@@ -0,0 +1,19 @@
+package hello.itemservice.item;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Item {
+ private Long id;
+ private String name;
+ private Integer price;
+ private Integer quantity;
+
+ public Item(String name, Integer price, Integer quantity){
+ this.name = name;
+ this.price = price;
+ this.quantity = quantity;
+ }
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemController.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemController.java
new file mode 100644
index 00000000..7481267e
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemController.java
@@ -0,0 +1,66 @@
+package hello.itemservice.item;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Controller
+@RequestMapping("/item")
+public class ItemController {
+
+ private final ItemRepository itemRepository;
+
+ @Autowired
+ public ItemController(ItemRepository itemRepository) {
+ this.itemRepository = itemRepository;
+ }
+
+ @GetMapping("/itemListForm")
+ public String getItemListForm(Model model){
+ List- itemList = itemRepository.findAll();
+ model.addAttribute("itemList",itemList);
+ return "ItemListForm";
+ }
+
+ @GetMapping("/{itemId}")
+ public String getItemDetailForm(@PathVariable Long itemId, Model model){
+ Item item = itemRepository.findById(itemId);
+ model.addAttribute("item",item);
+ return "ItemDetailForm";
+ }
+
+ @GetMapping("/itemSave")
+ public String getItemSaveForm(){
+ return "ItemSaveForm";
+ }
+
+ @PostMapping("/itemSave")
+ public String itemSave(@ModelAttribute Item item){
+ itemRepository.save(item);
+ return "ItemDetailForm";
+ }
+
+ @GetMapping("/{itemId}/itemUpdate")
+ public String getItemUpdateForm(@PathVariable Long itemId, Model model){
+ Item updateItem = itemRepository.findById(itemId);
+ model.addAttribute("item",updateItem);
+ return "ItemUpdateForm";
+ }
+
+ @PostMapping("/{itemId}/itemUpdate")
+ public String itemUpdate(@PathVariable Long itemId, @ModelAttribute Item item){
+ itemRepository.update(itemId, item);
+ return "redirect:/item/{itemId}";
+ }
+
+ @PostConstruct
+ public void init(){
+ itemRepository.save(new Item("testA",1000,10));
+ itemRepository.save(new Item("testB",2000,20));
+ }
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemRepository.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemRepository.java
new file mode 100644
index 00000000..c9901491
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemRepository.java
@@ -0,0 +1,14 @@
+package hello.itemservice.item;
+
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+
+public interface ItemRepository {
+ Item save(Item item);
+ Item findById(Long itemId);
+ void update(Long itemId, Item updatedItem);
+ List
- findAll();
+ void clearStore();
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemService.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemService.java
new file mode 100644
index 00000000..6f5d5005
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemService.java
@@ -0,0 +1,10 @@
+package hello.itemservice.item;
+
+import org.springframework.stereotype.Service;
+
+
+public interface ItemService {
+ void join(Item item);
+ void updateItem(Item item, String itemName, double itemPrice, int itemQuantity);
+ Item findItem(Long itemId);
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemServiceImpl.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemServiceImpl.java
new file mode 100644
index 00000000..36aee200
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/ItemServiceImpl.java
@@ -0,0 +1,32 @@
+package hello.itemservice.item;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ItemServiceImpl implements ItemService{
+ private final ItemRepository itemRepository;
+
+ @Autowired
+ public ItemServiceImpl(ItemRepository itemRepository) {
+ this.itemRepository = itemRepository;
+ }
+
+ @Override
+ public void join(Item item) {
+ itemRepository.save(item);
+ }
+
+ @Override
+ public void updateItem(Item item, String itemName, double itemPrice, int itemQuantity) {
+ item.setName(itemName);
+ item.setPrice(itemPrice);
+ item.setQuantity(itemQuantity);
+ itemRepository.update(item);
+ }
+
+ @Override
+ public Item findItem(Long itemId) {
+ return itemRepository.findById(itemId);
+ }
+}
diff --git a/4 WEEK/item-service/src/main/java/hello/itemservice/item/MemoryItemRepository.java b/4 WEEK/item-service/src/main/java/hello/itemservice/item/MemoryItemRepository.java
new file mode 100644
index 00000000..3a710bff
--- /dev/null
+++ b/4 WEEK/item-service/src/main/java/hello/itemservice/item/MemoryItemRepository.java
@@ -0,0 +1,45 @@
+package hello.itemservice.item;
+
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class MemoryItemRepository implements ItemRepository {
+ private static Map
store = new HashMap<>();
+ private static long SEQUENCE = 0L;
+ @Override
+ public Item save(Item item) {
+ item.setId(++SEQUENCE);
+ store.put(item.getId(),item);
+ return item;
+ }
+
+ @Override
+ public Item findById(Long itemId) {
+ return store.get(itemId);
+ }
+
+ @Override
+ public void update(Long itemId, Item updatedItem) {
+ Item findItem = findById(itemId);
+ findItem.setName(updatedItem.getName());
+ findItem.setPrice(updatedItem.getPrice());
+ findItem.setQuantity(updatedItem.getQuantity());
+ }
+
+ @Override
+ public List- findAll(){
+ return new ArrayList<>(store.values());
+ }
+
+ @Override
+ public void clearStore(){
+ store.clear();
+ SEQUENCE = 0L;
+ }
+
+}
diff --git a/4 WEEK/item-service/src/main/resources/application.properties b/4 WEEK/item-service/src/main/resources/application.properties
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/4 WEEK/item-service/src/main/resources/static/index.html b/4 WEEK/item-service/src/main/resources/static/index.html
new file mode 100644
index 00000000..76ee3ab3
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/static/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Title
+
+
+
+
+
\ No newline at end of file
diff --git a/4 WEEK/item-service/src/main/resources/templates/ItemDetailForm.html b/4 WEEK/item-service/src/main/resources/templates/ItemDetailForm.html
new file mode 100644
index 00000000..3359be49
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/templates/ItemDetailForm.html
@@ -0,0 +1,34 @@
+
+
+
+
+ 상품 상세
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/4 WEEK/item-service/src/main/resources/templates/ItemListForm.html b/4 WEEK/item-service/src/main/resources/templates/ItemListForm.html
new file mode 100644
index 00000000..887cd187
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/templates/ItemListForm.html
@@ -0,0 +1,42 @@
+
+
+
+
+ 상품 목록
+
+
+
+
+ 상품 등록
+
+
+
+
+
+ ID
+ 상품명
+ 가격
+ 수량
+
+
+
+ 상품id
+ 상품명
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/4 WEEK/item-service/src/main/resources/templates/ItemSaveForm.html b/4 WEEK/item-service/src/main/resources/templates/ItemSaveForm.html
new file mode 100644
index 00000000..5116207f
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/templates/ItemSaveForm.html
@@ -0,0 +1,30 @@
+
+
+
+
+ 상품 등록
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/4 WEEK/item-service/src/main/resources/templates/ItemUpdateForm.html b/4 WEEK/item-service/src/main/resources/templates/ItemUpdateForm.html
new file mode 100644
index 00000000..13c65d39
--- /dev/null
+++ b/4 WEEK/item-service/src/main/resources/templates/ItemUpdateForm.html
@@ -0,0 +1,31 @@
+
+
+
+
+ 상품 수정
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/4 WEEK/item-service/src/test/java/hello/itemservice/ItemRepositoryTest.java b/4 WEEK/item-service/src/test/java/hello/itemservice/ItemRepositoryTest.java
new file mode 100644
index 00000000..dbf9dd01
--- /dev/null
+++ b/4 WEEK/item-service/src/test/java/hello/itemservice/ItemRepositoryTest.java
@@ -0,0 +1,70 @@
+package hello.itemservice;
+
+import hello.itemservice.item.Item;
+import hello.itemservice.item.ItemRepository;
+import hello.itemservice.item.MemoryItemRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ItemRepositoryTest {
+ private ItemRepository itemRepository = new MemoryItemRepository();
+
+ @AfterEach
+ void afterLogic(){
+ itemRepository.clearStore();
+ }
+
+ @Test
+ void saveTest(){
+ //given
+ Item item = new Item("itemA",1000,10);
+
+ //when
+ Item savedItem = itemRepository.save(item);
+
+ //then
+ Item findItem = itemRepository.findById(item.getId());
+ assertThat(findItem).isEqualTo(savedItem);
+ }
+
+ @Test
+ void findAllTest(){
+ //given
+ Item item1 = new Item("item1",10000,10);
+ Item item2 = new Item("item2",2000,20);
+
+ itemRepository.save(item1);
+ itemRepository.save(item2);
+
+ //when
+ List- itemList = itemRepository.findAll();
+
+ //then
+ assertThat(itemList.size()).isEqualTo(2);
+ assertThat(itemList).contains(item1,item2);
+ }
+
+ @Test
+ void updateTest(){
+ //given
+ Item item = new Item("item1",10000,10);
+
+ Item savedItem = itemRepository.save(item);
+ Long itemId = savedItem.getId();
+
+ //when
+ Item updateItem = new Item("item2", 20000, 30);
+ itemRepository.update(itemId, updateItem);
+
+ Item findItem = itemRepository.findById(itemId);
+
+ //then
+ assertThat(findItem.getName()).isEqualTo(updateItem.getName());
+ assertThat(findItem.getPrice()).isEqualTo(updateItem.getPrice());
+ assertThat(findItem.getQuantity()).isEqualTo(updateItem.getQuantity());
+ }
+}
diff --git a/4 WEEK/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java b/4 WEEK/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java
new file mode 100644
index 00000000..e2ded1be
--- /dev/null
+++ b/4 WEEK/item-service/src/test/java/hello/itemservice/ItemServiceApplicationTests.java
@@ -0,0 +1,13 @@
+package hello.itemservice;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class ItemServiceApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/7 WEEK/7 WEEK MISSION.md b/7 WEEK/7 WEEK MISSION.md
index fbd823ff..a14967b0 100644
--- a/7 WEEK/7 WEEK MISSION.md
+++ b/7 WEEK/7 WEEK MISSION.md
@@ -37,7 +37,187 @@ spring 핵심원리 기본편은 학교에서 대부분 진행한 내용으로
read me 는 필요 시 다시 꺼내서 볼 수 있는 중요자료가 될 것 입니다.
---
+
스프링 핵심 원리 기본편 8-9강 요약
+
+빈 생명주기 콜백 시작
+데이터베이스 커넥션 풀이나, 네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요.
+
+객체를 생성하는 단계에는 url이 없고, 객체를 생성한 다음에 외부에서 수정자 주입을 통해서 setUrl()이 호출되어야 url이 존재하게됨.
+
+스프링 빈 라이프사이클
+객체 생성 -> 의존관계 주입
+스프링은 의존관계 주입이 완려되면 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려주는 다양한 기능을 제공하고 스프링 컨테이너가 종료되기 직전에 소멸 콜백을 줌.
+
+스프링 빈의 이벤트 라이프사이클
+스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸전 콜백 -> 스프링 종료
+- 초기화 콜백: 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
+- 소멸전 콜백: 빈이 소멸되기 직전에 호출
+
+! 객체의 생성과 초기화를 분리
+: 생성자 안에서 초기화 작업을 함께 하는 것 보다 분리하여 명확하게 나누는 것이 유지보수 관점에서 좋음.
+
+! 싱글톤 빈들은 스프링 컨테이너가 종료될 때 함께 종료되기 때문에 스프링 컨테이너가 종료되기 직전에 소멸전 콜백이 일어남.
+
+스프링의 빈 생명주기 콜백 지원
+1. 인터페이스
+- InitializingBean은 afterPropertiesset() 메서드로 초기화 지원
+- DisposableBean은 destroy() 메서드로 소멸 지원
+- 초기화, 소멸 인터페이스 단점:
+ 스프링 전용 인터페이스이기 때문에 코드가 스프링 전용 인터페이스에 의존,
+ 초기화, 소멸 메서드의 이름 변경 불가,
+ 코드를 고칠 수 없는 외부 라이브러리에 적용할 수 없음
+
+2. 설정 정보에 초기화 메서드, 종료 메서드 지정
+- 설정 정보에 @Bean(initMethod=“init”, destroyMethod=“close”)와 같이 초기화, 소멸 메서드를 지정할 수 있음.
+- 설정 정보 사용 특징:
+ 메서드 이름을 자유롭게 지정 가능,
+ 스프링 빈이 스프링 코드에 의존 하지않음,
+ 외부 라이브러리에도 초기화, 종료 메서드를 적용 가능
+- 종료 메서드 추론
+ @Bean의 destroyMethod는 기본값이 inferred로 등록되어있음,
+ inferred는 close, shutdown라는 이름의 메서드를 자동으로 호출,
+ 직접 스프링 빈으로 등록하면 종료 메서드는 따로 적어주지 않아도 잘 동작함,
+ inferred 기능을 사용하기 싫으면 destoryMedthod=“”로 빈 공백을 지정해주면 됨
+
+3. @PostConstruct, @PreDestroy 어노테이션 지원
+- 특징:
+ 매우 편리함, 최신 스프링에서 가장 권장하는 방법,
+ 스프링에 종속적인 기술이 아니라 스프링이 아닌 다른 컨테이너에서도 동작,
+ 컴포턴트 스캔과 잘 어울림,
+- 단점:
+ 외부 라이브러리에 적용하지 못함
+
+정리
+@PostConstruct, @PreDestroy 어노테이션을 주로 사용하되, 코드를 고칠 수 없는 외부 라이브러리를 초기화, 종료해야 된다면 @Bean의 intiMethod, destroyMethod를 사용하자.
+
+빈 스코프
+빈이 존재할 수 있는 범위
+
+스프링의 스코프 지원
+1. 싱글톤: 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
+- 싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환.
+- 싱글톤 빈 요청:
+ 싱글톤 스코프의 빈을 스프링 컨테이너에 요청
+ -> 스프링 컨테이너는 본인이 관리하는 스프링 빈을 반환
+ -> 이후에 스프링 컨테이너에 같은 요청이 와도 같은 객체 인스턴스의 스피링 빈을 반환
+- 싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드가 실행됨.
+- 싱글톤 빈은 스프링 컨테이너가 관리하기 때문에 컨테이너가 종료될 때 빈의 종료 메서드가 실행됨.
+
+2. 프로토타입: 스프링 컨테이너가 프로토타입 빈의 생성과 의존관계 주입까지만 관여하는 매우 짧은 범위의 스코프
+- 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성하여 반환
+- 프로토타입 빈 요청:
+ 프로토타입 스코프의 빈을 스프링 컨테이너에 요청:
+ -> 스프링 컨테이너는 이 시점에 프로토타입 빈을 생성하고, 필요한 의존관계를 주입
+ -> 생성한 프로토타입 빈을 클라이언트에 반환
+ -> 이후에 스프링 컨테이너에 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성하여 반환
+- 핵심:
+ 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계 주입, 초기화까지만 처리,
+ 생성된 프로토타입 빈을 관리하지 않음,
+ 따라서, @PreDestory 같은 종료 메서드가 호출되지 않음
+- 프로토타입 스코프의 빈은 스프링 컨테이너에서 빈을 조회할 때 생성되고, 초기화 메서드도 실행됨.
+- 프로토타입 빈을 2번 조회하면 완전히 다른 스프링 빈이 생성되고, 초기화도 2번 실행됨.
+- 싱글톤 빈과 함께 사용시 문제점:
+ 싱글톤 빈과 함께 사용할 때는 의도한 대로 잘 동작하지 않으므로 주의해야 함.
+
+3. 웹 관련 스코프
+- request: 웹 요청이 들어오고 나갈 때까지 유지되는 스코프
+- session: 웹 세션이 생성되고 종료될 때까지 유지되는 스코프
+- application: 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
+빈 스코프 등록 예시
+- 컴포넌트 스캔 자동 등록
+@Scope(“prototype”)
+@Component
+- 수동 등록
+@Scope(“prototype”)
+@Bean
+
+싱글톤에서 프로토타입 빈 사용
+싱글톤 빈이 내부에 가지고 있는 프로토타입 빈은 이미 과거에 주입이 끝난 빈이라, 주입 시점에 스프링 컨테이너에 요청해서 프로토타입 빈이 새로 생성이 된 것이지, 사용할 때마다 새로 생성되는 것은 아님.
+- 문제점:
+ 싱글톤 빈은 생성 시점에만 의존관계 주입을 받기 때문에, 프로토타입 빈이 새로 생성되기는 하지만, 싱글톤 빈과 함계 계속 유지되는 것이 문제
+
+! 여러 빈에서 같은 프로토타입 빈을 주입 받으면, 주입 받는 시점에 각각 새로운 프로토타입 빈이 생성됨.
+
+프로토타입 스코프, 싱글톤 빈과 함께 사용시 Provider로 문제 해결
+1. 스프링 컨테이너에 요청
+- 싱글톤 빈이 프로토타입을 사용할 때 마다 스프링 컨테이너에 새로 요청하는 것
+- 핵심 코드
+@Autowired
+private ApplicationContext ac;
+public int logic() {
+ PrototypeBean prototypeBean = ac.getBean(PrototypeBean.class);
+ prototypeBean.addCount();
+ int count = prototypeBean.getCount();
+ return count;
+}
+- 단점:
+ 스프링의 애플리케이션 컨텍스트 전체를 주입받게 되면, 스프링 컨테이너에 종속적인 코드가 되고, 단위 테스트도 어려워짐.
+
+2. ObjectFactory, ObjectProvider
+ObjectProvider는 지정한 빈을 컨테이너에서 대신 찾아주는 DL 서비스를 제공함.
+- ObjectProvider의 getObject()를 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아 반환함.(DL)
+- 스프링이 제공하는 기능을 사용하지만, 기능이 단순하므로 단위테스트를 만들거나 mock 코드를 만들기가 쉬워짐.
+- 특징:
+ ObjectFactory: 기능이 단순, 별도의 라이브러리 필요 없음, 스프링에 의존
+ ObjectProvider: ObjectFactory 상속, 옵션, 스트림 처리등 편의 기능이 많고, 별도의 라이브러리 필요없음, 스프링에 의존
+
+3. JSR-330 Provider
+javax.inject.Provider라는 JSR-330 자바 표준을 사용
+- 이 방법을 사용하려면 gradle에 라이브러리를 추가해야함
+ 스프링부트 3.0 미만: javax.inject:javax.inject:
+ 스프링부터 3.0 이상: jakarta.inject:jakarta.inject-api:2.0.1
+- provider의 get()을 호출하면 내부에서는 스프링 컨테이너를 통해 해당 빈을 찾아서 반환.(DL)
+- 특징:
+ 기능이 단순하므로 단위테스트를 만들거나, mock 코드를 만들기 훨씬 쉬워짐
+ get() 메서드 하나로 기능이 매우 단순함
+ 별도의 라이브러리가 필요
+ 자바 표준이므로 스프링이 아닌 다른 컨테이너에서도 사용 가능
+
+! @Lookup 어노테이션을 사용하는 방법도 있음.
+
+정리
+매번 사용할 때마다 의존관계 주입이 완료된 새로운 객체가 필요하면 프로토타입 빈 사용.
+ObjectProvider, JSR330 Provider등은 프로토타입 뿐만 아니라 DL이 필요한 경우는 언제든지 사용 가능.
+
+웹 스코프
+- 특징:
+ 웹 환경에서만 동작
+ 프로토타입과 다르게 스프링이 해당 스코프의 종료 시점까지 관리하여 종료 메서드가 호출됨
+- request: HTTP 요청 하나가 들어오고 나갈 때까지 유지되는 스코프, 각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리됨
+ 동시에 여러 HTTP 요청이 오면 정확히 어떤 요청이 남긴 로그인지 구분하기 힘들 때 사용하기 좋음
+
+- session: HTTP Session과 동일한 생명주기를 가지는 스코프
+
+- application: 서블릿 컨텍스트와 동일한 생명주기를 가지는 스코프
+
+- websocket: 웹 소켓과 동일한 생명주기를 가지는 스코프
+
+스프링 애플리케이션을 실행하는 시점에 싱글톤 빈은 생성해서 주입이 가능하지만, reqeust 스코프 빈은 아직 생성되지 않아 오류가 발생.
+1. Provider
+- ObjectProvider.getObject()를 호출하는 시점까지 request 스코프 빈의 생성을 지연할 수 있음.
+- ObjectProvider.getObject()를 호출하는 시점에는 HTTP 요청이 진행중이므로 request 스코프 빈의 생성이 정상 처리됨.
+- Controller, Service에서 각각 한번씩 따로 호출해도 같은 HTTP 요청이면 같은 스프링 빈이 반환됨.
+
+2. Proxy
+- 핵심: proxyMode=ScopedProxyMode.TARGET_CLASS
+ 적용 대상이 인터페이스가 아니면 TARGET_CLASS,
+ 적용 대상이 인터페이스면 INTERFACES
+- 가짜 프록시 클래스를 만들어두고 HTTP request와 상관없이 가짜 프록시 클래스를 다른 빈에 미리 주입해 둘 수 있음.
+- 동작 원리:
+ CGLIB라는 라이브러리로 내 클래스를 상속 받은 가짜 프록시 객체를 만들어서 주입.
+ 이 가짜 프록시 객체는 실제 요청이 오면 그때 내부에서 실제 빈을 요청하는 위임 로직이 들어있음.
+ 가짜 프록시 객체는 실제 request scope와는 관계가 없음.
+ 그냥 가짜이고, 내부에 단순한 위임 로직만 있고, 싱글톤처럼 동작.
+- 특징:
+ 진짜 객체 조회를 꼭 필요한 시점까지 지연처리 함.
+ 어노테이션 설정 변경만으로 원본 객체를 프록시 객체로 대체할 수 있음.
+ 웹 스코프가 아니어도 프록시 사용 가능
+- 주의점:
+ 싱글톤과 비슷하지만 다르게 동작하기 때문에 주의해서 사용해야함.
+ 꼭 필요한 곳에만 최소화하여 사용.
+ 무분별하게 사용하면 유지보수하기 어려워짐.
+
## Commit Message ROLE
Header, Body, Footer는 빈 행으로 구분한다
...
diff --git a/8 WEEK/8 WEEK MISSION.md b/8 WEEK/8 WEEK MISSION.md
index 2a9fc2ac..8461b5d9 100644
--- a/8 WEEK/8 WEEK MISSION.md
+++ b/8 WEEK/8 WEEK MISSION.md
@@ -34,6 +34,99 @@ MVC-1 1장 ~ 4장입니다.
read me 는 필요 시 다시 꺼내서 볼 수 있는 중요자료가 될 것 입니다.
---
+스프링 MVC 1-4강 요약
+
+MVC 패턴
+Model View Controller: JSP로 처리하던 것을 Controller와 View의 영역으로 역할을 나눈 것.
+-모델: 뷰에 출력할 데이터를 담아둠
+-컨트롤러: HTTP 요청을 받아서 파라미터를 검증하고, 비즈니스 로직을 실행, 뷰에 전달할 결과 데이터를 조회해서 모델에 담아둠
+-뷰: 모델에 담겨있는 데이터를 사용해서 화면을 출력
+
+!컨트롤러에 비즈니스 로직을 두면 너무 많은 역할을 담당하게 되어, 서비스라는 계층을 별도로 만들어 처리함. 컨트롤러는 비즈니스 로직이 있는 서비스를 호출하는 역할을 담당.
+
+MVC 패턴의 한계
+-MVC 컨트롤러의 단점:
+ 포워드 중복: View로 이동하는 코드가 항상 중복 호출되어야함
+ ViewPath의 중복, jsp가 아닌 thymeleaf같은 다른 뷰로 변경하면 전체 코드를 다 변경해야함
+ 사용하지 않는 코드: HttpServletRequest, HttpServletResponse등을 사용할 때도 있고, 하지 않을 때도 있음
+ 공통 처리의 어려움: 기능이 복잡해질수록 컨트롤러에서 공통으로 처리해야하는 부분이 증가, 실수로 호출하지 않으면 문제가 됨
+
+프론트 컨트롤러
+프론트 컨트롤러 서블릿 하나로 클라이언트의 요청을 받아 맞는 컨트롤러를 찾아서 호출
+-특징: 공통 처리 기능, 프론트 컨트롤러를 제외한 나머지 컨트롤러는 서블릿을 사용하지 않아도 됨
+
+프론트 컨트롤러 도입 V-1
+urlPatterns=“/front-controller/v1/*” 로 지정하여 /front-controller/v1을 포함한 하위 모든 요청이 이 서블릿에서 받아들이도록 함
+-주요 코드:
+urlPatterns 지정
+@WebServlet(name = "frontControllerServletV1", urlPatterns = "/front-controller/v1/*")
+url 매핑
+public FrontControllerServletV1() {
+ controllerMap.put("/front-controller/v1/members/new-form", new MemberFormControllerV1());
+ controllerMap.put("/front-controller/v1/members/save", new MemberSaveControllerV1());
+ controllerMap.put("/front-controller/v1/members", new MemberListControllerV1());
+ }
+
+프론트 컨트롤러 View 분리 V-2
+모든 컨트롤러에 뷰로 이동하는 부분이 중복됨
+-주요 코드:
+객체를 생성하여 뷰 이름을 넣고 반환
+return new MyView("/WEB-INF/views/new-form.jsp");
+return new MyView("/WEB-INF/views/save-result.jsp");
+return new MyView("/WEB-INF/views/members.jsp");
+
+프론트 컨트롤러 Model 추가 V-3
+-서블릿 종속성 제거:
+ 컨트롤러 입장에서 HttpServletRequest, HttpServletResponse는 꼭 필요하지 않음
+ 요청 파라미터 정보는 Map으로 대신 넘기도록하면 컨트롤러가 서블릿 기술을 몰라도 동작 가능함
+-뷰 이름 중복 제거:
+ 컨트롤러는 뷰의 논리 이름을 반환하고, 실제 물리 위치의 이름은 프론트 컨트롤러에서 처리하도록 함
+-뷰 리졸버:
+ 컨트롤러가 반환한 논리 뷰 이름을 실제 물리 뷰 경로로 변경시킴, 실제 물리 경로가 있는 객체를 반환
+-주요 코드:
+뷰의 논리적인 이름 지정
+@Override
+ public ModelView process(Map paramMap) {
+ return new ModelView("new-form");
+ }
+뷰의 실제 물리 경로가 있는 객체 반환
+MyView view = viewResolver(viewName);
+private MyView viewResolver(String viewName) {
+ return new MyView("/WEB-INF/views/" + viewName + ".jsp");
+ }
+
+
+프론트 컨트롤러 단순하고 실용적인 V-4
+ModelView 객체를 생성하고 반환하는 부분이 번거로우므로, 컨트롤러가 ModelView대신 ViewName만 반환하도록 함.
+모델이 파라미터로 전달되기 때문에, 모델을 직접 생성하지 않아도 됨.
+-주요 코드:
+뷰의 논리 이름 반환
+@Override
+ public String process(Map paramMap, Map model) {
+ return "new-form";
+ }
+
+프론트 컨트롤러 유연한 컨트롤러 V-5
+컨트롤러V3과 컨트롤러V4는 완전히 다른 인터페이스이기 때문에 호환이 불가능.
+어댑터 패턴을 사용하여 프론트 컨트롤러가 다양한 방식의 컨트롤러를 처리할 수 있도록 변경.
+-핸들러 어댑터:
+ 어댑터 역할을 해주어 다양한 종류의 컨트롤러를 호출
+-핸들러:
+ 컨트롤러를 더 넓은 범위의 핸들러로 변경
+-주요 코드:
+ 어댑터 인터페이스
+public interface MyHandlerAdapter {
+ boolean supports(Object handler);
+ ModelView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException, IOException;
+}
+어댑터 구현
+@Override
+ public boolean supports(Object handler) {
+ return (handler instanceof ControllerV4);
+ }
+
+
+
## Commit Message ROLE
Header, Body, Footer는 빈 행으로 구분한다
diff --git a/9 WEEK/9 WEEK MISSION.md b/9 WEEK/9 WEEK MISSION.md
index 81f85e9d..ebdb0087 100644
--- a/9 WEEK/9 WEEK MISSION.md
+++ b/9 WEEK/9 WEEK MISSION.md
@@ -35,6 +35,166 @@ Server 개발자의 기본 소양인 Spring MVC 부분 입니다.
read me 는 필요 시 다시 꺼내서 볼 수 있는 중요자료가 될 것 입니다.
---
+스프링 MVC 5-7강 요약
+
+스프링 MVC 전체 구조
+HTTP 요청
+-> 1. 핸들러 조회
+-> 핸들러를 처리할 수 있는 핸들러 어댑터 조회
+-> 핸들러 어댑터 실행: handle(handler)
+-> 핸들러 호출
+-> MovdelView 반환
+-> viewResolver 호출
+-> View 반환
+-> 뷰 렌더링: render(model)
+-> HTML 응답
+
+DispatcherServlet 구조
+스프링 MVC의 프론트 컨트롤러가 디스패처 서블릿임.
+-요청의 흐름:
+ 서블릿이 호출되면
+ -> HttpServlet.service() 호출 -> DispatcherServlet의 부모인 FrameworkServlet에서 service()를 오버라이드 해두어 FramworkServlet.service()로 여러 메서드가 호출됨 -> DispatcherServlet.doDispatch() 호출
+
+HttpRequestHandler
+서블릿과 가장 유사한 형태의 핸들러.
+-동작 방식:
+핸들러 매핑으로 핸들러 조회 -> 핸들러 어댑터 조회 -> 핸들러 어댑터 실행
+
+InternalResourceViewResolver
+-동작 방식:
+핸들러 어댑터 호출 -> ViewResolver 호출 -> InternalResourceViewResolver로 InternalResourceView 반환 -> InternalResourceView로 forward() 호출 -> view.render() 호출
+
+@RequestMapping
+요청 정보를 매핑, 해당 URL이 호출되면 그 메서드가 호출됨.
+대부분의 속성을 배열로 제공하여 다중 설정이 가능.
+-메서드 구분
+@RequestMapping(value=“”, method = RequestMethod.GET) -> @GetMapping
+@RequestMapping(value=“”, method = RequestMethod.POST) -> @PostMapping
+-그 외: Put, Delete, Patch
+
+@Controller
+스프링이 자동으로 스프링 빈으로 등록해줌.
+
+로그
+-로그 라이브러리:
+SLF4J(인터페이스), Logback(구현체)
+-로그 선언:
+private Logger log = LoggerFactory.getLogger(getClass());
+private static final Logger log = LoggerFactory.getLogger(Xxx.class);
+@Slf4j(롬복 사용)
+-로그 호출:
+log.info(“”)
+-Level:
+TRACE >DEBUG > INFO > WARN > ERROR
+개발 서버는 debug, 운영 서버는 info로 출력.
+-장점:
+스레드 정보와 같은 부가 정보를 함께 볼 수 있고, 출력 모양을 조정 가능.
+로그 레벨에 따라 개발 서버에서는 모든 로그를 출력하고, 운영 서버에서는 출력하지 않는 등 로그를 상황에 맞게 조절 가능.
+파일이나 네트워크 등 로그를 별도의 위치에 남길 수 있음
+System.out 보다 성능이 좋음
+
+@RestController
+반환 값으로 뷰를 찾는 것이 아닌, HTTP 메시지 바디에 바로 입력.
+
+@PathVariable
+변수명이 같으면 생략 가능.
+
+@RequestHeader(“”)
+특정 HTTP 헤더를 조회.
+
+@CookieValue(value=“”, required=)
+특정 쿠키를 조회.
+
+요청 파라미터
+-GET - 쿼리 파라미터
+메시지 바디 없이, URL의 쿼리 파라미터에 데이터를 포함해 전달.
+/request-param?username=hello&age=20
+
+-POST – HTML Form
+메시지 바디에 쿼리 파라미터 형식으로 전달
+content-type: application/x-www-form-urlencoded
+username=hello&age=20
+
+-HTTP message body에 데이터를 직접 담아서 요청
+데이터 형식은 주로 JSON, HTTP API에서 주로 사용
+
+@RequestParam
+파라미터 이름으로 바인딩.
+HTTP 파라미터 이름이 변수 이름과 같다면 생략 가능.
+파라미터 이름만 있고 값이 없는 경우에는 빈 문자로 통과.
+
+@ResponseBody
+View 조회를 무시하고, HTTP message body에 직접 해당 내용 입력.
+-동작 원리:
+HTTP의 body에 문자 내용을 직접 반환 -> viewResolver 대신 HttpMessageConverter 동작
+
+@RequestBody
+HTTP 메시지 바디 정보를 조회.
+생략 불가능. (생략하면 @ModelAttribute가 됨)
+
+@RequestParam Map<>, MultiValueMap<>
+파라미터를 Map, MultiValueMap으로 조회 가능.
+
+@Data
+@Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 자동으로 적용
+
+@ModelAttribute
+HTTP 요청 파라미터나 multipart/form-data 형태의 파라미터를 받아 객체로 사용.
+생략 가능하여 @RequestParam과 헷갈릴 수 있음.
+-규칙:
+String, int, Integer -> @RequestParam
+나머지 -> @ModelAttribute
+
+InputStream
+HTTP 요청 메시지 바디의 내용을 직접 조회.
+
+OutputStream
+HTTP응답 메시지의 바디에 직접 결과 출력.
+
+HTTPEntity
+메시지 바디 정보를 직접 조회, 반환 가능.
+헤더 정보 포함 가능.
+요청 파라미터 조회x, view 조회x.
+
+RequestEntity
+HttpMethod, url 정보 추가, 요청에서 사용.
+
+요청 매핑 핸들러 어댑터
+-RequestMappingHandlerAdapter 동작 방식:
+컨트롤러의 파라미터, 어노테이션 정보를 기반으로 전달 데이터 생성 -> 해당 컨트롤러 호출 –> 컨트롤러의 반환 값을 변환
+
+HTTP 메시지 컨버터
+컨트롤러가 필요로 하는 파라미터의 값에 사용됨.
+-요청:
+ArgumentResolver 가 HTTP 메시지 컨버터를 사용하여 필요한 객체 생성 -> @RequestBody와 HttpEntity 처리
+-응답:
+ReturnValueHandler 가 HTTP 메시지 컨버터를 호출하여 응답 결과 생성 -> @ResponseBody와 HttpEntity 처리
+
+단위 테스트 – JUnit
+-특징:
+assert 메서드로 테스트 케이스의 수행 결과를 판별
+@Test 메서드가 호출할 때마다 새로운 인스턴스를 생성하여 독립적인 테스트가 가능
+-어노테이션
+@Test: @Test가 선언된 메서드는 테스트를 수행
+@Before: @Test 메서드가 실행되기 전에 해당 메서드가 반드시 실행
+@After: @Test 메서드가 실행된 후 해당 메서드가 실행
+-given/ when/ then 패턴
+준비/ 실행/ 검증.
+given: 테스트에 사용하는 변수, 입력값 등을 정의함
+when: 실제로 동작하는 테스트를 실행함
+then: 예상한 값과 실제 실행을 통해 나온 값을 검증함
+
+Thymeleaf
+th:xxx 가 붙은 부분은 서버사이드에서 렌더링 되고, 기존 것을 대체.
+th:xxx 이 없으면 기존 html의 xxx속성이 그대로 사용됨.
+-선언:
+
+-표현식:
+th:href=“@{/xxx/xxxxx.xxx.xx}”
+th:onclick=“|location.href=’@{/xxx/xxx/xx}‘|”
+th:each=“item : ${items}”
+th:value=“${item.id}”
+
## Commit Message ROLE
Header, Body, Footer는 빈 행으로 구분한다