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 + + ![](./README/Untitled.png) + +- 스프링 웹개발 기초 + - 정적 컨텐츠 - like 웰컴 페이지, 그냥 파일을 브라우져에 내려줌. + - 스프링 부트는 자동 제공, static contents라고 검색해보셈 + - resouces에 있는 static 폴더 + + ![](./README/Untitled201.png) + + - MVC와 템플릿 엔진 - html을 그냥 주는게 아니라 서버에서 조금 동적으로 바꿔 줌 (이걸 위해서 전에 컨트롤러 이런거 했던거임) + - Model View Controller 임. 과거엔 뷰와 컨트롤러가 구분 X + - 그런데 현재는 구분함 → 뷰는 화면구현에 모든 역량을 집중해야 함, 컨트롤러는 뒷단 로직에 집중하고 모델에 화면과 관련된걸 담아서 보내줌 + - 예를 들어, 뷰파일 하나에 다 박으면 나중에 다른 사람은 구분도 못함 + - RequestParam(”name”) 했을때 주소창에 /경로?name=”입력” 으로 입력했음 + + ![](./README/Untitled202.png) + + - API - 다른 OS, 서버끼리 데이터 흐를때 요즘은 json이란 포맷으로 client한테 보내줌 + - data 로 바로 내린다, html 방식은 소스를 봤을 때 입력을 html 템플릿 포맷으로 갔다면 API는 data 그대로, 그래서 data를 달라는 요청을 할때 많이 씀 + - @ResponseBody → https 프로토콜의 body msg 부분에 이 데이터를 직접 넣겠다는 의미 + - 요즘은 json 방식으로 함 (key 와 밸류) - 심플하기 때문 + - @ResponseBody 사용원리 + - 객체가 넘어오면 Json 작동, 그냥 String 객체면 StringConverter + + ![](./README/Untitled203.png) + +- 회원 관리 예제 개발 + - 비즈니스 요구사항 정리 + + 데이터 : 회원 ID, 이름 + + 기능 : 회원 등록, 조회 + + 아직 DB가 선정되지 않음 + + ![](./README/Untitled204.png) + + ![](./README/Untitled%205.png) + + - 회원 도메인과 레포지토리 + 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(); + } + } + ``` + + + 각각의 장단점 있음 + + ![요즘은 생성자 주입이 대세 / 현재 시나리오에선 상황에 따라 레포지토리 바꿔야 해서 설정으로 스프링 빈 해놨음](./README/Untitled206.png) + + 요즘은 생성자 주입이 대세 / 현재 시나리오에선 상황에 따라 레포지토리 바꿔야 해서 설정으로 스프링 빈 해놨음 + +- 회원 웹 기능 + - 홈 화면 추가 + + 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. 어플리케이션을 조립하는 코드만 손대면 나머진 손 안대도 됨 + + ![](./README/Untitled207.png) + + - 스프링 통합 테스트 + - 이전의 테스트들은 스프링과 관련 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 - 공통 관심사 분리 + + ![](./README/Untitled%208.png) + + - 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"); + } + + } + } + ``` + + + +![](./README/Untitled%209.png) 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 @@ + + + +
+
+

Hello Spring

+

회원 기능

+

+ 회원 가입 + 회원 목록 +

+
+
+ + + \ 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차 확인 질문[스프링 입문]**` + + + + + + + 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 @@ + + + + +
+
+

Hello Spring

+

회원 기능

+

+ 회원 가입 + 회원 목록 +

+
+
+ + + \ 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 @@ + + + +
+
+

Hello Spring

+

회원 기능

+

+ 회원 가입 + 회원 목록 +

+
+
+ + \ 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이라고)을 입력하면 서버의 반응은? + > + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled.png) + + 1. controller에 hello-static이 mapping되어 있는지 확인 (우선순위를 갖는 다는 이야기) + 2. 없으면 resources 안에 있는 이름이 일치하는 html을 찾아서 띄워준다. + - **MVC와 템플릿 엔진** + + MVC : Model View Controller + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled%201.png) + + ```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; + } + } + ``` + + --- + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled%202.png) + + 이때 넘겨주는 값이 객체면 JsonConverter가, 단순 문자열이면 StringConverter가 작동 + +- **👣 Section 3 - 회원 관리 예제 (백엔드 개발)** + - **비즈니스 요구사항 정리** + - 데이터: 회원ID, 이름 + - 기능: 회원 등록, 조회 + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled%203.png) + + - 컨트롤러: 웹 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하면 자동으로 아래의 것도 같이 바뀜 + > + + --- + + + + ```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 적용** + + 시간 측정 로직을 원하는 곳에 적용! + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled%204.png) + + ![Untitled](SPRING%20BOOT%2068ea037869b94df18216e34ee4e174cc/Untitled%205.png) \ 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