diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/.gitignore" b/.idea/.gitignore
similarity index 100%
rename from "in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/.gitignore"
rename to .idea/.gitignore
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..6e86672
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/modules.xml" b/.idea/modules.xml
similarity index 61%
rename from "in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/modules.xml"
rename to .idea/modules.xml
index 68d513d..4add974 100644
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/modules.xml"
+++ b/.idea/modules.xml
@@ -2,7 +2,7 @@
-
+
\ No newline at end of file
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/vcs.xml" b/.idea/vcs.xml
similarity index 67%
rename from "in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/vcs.xml"
rename to .idea/vcs.xml
index c2365ab..35eb1dd 100644
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/vcs.xml"
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.md" "b/HxWOO/\354\203\235\355\231\234_\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.MD"
similarity index 100%
rename from "in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.md"
rename to "HxWOO/\354\203\235\355\231\234_\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.MD"
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
new file mode 100644
index 0000000..9a225d6
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
@@ -0,0 +1,573 @@
+# 스프링 입문
+
+실무 개발에 꼭 필요한 내용 학습
+
+학습 방법
+ - 직접 코딩하기
+
+- 프로젝트 생성
+ - start.spring.io 접속
+
+ -Gradle-Groovy 로 선택
+
+ -프로젝트명 : hello-spring
+
+ -디펜덴시 - spring-web, thymeleaf
+
+ - 생긴 파일들 해설
+
+ -gradle 은 버젼 설정하고 라이브러리 땡겨옴
+
+ -repository : 라이브러리를 다운 받을 곳을 적어 놓음 (수정도 가능)
+
+ -dependencies : 기본적으로 들어가는거 + 아까 설정한거
+
+ -말고도 git 이나 gradle 관련 파일들
+
+ - springboot 실행
+
+ main 실행 → springbootApplication 내장 Tomcat 서버로 서버 실행
+
+- 라이브러리 살피기
+
+ -gradle이 의존관계에 있는 라이브러리를 다 땡겨와 줌
+
+ -따라서 스프링부트 라이브러리를 땡기면 관련 라이브러리를 다 땡겨와줌 (코어, embeded 서버 등등)
+
+ *현업에선 system.out.println() 말고, logging을 이용해야 함 (나중에 모아볼수도 있고 다재다능)
+
+ - 스프링 부트 라이브러리
+ - spring-boot-starter-web
+ - spring-boot-starter-tomcat: 톰캣 (웹서버)
+ - spring-webmvc: 스프링 웹 MVC
+ - spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진(View)
+ - spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅
+ - spring-boot
+ - spring-core
+ - spring-boot-starter-logging
+ - logback, slf4j
+ - 테스트 라이브러리
+
+ spring-boot-starter-test
+ - junit: 테스트 프레임워크
+ - mockito: 목 라이브러리
+ - assertj: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리
+ - spring-test: 스프링 통합 테스트 지원
+
+- view 환경설정
+ - welcome 페이지 만들기 (index.html)
+
+ ```jsx
+
+
+ Hello
+
+
+
+ Hello
+ hello
+
+
+ ```
+
+
+ [spring.io](http://spring.io) 에서 boot 들어가서 검색하면 됨
+
+ 템플릿 엔진에서 검색해서 페이지를 동적으로 만들 수 있음
+
+ mvc = model view controller
+
+ 
+
+- 스프링 웹개발 기초
+ - 정적 컨텐츠 - like 웰컴 페이지, 그냥 파일을 브라우져에 내려줌.
+ - 스프링 부트는 자동 제공, static contents라고 검색해보셈
+ - resouces에 있는 static 폴더
+
+ 
+
+ - MVC와 템플릿 엔진 - html을 그냥 주는게 아니라 서버에서 조금 동적으로 바꿔 줌 (이걸 위해서 전에 컨트롤러 이런거 했던거임)
+ - Model View Controller 임. 과거엔 뷰와 컨트롤러가 구분 X
+ - 그런데 현재는 구분함 → 뷰는 화면구현에 모든 역량을 집중해야 함, 컨트롤러는 뒷단 로직에 집중하고 모델에 화면과 관련된걸 담아서 보내줌
+ - 예를 들어, 뷰파일 하나에 다 박으면 나중에 다른 사람은 구분도 못함
+ - RequestParam(”name”) 했을때 주소창에 /경로?name=”입력” 으로 입력했음
+
+ 
+
+ - API - 다른 OS, 서버끼리 데이터 흐를때 요즘은 json이란 포맷으로 client한테 보내줌
+ - data 로 바로 내린다, html 방식은 소스를 봤을 때 입력을 html 템플릿 포맷으로 갔다면 API는 data 그대로, 그래서 data를 달라는 요청을 할때 많이 씀
+ - @ResponseBody → https 프로토콜의 body msg 부분에 이 데이터를 직접 넣겠다는 의미
+ - 요즘은 json 방식으로 함 (key 와 밸류) - 심플하기 때문
+ - @ResponseBody 사용원리
+ - 객체가 넘어오면 Json 작동, 그냥 String 객체면 StringConverter
+
+ 
+
+- 회원 관리 예제 개발
+ - 비즈니스 요구사항 정리
+
+ 데이터 : 회원 ID, 이름
+
+ 기능 : 회원 등록, 조회
+
+ 아직 DB가 선정되지 않음
+
+ 
+
+ 
+
+ - 회원 도메인과 레포지토리
+ 1. hello.hellospring 패키지에 domain 패키지를 생성
+ - domain 패키지에 Member 클래스 생성 → Id, name 있음. 각각 get, set 함수 있음
+ 2. hello.hellospring 패키지에 repository 패키지 생성 후
+
+ 그곳에 MemberRepository 인터페이스 생성
+
+ - save, findByID, findByName, findall 함수 선언
+ - findBy는 Optional로 선언해서 NULL반환시 Optional로 감쌀 수 있게 함
+ 1. repository 패키지에 MemoryMemberRepository 클래스 생성
+ - implements 통해서 위에 인터페이스에 선언했던것들 구현
+
+ `private static Map *store* = new HashMap<>();`
+
+ `private static Long *sequence* = 0L;`
+
+ 멤버 생성 - store 엔 멤버 찾은 결과를 저장하고, sequence는 멤버에 ID 부여.
+
+
+ 느낀점 - java의 문법에 더 익숙해져야 할 듯 (람다식 같은거 …)
+
+ - 회원 리포지토리 테스트 케이스 작성
+
+ 테스트 케이스 : 방금 만든 클래스가 정상적으로 작동하는지 검증하는 방법
+
+ 메인 메소드를 이용해서 테스트를 하게되면 너무 오래걸리고, 반복하기 어려움
+
+ → 자바는 JUnit이라는 프레임워크로 테스트를 해서 이런 문제 해결
+
+ - 테스트 관례 : 만들때 “테스트할파일+test”
+ - 메소드는 순서에 의존적으로 설계하면 안 됨
+ - @AfterEach : 매 테스트 후 그 메소드를 실행하게 함
+ - test 부터 작성해놓고 그 뒤에 repository를 만들 수도 있음 : tdd(테스트주도개발)
+ - 회원 서비스 개발
+
+ 회원 repository, domain 활용해서 실제 비즈니스 로직을 작성함
+
+ service 클래스는 좀 더 비즈니스 의존적으로 설계해야 함 (네이밍부터 …)
+
+ - 회원 서비스 테스트
+
+ command+shift+T 로 테스트 생성가능
+
+ test는 직관적으로 한글로 해도 됨.
+
+ given, when, then 문법으로 설계
+
+ DI 를 통해 애매한 부분을 해결해줌
+
+ → 일단 객체 생성하고 나중에 new를 직접 지정
+
+- 스프링 빈과 의존관계
+ - 컴포넌트 스캔 이용 빈 등록, 자동 의존관계 설정
+
+ 화면을 붙임 (회원가입, 결과 html로 뿌려주기) → 컨트롤러, 뷰 템플릿 필요
+
+ →멤버 컨트롤러 필요 : 멤버 서비스 통해 회원가입, 데이터 조회 (컨트롤러가 서비스를 의존)
+
+ @Controller 만들면 spring 컨테이너 에 그 컨트롤러의 객체(빈)를 넣어둠
+
+ 객체를 여러번 new하지 말고 스프링 컨테이너에 등록하고 불러서 씀
+
+ → @Autowired 로 자동으로 연결해줌
+
+ @Component 하면 스프링 빈 자동으로 등록 - Controller, Service, Repository
+
+ →이게 컴포넌트 스캔 (스프링 빈 등록하는 법 1)
+
+ →기본적으로 Application 패키지 포함 하위에 있는 패키지들만 컴포넌트 스캔 가능
+
+ →싱글톤(유일)으로 등록해서 공유
+
+ 애지간한건 다 스프링 빈으로 등록해서 써야 이점이 많음
+
+ - 자바 코드로 직접 스프링 빈 등록하기
+
+ SpringConfig 파일 만들기 →@Configuration 선언 →@Bean 선언(Bean등록할거야~)
+
+ ```jsx
+ @Configuration
+ public class SpringConfig {
+
+ @Bean
+ public MemberService memberService(){
+ return new MemberService(memberRepository());
+ }
+
+ @Bean
+ public MemoryMemberRepository memberRepository(){
+ return new MemoryMemberRepository();
+ }
+ }
+ ```
+
+
+ 각각의 장단점 있음
+
+ 
+
+ 요즘은 생성자 주입이 대세 / 현재 시나리오에선 상황에 따라 레포지토리 바꿔야 해서 설정으로 스프링 빈 해놨음
+
+- 회원 웹 기능
+ - 홈 화면 추가
+
+ HomeController , home.html 추가해서 홈화면 넘김
+
+ ```jsx
+ @Controller
+ public class HomeController {
+
+ @GetMapping("/")
+ public String home(){
+ return "home";
+ }
+ }
+ ```
+
+ URL에 / 를 받기 때문에 바로 GetMapping으로 넘어가서 index.html이 아닌 home.html이 불러와짐
+
+ - 등록
+
+ data를 어딘가 폼같은데에 넣어서 전달할 때 post 방식 → @PostMapping
+
+ get 방식은 뭔가 조회 할때 → @GetMapping
+
+ - 같은 url 이더라도 get, post 두 방식으로 다르게 매핑 할 수 있음
+
+ ```jsx
+ @GetMapping("/members/new")
+ public String createForm() {
+ return "members/createMemberForm";
+ }
+
+ @PostMapping("/members/new")
+ public String create(MemberForm form){
+ Member member = new Member();
+ member.setName(form.getName());
+
+ memberService.join(member);
+
+ return "redirect:/";
+ }
+ ```
+
+ input 받은 name이 form의 name으로 넘어가고 그걸 이용해서 Member 클래스의 객체 생성해서 join 시킴
+
+ - 조회
+ - 코드
+
+ ```jsx
+ @GetMapping("/members")
+ public String list(Model model){
+ List members = memberService.findMembers();
+ model.addAttribute("members", members);
+ return "members/memberList";
+ }
+ ```
+
+ ```jsx
+
+
+
+
+
+
+
+
+ #
+ 이름
+
+
+
+
+
+
+
+
+
+
+
+
+ ```
+
+
+ html은 타임리프 문법으로 알아서 잘 model 안에 있는 값들을 전달받음
+
+ 멤버 밸류를 넘기기 위해 model 만들어서 잘 포장해서 넘겼음
+
+
+ 하지만, 지금까지 했던 자료들은 모두 메모리 안에 저장되기 때문에 자바를 재실행하면 다 날라간다는 점…
+
+- 스프링 DB 접근 기술
+ - H2 데이터베이스 설치
+
+ 교육용으로 좋음, 용량 적고, 가볍고, 웹으로 어드민 화면도 줌
+
+ - 순수 JDBC
+ 1. build.gradle 파일에 jdbc, h2 데이터베이스 관련 라이브러리 추가
+ 2. 스프링 부트 데이터베이스 연결 설정 추가
+ 3. 연결 됐으면 멤버 넘기기 위한 jdbc 레포지토리 구현
+ 1. db에 붙기 위한 datasource 선언
+ 2. datasource를 통해 커넥션을 받아서 받은 data를 db에 날림
+ 3. 우리가 MemoryMemberRepository에 했던 함수들을 jdbc멤레포 에 옮기기 위한 방대한 양의 코드들을 씀. ex) save메소드에서 db에서 sequence를 받아옴 …
+ 4. db와 만들었던 커넥션은 다 쓰고나면 제때제때 끊어줘야 함 → 클난다
+ 5. 쿼리를 sql로 날린다 첨 할때
+ 6. 커넥션은 DataSourceUtils를 통해 주고받아야 함
+ 4. SpringConfig 설정 → 아까 MemoryMemberRepositoy 였던 부분만 JdbcMemberRepository로 바꾸고 스프링 자체 데이터소스만 연결해주면 됨
+ 1. 이게 스프링이 좋은 이유임 → 스프링이 지원해줌
+ 2. 어플리케이션을 조립하는 코드만 손대면 나머진 손 안대도 됨
+
+ 
+
+ - 스프링 통합 테스트
+ - 이전의 테스트들은 스프링과 관련 X, 현재는 그럴 수 없으니 테스트를 스프링과 엮어서 함
+ - test case할땐 그냥 편한대로 하셈 like) 필드 @Autowired
+ - @SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행한다.
+ - @Transactional : 테스트 케이스에 이 애노테이션이 있으면, 테스트 시작 전에 트랜잭션을 시작하고, 테스트 완료 후에 항상 롤백한다. 이렇게 하면 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않는다. // 이런식으로 테스트 케이스에 붙었을 때만 항상 롤백하도록 동작
+ - test 전용 db 따로해서 test
+ - 가능한 한 순수한 단위 테스트(코드만으로 할 수 있는)가 젤 좋을 수 있음
+ - 스프링 JdbcTemplate
+ - jdbc랑 동일하게 설정하면 됨 . 실무에서도 많이 씀
+ - 스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다. 하지만 SQL은 직접 작성해야 한다.
+
+ *생성자 하나일때 @Autowired 생략 가능
+
+ - 쿼리를 RowMapper를 이용해 간단하게 가능
+ - JdbcTemplateMemberRepository 코드
+
+ ```jsx
+ package hello.hellospring.repository;
+
+ import hello.hellospring.domain.Member;
+ import org.springframework.jdbc.core.JdbcTemplate;
+ import org.springframework.jdbc.core.RowMapper;
+ import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+ import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+
+ import javax.sql.DataSource;
+ import java.util.*;
+
+ public class JdbcTemplateMemberRepository implements MemberRepository {
+
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcTemplateMemberRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public Member save(Member member) {
+ SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
+ jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
+
+ Map parameters = new HashMap<>();
+ parameters.put("name", member.getName());
+
+ Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
+ member.setId(key.longValue());
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findall() {
+ return jdbcTemplate.query("select * from member",memberRowMapper());
+ }
+
+ private RowMapper memberRowMapper(){
+ return (rs, rowNum) -> {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return member;
+ };
+ }
+
+ }
+ ```
+
+ - 자만하지 말고 테스트 잘 작성해서 하기 !
+ - JPA
+ - JPA를 들어가며
+ - 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행해준다.
+ - SQL과 데이터 중심의 설계 → 객체 중심의 설계로 패러다임을 전환을 할 수 있다.
+ - 개발 생산성을 크게 높일 수 있다.
+ - jpa라는 것은 인터페이스 제공 → 자바진영의 표준 인터페이스 - 구현은 업체들이
+ - 영한씨의 책 덕분에 대한민국에서 널리 퍼짐
+ - JPA 환경설정
+ - build-gradle 서 dependencies 추가하고 library 다운
+ - spring boot 에 sql 보이기, 테이브 자동 생성 끄기
+ - 엔티티를 매핑 해야함 - 여기부터 이어서
+ - ORM임 Object 와 relational db의 테이블을 매핑함 - 이게 엔티티
+ - DB 에 값을 저장하면 DB에서 ID 자동으로 생성하는거 - IDENTITY 전략
+ - JPA 사용
+ - EntityManager를 이용해서 함. 이건 매핑하면 스프링부트가 알아서 만들어줌
+ - 전에 썼던 데이터소스나 이런걸 내부적으로 다 들고 있어서 알아서 다 처리가능
+ - String형을 가지고 놀땐 jpql 이라는걸 작성해야 함 → sql과 비슷하지만 객체 자체를 지정
+ - @Transactional 이 있어야 함. 데이터를 저장하거나 변경할 땐 → 모든게 저 안에서 실행
+ - JpaMemberRepository의 코드
+
+ ```jsx
+ package hello.hellospring.repository;
+
+ import hello.hellospring.domain.Member;
+ import jakarta.persistence.EntityManager;
+ import org.springframework.transaction.annotation.Transactional;
+
+ import java.util.List;
+ import java.util.Optional;
+
+ @Transactional
+ public class JpaMemberRepository implements MemberRepository{
+
+ private final EntityManager em;
+
+ public JpaMemberRepository(EntityManager em) {
+ this.em = em;
+ }
+
+ @Override
+ public Member save(Member member) {
+ em.persist(member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ Member member = em.find(Member.class, id);
+ return Optional.ofNullable(member);
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = em.createQuery("select m from Member m where m.name = :name", Member.class)
+ .setParameter("name", name)
+ .getResultList();
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findall() {
+ return em.createQuery("select m from Member m", Member.class)
+ .getResultList();
+ }
+ }
+ ```
+
+ - 확연히 간결해지고 jpql을 사용하는 것을 볼 수 있음
+ - 스프링 데이터 JPA
+ - 인터페이스만으로도 개발 완료 가능, 반복적인 기본 CRUD 기능도 다 제공
+ - “금상첨화”의 ‘화’ → 핵심 비즈니스 로직을 개발하는데, 집중 할 수 있게 해줌
+ - jpa를 편리하게 사용하도록 도와주는 것이기 때문에 jpa공부가 선행돼야 함
+ - SpringDataJpaMemberRepository 의 코드
+ - 굉장히 간결해진 코드, JpaRepository에서 기본 CRUD 다 줘서 거기서 안 주는 findByName 만 선언해줌 → 스프링데이터JPA가 알아서 가져다 씀
+ - ex) findByName을 쓰면
+
+ → select m from Member m where [m.name](http://m.name) = ? 이런 jpql로 알아써 짜서 줌
+
+ ```jsx
+ package hello.hellospring.repository;
+
+ import hello.hellospring.domain.Member;
+ import org.springframework.data.jpa.repository.JpaRepository;
+
+ import java.util.Optional;
+
+ public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository {
+
+ Optional findByName(String name);
+ }
+ ```
+
+ - 단순한건 인터페이스만으로 끝나네 ㄹㅇ…
+ - 제공 기능
+
+ 인터페이스를 통한 기본적인 CRUD
+ findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공
+
+ 페이징 기능 자동 제공
+
+
+ -findAll() 메서드를 findall()로 작성했다가 오류남, 그 규칙을 잘 지켜줘야 할 듯
+
+
+ 실무에선 이 모든 기술들을 두루두루 다 알고 써야 함 → 대접의 이유
+
+- AOP
+
+ Aspect Oriented Programming - 공통 관심사 분리
+
+ 
+
+ - AOP가 필요한 상황
+ - 공통관심사항 : 앱의 기능에 전반적으로 공통적으로 사용되는 기능들
+ - 핵심관심사항 : 한 메서드를 수행할 때 공통관심사항과 달리 그 기능을 수행할때 핵심이 되는 로직
+ - 둘을 나눠서 관리해야 더 편함 → 이때 AOP 적용하면 됨
+ - AOP 적용
+ - AOP는 빈에 직접 등록해주는게 좋음 ← 남이 봤을 때 “아! AOP 쓰고있구나!?”
+ - 호출이 될 때마다 joinPoint 라는데에서 조작을 막 함
+ - AOP 동작 원리
+
+ 일단 적용 전에는 컨트롤러→서비스 이렇게 그냥 의존 함
+
+ 적용 후에는 프록시 → 컨트롤러→프록시(가짜로 만든 서비스) → joinPoint.proceed() 하면 → 실제 서비스 / 이런 방식임
+
+ AOP가 프록시를 알아서 DI(빈 만들기) 해줌. → AOP 가능해짐
+
+ - AOP코드
+
+ ```jsx
+ package hello.hellospring.aop;
+
+ import org.aspectj.lang.ProceedingJoinPoint;
+ import org.aspectj.lang.annotation.Around;
+ import org.aspectj.lang.annotation.Aspect;
+ import org.springframework.stereotype.Component;
+
+ @Component
+ @Aspect
+ public class TimeTraceAop {
+
+ @Around("execution(* hello.hellospring..*(..))")
+ public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
+
+ long start = System.currentTimeMillis();
+
+ System.out.println("Start : " + joinPoint.toString());
+
+ try{
+ return joinPoint.proceed();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = start - finish;
+
+ System.out.println("END : " + joinPoint.toString() + " " + timeMs + "ms");
+ }
+
+ }
+ }
+ ```
+
+
+
+
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png"
new file mode 100644
index 0000000..e984f86
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png"
new file mode 100644
index 0000000..78f15ce
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png"
new file mode 100644
index 0000000..f2a5017
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png"
new file mode 100644
index 0000000..5be7f87
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png"
new file mode 100644
index 0000000..e0b8373
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 6.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 6.png"
new file mode 100644
index 0000000..2f3b9ee
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 6.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 7.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 7.png"
new file mode 100644
index 0000000..0fcc79a
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 7.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 8.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 8.png"
new file mode 100644
index 0000000..10c6a61
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 8.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 9.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 9.png"
new file mode 100644
index 0000000..84d2717
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 9.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png"
new file mode 100644
index 0000000..bd3f86e
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/.gitignore" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/.gitignore"
new file mode 100644
index 0000000..c2065bc
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/.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/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/build.gradle" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/build.gradle"
new file mode 100644
index 0000000..2ff3ccc
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/build.gradle"
@@ -0,0 +1,29 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.0.5'
+ id 'io.spring.dependency-management' version '1.1.0'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = '17'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ //implementation 'org.springframework.boot:spring-boot-starter-jdbc'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ runtimeOnly 'com.h2database:h2'
+ testImplementation ('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar"
new file mode 100644
index 0000000..249e583
Binary files /dev/null and "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar" differ
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties"
new file mode 100644
index 0000000..774fae8
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties"
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew"
new file mode 100755
index 0000000..a69d9cb
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew"
@@ -0,0 +1,240 @@
+#!/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/master/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
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# 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"'
+
+# 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
+ which java >/dev/null 2>&1 || 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
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ 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
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew.bat" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew.bat"
new file mode 100644
index 0000000..53a6b23
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/gradlew.bat"
@@ -0,0 +1,91 @@
+@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=.
+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/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/settings.gradle" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/settings.gradle"
new file mode 100644
index 0000000..69a39da
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/settings.gradle"
@@ -0,0 +1 @@
+rootProject.name = 'hello-spring'
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/sql/dbl.sql" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/sql/dbl.sql"
new file mode 100644
index 0000000..46c3cac
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/sql/dbl.sql"
@@ -0,0 +1,7 @@
+drop table if exists member CASCADE;
+create table member
+(
+ id bigint generated by default as identity,
+ name varchar(255),
+ primary key (id)
+);
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java"
new file mode 100644
index 0000000..f0f0fd4
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java"
@@ -0,0 +1,13 @@
+package hello.hellospring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelloSpringApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HelloSpringApplication.class, args);
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/SpringConfig.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/SpringConfig.java"
new file mode 100644
index 0000000..68e8eb6
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/SpringConfig.java"
@@ -0,0 +1,26 @@
+package hello.hellospring;
+
+import hello.hellospring.repository.MemberRepository;
+import hello.hellospring.service.MemberService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SpringConfig {
+
+
+ private final MemberRepository memberRepository;
+
+ @Autowired
+ public SpringConfig(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+
+
+ @Bean
+ public MemberService memberService() {
+ return new MemberService(memberRepository);
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
new file mode 100644
index 0000000..a5fc193
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
@@ -0,0 +1,30 @@
+package hello.hellospring.aop;
+
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+@Component
+@Aspect
+public class TimeTraceAop {
+
+ @Around("execution(* hello.hellospring..*(..))")
+ public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
+
+ long start = System.currentTimeMillis();
+
+ System.out.println("Start : " + joinPoint.toString());
+
+ try{
+ return joinPoint.proceed();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = start - finish;
+
+ System.out.println("END : " + joinPoint.toString() + " " + timeMs + "ms");
+ }
+
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java"
new file mode 100644
index 0000000..39af351
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java"
@@ -0,0 +1,52 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class HelloController {
+
+ @GetMapping("hello")
+ public String hello(Model model){
+ model.addAttribute("data", "hello");
+ return "hello";
+ }
+
+ @GetMapping("hello-mvc")
+ public String helloMvc(@RequestParam("name") String name, Model model){
+ model.addAttribute("name", name);
+ return ("hello-template");
+ }
+
+
+ @GetMapping("hello-string")
+ @ResponseBody
+ public String helloString(@RequestParam("name") String name, Model model){
+ return "hello " + name;
+ }
+
+ @GetMapping("hello-api")
+ @ResponseBody
+ public Hello helloApi(@RequestParam("name") String name){
+ Hello hello = new Hello();
+ hello.setName(name);
+ return hello;
+ }
+
+
+
+ static class Hello {
+ private String name;
+
+ public String getName(){
+ return name;
+ }
+
+ public void setName(String name){
+ this.name = name;
+ }
+ }
+}
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java"
new file mode 100644
index 0000000..d74d0cc
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class HomeController {
+
+ @GetMapping("/")
+ public String home(){
+ return "home";
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java"
new file mode 100644
index 0000000..550f696
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java"
@@ -0,0 +1,45 @@
+package hello.hellospring.controller;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.service.MemberService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+
+@Controller
+public class MemberController {
+
+ private final MemberService memberService;
+
+ @Autowired
+ public MemberController(MemberService memberService) {
+ this.memberService = memberService;
+ }
+
+ @GetMapping("/members/new")
+ public String createForm() {
+ return "members/createMemberForm";
+ }
+
+ @PostMapping("/members/new")
+ public String create(MemberForm form){
+ Member member = new Member();
+ member.setName(form.getName());
+
+ memberService.join(member);
+
+ return "redirect:/";
+ }
+
+ @GetMapping("/members")
+ public String list(Model model){
+ List members = memberService.findMembers();
+ model.addAttribute("members", members);
+ return "members/memberList";
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java"
new file mode 100644
index 0000000..ee80768
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.controller;
+
+public class MemberForm {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java"
new file mode 100644
index 0000000..ff2f5fc
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java"
@@ -0,0 +1,32 @@
+package hello.hellospring.domain;
+
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+
+@Entity
+public class Member {
+
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
new file mode 100644
index 0000000..dc85bcd
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
@@ -0,0 +1,153 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class JdbcMemberRepository implements MemberRepository{
+
+ private final DataSource dataSource;
+
+ public JdbcMemberRepository(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+
+ @Override
+ public Member save(Member member) {
+ String sql = "insert into member(name) values(?)";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+
+ pstmt.setString(1, member.getName());
+ pstmt.executeUpdate();
+ rs = pstmt.getGeneratedKeys();
+ if (rs.next()) {
+ member.setId(rs.getLong(1));
+ } else {
+ throw new SQLException("id 조회 실패");
+ }
+ return member;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ String sql = "select * from member where id = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ } else {
+ return Optional.empty();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ String sql = "select * from member where name = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, name);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ }
+ return Optional.empty();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+
+ @Override
+ public List findAll() {
+ String sql = "select * from member";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+ List members = new ArrayList<>();
+ while(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ members.add(member);
+ }
+ return members;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+
+ private Connection getConnection() {
+ return DataSourceUtils.getConnection(dataSource);
+ }
+
+ private void close(Connection conn, PreparedStatement pstmt, ResultSet rs)
+ {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } try {
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (conn != null) {
+ close(conn);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ private void close(Connection conn) throws SQLException {
+ DataSourceUtils.releaseConnection(conn, dataSource);
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
new file mode 100644
index 0000000..1e71476
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
@@ -0,0 +1,62 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+
+import javax.sql.DataSource;
+import java.util.*;
+
+public class JdbcTemplateMemberRepository implements MemberRepository {
+
+
+
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcTemplateMemberRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+
+ @Override
+ public Member save(Member member) {
+ SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
+ jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
+
+ Map parameters = new HashMap<>();
+ parameters.put("name", member.getName());
+
+ Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
+ member.setId(key.longValue());
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return jdbcTemplate.query("select * from member",memberRowMapper());
+ }
+
+ private RowMapper memberRowMapper(){
+ return (rs, rowNum) -> {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return member;
+ };
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
new file mode 100644
index 0000000..59a4f6e
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
@@ -0,0 +1,44 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import jakarta.persistence.EntityManager;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+@Transactional
+public class JpaMemberRepository implements MemberRepository{
+
+ private final EntityManager em;
+
+ public JpaMemberRepository(EntityManager em) {
+ this.em = em;
+ }
+
+ @Override
+ public Member save(Member member) {
+ em.persist(member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ Member member = em.find(Member.class, id);
+ return Optional.ofNullable(member);
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = em.createQuery("select m from Member m where m.name = :name", Member.class)
+ .setParameter("name", name)
+ .getResultList();
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return em.createQuery("select m from Member m", Member.class)
+ .getResultList();
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java"
new file mode 100644
index 0000000..c7ca5aa
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface MemberRepository {
+ Member save(Member member);
+ Optional findById(Long id);
+ Optional findByName(String name);
+ List findAll();
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
new file mode 100644
index 0000000..cd6bad9
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
@@ -0,0 +1,40 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+
+import java.util.*;
+
+public class MemoryMemberRepository implements MemberRepository{
+ private static Map store = new HashMap<>(); //예제니깐 그냥 HashMap 씀
+ private static Long sequence = 0L;
+
+
+
+ @Override
+ public Member save(Member member) {
+ member.setId(++sequence);
+ store.put(member.getId(), member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ return Optional.ofNullable(store.get(id));
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ return store.values().stream()
+ .filter(member -> member.getName().equals(name))
+ .findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return new ArrayList<>(store.values());
+ }
+
+ public void clearStore(){
+ store.clear();
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
new file mode 100644
index 0000000..44ca046
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
@@ -0,0 +1,11 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository {
+
+ Optional findByName(String name);
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java"
new file mode 100644
index 0000000..c407347
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java"
@@ -0,0 +1,39 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+
+public class MemberService {
+
+ private final MemberRepository memberRepository;
+
+ public MemberService(MemberRepository memberRepository){
+ this.memberRepository = memberRepository;
+ }
+
+ public Long join(Member member){
+ validateDuplicateMember(member); //회원 중복 검증
+ memberRepository.save(member);
+ return member.getId();
+ }
+
+ public void validateDuplicateMember(Member member) {
+ memberRepository.findByName(member.getName())
+ .ifPresent(m -> {
+ throw new IllegalStateException("이미 존재하는 회원입니다.");
+ });
+ }
+
+ public List findMembers() { //전체 회원 조회
+ return memberRepository.findAll();
+ }
+
+ public Optional findOne(Long memberId) {
+ return memberRepository.findById(memberId);
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/application.properties" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/application.properties"
new file mode 100644
index 0000000..d01e763
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/application.properties"
@@ -0,0 +1,6 @@
+spring.datasource.url=jdbc:h2:tcp://localhost/~/test
+spring.datasource.driver-class-name=org.h2.Driver
+spring.datasource.username=sa
+
+spring.jpa.show-sql=true
+spring.jpa.hibernate.ddl-auto=none
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html"
new file mode 100644
index 0000000..a163199
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html"
@@ -0,0 +1,10 @@
+
+
+
+ static content
+
+
+
+정적 컨텐츠 입니다.
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html"
new file mode 100644
index 0000000..d48451b
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html"
@@ -0,0 +1,11 @@
+
+
+
+ Hello
+
+
+
+Hello
+hello
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html"
new file mode 100644
index 0000000..66c25d8
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html"
@@ -0,0 +1,5 @@
+
+
+hello! empty
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html"
new file mode 100644
index 0000000..81f8f1c
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html"
@@ -0,0 +1,10 @@
+
+
+
+ Hello
+
+
+
+안녕하세요. 손님
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html"
new file mode 100644
index 0000000..1f32c58
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html"
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html"
new file mode 100644
index 0000000..4024e49
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html"
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html"
new file mode 100644
index 0000000..d4d6b7f
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html"
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+ #
+ 이름
+
+
+
+
+
+
+
+
+
+
+
+
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
new file mode 100644
index 0000000..87d37cf
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
@@ -0,0 +1,13 @@
+package hello.hellospring;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HelloSpringApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
new file mode 100644
index 0000000..99fff59
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
@@ -0,0 +1,59 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+class MemoryMemberRepositoryTest {
+
+ MemoryMemberRepository repository = new MemoryMemberRepository();
+
+
+ @AfterEach
+ public void afterEach(){
+ repository.clearStore();
+ }
+ @Test
+ public void save() {
+ Member member = new Member();
+ member.setName("spring");
+
+ repository.save(member);
+
+ Member result = repository.findById(member.getId()).get();
+ Assertions.assertThat(result).isEqualTo(member);
+ }
+
+ @Test
+ public void findByName() {
+ Member member1 = new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2 = new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+
+ Member result = repository.findByName("spring1").get();
+
+ Assertions.assertThat(result).isEqualTo(member1);
+ }
+
+ @Test
+ public void findAll() {
+ Member member1 = new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2 = new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+
+ List result = repository.findAll();
+
+ Assertions.assertThat(result.size()).isEqualTo(2);
+ }
+}
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
new file mode 100644
index 0000000..2ec202f
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
@@ -0,0 +1,48 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+@SpringBootTest
+@Transactional
+class MemberServiceIntegrationTest {
+
+ @Autowired MemberService service;
+ @Autowired MemberRepository memberRepository;
+
+
+ @Test
+ void 회원가입() {
+ //given
+ Member member = new Member();
+ member.setName("spring");
+ //when
+ Long saveId = service.join(member);
+ //then
+ Member member1 = service.findOne(saveId).get();
+ Assertions.assertThat(member.getName()).isEqualTo(member1.getName());
+ }
+
+ @Test
+ void 회원_중복_예외() {
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+ //when
+ service.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class,
+ () -> service.join(member2));
+ //then
+ Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ }
+
+}
\ No newline at end of file
diff --git "a/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java" "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java"
new file mode 100644
index 0000000..67062be
--- /dev/null
+++ "b/HxWOO/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java"
@@ -0,0 +1,60 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class MemberServiceTest {
+
+ MemberService service;
+ MemoryMemberRepository memberRepository;
+
+ @BeforeEach
+ void beforeEach() {
+ memberRepository = new MemoryMemberRepository();
+ service = new MemberService(memberRepository);
+ }
+ @Test
+ void 회원가입() {
+ //given
+ Member member = new Member();
+ member.setName("spring");
+ //when
+ Long saveId = service.join(member);
+ //then
+ Member member1 = service.findOne(saveId).get();
+ Assertions.assertThat(member.getName()).isEqualTo(member1.getName());
+ }
+
+ @Test
+ void 회원_중복_예외() {
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+ //when
+ service.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class,
+ () -> service.join(member2));
+ //then
+ Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ }
+
+ @Test
+ void validateDuplicateMember() {
+ }
+
+ @Test
+ void findMembers() {
+ }
+
+ @Test
+ void findOne() {
+ }
+}
\ No newline at end of file
diff --git a/Iaminjae/README.md b/Iaminjae/README.md
new file mode 100644
index 0000000..891c1bc
--- /dev/null
+++ b/Iaminjae/README.md
@@ -0,0 +1,60 @@
+- `**스프링 2차 확인 질문[스프링 입문]**`
+
+ 💡 다음과 같은 상황을 서술하시오. (정해진 답은 없고, 공부 복습 차원)
+
+ 1. **GetMapping(”hello”)의 의미? 해당 화면을 보고 싶으면 어떤 url로 접속하면 되는지?**
+
+ localhost:8080/hello
+
+ 2. **model은 뭐하러 쓰는지?** (자유롭게 서술하지만, 1. 모델을 굳이 선언해서 사용하는 이유, 2. “data”를 html파일에서 사용하는 방법 을 포함하여.)
+
+ 캡슐화 → 밖에서 접근을 못하게 하고, 바뀌지 않게 보호를 해야 한다.
+
+ view 와 controller 가 model 을 임의로 조작할 수 없다.
+
+ 3. **return “hello”; 를 하는 이유?**
+
+ 
+
+ 반환형이 string 이기도 하고, view 에 data 를 반환해주기 위해.
+
+ 1. **만약 GetMapping 밑에@ResponseBody를 삽입한다면** `localhost:8080/hello-string`**에 접속 시 무엇이 출력 될 것인가?** 모르겠다면 진행해보자. 현재로써 뷰리졸버 등등 어려운 용어는 절대 외울 필요 없다.
+
+ 
+
+ 파라미터로 받은 name 의 값이 hello 뒤에 나오게 된다.
+
+
+
+
+ 💡 회원 리스트 html에서 아래 사진의 실행결과를 출력해서 붙여넣기하시오
+
+ **members 리스트는 강의대로 사용해도 좋고, 현 umc 서버 멤버 이름을 사용한다면 더 좋음.**
+
+ 
+
+
+
+
+ 💡 아래 사진의 클래스를 스프링 빈으로 등록하고 싶다면 어떤 어노테이션을 사용하면 되는가?
+
+ 1. @Controller
+
+ 
+
+ 1. @Repository
+
+ 
+
+ 이런 어노테이션을 왜 사용하는지 이해가 안될텐데 그냥 써야된다는 것만 알아둬도 충분하다. ~~(약간 설명 주자면 음 스프링 실행시에 스프링한테 리포지토리로 이걸 쓸거다 우리가 말해주는 느낌?)~~
+
+
+
+
+ 💡 JPA란? (직접 구글링, 매우 중요함. DB에 넣고 출력할 때 무조건 JPA 다 사용할 예정. 지금은 어지럽겠지만 개념만 알아두자. 왜쓰는지만.)
+ 1. **JPA를 굳이 왜 쓰지?** (구글링 그대로 받아들이기보다 그냥 자신의 이해내용을 막 적기)
+ 2. jpql이란? **필수아님. →** 가능하다면 sql로 “select * from user where id = 1” 을 jpql로 바꿔볼 수 있을까?
+
+ 쿼리를 대신 만들어서 날려줌. DB 마다 쿼리문의 문법이 조금씩 다른데 JPA 가 알아서 자동으로 쿼리문을 적절하게 날려줌.
+
+
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/practice.iml" b/UMC.iml
similarity index 74%
rename from "in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/practice.iml"
rename to UMC.iml
index c90834f..4bf07d7 100644
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/practice.iml"
+++ b/UMC.iml
@@ -3,7 +3,7 @@
-
+
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/.gitignore" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/.gitignore"
new file mode 100644
index 0000000..86d29b4
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/.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
+.springBea
+.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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
new file mode 100644
index 0000000..4666e36
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
@@ -0,0 +1,13 @@
+Ctrl + Space : intellij import 단축어
+
+Ctrl + Alt + v : return을 그냥 해줌
+
+Alt + Enter : 오류 수정, 인텐션 액션, 검사
+
+Ctrl + Alt + n : inline 단축키
+
+Ctrl + B : 해당 코드가 정의된 곳으로 이동하기
+
+Ctrl + Alt + B : 해당 코드가 구현된 곳으로 이동하기
+
+단위 테스트를 잘 만드는 것이 좋은 테스트이다.
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/build.gradle" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/build.gradle"
new file mode 100644
index 0000000..8e8d2b2
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/build.gradle"
@@ -0,0 +1,31 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.1.4'
+ id 'io.spring.dependency-management' version '1.1.3'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ //implementation 'org.springframework.boot:spring-boot-starter-jdbc'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ runtimeOnly 'com.h2database:h2'
+ testImplementation ('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.jar" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.jar"
new file mode 100644
index 0000000..033e24c
Binary files /dev/null and "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.jar" differ
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.properties" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.properties"
new file mode 100644
index 0000000..9f4197d
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradle/wrapper/gradle-wrapper.properties"
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradlew" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradlew"
new file mode 100644
index 0000000..fcb6fca
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradlew"
@@ -0,0 +1,248 @@
+#!/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##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && 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=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=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, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradlew.bat" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/gradlew.bat"
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/settings.gradle" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/settings.gradle"
new file mode 100644
index 0000000..69a39da
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/settings.gradle"
@@ -0,0 +1 @@
+rootProject.name = 'hello-spring'
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/sql/ddl.sql" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/sql/ddl.sql"
new file mode 100644
index 0000000..b20616c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/sql/ddl.sql"
@@ -0,0 +1,7 @@
+drop table if exists member CASCADE;
+create table member
+(
+ id bigint generated by default as identity,
+ name varchar(255),
+ primary key (id)
+);
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/HelloSpringApplication.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/HelloSpringApplication.java"
new file mode 100644
index 0000000..8b59cc3
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/HelloSpringApplication.java"
@@ -0,0 +1,14 @@
+package hello.hellospring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelloSpringApplication {
+
+ public static void main(String[] args) {
+
+ SpringApplication.run(HelloSpringApplication.class, args);
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/SpringConfig.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/SpringConfig.java"
new file mode 100644
index 0000000..bc723ff
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/SpringConfig.java"
@@ -0,0 +1,54 @@
+package hello.hellospring;
+
+import hello.hellospring.aop.TimeTraceAop;
+import hello.hellospring.repository.JdbcMemberRepository;
+import hello.hellospring.repository.JpaMemberRepository;
+import hello.hellospring.repository.MemberRepository;
+import hello.hellospring.service.MemberService;
+import jakarta.persistence.EntityManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class SpringConfig {
+
+ /*private final DataSource dataSource;
+
+ @Autowired
+ public SpringConfig(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+ */
+
+ /*private EntityManager em;
+
+ @Autowired
+ public SpringConfig(EntityManager em) {
+ this.em = em;
+ }
+ */
+
+ private final MemberRepository memberRepository;
+
+ @Autowired
+ public SpringConfig(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+
+ @Bean
+ public MemberService memberService() {
+ return new MemberService(memberRepository);
+ }
+
+ //@Bean
+ //public MemberRepository memberRepository() {
+ // return new MemoryMemberRepository();
+ //return new JdbcMemberRepository(dataSource);
+ //return new JdbcTemplateMemberRepository(dataSource);
+ //return new JpaMemberRepository(em);
+
+ //}
+
+ //Controller는 어차피 spring이 관리하므로 컴포넌트 스캔으로 올라가서 Autowired로 한다
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/aop/TimeTraceAop.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
new file mode 100644
index 0000000..afe808a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
@@ -0,0 +1,23 @@
+package hello.hellospring.aop;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+
+@Aspect
+@Component
+public class TimeTraceAop {
+ @Around("execution(* hello.hellospring..*(..))") //적용 대상
+ public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
+ long start = System.currentTimeMillis();
+ System.out.println("START: " + joinPoint.toString());
+ try {
+ return joinPoint.proceed();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = finish - start;
+ System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HelloController.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HelloController.java"
new file mode 100644
index 0000000..cac7ca1
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HelloController.java"
@@ -0,0 +1,50 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class HelloController { //컨트롤러 보고 스프링 뜰 때 HelloController라는 객체 생성히여 스프링 컨테이너에서 빈이 관리됨
+
+ @GetMapping("hello")
+ public String hello(Model model) {
+ model.addAttribute("data", "hello!!");
+ return "hello";
+ }
+
+ @GetMapping("hello-mvc")
+ public String helloMvc(@RequestParam("name") String name, Model model) {
+ model.addAttribute("name", name);
+ return "hello-template";
+ }
+
+ @GetMapping("hello-string") // 문자로 받았으니 string 방식
+ @ResponseBody // 바디부에 이 데이터를 직접 넣어주겠다
+ public String helloString(@RequestParam("name") String name) {
+ return "hello " + name; //"hello spring" view같은거 x, 이 문자가 그대로 내려감
+ }
+
+ @GetMapping("hello-api") // 객체로 받았으니 json 방식
+ @ResponseBody
+ public Hello helloApi(@RequestParam("name") String name) {
+ Hello hello = new Hello();
+ hello.setName(name);
+ return hello;
+ }
+
+ static class Hello {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+}
+
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HomeController.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HomeController.java"
new file mode 100644
index 0000000..d9c2007
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/HomeController.java"
@@ -0,0 +1,14 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class HomeController {
+
+ @GetMapping("/")
+ public String home() {
+ return "home";
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberController.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberController.java"
new file mode 100644
index 0000000..1e5c960
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberController.java"
@@ -0,0 +1,48 @@
+package hello.hellospring.controller;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.service.MemberService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+
+@Controller
+public class MemberController {
+
+ private final MemberService memberService;
+
+ @Autowired //생성자에 Autowired: 스프링이 스프링 컨테이너에 있는 멤버 서비스를 가져다가 연결을 해줌
+ public MemberController(MemberService memberService) {
+ this.memberService = memberService;
+ System.out.println("memberService = " + memberService.getClass());
+ }
+
+ @GetMapping("/members/new") //조회할 때 사용
+ public String createdForm() {
+ return "members/createMemberForm";
+ }
+
+ @PostMapping("/members/new") //폼 같은 곳에 넣어서 전달할 때 사용
+ public String create(MemberForm form) {
+ Member member = new Member();
+ member.setName(form.getName());
+
+ // System.out.println("member = " + member.getName());
+
+ memberService.join(member);
+
+ return "redirect:/";
+ }
+
+ @GetMapping("/members")
+ public String list(Model model) {
+ List members = memberService.findMembers();
+ model.addAttribute("members", members);
+ return "members/memberList";
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberForm.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberForm.java"
new file mode 100644
index 0000000..ee80768
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/controller/MemberForm.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.controller;
+
+public class MemberForm {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/domain/Member.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/domain/Member.java"
new file mode 100644
index 0000000..d09a0ad
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/domain/Member.java"
@@ -0,0 +1,29 @@
+package hello.hellospring.domain;
+
+import jakarta.persistence.*;
+
+@Entity
+public class Member {
+
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @Column(name = "username")
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
new file mode 100644
index 0000000..70d6376
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
@@ -0,0 +1,137 @@
+package hello.hellospring.repository;
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+public class JdbcMemberRepository implements MemberRepository {
+ private final DataSource dataSource;
+ public JdbcMemberRepository(DataSource dataSource) {
+ this.dataSource = dataSource; }
+ @Override
+ public Member save(Member member) {
+ String sql = "insert into member(name) values(?)";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql,
+ Statement.RETURN_GENERATED_KEYS);
+ pstmt.setString(1, member.getName());
+ pstmt.executeUpdate();
+ rs = pstmt.getGeneratedKeys();
+ if (rs.next()) {
+ member.setId(rs.getLong(1));
+ } else {
+ throw new SQLException("id 조회 실패");
+ }
+ return member;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public Optional findById(Long id) {
+ String sql = "select * from member where id = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null; ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ } else {
+ return Optional.empty();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public List findAll() {
+ String sql = "select * from member";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery(); List members = new ArrayList<>();
+ while(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ members.add(member);
+ }
+ return members;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public Optional findByName(String name) {
+ String sql = "select * from member where name = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, name);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ } return Optional.empty();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ private Connection getConnection() {
+ return DataSourceUtils.getConnection(dataSource);
+ }
+ private void close(Connection conn, PreparedStatement pstmt, ResultSet rs)
+ {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (conn != null) {
+ close(conn);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ private void close(Connection conn) throws SQLException {
+ DataSourceUtils.releaseConnection(conn, dataSource); }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
new file mode 100644
index 0000000..d189694
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
@@ -0,0 +1,62 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class JdbcTemplateMemberRepository implements MemberRepository{
+
+ private final JdbcTemplate jdbcTemplate;
+
+ public JdbcTemplateMemberRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+
+ @Override
+ public Member save(Member member) {
+ SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
+ jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
+ Map parameters = new HashMap<>();
+ parameters.put("name", member.getName());
+ Number key = jdbcInsert.executeAndReturnKey(new
+ MapSqlParameterSource(parameters));
+ member.setId(key.longValue());
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return jdbcTemplate.query("select * from member", memberRowMapper());
+ }
+
+ private RowMapper memberRowMapper() {
+ return (rs, rowNum) -> {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return member;
+ };
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JpaMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
new file mode 100644
index 0000000..9ea1aaf
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
@@ -0,0 +1,42 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import jakarta.persistence.EntityManager;
+
+import java.util.List;
+import java.util.Optional;
+
+public class JpaMemberRepository implements MemberRepository {
+
+ private final EntityManager em; //JPA 사용하려면 EntityManager은 필수
+ public JpaMemberRepository(EntityManager em) {
+ this.em = em;
+ }
+
+ @Override
+ public Member save(Member member) {
+ em.persist(member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ Member member = em.find(Member.class, id);
+ return Optional.ofNullable(member);
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ List result = em.createQuery("select m from Member m where m.name = :name", Member.class)
+ .setParameter("name", name)
+ .getResultList();
+
+ return result.stream().findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return em.createQuery("select m from Member m", Member.class)
+ .getResultList();
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemberRepository.java"
new file mode 100644
index 0000000..fba045b
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemberRepository.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+
+import java.util.List;
+import java.util.Optional;
+public interface MemberRepository {
+ Member save(Member member);
+ Optional findById(Long id);
+ Optional findByName(String name);
+ List findAll();
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
new file mode 100644
index 0000000..3545f43
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
@@ -0,0 +1,40 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.stereotype.Repository;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import java.util.*;
+
+public class MemoryMemberRepository implements MemberRepository {
+
+ private static Map store = new HashMap<>();
+ private static long sequence = 0L;
+ @Override
+ public Member save(Member member) {
+ member.setId(++sequence);
+ store.put(member.getId(),member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ return Optional.ofNullable(store.get(id)); // NULL의 가능성으로 Optional로 감싼다.
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ return store.values().stream()
+ .filter(member -> member.getName().equals(name))
+ .findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return new ArrayList<>(store.values());
+ }
+
+ public void clearStore() {
+ store.clear();
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
new file mode 100644
index 0000000..b0cc5aa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
@@ -0,0 +1,12 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository {
+ //JPQL select m from Member m where m.name = ?
+ @Override
+ Optional findByName(String name);
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/service/MemberService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/service/MemberService.java"
new file mode 100644
index 0000000..596afaa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/java/hello/hellospring/service/MemberService.java"
@@ -0,0 +1,49 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+@Transactional
+public class MemberService {
+ private final MemberRepository memberRepository;
+
+ public MemberService(MemberRepository memberRepository) { //외부에서 memberRepository 넣어줌 -> memberService 입장에선 di라고 함
+ this.memberRepository = memberRepository;
+ }
+
+ /**
+ * 회원가입
+ */
+ public Long join(Member member) {
+
+ //같은 이름이 있는 중복 회원 X
+ validateDuplicateMember(member); //중복 회원 검증
+ memberRepository.save(member);
+ return member.getId();
+ }
+
+ private void validateDuplicateMember(Member member) {
+ memberRepository.findByName(member.getName())
+ .ifPresent(member1 -> {
+ throw new IllegalStateException("이미 존재하는 회원입니다.");
+ });
+ }
+
+ /**
+ * 전체 회원 조회
+ */
+ public List findMembers() {
+ return memberRepository.findAll();
+ }
+
+ public Optional findOne(Long memberId) {
+ return memberRepository.findById((memberId));
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/application.properties" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/application.properties"
new file mode 100644
index 0000000..5651e4a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/application.properties"
@@ -0,0 +1,6 @@
+spring.datasource.url=jdbc:h2:tcp://localhost/~/test
+spring.datasource.driver-class-name=org.h2.Driver
+
+spring.datasource.username=sa
+spring.jpa.show-sql = true
+spring.jpa.hibernate.ddl-auto = create
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/hello-static.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/hello-static.html"
new file mode 100644
index 0000000..17b699a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/hello-static.html"
@@ -0,0 +1,10 @@
+
+
+
+ static content
+
+
+
+정적 컨텐츠 입니다.
+
+
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/index.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/index.html"
new file mode 100644
index 0000000..3bf7dfa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/static/index.html"
@@ -0,0 +1,11 @@
+
+
+
+ Hello
+
+
+
+Hello
+hello
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello-template.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello-template.html"
new file mode 100644
index 0000000..66c25d8
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello-template.html"
@@ -0,0 +1,5 @@
+
+
+hello! empty
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello.html"
new file mode 100644
index 0000000..2583060
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/hello.html"
@@ -0,0 +1,11 @@
+
+
+
+ Hello
+
+
+
+안녕하세요. 손님
+
+
+
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/home.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/home.html"
new file mode 100644
index 0000000..3cf8ef8
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/home.html"
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/createMemberForm.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/createMemberForm.html"
new file mode 100644
index 0000000..a7ff4a5
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/createMemberForm.html"
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/memberList.html" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/memberList.html"
new file mode 100644
index 0000000..d36135a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/main/resources/templates/members/memberList.html"
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+ #
+ 이름
+
+
+
+ // $는 모델 안에 있는 값을 꺼낸다
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/HelloSpringApplicationTests.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
new file mode 100644
index 0000000..87d37cf
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
@@ -0,0 +1,13 @@
+package hello.hellospring;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HelloSpringApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
new file mode 100644
index 0000000..a9d03b2
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
@@ -0,0 +1,61 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+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 MemoryMemberRepositoryTest {
+
+ MemoryMemberRepository repository = new MemoryMemberRepository();
+
+ @AfterEach
+ public void afterEach() {
+ repository.clearStore(); // 테스트가 끝날 때마다 공용데이터를 깜끔하게 지워주어야 함
+ }
+
+ @Test
+ public void save() {
+ Member member = new Member();
+ member.setName("spring");
+
+ repository.save(member);
+
+ Member result = repository.findById(member.getId()).get();
+ assertThat(member).isEqualTo(result);
+ }
+
+ @Test
+ public void findByName() {
+ Member member1 = new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2 = new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+
+ Member result = repository.findByName("spring1").get();
+
+ assertThat(result).isEqualTo(member1);
+ }
+
+ @Test
+ public void findAll() {
+ Member member1 = new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2 = new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+ git push -u origin master
+ List result = repository.findAll();
+ assertThat(result.size()).isEqualTo(2);
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
new file mode 100644
index 0000000..c2b34aa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
@@ -0,0 +1,53 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.Commit;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@SpringBootTest
+@Transactional //트랜젝션 실행, db에 데이터를 인서트 쿼리를 다 하고 다 넣은 다음 테스트 끝나고 롤백해줌 - db에 넣었던 데이터 반영 안되고 다 지워줌 - 다음 테스트에 영향 안 줌
+class MemberServiceIntegrationTest {
+
+ @Autowired MemberService memberService;
+ @Autowired MemberRepository memberRepository;
+
+ @Test
+ void 회원가입() { //주석이 도움이 많이 된다
+ //given 주어졌을 때
+ Member member = new Member();
+ member.setName("spring100");
+
+ //when 실행했을 때
+ Long saveId = memberService.join(member);
+
+ //then 나와야 해
+ Member findMember = memberService.findOne(saveId).get();
+ assertThat(member.getName()).isEqualTo(findMember.getName());
+
+ }
+
+ @Test
+ public void 중복_회원_예외() {
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+
+ //when
+ memberService.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ }
+}
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceTest.java"
new file mode 100644
index 0000000..ac677fb
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/src/test/java/hello/hellospring/service/MemberServiceTest.java"
@@ -0,0 +1,77 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class MemberServiceTest {
+
+ MemberService memberService;
+ MemoryMemberRepository memberRepository;
+
+ @BeforeEach
+ public void beforeEach() {
+ memberRepository = new MemoryMemberRepository();
+ memberService = new MemberService(memberRepository); //같은 memberRepository 사용 가능 (따로따로 객체 생성 x)
+ }
+
+ @AfterEach
+ public void afterEach() {
+ memberRepository.clearStore(); // 테스트가 끝날 때마다 db값 지워짐
+ }
+
+ @Test
+ void 회원가입() { //주석이 도움이 많이 된다
+ //given 주어졌을 때
+ Member member = new Member();
+ member.setName("spring");
+
+ //when 실행했을 때
+ Long saveId = memberService.join(member);
+
+ //then 나와야 해
+ Member findMember = memberService.findOne(saveId).get();
+ assertThat(member.getName()).isEqualTo(findMember.getName());
+
+ }
+
+ @Test
+ public void 중복_회원_예외() {
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+
+ //when
+ memberService.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+/*
+ try {
+ memberService.join(member2);
+ fail("예외가 발생했습니다.");
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ }
+*/
+ //then
+ }
+
+ @Test
+ void findMembers() {
+ }
+
+ @Test
+ void findOne() {
+ }
+}
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.MD" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.MD"
new file mode 100644
index 0000000..88f4a01
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.MD"
@@ -0,0 +1,5 @@
+https://six-warlock-900.notion.site/2-1-189af929a9c84b4d835c5e59a87d0ca6?pvs=4 (1/3)
+
+https://six-warlock-900.notion.site/3-2-d347a708f08842ff836b724a05beb161?pvs=4 (2/3)
+
+https://six-warlock-900.notion.site/4-3-fc25a8fd405a4179a15d0c43883ac371?pvs=4 (3/3)
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/.gitignore" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/.gitignore"
new file mode 100644
index 0000000..c2065bc
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/.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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/build.gradle" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/build.gradle"
new file mode 100644
index 0000000..d2f7658
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/build.gradle"
@@ -0,0 +1,46 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.1.4'
+ id 'io.spring.dependency-management' version '1.1.3'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+//lombok 설정 추가 시작
+configurations {
+ compileOnly {
+ extendsFrom annotationProcessor
+ }
+}
+//lombok 설정 추가 끝
+
+java {
+ sourceCompatibility = '17'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter'
+ //web 라이브러리 추가
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ implementation 'jakarta.inject:jakarta.inject-api:2.0.1'
+
+ //lombok 라이브러리 추가 시작
+ compileOnly 'org.projectlombok:lombok'
+ annotationProcessor 'org.projectlombok:lombok'
+ testCompileOnly 'org.projectlombok:lombok'
+ testAnnotationProcessor 'org.projectlombok:lombok'
+ //lombok 라이브러리 추가 끝
+
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.jar" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.jar"
new file mode 100644
index 0000000..033e24c
Binary files /dev/null and "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.jar" differ
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.properties" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.properties"
new file mode 100644
index 0000000..9f4197d
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradle/wrapper/gradle-wrapper.properties"
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradlew" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradlew"
new file mode 100644
index 0000000..fcb6fca
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradlew"
@@ -0,0 +1,248 @@
+#!/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##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && 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=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=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, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradlew.bat" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/gradlew.bat"
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/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/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/settings.gradle" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/settings.gradle"
new file mode 100644
index 0000000..4d52ac5
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/settings.gradle"
@@ -0,0 +1 @@
+rootProject.name = 'core'
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AppConfig.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AppConfig.java"
new file mode 100644
index 0000000..c88d168
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AppConfig.java"
@@ -0,0 +1,42 @@
+package hello.core;
+
+import hello.core.discount.DiscountPolicy;
+import hello.core.discount.FixDiscountPolicy;
+import hello.core.discount.RateDiscountPolicy;
+import hello.core.member.MemberRepository;
+import hello.core.member.MemberService;
+import hello.core.member.MemberServiceImpl;
+import hello.core.member.MemoryMemberRepository;
+import hello.core.order.OrderService;
+import hello.core.order.OrderServiceImpl;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AppConfig { // 애플리케이션의 설정, 구성 정보
+
+ @Bean // Bean을 붙이면 스프링 컨테이너에 등록이 된다.
+ public MemberService memberService() {
+
+ System.out.println("call AppConfig.memberService");
+ return new MemberServiceImpl(memberRepository());
+ }
+ @Bean
+ public MemberRepository memberRepository() {
+
+ System.out.println("call AppConfig.memberRepository");
+ return new MemoryMemberRepository();
+ }
+ @Bean
+ public OrderService orderService() {
+
+ System.out.println("call AppConfig.orderService");
+ return new OrderServiceImpl(memberRepository(), discountPolicy());
+ }
+ @Bean
+ public DiscountPolicy discountPolicy() {
+ //return new FixDiscountPolicy();
+ return new RateDiscountPolicy(); // 구현 객체만 바꾸면 된다!
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AutoAppConfig.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AutoAppConfig.java"
new file mode 100644
index 0000000..61dc6d9
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/AutoAppConfig.java"
@@ -0,0 +1,24 @@
+package hello.core;
+
+import hello.core.member.MemberRepository;
+import hello.core.member.MemoryMemberRepository;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+import org.springframework.stereotype.Component;
+
+@Configuration
+@ComponentScan(
+ basePackages = "hello.core.member",
+ basePackageClasses = AutoAppConfig.class,
+ excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class) //그중에서 뺄 것을 지정
+) //스프링 빈을 쫙 긁어서 자동으로 끌어 올려줌
+public class AutoAppConfig {
+
+ /*@Bean(name = "memoryMemberRepository")
+ MemberRepository memberRepository() {
+ return new MemoryMemberRepository();
+ }
+ */
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/CoreApplication.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/CoreApplication.java"
new file mode 100644
index 0000000..5bc183f
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/CoreApplication.java"
@@ -0,0 +1,13 @@
+package hello.core;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CoreApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CoreApplication.class, args);
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/HelloLombok.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/HelloLombok.java"
new file mode 100644
index 0000000..ab0d417
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/HelloLombok.java"
@@ -0,0 +1,25 @@
+package hello.core;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+import java.lang.annotation.Target;
+
+@Getter
+@Setter
+//롬복이 자동으로 변수보고 getter, setter 만들어 줌
+@ToString
+public class HelloLombok {
+
+ private String name;
+ private int age;
+
+ public static void main(String[] args) {
+ HelloLombok helloLombok = new HelloLombok();
+ helloLombok.setName("sdgssge");
+
+ String name = helloLombok.getName();
+ System.out.println("helloLombok = " + helloLombok);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/MemberApp.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/MemberApp.java"
new file mode 100644
index 0000000..95e410e
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/MemberApp.java"
@@ -0,0 +1,30 @@
+package hello.core;
+
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import hello.core.member.MemberService;
+import hello.core.member.MemberServiceImpl;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class MemberApp {
+
+ public static void main(String[] args) {
+ //AppConfig appConfig = new AppConfig();
+ //MemberService memberService = appConfig.memberService(); //memberService에는 MemberServiceImpl이 들어가 있음
+ //appConfig에서 memberService를 직접 찾아오는 것이 아닌
+ //MemberService memberService = new MemberServiceImpl(); //기존에는 내가 직접 메인 메소드에서 MemberServiceImpl을 생성 해줌
+
+ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);//스프링의 시작, 스프링 컨테이너라고 보면 됨. 얘가 모든 것을 관리해 줌
+ // AppConfig에 있는 환경 설정 정보를 가지고 스프링 컨테이너에 객체 생성한 것을 집어 넣어서 관리 해준다.
+ MemberService memberService = applicationContext.getBean("memberService", MemberService.class); //이름은 첫번째 파라미타, 타입은 두번째 파라미타야.해서 찾아 꺼낸다.
+ //스프링 컨테이너를 통해서 직접 찾아와야 한다.
+
+ Member member = new Member(1L, "memberA", Grade.Vip); //Long타입이라 1뒤에 L붙여주어야 함
+ memberService.join(member);
+
+ Member findMember = memberService.findMember(1L);
+ System.out.println("new member = " + member.getName());
+ System.out.println("find Member = " + findMember.getName());
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/OrderApp.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/OrderApp.java"
new file mode 100644
index 0000000..0d24b0c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/OrderApp.java"
@@ -0,0 +1,33 @@
+package hello.core;
+
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import hello.core.member.MemberService;
+import hello.core.member.MemberServiceImpl;
+import hello.core.order.Order;
+import hello.core.order.OrderService;
+import hello.core.order.OrderServiceImpl;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class OrderApp {
+ public static void main(String[] args) {
+ //MemberService memberService = new MemberServiceImpl();
+ //OrderService orderService = new OrderServiceImpl();
+ //AppConfig appConfig = new AppConfig();
+ //MemberService memberService = appConfig.memberService();
+ //OrderService orderService = appConfig.orderService();
+
+ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
+ MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
+ OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
+
+ Long memberId = 1L;
+ Member member = new Member(memberId, "memberA", Grade.Vip);
+ memberService.join(member);
+
+ Order order = orderService.createOrder(memberId, "itemA", 10000);
+ System.out.println("order = " + order);
+ System.out.println("order.calculatePrice = " + order.calculatePrice());
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/annotation/MainDiscountPolicy.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/annotation/MainDiscountPolicy.java"
new file mode 100644
index 0000000..5152692
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/annotation/MainDiscountPolicy.java"
@@ -0,0 +1,13 @@
+package hello.core.annotation;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@Qualifier("mainDiscountPolicy")
+public @interface MainDiscountPolicy {
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/common/MyLogger.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/common/MyLogger.java"
new file mode 100644
index 0000000..bd59e6a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/common/MyLogger.java"
@@ -0,0 +1,36 @@
+package hello.core.common;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+import org.springframework.stereotype.Component;
+
+import java.util.UUID;
+
+@Component
+@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
+public class MyLogger {
+
+ private String uuid;
+ private String requestURL;
+
+ public void setRequestURL(String requestURL) {
+ this.requestURL = requestURL;
+ }
+
+ public void log(String message) {
+ System.out.println("[" + uuid + "]" + "[" + requestURL + "] " + message);
+ }
+
+ @PostConstruct
+ public void init() {
+ uuid = UUID.randomUUID().toString(); //전 세계 하나뿐인 글로벌한 ID 생성
+ System.out.println("[" + uuid + "] request scope bean create: " + this);
+ }
+
+ @PreDestroy
+ public void close() {
+ System.out.println("[" + uuid + "] request scope bean close: " + this);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/DiscountPolicy.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/DiscountPolicy.java"
new file mode 100644
index 0000000..f1b5cc1
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/DiscountPolicy.java"
@@ -0,0 +1,11 @@
+package hello.core.discount;
+
+import hello.core.member.Member;
+
+public interface DiscountPolicy {
+
+ /**
+ * @return 할인 대상 금액
+ */
+ int discount(Member member, int price);
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/FixDiscountPolicy.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/FixDiscountPolicy.java"
new file mode 100644
index 0000000..e9dac60
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/FixDiscountPolicy.java"
@@ -0,0 +1,21 @@
+package hello.core.discount;
+
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+@Component
+public class FixDiscountPolicy implements DiscountPolicy {
+
+ private int discountFixAmount = 1000; //1000원 할인
+ @Override
+ public int discount(Member member, int price) {
+ if(member.getGrade() == Grade.Vip) {
+ return discountFixAmount;
+ }
+ else {
+ return 0;
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/RateDiscountPolicy.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/RateDiscountPolicy.java"
new file mode 100644
index 0000000..5d7e83c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/discount/RateDiscountPolicy.java"
@@ -0,0 +1,23 @@
+package hello.core.discount;
+
+import hello.core.annotation.MainDiscountPolicy;
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Component;
+
+@Component
+@MainDiscountPolicy
+public class RateDiscountPolicy implements DiscountPolicy {
+
+ private int discountPercent = 10;
+ @Override
+ public int discount(Member member, int price) {
+ if(member.getGrade()== Grade.Vip) {
+ return price * discountPercent / 100;
+ } else {
+ return 0;
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Grade.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Grade.java"
new file mode 100644
index 0000000..7b8f59c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Grade.java"
@@ -0,0 +1,6 @@
+package hello.core.member;
+
+public enum Grade {
+ Basic,
+ Vip
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Member.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Member.java"
new file mode 100644
index 0000000..b613584
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/Member.java"
@@ -0,0 +1,37 @@
+package hello.core.member;
+
+public class Member {
+ private Long id;
+ private String name;
+ private Grade grade;
+
+ public Member(Long id, String name, Grade grade) {
+ this.id = id;
+ this.name = name;
+ this.grade = grade;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Grade getGrade() {
+ return grade;
+ }
+
+ public void setGrade(Grade grade) {
+ this.grade = grade;
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberRepository.java"
new file mode 100644
index 0000000..86e565a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberRepository.java"
@@ -0,0 +1,7 @@
+package hello.core.member;
+
+public interface MemberRepository {
+ void save(Member member);
+
+ Member findById(Long memberId);
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberService.java"
new file mode 100644
index 0000000..feb3aa6
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberService.java"
@@ -0,0 +1,7 @@
+package hello.core.member;
+
+public interface MemberService {
+ void join(Member member);
+
+ Member findMember(Long memberId);
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberServiceImpl.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberServiceImpl.java"
new file mode 100644
index 0000000..66b5853
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemberServiceImpl.java"
@@ -0,0 +1,31 @@
+package hello.core.member;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class MemberServiceImpl implements MemberService {
+ private final MemberRepository memberRepository;
+
+ @Autowired //의존관계 자동 주입 (의존관계 직접 명시되어 있지 않으므로)
+ //ac.getBean(MemberRepository.class) 라는 동작을 한다고 보면 된다
+ public MemberServiceImpl(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+ // 생성자를 통해 MemberRepository에 무슨 구현체가 들어갈건지 선택을 한다
+
+ @Override
+ public void join(Member member) {
+ memberRepository.save(member);
+ }
+
+ @Override
+ public Member findMember(Long memberId) {
+ return memberRepository.findById(memberId); //
+ }
+
+ //테스트 용도
+ public MemberRepository getMemberRepository() {
+ return memberRepository;
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemoryMemberRepository.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemoryMemberRepository.java"
new file mode 100644
index 0000000..00a780f
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/member/MemoryMemberRepository.java"
@@ -0,0 +1,21 @@
+package hello.core.member;
+
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component //name = memoryMemberRepository
+public class MemoryMemberRepository implements MemberRepository{
+
+ private static Map store= new HashMap<>();
+ @Override
+ public void save(Member member) {
+ store.put(member.getId(), member);
+ }
+
+ @Override
+ public Member findById(Long memberId) {
+ return store.get(memberId);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/Order.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/Order.java"
new file mode 100644
index 0000000..59a6dfa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/Order.java"
@@ -0,0 +1,61 @@
+package hello.core.order;
+
+public class Order {
+ private Long memberId;
+ private String itemName;
+ private int itemPrice;
+ private int discountPrice;
+
+ public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
+ this.memberId = memberId;
+ this.itemName = itemName;
+ this.itemPrice = itemPrice;
+ this.discountPrice = discountPrice;
+ }
+
+ public int calculatePrice() {
+ return itemPrice - discountPrice;
+ }
+
+ public Long getMemberId() {
+ return memberId;
+ }
+
+ public void setMemberId(Long memberId) {
+ this.memberId = memberId;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+
+ public int getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setItemPrice(int itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public int getDiscountPrice() {
+ return discountPrice;
+ }
+
+ public void setDiscountPrice(int discountPrice) {
+ this.discountPrice = discountPrice;
+ }
+
+ @Override
+ public String toString() { //toString()은 데이터를 편하게 볼 수 있게 하는 단축키
+ return "Order{" +
+ "memberId=" + memberId +
+ ", itemName='" + itemName + '\'' +
+ ", itemPrice=" + itemPrice +
+ ", discountPrice=" + discountPrice +
+ '}';
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderService.java"
new file mode 100644
index 0000000..1bd5164
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderService.java"
@@ -0,0 +1,5 @@
+package hello.core.order;
+
+public interface OrderService {
+ Order createOrder(Long memberId, String itemName, int itemPrice); //최종 주문 결과 반환
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderServiceImpl.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderServiceImpl.java"
new file mode 100644
index 0000000..0814953
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/order/OrderServiceImpl.java"
@@ -0,0 +1,41 @@
+package hello.core.order;
+
+import hello.core.annotation.MainDiscountPolicy;
+import hello.core.discount.DiscountPolicy;
+import hello.core.discount.FixDiscountPolicy;
+import hello.core.discount.RateDiscountPolicy;
+import hello.core.member.Member;
+import hello.core.member.MemberRepository;
+import hello.core.member.MemoryMemberRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+@Component
+//@RequiredArgsConstructor //final이 붙은 값을 가지고 생성자를 만들어 줌
+public class OrderServiceImpl implements OrderService{
+ private final MemberRepository memberRepository;
+ private final DiscountPolicy discountPolicy;
+
+ @Autowired
+ public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
+ this.memberRepository = memberRepository;
+ this.discountPolicy = discountPolicy;
+ }
+
+ @Override
+ public Order createOrder(Long memberID, String itemName, int itemPrice) {
+ Member member = memberRepository.findById(memberID);
+ int discountPrice = this.discountPolicy.discount(member, itemPrice);
+
+
+ return new Order(memberID, itemName, itemPrice, discountPrice);
+ }
+
+ //테스트 용도
+ public MemberRepository getMemberRepository() {
+ return memberRepository;
+ }
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoController.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoController.java"
new file mode 100644
index 0000000..ddb2ff2
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoController.java"
@@ -0,0 +1,30 @@
+package hello.core.web;
+
+import hello.core.common.MyLogger;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequiredArgsConstructor
+public class LogDemoController {
+
+ private final LogDemoService logDemoService;
+ private final MyLogger myLogger; //주입받는 것이 아닌 찾을 수 있는 DL 기능 객체가 주입 됨
+
+ @RequestMapping("log-demo")
+ @ResponseBody //문자를 그대로 온다고 보낼 수 있음
+ public String logDemo(HttpServletRequest request) throws InterruptedException { //자바에서 제공하는 표준 survlet에 의한 http-request 정보(고객 요청 정보)를 받을 수 있음
+ String requestURl = request.getRequestURL().toString();
+
+ System.out.println("myLogger = " + myLogger.getClass());
+ myLogger.setRequestURL(requestURl);
+
+ myLogger.log("controller test");
+ logDemoService.logic("testId");
+ return "OK";
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoService.java"
new file mode 100644
index 0000000..5aa1a4c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/java/hello/core/web/LogDemoService.java"
@@ -0,0 +1,16 @@
+package hello.core.web;
+
+import hello.core.common.MyLogger;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class LogDemoService {
+
+ private final MyLogger myLogger;
+ public void logic(String id) {
+ myLogger.log("service id = " + id);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/appConfig.xml" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/appConfig.xml"
new file mode 100644
index 0000000..a56c08c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/appConfig.xml"
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/application.properties" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/application.properties"
new file mode 100644
index 0000000..f190e3b
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/main/resources/application.properties"
@@ -0,0 +1 @@
+spring.main.allow-bean-definition-overriding=false
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/CoreApplicationTests.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/CoreApplicationTests.java"
new file mode 100644
index 0000000..79b7fbf
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/CoreApplicationTests.java"
@@ -0,0 +1,16 @@
+package hello.core;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class CoreApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+ //Spring이라 실행시간 다른 것에 비해 오래 걸림. But 다른 라이브러리 많이 들어가고 하면 훨씬 오래 걸림.
+ //단위테스트를 잘 만드는 것이 엄청나게 중요하다!!!
+ //여기서 단위테스트란 스프링이나 이런 컨테이너의 도움 없이 그냥 순수하게 자바 코드로 테스트 하는 것
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AllBeanTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AllBeanTest.java"
new file mode 100644
index 0000000..4dfadaa
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AllBeanTest.java"
@@ -0,0 +1,50 @@
+package hello.core.autowired;
+
+import hello.core.AutoAppConfig;
+import hello.core.discount.DiscountPolicy;
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.*;
+
+public class AllBeanTest {
+
+ @Test
+ void findAllBean() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);
+ //DiscountService를 스프링 빈에 등록, 후에 AutoAppConfig 추가했으므로 AutoAppConfig도 다 등록, 이때 AutoAppConfig는 컴포넌트 스캔을 한다
+ DiscountService discountService = ac.getBean(DiscountService.class);
+ Member member = new Member(1L, "userA", Grade.Vip);
+ int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");
+
+ assertThat(discountService).isInstanceOf(DiscountService.class);
+ assertThat(discountPrice).isEqualTo(1000);
+
+ int rateDiscountPrice = discountService.discount(member, 20000, "rateDiscountPolicy");
+ assertThat(rateDiscountPrice).isEqualTo(2000);
+ }
+
+ static class DiscountService { //기존 오더 서비스를 손대면 너무 복잡해지므로, 새로운 서비스를 만듬
+ private final Map policyMap;
+ private final List policies;
+
+ public DiscountService(Map policyMap, List policies) {
+ this.policyMap = policyMap;
+ this.policies = policies;
+ System.out.println("policyMap = " + policyMap);
+ System.out.println("policies = " + policies);
+ }
+
+ public int discount(Member member, int price, String discountCode) { //할인 코드를 빈 이름이랑 매칭시킨다
+ DiscountPolicy discountPolicy = policyMap.get(discountCode);
+ return discountPolicy.discount(member, price);
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AutowiredTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AutowiredTest.java"
new file mode 100644
index 0000000..e045ad2
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/autowired/AutowiredTest.java"
@@ -0,0 +1,37 @@
+package hello.core.autowired;
+
+import hello.core.member.Member;
+import jakarta.annotation.Nullable;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import java.util.Optional;
+
+public class AutowiredTest {
+ @Test
+ void AutowiredOption() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);//TestBean이 스프링 빈으로 등록이 된다.
+ //ac.getBean(); //TestBean 받기
+ }
+
+ static class TestBean {
+
+ @Autowired(required = false) //false 안해주면 멤버가 빈으로 등록되는 것이 아니라서 오류가 난다
+ //required = false를 해두면 의존관계가 없을 시, 메소드 자체가 호출이 아예 안된다.
+ public void setNoBean1(Member noBean1) { //Member는 스프링 관련된 빈이 아님. 즉 스프링 컨테이너에서 관리 되는 것이 아닌 것을 아무거나 집어 넣은 것.
+ System.out.println("noBean1 = " + noBean1);
+ }
+
+ @Autowired
+ public void setNoBean2(@Nullable Member noBean2) { //호출은 되지만, null로 들어간다
+ System.out.println("noBean2 = " + noBean2);
+ }
+
+ @Autowired(required = false)
+ public void setNoBean3(Optional noBean3) {
+ System.out.println("noBean3 = " + noBean3);
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beandefinition/BeanDefinitionTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beandefinition/BeanDefinitionTest.java"
new file mode 100644
index 0000000..029efc6
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beandefinition/BeanDefinitionTest.java"
@@ -0,0 +1,29 @@
+package hello.core.beandefinition;
+
+import hello.core.AppConfig;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.context.support.GenericXmlApplicationContext;
+
+public class BeanDefinitionTest {
+ //AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
+ //여기서 ApplicationContext를 안 한 이유는 getBeanDefinition를 사용할 수 없기 때문 (정의가 안 되어 있다)
+ GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
+
+ @Test
+ @DisplayName("빈 설정 메타정보 확인")
+ void findApplicationBean() {
+ String[] beanDefinitionNames = ac.getBeanDefinitionNames();
+ for (String beanDefinitionName : beanDefinitionNames) { //ApplicationContext에서 getBeanDefinition 정보를 알아낼 수 있다
+ BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
+
+ if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
+ System.out.println("beanDefinitionName = " + beanDefinitionName +
+ " beanDefinition = " + beanDefinition);
+ }
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextBasicFindTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextBasicFindTest.java"
new file mode 100644
index 0000000..a1436ad
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextBasicFindTest.java"
@@ -0,0 +1,49 @@
+package hello.core.beanfind;
+
+import hello.core.AppConfig;
+import hello.core.member.MemberService;
+import hello.core.member.MemberServiceImpl;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class ApplicationContextBasicFindTest {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ @Test
+ @DisplayName("빈 이름으로 조회")
+ void findBeanByName() {
+ MemberService memberService = ac.getBean("memberService", MemberService.class);
+ assertThat(memberService).isInstanceOf(MemberServiceImpl.class); // 검증은 Assertions
+ }
+
+ @Test
+ @DisplayName("이름 없이 타입으로만 조회")
+ void findBeanByType() {
+ MemberService memberService = ac.getBean(MemberService.class); //이름 제거
+ //현재는 인터페이스로 조회, 인터페이스의 구현체가 대상이 됨
+ assertThat(memberService).isInstanceOf(MemberServiceImpl.class); // 검증은 Assertions
+ }
+
+ @Test
+ @DisplayName("구체 타입으로 조회")
+ void findBeanByName2() {
+ MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class); //스프링 컨테이너에 저런 객체가 등록이 되어있으면 조회 가능
+ assertThat(memberService).isInstanceOf(MemberServiceImpl.class); // 검증은 Assertions
+ }
+ //그러나 구체 타입으로 적는 것은 안좋다. 유연성이 떨어짐 -> 역할과 구현 구분해야 하고, 역할에 의존 해야함.
+
+ @Test
+ @DisplayName("빈 이름으로 조회X") //실패 경우의 test도 만들어야 한다
+ void findBeanByNameX() {
+ //ac.getBean("xxxxx", MemberService.class);
+ assertThrows(NoSuchBeanDefinitionException.class,
+ () -> ac.getBean("xxxxx", MemberService.class)); //자바파일의 람다 기능 사용, 위에 static import 두개
+ //오른쪽 로직을 실행하면 왼쪽의 예외가 터지면 성공
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextExtendsFindTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextExtendsFindTest.java"
new file mode 100644
index 0000000..de63330
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextExtendsFindTest.java"
@@ -0,0 +1,79 @@
+package hello.core.beanfind;
+
+import hello.core.AppConfig;
+import hello.core.discount.DiscountPolicy;
+import hello.core.discount.FixDiscountPolicy;
+import hello.core.discount.RateDiscountPolicy;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class ApplicationContextExtendsFindTest {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
+
+ @Test
+ @DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 중복 오류가 발생한다")
+ void findBeanByParentTypeDuplicate() {
+ assertThrows(NoUniqueBeanDefinitionException.class,
+ () -> ac.getBean(DiscountPolicy.class));
+ }
+
+ @Test
+ @DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정하면 된다")
+ void findBeanByParentTypeBeanName() {
+ DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class); //타입은 DiscountPolicy지만, 구현객체는 rateDiscountPolicy가 나옴
+ assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
+ }
+
+ @Test
+ @DisplayName("특정 하위 타입으로 조회") //안 좋은 방법이다
+ void findBeanBySubType() {
+ RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
+ assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
+ }
+
+ @Test
+ @DisplayName("부모 타입으로 모두 조회하기")
+ void findAllBeanByParentType() {
+ Map beansOfType = ac.getBeansOfType(DiscountPolicy.class);
+ assertThat(beansOfType.size()).isEqualTo(2);
+ for (String key : beansOfType.keySet()) {
+ System.out.println("key = " + key + " value = " + beansOfType.get(key)); //실제 테스트 케이스 짤 때는 이러한 출력물을 만들면 안된다.
+ // 나중에 자동 통과 실패를 시스템이 결정해야 하므로 눈으로 일일이 볼 수 없다. 테스트 자체를 디버깅해보고 싶을 때 남길 수는 있다.
+ }
+
+ }
+
+ @Test
+ @DisplayName("부모 타입으로 모두 조회하기 - Object") // 스프링의 모든 빈들 다 튀어나옴. Java객체는 모든 것이 Object타입이기 때문
+ void findAllBeanByObjectType() {
+ Map beansOfType = ac.getBeansOfType(Object.class);
+ for (String key : beansOfType.keySet()) {
+ System.out.println("key = " + key + " value = " + beansOfType.get(key));
+ }
+ }
+
+ @Configuration
+ static class TestConfig { //DiscountPolicy를 조회하면 자식 타입인 rate와 fix가 둘 다 조회되어야 함
+ @Bean
+ public DiscountPolicy rateDiscountPolicy() { //여기서 DiscountPolicy를 RateDiscountPolicy로 해두어도 됨.
+ // 그러나 DiscountPolicy로 해두는 이유는 역할과 구현을 구분하는 이유와 같은 이유이다.
+ // 이것을 보고 역할을 보는 셈. 그래야 다른 곳에서 의존관계 주입시에도 이 역할을 보고 의존할 수 있다.
+ return new RateDiscountPolicy();
+ }
+
+ @Bean
+ public DiscountPolicy fixDiscountPolicy() {
+ return new FixDiscountPolicy();
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextSameBeanFindTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextSameBeanFindTest.java"
new file mode 100644
index 0000000..dd52419
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextSameBeanFindTest.java"
@@ -0,0 +1,64 @@
+package hello.core.beanfind;
+
+import hello.core.AppConfig;
+import hello.core.discount.DiscountPolicy;
+import hello.core.member.MemberRepository;
+import hello.core.member.MemoryMemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class ApplicationContextSameBeanFindTest {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class); //SameBeanConfig만 가지고 실행
+
+ @Test
+ @DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다")
+ void findBeanByTypeDuplicate() {
+ //MemberRepository bean = ac.getBean(MemberRepository.class); //여기서 MemberRepository 조회하면 두개가 나옴 -> 스프링 입장에서 예외가 터짐
+ assertThrows(NoUniqueBeanDefinitionException.class,
+ () -> ac.getBean(MemberRepository.class));
+ //예외가 터지면 성공
+ }
+
+ @Test
+ @DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 빈 이름을 저장하면 된다")
+ void findBeanByName() {
+ MemberRepository memberRepository = ac.getBean("memberRepository1",MemberRepository.class); //타입 앞에 빈 이름을 지정해 주면 됨
+ assertThat(memberRepository).isInstanceOf(MemberRepository.class);
+ }
+
+ @Test
+ @DisplayName("특정 타입을 모두 조회하기") //한번에 조회하기는 Autowired해서 자동으로 의존관계 주입할 때도 이런 기능이 적용되기도 함
+ void findAllBeanByType() {
+ Map beansOfType = ac.getBeansOfType(MemberRepository.class);
+ for (String key : beansOfType.keySet()) {
+ System.out.println("key = " + key + " value = " + beansOfType.get(key));
+ }
+ System.out.println("beansOfType = " + beansOfType);
+ assertThat(beansOfType.size()).isEqualTo(2); //2개여야 함
+ }
+
+
+ @Configuration
+ static class SameBeanConfig { //이 안에서만 쓸 것. AppConfig 고치기 싫어서
+ //빈의 이름이 다르고 객체 인스턴스(클래스) 타입이 같을 수 있다
+ @Bean
+ public MemberRepository memberRepository1() {
+ return new MemoryMemberRepository();
+ }
+
+ @Bean
+ public MemberRepository memberRepository2() {
+ return new MemoryMemberRepository();
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextinfoTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextinfoTest.java"
new file mode 100644
index 0000000..d003e88
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/beanfind/ApplicationContextinfoTest.java"
@@ -0,0 +1,36 @@
+package hello.core.beanfind;
+
+import hello.core.AppConfig;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+public class ApplicationContextinfoTest {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
+
+ @Test
+ @DisplayName("모든 빈 출력하기")
+ void findAllBean() {
+ String[] beanDefinitionNames = ac.getBeanDefinitionNames();
+ for (String beanDefinitionName : beanDefinitionNames) {
+ Object bean = ac.getBean(beanDefinitionName);
+ System.out.println("name = " + beanDefinitionName + " object = " + bean); // soutv
+ }
+ }
+
+ @Test
+ @DisplayName("어플리케이션 빈 출력하기")
+ void findApplicationBean() {
+ String[] beanDefinitionNames = ac.getBeanDefinitionNames();
+ for (String beanDefinitionName : beanDefinitionNames) {
+ BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);//getBeanDefinition 빈에 대한 메타데이터 정보
+
+ if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {// Role은 크게 3가지가 있는데, 주로 쓰는 것은 ROLE_APPLICATION.
+ //이것은 스프링의 내부 뭔가를 하기 위해서 등록된 빈들이 아니라 내가 어플리케이션을 주로 개발하기 위해서 등록한 빈들. 외부 라이브러리 등
+ Object bean = ac.getBean(beanDefinitionName);
+ System.out.println("name = " + beanDefinitionName + " object = " + bean); // soutv
+ }
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/discount/RateDiscountPolicyTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/discount/RateDiscountPolicyTest.java"
new file mode 100644
index 0000000..b1db587
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/discount/RateDiscountPolicyTest.java"
@@ -0,0 +1,39 @@
+package hello.core.discount;
+
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+class RateDiscountPolicyTest {
+
+ RateDiscountPolicy discountPolicy = new RateDiscountPolicy();
+
+ @Test
+ @DisplayName("VIP는 10% 할인이 적용되어야 한다")
+ void vip_o() {
+ //given
+ Member member = new Member(1L, "memberVIP", Grade.Vip);
+ //when
+ int discount = discountPolicy.discount(member, 10000);
+ //then
+ assertThat(discount).isEqualTo(1000); //여기서는 static import를 하는 것이 좋다. Alt + Enter
+ }
+
+ @Test
+ @DisplayName("VIP가 아니면 할인이 적용되지 않아야 한다.")
+ void vip_x() {
+ //given
+ Member member = new Member(1L, "memberBASIC", Grade.Basic);
+ //when
+ int discount = discountPolicy.discount(member, 10000);
+ //then
+ //assertThat(discount).isEqualTo(1000);
+
+ //캡쳐한 error 메시지 참고하자
+ }
+}
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/BeanLifeCycleTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/BeanLifeCycleTest.java"
new file mode 100644
index 0000000..30e2439
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/BeanLifeCycleTest.java"
@@ -0,0 +1,29 @@
+package hello.core.lifecycle;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+public class BeanLifeCycleTest {
+
+ @Test
+ public void lifeCycleTest() {
+ ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
+ NetworkClient client = ac.getBean(NetworkClient.class);
+ ac.close();
+ }
+
+ @Configuration
+ static class LifeCycleConfig {
+ @Bean
+ public NetworkClient networkClient() {
+ NetworkClient networkClient = new NetworkClient();
+ networkClient.setUrl("http://hello-spring.dev");
+ return networkClient;
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/NetworkClient.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/NetworkClient.java"
new file mode 100644
index 0000000..638b448
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/lifecycle/NetworkClient.java"
@@ -0,0 +1,45 @@
+package hello.core.lifecycle;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+
+public class NetworkClient {
+
+ private String url;
+
+ public NetworkClient() {
+ System.out.println("생성자 호출, url = " + url);
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ //서비스 시작시 호출
+ public void connect() {
+ System.out.println("connect: " + url);
+ }
+
+ public void call(String message) { //연결한 서버에 메시지를 던질 수 있는 call메소드
+ System.out.println("call: " + url + " meessage = " + message);
+ }
+
+ //서비스 종료시 호출
+ public void disconnect() {
+ System.out.println("close " + url);
+ }
+
+ @PostConstruct
+ public void init() {
+ // properties가 세팅이 끝나면 = 의존 관계 주입이 끝나면 호출해 주겠다.
+ System.out.println("NetworkClient.init");
+ connect();
+ call("초기화 연결 메시지");
+ }
+
+ @PreDestroy
+ public void close() {
+ System.out.println("NetworkClient.close");
+ disconnect();
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/member/MemberServiceTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/member/MemberServiceTest.java"
new file mode 100644
index 0000000..8833ae8
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/member/MemberServiceTest.java"
@@ -0,0 +1,32 @@
+package hello.core.member;
+
+import hello.core.AppConfig;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class MemberServiceTest {
+
+ //MemberService memberService = new MemberServiceImpl();
+ MemberService memberService; //Test는 appconfig에서 바로 꺼내주기가 애매하다
+ @BeforeEach
+ public void beforeEach() { //BeforeEach란 테스트를 실행하기 전에 무조건 실행이 되게 함, Test 2개면 2번 돌듯이 Test 갯수대로 돈다.
+ AppConfig appConfig = new AppConfig();
+ memberService = appConfig.memberService();
+ }
+
+ @Test
+ void join() {
+ //given: 주어졌을 때
+ Member member = new Member(1L, "memberA", Grade.Vip);
+
+ //when: 이렇게 했을 때
+ memberService.join(member);
+ Member findMember = memberService.findMember(1L);
+
+ //then: 이렇게 된다
+ Assertions.assertThat(member).isEqualTo(findMember); //검증은 Assertions 사용
+ }
+}
+
+//오류가 나면 바로 x가 뜨면서 나온다. 어떤 부분에서 테스트가 실패했는지 빨리 캐치가 가능. 테스트 코드는 필수 중에 필수!!!
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceImplTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceImplTest.java"
new file mode 100644
index 0000000..bcaccf8
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceImplTest.java"
@@ -0,0 +1,24 @@
+package hello.core.order;
+
+import hello.core.discount.FixDiscountPolicy;
+import hello.core.member.Grade;
+import hello.core.member.Member;
+import hello.core.member.MemoryMemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.*;
+
+class OrderServiceImplTest {
+
+ @Test
+ void createOrder() {
+ MemoryMemberRepository memberRepository = new MemoryMemberRepository();
+ memberRepository.save(new Member(1L, "name", Grade.Vip)); //member 하나를 아무렇게나 만들어줘야 예외가 안뜸
+
+ OrderServiceImpl orderService = new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
+ Order order = orderService.createOrder(1L, "itemA", 10000);
+ assertThat(order.getDiscountPrice()).isEqualTo(1000);
+ }
+}
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceTest.java"
new file mode 100644
index 0000000..5400f47
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/order/OrderServiceTest.java"
@@ -0,0 +1,33 @@
+package hello.core.order;
+
+import hello.core.AppConfig;
+import hello.core.discount.FixDiscountPolicy;
+import hello.core.member.*;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.internal.matchers.Or;
+
+public class OrderServiceTest {
+ //MemberService memberService = new MemberServiceImpl();
+ //OrderService orderService = new OrderServiceImpl();
+
+ MemberService memberService;
+ OrderService orderService;
+ @BeforeEach
+ public void beforeEach() {
+ AppConfig appConfig = new AppConfig();
+ memberService = appConfig.memberService();
+ orderService = appConfig.orderService();
+ }
+
+ @Test
+ void createOrder() {
+ Long memberID = 1L; // primitive 타입인 long을 쓰면 null을 넣을 수가 없음. 나중에 DB에 null 넣을 때 불가능
+ Member member = new Member(memberID, "memberA", Grade.Vip);
+ memberService.join(member);
+
+ Order order = orderService.createOrder(memberID, "item", 10000);
+ Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);//검증을 assertions (org-assertj.core.api)를 써야 method-chain..에서 편하게 테스트 만들 수 있음
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/AutoAppConfigTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/AutoAppConfigTest.java"
new file mode 100644
index 0000000..21e9390
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/AutoAppConfigTest.java"
@@ -0,0 +1,27 @@
+package hello.core.scan;
+
+import hello.core.AutoAppConfig;
+import hello.core.member.MemberRepository;
+import hello.core.member.MemberService;
+import hello.core.member.MemberServiceImpl;
+import hello.core.order.OrderServiceImpl;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class AutoAppConfigTest {
+
+ @Test
+ void basicScan() {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
+
+ MemberService memberService = ac.getBean(MemberService.class);
+ assertThat(memberService).isInstanceOf(MemberService.class);
+
+ OrderServiceImpl bean = ac.getBean(OrderServiceImpl.class);
+ MemberRepository memberRepository = bean.getMemberRepository();
+ System.out.println("memberRepository = " + memberRepository);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanA.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanA.java"
new file mode 100644
index 0000000..a7f4b23
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanA.java"
@@ -0,0 +1,5 @@
+package hello.core.scan.filter;
+
+@MyIncludeComponent
+public class BeanA {
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanB.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanB.java"
new file mode 100644
index 0000000..56fac76
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/BeanB.java"
@@ -0,0 +1,5 @@
+package hello.core.scan.filter;
+
+@MyExcludeComponent
+public class BeanB {
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/ComponentFilterAppConfigTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/ComponentFilterAppConfigTest.java"
new file mode 100644
index 0000000..0a70449
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/ComponentFilterAppConfigTest.java"
@@ -0,0 +1,38 @@
+package hello.core.scan.filter;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.FilterType;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.springframework.context.annotation.ComponentScan.*;
+
+public class ComponentFilterAppConfigTest {
+
+ @Test
+ void filterScan() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(ComponentFilterAppConfig.class);
+ BeanA beanA = ac.getBean("beanA", BeanA.class);
+ assertThat(beanA).isNotNull();
+
+ assertThrows(
+ NoSuchBeanDefinitionException.class,
+ () -> ac.getBean("beanB", BeanB.class));
+
+ }
+
+ @Configuration
+ @ComponentScan( //나만의 컴포넌트 스캔을 할 수 있는 기능이 만들어짐
+ includeFilters = @Filter(type = FilterType.ANNOTATION, classes = MyIncludeComponent.class),
+ excludeFilters = @Filter(classes = MyExcludeComponent.class) //type = FilterType.ANNOTATION은 기본값이라 생략 가능
+ )
+ static class ComponentFilterAppConfig {
+
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyExcludeComponent.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyExcludeComponent.java"
new file mode 100644
index 0000000..d8aa0cd
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyExcludeComponent.java"
@@ -0,0 +1,9 @@
+package hello.core.scan.filter;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE) //TYPE이면 클래스 레벨에 붙는 것
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface MyExcludeComponent {
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyIncludeComponent.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyIncludeComponent.java"
new file mode 100644
index 0000000..9b32320
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scan/filter/MyIncludeComponent.java"
@@ -0,0 +1,9 @@
+package hello.core.scan.filter;
+
+import java.lang.annotation.*;
+
+@Target(ElementType.TYPE) //TYPE이면 클래스 레벨에 붙는 것
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface MyIncludeComponent {
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/PrototypeTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/PrototypeTest.java"
new file mode 100644
index 0000000..5a79f51
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/PrototypeTest.java"
@@ -0,0 +1,43 @@
+package hello.core.scope;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Scope;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PrototypeTest {
+ @Test
+ void prototypeBeanFind() {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
+ //AnnotationConfigApplicationContext에 지정한 클래스가 Component 스캔의 대상 자체처럼 동작하기 때문에 바로 스프링 빈으로 등록한다.
+ //따라서 밑에 PrototypeBean에 @Component 안붙여도 된다.
+ System.out.println("find prototypeBean1"); //prototypeBean을 조회하기 직전에 생성되므로
+ PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
+ System.out.println("find prototypeBean2");
+ PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
+ System.out.println("prototypeBean1 = " + prototypeBean1);
+ System.out.println("prototypeBean2 = " + prototypeBean2);
+ assertThat(prototypeBean1).isNotSameAs(prototypeBean2);
+
+ ac.close();
+
+ prototypeBean1.destroy();
+ prototypeBean2.destroy();
+ }
+
+ @Scope("prototype")
+ static class PrototypeBean {
+ @PostConstruct
+ public void init() {
+ System.out.println("PrototypeBean.init");
+ }
+
+ @PreDestroy
+ public void destroy() {
+ System.out.println("PrototypeBean.destroy");
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonTest.java"
new file mode 100644
index 0000000..f9ba594
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonTest.java"
@@ -0,0 +1,36 @@
+package hello.core.scope;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Scope;
+
+import static org.assertj.core.api.Assertions.*;
+
+public class SingletonTest {
+ @Test
+ void singletonBeanFind() {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);
+ SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
+ SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
+ System.out.println("singletonBean1 = " + singletonBean1);
+ System.out.println("singletonBean2 = " + singletonBean2);
+ assertThat(singletonBean1).isSameAs(singletonBean2);
+
+ ac.close();
+ }
+ @Scope("singleton") //default값이 singleton이라 굳이 안써도 됨
+ static class SingletonBean {
+ @PostConstruct
+ public void init() {
+ System.out.println("SingletonBean.init");
+ }
+
+ @PreDestroy
+ public void destroy() {
+ System.out.println("SingletonBean.destroy");
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonWithPrototypeTest1.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonWithPrototypeTest1.java"
new file mode 100644
index 0000000..330eb03
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/scope/SingletonWithPrototypeTest1.java"
@@ -0,0 +1,77 @@
+package hello.core.scope;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
+import jakarta.inject.Provider;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Scope;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SingletonWithPrototypeTest1 {
+ @Test
+ void prototypeFind() {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
+ PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
+ prototypeBean1.addCount();
+ assertThat(prototypeBean1.getCount()).isEqualTo(1);
+
+ PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
+ prototypeBean2.addCount();
+ assertThat(prototypeBean2.getCount()).isEqualTo(1);
+ }
+
+ @Test
+ void singletonClientUsePrototype() {
+ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ClientBean.class, PrototypeBean.class);
+ ClientBean clientBean1 = ac.getBean(ClientBean.class);
+ int count1 = clientBean1.logic();
+ assertThat(count1).isEqualTo(1);
+
+ ClientBean clientBean2 = ac.getBean(ClientBean.class);
+ int count2 = clientBean2.logic();
+ assertThat(count2).isEqualTo(1);
+
+ }
+
+ @Scope("singleton")
+ static class ClientBean {
+
+ @Autowired
+ private Provider prototypeBeanProvider; //필드 주입
+
+ public int logic() {
+ PrototypeBean prototypeBean = prototypeBeanProvider.get();
+ prototypeBean.addCount();
+ int count = prototypeBean.getCount();
+ return count;
+ }
+ }
+
+ @Scope("prototype")
+ static class PrototypeBean {
+ private int count = 0;
+
+ public void addCount() {
+ count++;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ @PostConstruct
+ public void init() {
+ System.out.println("PrototypeBean.init" + this);
+ }
+
+ @PreDestroy
+ public void destroy() {
+ System.out.println("PrototypeBean.destroy");
+ }
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/ConfigurationSingletonTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/ConfigurationSingletonTest.java"
new file mode 100644
index 0000000..5d7ed6f
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/ConfigurationSingletonTest.java"
@@ -0,0 +1,42 @@
+package hello.core.singleton;
+
+import hello.core.AppConfig;
+import hello.core.member.MemberRepository;
+import hello.core.member.MemberServiceImpl;
+import hello.core.order.OrderServiceImpl;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ConfigurationSingletonTest {
+
+ @Test
+ void configurationTest() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
+ MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class); //getMemberRepository() 꺼내려고, 원래는 구체타입으로 꺼내는 것 안좋다
+ OrderServiceImpl orderService = ac.getBean("orderService", OrderServiceImpl.class);//getMemberRepository() 꺼내려고, 원래는 구체타입으로 꺼내는 것 안좋다
+ MemberRepository memberRepository = ac.getBean("memberRepository", MemberRepository.class);
+
+ MemberRepository memberRepository1 = memberService.getMemberRepository();
+ MemberRepository memberRepository2 = orderService.getMemberRepository();
+
+ System.out.println("memberService -> memberRepository = " + memberRepository1);
+ System.out.println("orderService -> memberRepository = " + memberRepository2);
+ System.out.println("memberRepository = " + memberRepository);
+
+ assertThat(memberService.getMemberRepository()).isSameAs(memberRepository);
+ assertThat(orderService.getMemberRepository()).isSameAs(memberRepository);
+ }
+
+ @Test
+ void configurationDeep() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); //AppConfig도 스프링빈으로 등록이 됨
+ AppConfig bean = ac.getBean(AppConfig.class);
+
+ System.out.println("bean = " + bean.getClass()); //getClass()를 씀으로써 classtype이 무엇인지 본다
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonService.java"
new file mode 100644
index 0000000..efe5acd
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonService.java"
@@ -0,0 +1,27 @@
+package hello.core.singleton;
+
+public class SingletonService {
+
+ private static final SingletonService instance = new SingletonService(); //자기 자신을 내부의 private으로 하나 가지고 있는데, static으로 가지고 있음
+ //클래스 레벨에 올라 가기 때문에 딱 하나만 존재 하게 됨
+ //자기 자신을 실행한 후, 객체를 생성한 다음에 instance에 참조를 넣어둔다
+ //자기 자신 인스턴스 객체를 하나 딱 생성하여 instance 안에만 들어가 있는 것
+
+ public static SingletonService getInstance() {
+ return instance; //instance의 참조를 꺼낼 수 있는 유일한 존재
+ }
+
+ private SingletonService() { //private 생성자로 SingletonSerive를 여러개 만드는 것 금지시켜 버림
+ }
+
+ public void logic() {
+ System.out.println("싱글톤 객체 로직 호출");
+ }
+
+ /*
+ public static void main(String[] arg) { 이렇게 다른 곳에서 new SingletonSerive를 두개 만들어 버릴 수도 있어서 private 생성자를 사용한다
+ SingletonService singletonService = new SingletonService();
+ }
+ */
+
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonTest.java"
new file mode 100644
index 0000000..b72ba8c
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/SingletonTest.java"
@@ -0,0 +1,63 @@
+package hello.core.singleton;
+
+import hello.core.AppConfig;
+import hello.core.member.MemberService;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SingletonTest {
+
+ @Test
+ @DisplayName("스프링 없는 순수한 DI 컨테이너")
+ void pureContainer(){
+ AppConfig appConfig = new AppConfig();
+ //1.조회: 호출할 때마다 객체를 생성
+ MemberService memberService1 = appConfig.memberService();
+
+ //2.조회: 호출할 때마다 객체를 생성
+ MemberService memberService2 = appConfig.memberService();
+
+ //참조값이 다른 것을 확인
+ System.out.println("memberService1 = " + memberService1);
+ System.out.println("memberService2 = " + memberService2);
+
+ //memberService != memberService2
+ assertThat(memberService1).isNotSameAs(memberService2);
+ }
+
+ @Test
+ @DisplayName("싱글톤 패턴을 적용한 객체 사용")
+ void singletonServiceTest() {
+ SingletonService singletonService1 = SingletonService.getInstance();
+ SingletonService singletonService2 = SingletonService.getInstance();
+
+ System.out.println("singletonService1 = " + singletonService1);
+ System.out.println("singletonService2 = " + singletonService2);
+
+ assertThat(singletonService1).isSameAs(singletonService2); //진짜 인스턴스와 같은 비교를 하므로 isSameAs() 사용
+ //same: ==
+ //equal: equals메소드 오버라이드
+ }
+
+ @Test
+ @DisplayName("스프링 컨테이너와 싱글톤")
+ void springContainer() {
+
+ //AppConfig appConfig = new AppConfig();
+ ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
+ MemberService memberService1 = ac.getBean("memberService", MemberService.class);
+ MemberService memberService2 = ac.getBean("memberService", MemberService.class);
+
+ //참조값이 다른 것을 확인
+ System.out.println("memberService1 = " + memberService1);
+ System.out.println("memberService2 = " + memberService2);
+
+ //memberService != memberService2
+ assertThat(memberService1).isSameAs(memberService2);
+ }
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulService.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulService.java"
new file mode 100644
index 0000000..303c74a
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulService.java"
@@ -0,0 +1,15 @@
+package hello.core.singleton;
+
+public class StatefulService {
+
+// private int price; //상태를 유지하는 필드
+ public int order(String name, int price) {
+ System.out.println("name = " + name + " price = " + price);
+ // this.price = price; //여기가 문제!
+ return price;
+ }
+ /* public int getPrice() {
+ return price;
+ }
+ */
+}
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulServiceTest.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulServiceTest.java"
new file mode 100644
index 0000000..eae9a63
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/singleton/StatefulServiceTest.java"
@@ -0,0 +1,38 @@
+package hello.core.singleton;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class StatefulServiceTest {
+
+ @Test
+ void statefulServiceSingleton() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
+ StatefulService statefulService1 = ac.getBean(StatefulService.class);
+ StatefulService statefulService2 = ac.getBean(StatefulService.class);
+
+ //ThreadA: A사용자 10000원 주문
+ int userAPrice = statefulService1.order("userA", 10000);
+ //ThreadB: B사용자 20000원 주문
+ int userBPrice = statefulService2.order("userA", 20000);
+
+ //ThreadA: 사용자A 주문 금액 조회
+ //int price = statefulService1.getPrice();
+ System.out.println("price = " + userAPrice);
+
+ //Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
+ }
+ static class TestConfig {
+
+ @Bean
+ public StatefulService statefulService() {
+ return new StatefulService();
+ }
+ }
+
+}
\ No newline at end of file
diff --git "a/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/xml/XmlAppContext.java" "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/xml/XmlAppContext.java"
new file mode 100644
index 0000000..4cc9db8
--- /dev/null
+++ "b/hyeon-ju/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/core/src/test/java/hello/core/xml/XmlAppContext.java"
@@ -0,0 +1,20 @@
+package hello.core.xml;
+
+import hello.core.member.MemberService;
+import net.bytebuddy.description.type.TypeList;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.GenericXmlApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class XmlAppContext {
+
+ @Test
+ void xmlAppContext() {
+ ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml"); //설정 정보가 클래스파일에서 xml로 바뀐 것밖에 없다
+ MemberService memberService = ac.getBean("memberService", MemberService.class);
+ assertThat(memberService).isInstanceOf(MemberService.class);
+ }
+}
diff --git "a/hyeon-ju/\354\233\214\355\201\254\353\266\201/1\354\243\274\354\260\250/README.md" "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/1\354\243\274\354\260\250/README.md"
new file mode 100644
index 0000000..bd8b4dc
--- /dev/null
+++ "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/1\354\243\274\354\260\250/README.md"
@@ -0,0 +1 @@
+https://six-warlock-900.notion.site/1-037992877d3b4442ba5c35ac11acd8d6?pvs=4
\ No newline at end of file
diff --git "a/hyeon-ju/\354\233\214\355\201\254\353\266\201/2\354\243\274\354\260\250/README.md" "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/2\354\243\274\354\260\250/README.md"
new file mode 100644
index 0000000..70d92f7
--- /dev/null
+++ "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/2\354\243\274\354\260\250/README.md"
@@ -0,0 +1 @@
+https://six-warlock-900.notion.site/2-b351094f2c45498b96f74da131262ae2?pvs=4
\ No newline at end of file
diff --git "a/hyeon-ju/\354\233\214\355\201\254\353\266\201/3\354\243\274\354\260\250/README.md" "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/3\354\243\274\354\260\250/README.md"
new file mode 100644
index 0000000..8a12e24
--- /dev/null
+++ "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/3\354\243\274\354\260\250/README.md"
@@ -0,0 +1 @@
+https://six-warlock-900.notion.site/3-15857f41f3834fd582bb8d19f00f5bcb?pvs=4
\ No newline at end of file
diff --git "a/hyeon-ju/\354\233\214\355\201\254\353\266\201/4\354\243\274\354\260\250/README.md" "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/4\354\243\274\354\260\250/README.md"
new file mode 100644
index 0000000..611da94
--- /dev/null
+++ "b/hyeon-ju/\354\233\214\355\201\254\353\266\201/4\354\243\274\354\260\250/README.md"
@@ -0,0 +1 @@
+https://six-warlock-900.notion.site/4-DATABASE-AWS-RDS-2a770da184b445e4bebafefb35068078?pvs=4
\ No newline at end of file
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/misc.xml" "b/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/misc.xml"
deleted file mode 100644
index 7d862fb..0000000
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/.idea/misc.xml"
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/out/production/practice/Main.class" "b/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/out/production/practice/Main.class"
deleted file mode 100644
index 80e96eb..0000000
Binary files "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/out/production/practice/Main.class" and /dev/null differ
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/DD.java" "b/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/DD.java"
deleted file mode 100644
index c9a3d31..0000000
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/DD.java"
+++ /dev/null
@@ -1,2 +0,0 @@
-public class DD {
-}
diff --git "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/Main.java" "b/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/Main.java"
deleted file mode 100644
index 3e59c38..0000000
--- "a/in-seo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/practice/src/Main.java"
+++ /dev/null
@@ -1,5 +0,0 @@
-public class Main {
- public static void main(String[] args) {
- System.out.println("Hello world!");
- }
-}
\ No newline at end of file
diff --git "a/in-seo/\354\212\244\355\224\204\353\247\201_\353\266\200\355\212\270\354\231\200_JPA_\355\231\234\354\232\2511/README.md" "b/in-seo/\354\212\244\355\224\204\353\247\201_\353\266\200\355\212\270\354\231\200_JPA_\355\231\234\354\232\2511/README.md"
deleted file mode 100644
index b1b7161..0000000
--- "a/in-seo/\354\212\244\355\224\204\353\247\201_\353\266\200\355\212\270\354\231\200_JPA_\355\231\234\354\232\2511/README.md"
+++ /dev/null
@@ -1 +0,0 @@
-init
diff --git "a/in-seo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md" "b/in-seo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
deleted file mode 100644
index b1b7161..0000000
--- "a/in-seo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
+++ /dev/null
@@ -1 +0,0 @@
-init
diff --git "a/in-seo/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.md" "b/in-seo/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.md"
deleted file mode 100644
index b1b7161..0000000
--- "a/in-seo/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254_\354\233\220\353\246\254/README.md"
+++ /dev/null
@@ -1 +0,0 @@
-init
diff --git "a/in-seo/\354\233\214\355\201\254\353\266\201/README.md" "b/in-seo/\354\233\214\355\201\254\353\266\201/README.md"
deleted file mode 100644
index b1b7161..0000000
--- "a/in-seo/\354\233\214\355\201\254\353\266\201/README.md"
+++ /dev/null
@@ -1 +0,0 @@
-init
diff --git "a/in-seo/\354\236\220\353\260\224_ORM_\355\221\234\354\244\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/README.md" "b/in-seo/\354\236\220\353\260\224_ORM_\355\221\234\354\244\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/README.md"
deleted file mode 100644
index b1b7161..0000000
--- "a/in-seo/\354\236\220\353\260\224_ORM_\355\221\234\354\244\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/README.md"
+++ /dev/null
@@ -1 +0,0 @@
-init
diff --git "a/jeongyeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring" "b/jeongyeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring"
new file mode 160000
index 0000000..8e4a2f2
--- /dev/null
+++ "b/jeongyeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring"
@@ -0,0 +1 @@
+Subproject commit 8e4a2f2f8bc9b7e0155b00e5f4e6485231cc8262
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/.gitignore" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/.gitignore"
new file mode 100644
index 0000000..c2065bc
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/.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/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/build.gradle" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/build.gradle"
new file mode 100644
index 0000000..9db48d1
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/build.gradle"
@@ -0,0 +1,31 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '2.7.15'
+ id 'io.spring.dependency-management' version '1.0.15.RELEASE'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '11'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ implementation 'org.springframework.boot:spring-boot-starter-jdbc'
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+ runtimeOnly 'com.h2database:h2'
+ testImplementation('org.springframework.boot:spring-boot-starter-test') {
+ exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
+ }
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar"
new file mode 100644
index 0000000..033e24c
Binary files /dev/null and "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.jar" differ
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties"
new file mode 100644
index 0000000..9f4197d
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradle/wrapper/gradle-wrapper.properties"
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradlew" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradlew"
new file mode 100644
index 0000000..fcb6fca
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradlew"
@@ -0,0 +1,248 @@
+#!/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##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && 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=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=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, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradlew.bat" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/gradlew.bat"
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/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/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/settings.gradle" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/settings.gradle"
new file mode 100644
index 0000000..69a39da
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/settings.gradle"
@@ -0,0 +1 @@
+rootProject.name = 'hello-spring'
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/sql/ddl.sql" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/sql/ddl.sql"
new file mode 100644
index 0000000..0f26cec
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/sql/ddl.sql"
@@ -0,0 +1,7 @@
+drop table if exists member CASCADE;
+create table member
+(
+ id bigint generated by default as identity,
+ name varchar(255),
+ primary key (id)
+);
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java"
new file mode 100644
index 0000000..f0f0fd4
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/HelloSpringApplication.java"
@@ -0,0 +1,13 @@
+package hello.hellospring;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelloSpringApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HelloSpringApplication.class, args);
+ }
+
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
new file mode 100644
index 0000000..a8ed6a1
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/aop/TimeTraceAop.java"
@@ -0,0 +1,21 @@
+package hello.hellospring.aop;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.stereotype.Component;
+@Component
+@Aspect
+public class TimeTraceAop {
+ @Around("execution(* hello.hellospring..*(..))")
+ public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
+ long start = System.currentTimeMillis();
+ System.out.println("START: " + joinPoint.toString());
+ try {
+ return joinPoint.proceed();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = finish - start;
+ System.out.println("END: " + joinPoint.toString()+ " " + timeMs + "ms");
+ }
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java"
new file mode 100644
index 0000000..874701a
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HelloController.java"
@@ -0,0 +1,49 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+public class HelloController {
+ @GetMapping("hello")
+ public String hello(Model model){
+ model.addAttribute("data","hello!!");
+ return "hello";
+ }
+
+ @GetMapping("hello-mvc")
+ public String helloMvc(@RequestParam("name") String name, Model model){
+ model.addAttribute("name", name);
+ return "hello-template";
+ }
+
+ @GetMapping("hello-string")
+ @ResponseBody
+ public String helloString(@RequestParam("name") String name){
+ return "hello " + name;
+ }
+
+ @GetMapping("hello-api")
+ @ResponseBody
+ public Hello helloApi(@RequestParam("name") String name){
+ Hello hello = new Hello();
+ hello.setName(name);
+ return hello;
+ }
+
+ static class Hello {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java"
new file mode 100644
index 0000000..7692926
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/HomeController.java"
@@ -0,0 +1,12 @@
+package hello.hellospring.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class HomeController {
+ @GetMapping("/")
+ public String home(){
+ return "home";
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java"
new file mode 100644
index 0000000..976e382
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberController.java"
@@ -0,0 +1,45 @@
+package hello.hellospring.controller;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.service.MemberService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+
+@Controller
+public class MemberController {
+
+ private final MemberService memberService;
+
+ @Autowired
+ public MemberController(MemberService memberService) {
+ this.memberService = memberService;
+ }
+
+ @GetMapping("/members/new")
+ public String createForm(){
+ return "members/createMemberForm";
+ }
+
+
+ @PostMapping("/members/new")
+ public String create(MemberForm form){
+ Member member = new Member();
+ member.setName(form.getName());
+
+ memberService.join(member);
+
+ return "redirect:/";
+ }
+
+ @GetMapping("/members")
+ public String list(Model model){
+ List members = memberService.findMembers();
+ model.addAttribute("members", members);
+ return "members/memberList";
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java"
new file mode 100644
index 0000000..ee80768
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/controller/MemberForm.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.controller;
+
+public class MemberForm {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java"
new file mode 100644
index 0000000..d64b60b
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/domain/Member.java"
@@ -0,0 +1,23 @@
+package hello.hellospring.domain;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+@Entity
+public class Member {
+ @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String name;
+ public Long getId() {
+ return id;
+ }
+ public void setId(Long id) {
+ this.id = id;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
new file mode 100644
index 0000000..2ecd82a
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcMemberRepository.java"
@@ -0,0 +1,144 @@
+package hello.hellospring.repository;
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.datasource.DataSourceUtils;
+import javax.sql.DataSource;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class JdbcMemberRepository implements MemberRepository {
+ private final DataSource dataSource;
+ public JdbcMemberRepository(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+ @Override
+ public Member save(Member member) {
+
+ String sql = "insert into member(name) values(?)";
+
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
+ pstmt.setString(1, member.getName());
+ pstmt.executeUpdate();
+ rs = pstmt.getGeneratedKeys();
+ if (rs.next()) {
+ member.setId(rs.getLong(1));
+ } else {
+ throw new SQLException("id 조회 실패");
+ }
+ return member;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public Optional findById(Long id) {
+ String sql = "select * from member where id = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ } else {
+ return Optional.empty();
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public List findAll() {
+ String sql = "select * from member";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+ List members = new ArrayList<>();
+ while(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ members.add(member);
+ }
+ return members;
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ @Override
+ public Optional findByName(String name) {
+ String sql = "select * from member where name = ?";
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ conn = getConnection();
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, name);
+ rs = pstmt.executeQuery();
+ if(rs.next()) {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return Optional.of(member);
+ }
+ return Optional.empty();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ close(conn, pstmt, rs);
+ }
+ }
+ private Connection getConnection() {
+ return DataSourceUtils.getConnection(dataSource);
+ }
+ private void close(Connection conn, PreparedStatement pstmt, ResultSet rs)
+ {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (pstmt != null) {
+ pstmt.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ try {
+ if (conn != null) {
+ close(conn);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+ private void close(Connection conn) throws SQLException {
+ DataSourceUtils.releaseConnection(conn, dataSource);
+ }
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
new file mode 100644
index 0000000..ff26aa6
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JdbcTemplateMemberRepository.java"
@@ -0,0 +1,52 @@
+package hello.hellospring.repository;
+import hello.hellospring.domain.Member;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
+import javax.sql.DataSource;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+public class JdbcTemplateMemberRepository implements MemberRepository {
+ private final JdbcTemplate jdbcTemplate;
+ public JdbcTemplateMemberRepository(DataSource dataSource) {
+ jdbcTemplate = new JdbcTemplate(dataSource);
+ }
+ @Override
+ public Member save(Member member) {
+ SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
+ jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
+ Map parameters = new HashMap<>();
+ parameters.put("name", member.getName());
+ Number key = jdbcInsert.executeAndReturnKey(new
+ MapSqlParameterSource(parameters));
+ member.setId(key.longValue());
+ return member;
+ }
+ @Override
+ public Optional findById(Long id) {
+ List result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
+ return result.stream().findAny();
+ }
+ @Override
+ public List findAll() {
+ return jdbcTemplate.query("select * from member", memberRowMapper());
+ }
+ @Override
+ public Optional findByName(String name) {
+ List result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
+ return result.stream().findAny();
+ }
+ private RowMapper memberRowMapper() {
+ return (rs, rowNum) -> {
+ Member member = new Member();
+ member.setId(rs.getLong("id"));
+ member.setName(rs.getString("name"));
+ return member;
+ };
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
new file mode 100644
index 0000000..446cd3c
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/JpaMemberRepository.java"
@@ -0,0 +1,28 @@
+package hello.hellospring.repository;
+import hello.hellospring.domain.Member;
+import javax.persistence.EntityManager;
+import java.util.List;
+import java.util.Optional;
+public class JpaMemberRepository implements MemberRepository {
+ private final EntityManager em;
+ public JpaMemberRepository(EntityManager em) {
+ this.em = em;
+ }
+ public Member save(Member member) {
+ em.persist(member);
+ return member;
+ }
+ public Optional findById(Long id) {
+ Member member = em.find(Member.class, id);
+ return Optional.ofNullable(member);
+ }
+ public List findAll() {
+ return em.createQuery("select m from Member m", Member.class).getResultList();
+ }
+ public Optional findByName(String name) {
+ List result = em.createQuery("select m from Member m where m.name = :name", Member.class)
+ .setParameter("name", name)
+ .getResultList();
+ return result.stream().findAny();
+ }
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java"
new file mode 100644
index 0000000..f04626a
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemberRepository.java"
@@ -0,0 +1,13 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface MemberRepository {
+ Member save(Member member);
+ Optional findById(Long id);
+ Optional findByName(String name);
+ List findAll();
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
new file mode 100644
index 0000000..b06770d
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/MemoryMemberRepository.java"
@@ -0,0 +1,37 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.stereotype.Repository;
+
+import java.util.*;
+
+public class MemoryMemberRepository implements MemberRepository {
+
+ private static Map store = new HashMap<>();
+ private static long sequence = 0L;
+ @Override
+ public Member save(Member member) {
+ member.setId(++sequence);
+ store.put(member.getId(), member);
+ return member;
+ }
+
+ @Override
+ public Optional findById(Long id) {
+ return Optional.ofNullable(store.get(id));
+ }
+
+ @Override
+ public Optional findByName(String name) {
+ return store.values().stream().filter(member -> member.getName().equals(name)).findAny();
+ }
+
+ @Override
+ public List findAll() {
+ return new ArrayList<>(store.values());
+ }
+
+ public void clearStore(){
+ store.clear();
+ }
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
new file mode 100644
index 0000000..524987e
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/repository/SpringDataJpaMemberRepository.java"
@@ -0,0 +1,12 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.Optional;
+
+public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository {
+
+ @Override
+ Optional findByName(String name);
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java"
new file mode 100644
index 0000000..ec606d4
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/MemberService.java"
@@ -0,0 +1,54 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+@Transactional
+public class MemberService {
+
+ private MemberRepository memberRepository;
+
+ public MemberService(MemberRepository memberRepository) {
+ this.memberRepository = memberRepository;
+ }
+
+ /**
+ * 회원가입
+ */
+ public Long join(Member member) {
+ long start = System.currentTimeMillis();
+ try {
+ validateDuplicateMember(member); //중복 회원 검증
+ memberRepository.save(member);
+ return member.getId();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = finish - start;
+ System.out.println("join " + timeMs + "ms");
+ }
+ }
+
+ private void validateDuplicateMember(Member member) {
+ memberRepository.findByName(member.getName()).ifPresent(m -> {
+ throw new IllegalStateException("이미 존재하는 회원입니다.");
+ });
+ }
+ /**
+ * 전체 회원 조회
+ */
+ public List findMembers() {
+ long start = System.currentTimeMillis();
+ try {
+ return memberRepository.findAll();
+ } finally {
+ long finish = System.currentTimeMillis();
+ long timeMs = finish - start;
+ System.out.println("findMembers " + timeMs + "ms");
+ }
+ }
+
+ public Optional findOne(Long memberId){return memberRepository.findById(memberId);}
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/SpringConfig.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/SpringConfig.java"
new file mode 100644
index 0000000..a2c1b41
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/java/hello/hellospring/service/SpringConfig.java"
@@ -0,0 +1,43 @@
+package hello.hellospring.service;
+
+import hello.hellospring.repository.MemberRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.persistence.EntityManager;
+import javax.sql.DataSource;
+
+@Configuration
+public class SpringConfig {
+
+ private final DataSource dataSource;
+ private final EntityManager em;
+ private final MemberRepository memberRepository;
+
+ @Autowired
+ public SpringConfig(DataSource dataSource, EntityManager em, MemberRepository memberRepository) {
+
+ this.dataSource = dataSource;
+ this.em = em;
+ this.memberRepository = memberRepository;
+ }
+
+ @Bean
+ public MemberService memberService(){
+
+ return new MemberService(memberRepository);
+ }
+
+
+ //@Bean
+ // public MemberRepository memberRepository(){
+
+ //return new MemoryMemberRepository();
+ //return new JdbcMemberRepository(dataSource);
+ //return new JdbcTemplateMemberRepository(dataSource);
+ // return new JpaMemberRepository(em);
+ //}
+
+
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/application.properties" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/application.properties"
new file mode 100644
index 0000000..8d67af3
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/application.properties"
@@ -0,0 +1,4 @@
+spring.datasource.url=jdbc:h2:tcp://localhost/~/test
+spring.datasource.driver-class-name=org.h2.Driver
+spring.datasource.username=sa
+
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html"
new file mode 100644
index 0000000..68254b2
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/hello-static.html"
@@ -0,0 +1,10 @@
+
+
+
+ static content
+
+
+
+정적 컨텐츠 입니다.
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html"
new file mode 100644
index 0000000..3bf7dfa
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/static/index.html"
@@ -0,0 +1,11 @@
+
+
+
+ Hello
+
+
+
+Hello
+hello
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html"
new file mode 100644
index 0000000..e560278
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello-template.html"
@@ -0,0 +1,5 @@
+
+
+hello! empty
+
+
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html"
new file mode 100644
index 0000000..81f8f1c
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/hello.html"
@@ -0,0 +1,10 @@
+
+
+
+ Hello
+
+
+
+안녕하세요. 손님
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html"
new file mode 100644
index 0000000..109d59d
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/home.html"
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html"
new file mode 100644
index 0000000..e4e7a2c
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/createMemberForm.html"
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html"
new file mode 100644
index 0000000..c59df46
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/main/resources/templates/members/memberList.html"
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+ #
+ 이름
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
new file mode 100644
index 0000000..87d37cf
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/HelloSpringApplicationTests.java"
@@ -0,0 +1,13 @@
+package hello.hellospring;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HelloSpringApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
new file mode 100644
index 0000000..44de132
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/repository/MemoryMemberRepositoryTest.java"
@@ -0,0 +1,62 @@
+package hello.hellospring.repository;
+
+import hello.hellospring.domain.Member;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.*;
+
+public class MemoryMemberRepositoryTest {
+
+ MemoryMemberRepository repository = new MemoryMemberRepository();
+
+ @AfterEach
+ public void afterEach(){
+ repository.clearStore();
+ }
+
+ @Test
+ public void save(){
+ Member member = new Member();
+ member.setName("spring");
+
+ repository.save(member);
+
+ Member result = repository.findById(member.getId()).get();
+
+ assertThat(member).isEqualTo(result);
+ }
+
+ @Test
+ public void findByName(){
+ Member member1= new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2= new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+
+ Member result = repository.findByName("spring1").get();
+
+ assertThat(result).isEqualTo(member1);
+ }
+
+ @Test
+ public void findAll(){
+ Member member1= new Member();
+ member1.setName("spring1");
+ repository.save(member1);
+
+ Member member2= new Member();
+ member2.setName("spring2");
+ repository.save(member2);
+
+ List result = repository.findAll();
+
+ assertThat(result.size()).isEqualTo(2);
+ }
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
new file mode 100644
index 0000000..279050a
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceIntegrationTest.java"
@@ -0,0 +1,62 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemberRepository;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.Commit;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@SpringBootTest
+@Transactional
+class MemberServiceIntegrationTest {
+
+ @Autowired MemberService memberService;
+ @Autowired MemberRepository memberRepository;
+
+ @Test
+ void 회원가입() {
+ //given
+ Member member = new Member();
+ member.setName("spring");
+
+ //when
+ Long saveId = memberService.join(member);
+
+ //then
+ Member findMember = memberService.findOne(saveId).get();
+ assertThat(member.getName()).isEqualTo(findMember.getName());
+ }
+
+ @Test
+ public void 중복_회원_예외(){
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+
+ //when
+ memberService.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+// try {
+// memberService.join(member2);
+// fail();
+// } catch (IllegalStateException e) {
+// assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ // }
+
+ //then
+
+ }
+
+}
\ No newline at end of file
diff --git "a/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java" "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java"
new file mode 100644
index 0000000..48e3ea3
--- /dev/null
+++ "b/oznchex/\354\212\244\355\224\204\353\247\201 \354\236\205\353\254\270/hello-spring/src/test/java/hello/hellospring/service/MemberServiceTest.java"
@@ -0,0 +1,74 @@
+package hello.hellospring.service;
+
+import hello.hellospring.domain.Member;
+import hello.hellospring.repository.MemoryMemberRepository;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+class MemberServiceTest {
+
+ MemberService memberService;
+ MemoryMemberRepository memberRepository;
+
+ @BeforeEach
+ public void beforeEach(){
+ memberRepository = new MemoryMemberRepository();
+ memberService = new MemberService(memberRepository);
+ }
+
+ @AfterEach
+ public void afterEach(){
+ memberRepository.clearStore();
+ }
+
+ @Test
+ void 회원가입() {
+ //given
+ Member member = new Member();
+ member.setName("hello");
+
+ //when
+ Long saveId = memberService.join(member);
+
+ //then
+ Member findMember = memberService.findOne(saveId).get();
+ assertThat(member.getName()).isEqualTo(findMember.getName());
+ }
+
+ @Test
+ public void 중복_회원_예외(){
+ //given
+ Member member1 = new Member();
+ member1.setName("spring");
+
+ Member member2 = new Member();
+ member2.setName("spring");
+
+ //when
+ memberService.join(member1);
+ IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
+ assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+// try {
+// memberService.join(member2);
+// fail();
+// } catch (IllegalStateException e) {
+// assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
+ // }
+
+ //then
+
+ }
+
+ @Test
+ void findMembers() {
+ }
+
+ @Test
+ void findOne() {
+ }
+}
\ No newline at end of file
diff --git "a/so-yeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring3" "b/so-yeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring3"
new file mode 160000
index 0000000..e8f115d
--- /dev/null
+++ "b/so-yeon/\354\212\244\355\224\204\353\247\201\354\236\205\353\254\270/hello-spring3"
@@ -0,0 +1 @@
+Subproject commit e8f115d2fbf171f1b495100efbaef037b964fc03
diff --git "a/yoonsseoo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.md" "b/yoonsseoo/\354\203\235\355\231\234\354\275\224\353\224\251_\352\270\260\354\264\210_JAVA\355\216\270/README.md"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/checksums.lock" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/checksums.lock"
new file mode 100644
index 0000000..29c6456
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/checksums.lock" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/md5-checksums.bin" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/md5-checksums.bin"
new file mode 100644
index 0000000..536ba8d
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/md5-checksums.bin" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/sha1-checksums.bin" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/sha1-checksums.bin"
new file mode 100644
index 0000000..54a2430
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/checksums/sha1-checksums.bin" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/dependencies-accessors/dependencies-accessors.lock" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/dependencies-accessors/dependencies-accessors.lock"
new file mode 100644
index 0000000..3177972
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/dependencies-accessors/dependencies-accessors.lock" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/dependencies-accessors/gc.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/dependencies-accessors/gc.properties"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/executionHistory/executionHistory.lock" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/executionHistory/executionHistory.lock"
new file mode 100644
index 0000000..5e60894
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/executionHistory/executionHistory.lock" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileChanges/last-build.bin" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileChanges/last-build.bin"
new file mode 100644
index 0000000..f76dd23
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileChanges/last-build.bin" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileHashes/fileHashes.lock" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileHashes/fileHashes.lock"
new file mode 100644
index 0000000..965ffa4
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/fileHashes/fileHashes.lock" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/gc.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/8.2.1/gc.properties"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/buildOutputCleanup.lock" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/buildOutputCleanup.lock"
new file mode 100644
index 0000000..005a66a
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/buildOutputCleanup.lock" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/cache.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/cache.properties"
new file mode 100644
index 0000000..7f801d8
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/buildOutputCleanup/cache.properties"
@@ -0,0 +1,2 @@
+#Tue Sep 19 16:51:34 KST 2023
+gradle.version=8.2.1
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/vcs-1/gc.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.gradle/vcs-1/gc.properties"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/.gitignore" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/.gitignore"
new file mode 100644
index 0000000..13566b8
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/.gitignore"
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/compiler.xml" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/compiler.xml"
new file mode 100644
index 0000000..b589d56
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/compiler.xml"
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/gradle.xml" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/gradle.xml"
new file mode 100644
index 0000000..ce1c62c
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/gradle.xml"
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/jarRepositories.xml" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/jarRepositories.xml"
new file mode 100644
index 0000000..fdc392f
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/jarRepositories.xml"
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/misc.xml" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/misc.xml"
new file mode 100644
index 0000000..f937d01
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/misc.xml"
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/vcs.xml" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/vcs.xml"
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/.idea/vcs.xml"
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/build.gradle" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/build.gradle"
new file mode 100644
index 0000000..972c825
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/build.gradle"
@@ -0,0 +1,26 @@
+plugins {
+ id 'java'
+ id 'org.springframework.boot' version '3.1.3'
+ id 'io.spring.dependency-management' version '1.1.3'
+}
+
+group = 'hello'
+version = '0.0.1-SNAPSHOT'
+
+java {
+ sourceCompatibility = '17'
+}
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
+ implementation 'org.springframework.boot:spring-boot-starter-web'
+ testImplementation 'org.springframework.boot:spring-boot-starter-test'
+}
+
+tasks.named('test') {
+ useJUnitPlatform()
+}
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.jar" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.jar"
new file mode 100644
index 0000000..033e24c
Binary files /dev/null and "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.jar" differ
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.properties"
new file mode 100644
index 0000000..9f4197d
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradle/wrapper/gradle-wrapper.properties"
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradlew" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradlew"
new file mode 100644
index 0000000..fcb6fca
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradlew"
@@ -0,0 +1,248 @@
+#!/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##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && 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=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=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, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+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/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradlew.bat" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/gradlew.bat"
new file mode 100644
index 0000000..93e3f59
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/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/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/settings.gradle" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/settings.gradle"
new file mode 100644
index 0000000..8569cd6
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/settings.gradle"
@@ -0,0 +1 @@
+rootProject.name = 'hello-spring2'
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/java/hello/hellospring2/HelloSpring2Application.java" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/java/hello/hellospring2/HelloSpring2Application.java"
new file mode 100644
index 0000000..21fda76
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/java/hello/hellospring2/HelloSpring2Application.java"
@@ -0,0 +1,13 @@
+package hello.hellospring2;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class HelloSpring2Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(HelloSpring2Application.class, args);
+ }
+
+}
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/resources/application.properties" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/resources/application.properties"
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/main/resources/application.properties"
@@ -0,0 +1 @@
+
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/test/java/hello/hellospring2/HelloSpring2ApplicationTests.java" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/test/java/hello/hellospring2/HelloSpring2ApplicationTests.java"
new file mode 100644
index 0000000..882f671
--- /dev/null
+++ "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/hello-spring2/src/test/java/hello/hellospring2/HelloSpring2ApplicationTests.java"
@@ -0,0 +1,13 @@
+package hello.hellospring2;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class HelloSpring2ApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254\354\233\220\353\246\254/README.md" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201_\355\225\265\354\213\254\354\233\220\353\246\254/README.md"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\212\244\355\224\204\353\247\201\353\266\200\355\212\270\354\231\200_JPA_\355\231\234\354\232\2511/README.md" "b/yoonsseoo/\354\212\244\355\224\204\353\247\201\353\266\200\355\212\270\354\231\200_JPA_\355\231\234\354\232\2511/README.md"
new file mode 100644
index 0000000..e69de29
diff --git "a/yoonsseoo/\354\236\220\353\260\224_ORM_\355\221\234\354\244\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/README.md" "b/yoonsseoo/\354\236\220\353\260\224_ORM_\355\221\234\354\244\200_\355\224\204\353\241\234\352\267\270\353\236\230\353\260\215/README.md"
new file mode 100644
index 0000000..e69de29
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
new file mode 100644
index 0000000..c8b45c6
--- /dev/null
+++ "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README.md"
@@ -0,0 +1,381 @@
+# SPRING BOOT
+
+
+
+- **👣 Section 1 - 프로젝트 환경 설정**
+ - **프로젝트 생성**
+
+ 요즘은 [https://start.spring.io](https://start.spring.io) 에서 기본 툴을 받고 파일을 open해서 시작한다.
+
+ - build.gradle이란?
+
+ 버전 설정 & 라이브러리 땡겨 오는 역할 정도만 이해하자
+
+
+ ```jsx
+ @SpringBootApplication
+ public class HelloSpringApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(HelloSpringApplication.class, args);
+ }
+ ```
+
+ - **라이브러리 살펴보기**
+
+ 그냥 하나만 불러도 연쇄적으로 다 이어서 불려 나온다.
+
+ - **view 환경 설정**
+
+ > **검색 방법**
+ >
+
+ (예) Welcome Page어떻게 만들지?
+
+ - spring.io접속 -> project > spring boot로 들어가기 -> learn 들어가서 내 버전의 reference document들어가기 -> 원하는 내용 찾기
+
+ ```jsx
+ @GetMapping("hello")
+ public String hello(Model model) {
+ model.addAttribute("data", "hello!!");
+ return "hello";
+ }
+ ```
+
+ - **빌드하고 실행하기**
+
+ 콘솔로 이동(git bash/cmd) -> 해당 파일 안에 들어가기 -> gradlew 치고 엔터 -> gradlew build하고 엔터 -> cd build -> cd libs -> 무슨무슨 SNAPSHOT.jar 파일이 있음 -> java -jar (파일 이름).jar 하면 실행 완
+
+ 나중에 배포 시에는 무슨무슨 SNAPSHOT.jar 파일만 서버에 넣고 java -jar로 실행하면 됨
+
+ + 오류시에는 gradlew clean 하면 build가 삭제됨. 그 후에 다시해보기
+
+- **👣 Section 2 - 스프링 웹 개발 기초**
+ - **정적 컨텐츠**
+
+ > resources>static에 hello-static.html을 만들고
+ >
+ >
+ > [localhost:8080/hello-static.html](http://localhost:8080/hello-static.html이라고)을 입력하면 서버의 반응은?
+ >
+
+ 
+
+ 1. controller에 hello-static이 mapping되어 있는지 확인 (우선순위를 갖는 다는 이야기)
+ 2. 없으면 resources 안에 있는 이름이 일치하는 html을 찾아서 띄워준다.
+ - **MVC와 템플릿 엔진**
+
+ MVC : Model View Controller
+
+ 
+
+ ```jsx
+ @GetMapping("hello-mvc")
+ public String helloMvc(@RequestParam("name") String name, Model model) {
+ model.addAttribute("name", name);
+ return "hello-template";
+ }
+ ```
+
+ - **API**
+ - MVC : View를 찾아 템플릿 엔진을 통해 화면을 렌더링 해 직접적인 html을 띄움
+ - API : 오직 필요한 데이터를 바로 넘겨줌
+
+ > getter setter 단축키 : Alt + Insert
+ >
+
+ ```jsx
+ @GetMapping("hello-api")
+ @ResponseBody
+ public Hello helloApi(@RequestParam("name") String name) {
+ Hello hello = new Hello();
+ hello.setName(name);
+ return hello;
+ }
+
+ static class Hello {
+ private String name;
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ }
+ ```
+
+ ---
+
+ 
+
+ 이때 넘겨주는 값이 객체면 JsonConverter가, 단순 문자열이면 StringConverter가 작동
+
+- **👣 Section 3 - 회원 관리 예제 (백엔드 개발)**
+ - **비즈니스 요구사항 정리**
+ - 데이터: 회원ID, 이름
+ - 기능: 회원 등록, 조회
+
+ 
+
+ - 컨트롤러: 웹 MVC의 컨트롤러 역할
+
+ - 서비스: 핵심 비즈니스 로직 구현
+
+ - 리포지토리: 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리
+
+ - 도메인: 비즈니스 도메인 객체
+
+ 예) 회원, 주문, 쿠폰 등등 주로 데이터베이스에 저장하고 관리됨
+
+ - **회원 도메인과 리포지토리 만들기**
+
+ ```jsx
+ public interface MemberRepository {
+ Member save(Member member); //회원이 저장소에 저장
+ Optional findById(Long id); //ID로 회원 찾기
+ Optional findByName(String name); //Name으로 회원 찾기
+ List findAll(); //지금까지 저장된 모든 회원 리스트 반환
+ }
+ ```
+
+ ```jsx
+ public class MemoryMemberRepository implements MemberRepository{
+ private static Map store = new HashMap<>();
+ private static long sequence = 0L;
+
+ @Override
+ public Member save(Member member) {
+ member.setId(++sequence); //고객의 ID를 시스템이 정하도록
+ store.put(member.getId(), member);
+ return member;
+ }
+ @Override
+ public Optional findById(Long id) {
+ return Optional.ofNullable(store.get(id));
+ }
+ @Override
+ public Optional findByName(String name) {
+ return store.values().stream()
+ .filter(member -> member.getName().equals(name))
+ .findAny();
+ }
+ @Override
+ public List findAll() {
+ return new ArrayList<>(store.values());
+ }
+ }
+ ```
+
+ - **회원 리포지토리 테스트 케이스 작성**
+
+ ```jsx
+ class MemoryMemberRepositoryTest {
+ MemoryMemberRepository repository = new MemoryMemberRepository();
+
+ @Test
+ public void save() {
+ Member member = new Member();
+ member.setName("spring");
+ repository.save(member);
+ Member result = repository.findById(member.getId()).get();
+ Assertions.assertEquals(result,member);
+ assertThat(member).isEqualTo(result);
+ }
+ }
+ ```
+
+ > 바꾸고자 하는 단어에서 Shift + F6하면 자동으로 아래의 것도 같이 바뀜
+ >
+
+ ---
+
+
+ 💡 test는 순서와 관계없이 서로 의존관계가 없어야 한다.
+
+
+
+ ```jsx
+ public void clearStore() {
+ store.clear();
+ }
+ ```
+
+ ```jsx
+ @AfterEach
+ public void afterEach() {
+ repository.clearStore();
+ }
+ ```
+
+ - **회원 서비스 개발**
+
+ ```jsx
+ private final MemberRepository memberRepository = new MemoryMemberRepository();
+
+ public Long join(Member member) { //회원가입
+ validateDuplicateMember(member); //중복 회원 검증
+ memberRepository.save(member);
+ return member.getId();
+ }
+ private void validateDuplicateMember(Member member) {
+ memberRepository.findByName(member.getName())
+ .ifPresent(m -> {
+ throw new IllegalStateException("이미 존재하는 회원입니다.");
+ });
+ }
+ ```
+
+ - **회원 서비스 테스트**
+
+ test 쉽게 만드는 법 : ctrl + shift + T하고 create 하고 밑에 검사할 것 선택
+
+ > given, when, then 주석 처리하는 습관 갖기
+ >
+
+ ---
+
+ ```jsx
+ MemberService memberService;
+ MemoryMemberRepository memberRepository;
+
+ @BeforeEach
+ public void beforeEach() {
+ memberRepository = new MemoryMemberRepository();
+ memberService = new MemberService(memberRepository);
+ }
+ ```
+
+- **👣 Section 4 - 스프링 빈과 의존관계**
+ - **스프링 빈을 등록하는 2가지 방법‼️**
+ - **1. 컴포넌트 스캔과 자동 의존관계 설정**
+
+ ```jsx
+ @Controller
+ public class MemberController {
+ private final MemberService memberService;
+ @Autowired
+ public MemberController(MemberService memberService) {
+ this.memberService = memberService;
+ }
+ }
+ ```
+
+ 객체를 생성해서 넣어둔게 spring bin.( = 스프링 빈 등록)
+
+ (생성하는 것은 @Component가 하는데 @Controller, @Service, @Repository 모두 포함하고 있음)
+
+ 비슷한 결로 @Service, @Repository도 있다.
+
+ @Autowired는 dependency injection 역할을 한다. 따라서 위에서는 controller와 service를 연결해 준 것.
+
+ - **2. 자바 코드로 직접 스프링 빈 등록하기**
+
+ ```jsx
+ @Configuration
+ public class SpringConfig {
+ @Bean
+ public MemberService memberService() {
+ return new MemberService(memberRepository());
+ }
+ @Bean
+ public MemberRepository memberRepository() {
+ return new MemoryMemberRepository();
+ }
+ }
+ ```
+
+ MemberService가 등록이 되는데 service가 repository를 필요로 하므로 밑에서 repository 등록 → service는 repository와 엮여야하므로 return new MemberService(memberRepository());
+
+
+ > 컴포넌트 스캔과 비교했을 때 직접 코드 넣으면 지금 처럼 구현 클래스 변경 시(정형화 되지 않은 클래스 설정) 마지막 return 부분만 바꿔주면 돼서 간편하다. (컴포넌트 스캔은 코드 구석구석 다 바꿔야 함)
+ >
+- **👣 Section 5 - 회원 관리 예제 (웹 MVC 개발)**
+ - **홈 화면 추가 (웹 기능)**
+
+ ```jsx
+ @Controller
+ public class HomeController {
+ @GetMapping("/")
+ public String home() {
+ return "home";
+ }
+ }
+ ```
+
+ - **등록 (웹 기능)**
+
+ ```jsx
+ @PostMapping("/members/new")
+ public String create(MemberForm form) {
+ Member member = new Member();
+ member.setName(form.getName());
+
+ memberService.join(member);
+
+ return "redirect:/";
+ }
+ ```
+
+ **@GetMapping :** 데이터 조회 시 (주로)
+
+ ⇒ url 창에 바로 치는 그것
+
+ **@PostMapping :** 데이터 등록 시 (주로)
+
+ ⇒ 데이터를 form에 넣어 전달할 때
+
+ - **조회 (웹 기능)**
+
+
+- **👣 Section 6 - 스프링 DB 접근 기술**
+ - **순수 JDBC**
+
+
+ - **스프링 통합 테스트**
+
+ `@SpringBootTest`
+
+ → 스프링 컨테이너와 테스트를 함께 실행한다.
+
+ `@Transactional`
+
+ → 매 test마다 aftereach로 데이터를 초기화/삭제할 필요없이 transaction을 먼저 실행하고 난 후 테스트 후 테스트가 끝나면 알아서 롤백을 해준다.
+
+ ⇒ `@AfterEach` 는 단위테스트( 스프링 컨테이너 없이 자바로만)
+
+ - **스프링 JDBC Template**
+
+
+ - **JPA**
+
+ 간단하게 JPA는 interface, Hibernate는 구현체
+
+ JPA = 객체 + ORM(object,relational, mapping)
+
+ - **스프링 데이터 JPA**
+
+ ```jsx
+ public interface SpringDataJpaMemberRepository extends JpaRepository, MemberRepository {
+ Optional findByName(String name);
+ }
+ ```
+
+ **스프링 데이터 JPA 제공 기능**
+
+ - 인터페이스를 통한 기본적인 CRUD
+ - findByName() , findByEmail() 처럼 메서드 이름 만으로 조회 기능 제공
+ - 페이징 기능 자동 제공
+- **👣 Section 7 - AOP**
+ - **AOP가 필요한 상황**
+
+ 여러 로직들의 시간을 측정할 때 효율적으로 할 수 있게 해주는 것
+
+ - **AOP 적용**
+
+ 시간 측정 로직을 원하는 곳에 적용!
+
+ 
+
+ 
\ No newline at end of file
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png"
new file mode 100644
index 0000000..fd24544
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 1.png" differ
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png"
new file mode 100644
index 0000000..165b359
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 2.png" differ
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png"
new file mode 100644
index 0000000..b96146c
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 3.png" differ
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png"
new file mode 100644
index 0000000..ec26ed5
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 4.png" differ
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png"
new file mode 100644
index 0000000..7c0281e
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled 5.png" differ
diff --git "a/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png" "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png"
new file mode 100644
index 0000000..10424c5
Binary files /dev/null and "b/yuuddin/\354\212\244\355\224\204\353\247\201_\354\236\205\353\254\270/README/Untitled.png" differ