From 1f77f4daa0db3dbd82077d7e46c2c2351cf6a9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A3=BC=ED=98=95?= Date: Wed, 15 Dec 2021 15:12:52 +0900 Subject: [PATCH 01/10] =?UTF-8?q?create:=20[Spring]=20=EB=8B=A4=EC=96=91?= =?UTF-8?q?=ED=95=9C=20=EC=9D=98=EC=A1=B4=EA=B4=80=EA=B3=84=20=EC=A3=BC?= =?UTF-8?q?=EC=9E=85(#6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\354\236\205 \353\260\251\353\262\225.md" | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 "Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" diff --git "a/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" "b/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" new file mode 100644 index 0000000..85ea3e9 --- /dev/null +++ "b/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" @@ -0,0 +1,104 @@ +# 의존성 주입 방법 +# 요약 + - [생성자 주입(권장) - 불변, 필수](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=1.%20%EC%83%9D%EC%84%B1%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Constructor%20Injection%29) + - [수정자 주입 - 선택, 변경](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=2.%20%EC%88%98%EC%A0%95%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Setter%20Injection%29) + - [필드 주입 - 테스트 용이](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=3.%20%ED%95%84%EB%93%9C%20%EC%A3%BC%EC%9E%85%28Field%20Injection%29) + +# 1. 생성자 주입(Constructor Injection) + - 생성자를 통해 의존 관계를 주입하는 방법 + - 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨 + -> 객체 생성 시, 개발자가 설정한 그대로 의존 관계가 주입됨 + - 때문에 주입받은 객체가 ::변하지 않거나::, 반드시 객체의 주입이 ::필요한 경우::에 강제하기 위해 사용할 수 있다 -> **불변,** **필수**(강제) +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + @Autowired + public UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + + - 생성자 1개만 있을 경우 @Autowired 생략해도 자동 주입 됨 +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + public UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + +> Spring 프레임워크에서도 생성자 주입을 추천하고 있음(**Always**) +> `Spring Team recommends: "Always use constructor based dependency injection in your beans` + + +# 2. 수정자 주입(Setter Injection) + - 필드 값을 변경하는 수정자 메서드인 Setter를 사용해 의존 관계를 주입하는 방법 + - 주입받는 객체가 변경될 가능성이 있는 경우에 사용(사용해본적은 없는데, 필요한 경우도 드물다고 함..) + - 수정이 가능하기에 **선택**, **변경** 가능성이 있는 의존 관계에 사용 +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + @Autowired + public setUserRepository(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + +> @Autowired의 기본 동작은 주입할 대상이 없으면 오류 발생. +> 주입할 대상이 없어도 동작하게 하려면 `@Autowired(required = false)`로 지정 + + +## . 필드 주입(Field Injection) + - 필드에 의존 관계를 바로 주입하는 방법 + - **단점**(사용하지 말자!) + - 외부에서 변경이 불가능 + - DI 프레임워크가 반드시 필요(순수 자바 테스트에서는 사용 불가능) + +``` +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserRepository userRepository; +} +``` + +> 테스트 코드, 또는 @Configuration 같은 곳에서만 특별한 용도로 사용(실제 코드와 상관없으며, 간결하기 때문에) + +> 테스트 코드는 순수한 자바 테스트가 기본임으로 @Autowired 동작X +> `@SpringBootTest` 어노테이션으로 스프링 컨테이너를 테스트에 통합한 경우에만 가능 + + +# 4. 일반 메서드 주입(Method Injection) + - 일반 메서드를 통해서 주입하는 방법 + - 한번에 여러 필드를 주입할 수 있지만, 일반적으로 사용X + +``` +@Service +public class UserServiceImpl implements UserService { + + private UserRepository userRepository; + private AAAA aaaa; + + @Autowired + public void init(UserRepository userRepository, AAAA aaaa) { + this.userRepository = userRepository; + this.aaaa = aaaa; + } +} +``` + + + + +## 출처 +- [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) From 8876763a2347db89e576155715d9d9b1aad1c527 Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Wed, 15 Dec 2021 15:35:51 +0900 Subject: [PATCH 02/10] =?UTF-8?q?create:=20[Spring]=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=B4=EC=95=BC=ED=95=98=EB=8A=94=20=EC=9D=B4=EC=9C=A0(#8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\353\212\224 \354\235\264\354\234\240.md" | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 "Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" diff --git "a/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" new file mode 100644 index 0000000..5ad3d5a --- /dev/null +++ "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" @@ -0,0 +1,150 @@ +# 생성자 주입을 사용해야하는 이유 +# 요약 +- [객체의 불변성 확보](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=1.%20%EA%B0%9D%EC%B2%B4%EC%9D%98%20%EB%B6%88%EB%B3%80%EC%84%B1%20%ED%99%95%EB%B3%B4) +- [테스트 코드 작성 용이](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=2.%20%ED%85%8C%EC%8A%A4%ED%8A%B8%20%EC%BD%94%EB%93%9C%EC%9D%98%20%EC%9E%91%EC%84%B1) +- [final키워드 작성으로 실수를 줄이고 Lombok과의 연계가 좋다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=3.%20final%20%ED%82%A4%EC%9B%8C%EB%93%9C%20%EC%9E%91%EC%84%B1%20%EB%B0%8F%20Lombok%EA%B3%BC%EC%9D%98%20%EA%B2%B0%ED%95%A9) +- [순환 참조 에러를 사전에 방지한다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=4.%20%EC%88%9C%ED%99%98%20%EC%B0%B8%EC%A1%B0%20%EC%97%90%EB%9F%AC%20%EB%B0%A9%EC%A7%80) + +# 1. 객체의 불변성 확보 + - 대부분 의존 관계 주입은 애플리케이션 종료시점까지 변하면 안됨! + - Setter를 열어두는 것은 좋은 설계 방법이 아님(누군가 실수로 변경할 수 있음) + -> OCP(Open/closed principle) 위배 + - 생성자 주입은 생성 시 딱 1번만 호출됨으로 불변하게 설계할 수 있음 + - final 키워드 설정 가능(불변임으로) + +# 2. 테스트 코드의 작성 +## 생성자 주입이 아닐 경우 + - 필드 주입을 사용한다면 테스트 환경은 실제 코드의 DI 프레임워크 위에서 동작하지 않고, 순수한 자바 코드로 동작 -> **Null Point Exception 에러 발생, 테스트 하는 것이 불가능** + +### 실제 코드 +``` +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserRepository userRepository; + + public UserRepository getUserRepository() { + return userRepository; + } +} +``` + +### 테스트 코드 +``` +public class UserServiceTest { + @Test + public void injectionTest() { + UserService userSerivce = new UserServiceImpl(); + UserRepository ur = userService.getUserRepository(); + System.out.println(ur); + } +``` + +> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생 + + - 위의 문제를 해결하기 위해선 Setter를 사용하면 되지만**, 싱글톤 패턴을 해칠 수 있다.** 또한 수정자 주입과 다를 바가 없으면서 수정자 주입 역시 **OCP 위배**한다는 문제가 있음 + + +## 생성자 주입일 경우 + - 의존 관계 주입이 누락될 경우 **컴파일 오류**가 발생 + - 어떤 값을 필수로 주입해야하는 지 확실하게 알 수 있음! + +### 실제 코드 +``` +@Service +public class UserServiceImpl implements UserService { + + private UserRepository userRepository; + + @Autowired + public UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public UserRepository getUserRepository() { + return userRepository; + } +} +``` + +### 테스트 코드 +``` +public class UserServiceTest { + @Test + public void injectionTest() { + UserService userSerivce = new UserServiceImpl(); + UserRepository ur = userService.getUserRepository(); + System.out.println(ur); + } +``` + +> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository` + + +# 3. final 키워드 작성 및 Lombok과의 결합 +## final 키워드 작성 + - 생성자 주입은 final 키워드 사용 가능 + -> 값 설정 누락 시 컴파일 시점에 오류 발생 + - 누락된 의존성 확인이 빠름! + +## Lombok과의 결합 + - `@RequiredArgsConstructor` + -> final이 붙은 필드(변수)를 모두 모아 생성자를 자동으로 생성 + - 필드 주입보다 더 간결한 코드! + +> **최종 코드** +``` +@Service +@RequiredArgsConstructor +public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; +} +``` + + +# 4. 순환 참조 에러 방지 + +## 필드 or 수정자 주입의 경우 + - 예시 (닭은 알을 낳고, 알은 닭으로 부화하고) +``` +@Component +public class Chicken { + @Autowired Egg egg; + + public void layEgg() { + egg.hatch(); + } +} +``` + +``` +@Component +public class Egg { + @Autowired Chicken chicken; + + public void hatch() { + chicken.layEgg; + } +} +``` + +> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생 + +## 생성자 주입의 경우 + - 애플리케이션 구동 시점(객체 생성 시점)에 컴파일 오류를 발생시켜 순환 참조 에러를 방지 + +``` +Description: The dependencies of some of the beans in the application context form a cycle: +┌─────┐ +| chicken defined in file [(경로)/Chicken.class] +↑ ↓ +| egg defined in file [(경로)\Egg.class] +└─────┘ +``` + +> 생성자 주입의 컴파일 에러가 오류 잡기 좋다.. + +## 출처 +- [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) \ No newline at end of file From b9133376a1b3600266faac0c9c8014cff6f30bc3 Mon Sep 17 00:00:00 2001 From: leeejuhyeong <83570399+leeejuhyeong@users.noreply.github.com> Date: Wed, 15 Dec 2021 15:50:18 +0900 Subject: [PATCH 03/10] =?UTF-8?q?Delete=20=EC=9D=98=EC=A1=B4=EC=84=B1=20?= =?UTF-8?q?=EC=A3=BC=EC=9E=85=20=EB=B0=A9=EB=B2=95.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\354\236\205 \353\260\251\353\262\225.md" | 104 ------------------ 1 file changed, 104 deletions(-) delete mode 100644 "Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" diff --git "a/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" "b/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" deleted file mode 100644 index 85ea3e9..0000000 --- "a/Spring/\354\235\230\354\241\264\354\204\261 \354\243\274\354\236\205 \353\260\251\353\262\225.md" +++ /dev/null @@ -1,104 +0,0 @@ -# 의존성 주입 방법 -# 요약 - - [생성자 주입(권장) - 불변, 필수](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=1.%20%EC%83%9D%EC%84%B1%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Constructor%20Injection%29) - - [수정자 주입 - 선택, 변경](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=2.%20%EC%88%98%EC%A0%95%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Setter%20Injection%29) - - [필드 주입 - 테스트 용이](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=3.%20%ED%95%84%EB%93%9C%20%EC%A3%BC%EC%9E%85%28Field%20Injection%29) - -# 1. 생성자 주입(Constructor Injection) - - 생성자를 통해 의존 관계를 주입하는 방법 - - 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨 - -> 객체 생성 시, 개발자가 설정한 그대로 의존 관계가 주입됨 - - 때문에 주입받은 객체가 ::변하지 않거나::, 반드시 객체의 주입이 ::필요한 경우::에 강제하기 위해 사용할 수 있다 -> **불변,** **필수**(강제) -``` -@Service -public class UserServiceImpl implements UserService { - private UserRepository userRepository; - - @Autowired - public UserServiceImpl(UserRepository userRepository) { - this.userRepository = userRepository; - } -} -``` - - - 생성자 1개만 있을 경우 @Autowired 생략해도 자동 주입 됨 -``` -@Service -public class UserServiceImpl implements UserService { - private UserRepository userRepository; - - public UserServiceImpl(UserRepository userRepository) { - this.userRepository = userRepository; - } -} -``` - -> Spring 프레임워크에서도 생성자 주입을 추천하고 있음(**Always**) -> `Spring Team recommends: "Always use constructor based dependency injection in your beans` - - -# 2. 수정자 주입(Setter Injection) - - 필드 값을 변경하는 수정자 메서드인 Setter를 사용해 의존 관계를 주입하는 방법 - - 주입받는 객체가 변경될 가능성이 있는 경우에 사용(사용해본적은 없는데, 필요한 경우도 드물다고 함..) - - 수정이 가능하기에 **선택**, **변경** 가능성이 있는 의존 관계에 사용 -``` -@Service -public class UserServiceImpl implements UserService { - private UserRepository userRepository; - - @Autowired - public setUserRepository(UserRepository userRepository) { - this.userRepository = userRepository; - } -} -``` - -> @Autowired의 기본 동작은 주입할 대상이 없으면 오류 발생. -> 주입할 대상이 없어도 동작하게 하려면 `@Autowired(required = false)`로 지정 - - -## . 필드 주입(Field Injection) - - 필드에 의존 관계를 바로 주입하는 방법 - - **단점**(사용하지 말자!) - - 외부에서 변경이 불가능 - - DI 프레임워크가 반드시 필요(순수 자바 테스트에서는 사용 불가능) - -``` -@Service -public class UserServiceImpl implements UserService { - - @Autowired - private UserRepository userRepository; -} -``` - -> 테스트 코드, 또는 @Configuration 같은 곳에서만 특별한 용도로 사용(실제 코드와 상관없으며, 간결하기 때문에) - -> 테스트 코드는 순수한 자바 테스트가 기본임으로 @Autowired 동작X -> `@SpringBootTest` 어노테이션으로 스프링 컨테이너를 테스트에 통합한 경우에만 가능 - - -# 4. 일반 메서드 주입(Method Injection) - - 일반 메서드를 통해서 주입하는 방법 - - 한번에 여러 필드를 주입할 수 있지만, 일반적으로 사용X - -``` -@Service -public class UserServiceImpl implements UserService { - - private UserRepository userRepository; - private AAAA aaaa; - - @Autowired - public void init(UserRepository userRepository, AAAA aaaa) { - this.userRepository = userRepository; - this.aaaa = aaaa; - } -} -``` - - - - -## 출처 -- [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) From 3cb2f6e2b59234312114d9718565c54e9caa2989 Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Wed, 15 Dec 2021 15:53:08 +0900 Subject: [PATCH 04/10] =?UTF-8?q?create:=20[Spring]=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EA=B4=80=EA=B3=84=20=EC=A3=BC=EC=9E=85=20=EB=B0=A9=EB=B2=95(#6?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\354\236\205 \353\260\251\353\262\225.md" | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 "Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" diff --git "a/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" "b/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" new file mode 100644 index 0000000..85ea3e9 --- /dev/null +++ "b/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" @@ -0,0 +1,104 @@ +# 의존성 주입 방법 +# 요약 + - [생성자 주입(권장) - 불변, 필수](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=1.%20%EC%83%9D%EC%84%B1%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Constructor%20Injection%29) + - [수정자 주입 - 선택, 변경](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=2.%20%EC%88%98%EC%A0%95%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Setter%20Injection%29) + - [필드 주입 - 테스트 용이](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=3.%20%ED%95%84%EB%93%9C%20%EC%A3%BC%EC%9E%85%28Field%20Injection%29) + +# 1. 생성자 주입(Constructor Injection) + - 생성자를 통해 의존 관계를 주입하는 방법 + - 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨 + -> 객체 생성 시, 개발자가 설정한 그대로 의존 관계가 주입됨 + - 때문에 주입받은 객체가 ::변하지 않거나::, 반드시 객체의 주입이 ::필요한 경우::에 강제하기 위해 사용할 수 있다 -> **불변,** **필수**(강제) +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + @Autowired + public UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + + - 생성자 1개만 있을 경우 @Autowired 생략해도 자동 주입 됨 +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + public UserServiceImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + +> Spring 프레임워크에서도 생성자 주입을 추천하고 있음(**Always**) +> `Spring Team recommends: "Always use constructor based dependency injection in your beans` + + +# 2. 수정자 주입(Setter Injection) + - 필드 값을 변경하는 수정자 메서드인 Setter를 사용해 의존 관계를 주입하는 방법 + - 주입받는 객체가 변경될 가능성이 있는 경우에 사용(사용해본적은 없는데, 필요한 경우도 드물다고 함..) + - 수정이 가능하기에 **선택**, **변경** 가능성이 있는 의존 관계에 사용 +``` +@Service +public class UserServiceImpl implements UserService { + private UserRepository userRepository; + + @Autowired + public setUserRepository(UserRepository userRepository) { + this.userRepository = userRepository; + } +} +``` + +> @Autowired의 기본 동작은 주입할 대상이 없으면 오류 발생. +> 주입할 대상이 없어도 동작하게 하려면 `@Autowired(required = false)`로 지정 + + +## . 필드 주입(Field Injection) + - 필드에 의존 관계를 바로 주입하는 방법 + - **단점**(사용하지 말자!) + - 외부에서 변경이 불가능 + - DI 프레임워크가 반드시 필요(순수 자바 테스트에서는 사용 불가능) + +``` +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserRepository userRepository; +} +``` + +> 테스트 코드, 또는 @Configuration 같은 곳에서만 특별한 용도로 사용(실제 코드와 상관없으며, 간결하기 때문에) + +> 테스트 코드는 순수한 자바 테스트가 기본임으로 @Autowired 동작X +> `@SpringBootTest` 어노테이션으로 스프링 컨테이너를 테스트에 통합한 경우에만 가능 + + +# 4. 일반 메서드 주입(Method Injection) + - 일반 메서드를 통해서 주입하는 방법 + - 한번에 여러 필드를 주입할 수 있지만, 일반적으로 사용X + +``` +@Service +public class UserServiceImpl implements UserService { + + private UserRepository userRepository; + private AAAA aaaa; + + @Autowired + public void init(UserRepository userRepository, AAAA aaaa) { + this.userRepository = userRepository; + this.aaaa = aaaa; + } +} +``` + + + + +## 출처 +- [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) From 54e279288d13e1f46602526105caf82a74e69af2 Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Tue, 21 Dec 2021 18:00:13 +0900 Subject: [PATCH 05/10] =?UTF-8?q?docs:=20=EC=9D=98=EC=A1=B4=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=A3=BC=EC=9E=85=20=EB=B0=A9=EB=B2=95.md=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\353\212\224 \354\235\264\354\234\240.md" | 10 +++--- ...4\354\236\205 \353\260\251\353\262\225.md" | 32 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git "a/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" index 5ad3d5a..12e382a 100644 --- "a/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" +++ "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" @@ -41,7 +41,7 @@ public class UserServiceTest { } ``` -> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생 +> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생 - 위의 문제를 해결하기 위해선 Setter를 사용하면 되지만**, 싱글톤 패턴을 해칠 수 있다.** 또한 수정자 주입과 다를 바가 없으면서 수정자 주입 역시 **OCP 위배**한다는 문제가 있음 @@ -79,7 +79,7 @@ public class UserServiceTest { } ``` -> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository` +> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository` # 3. final 키워드 작성 및 Lombok과의 결합 @@ -93,7 +93,7 @@ public class UserServiceTest { -> final이 붙은 필드(변수)를 모두 모아 생성자를 자동으로 생성 - 필드 주입보다 더 간결한 코드! -> **최종 코드** +> **최종 코드** ``` @Service @RequiredArgsConstructor @@ -130,7 +130,7 @@ public class Egg { } ``` -> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생 +> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생 ## 생성자 주입의 경우 - 애플리케이션 구동 시점(객체 생성 시점)에 컴파일 오류를 발생시켜 순환 참조 에러를 방지 @@ -144,7 +144,7 @@ Description: The dependencies of some of the beans in the application context fo └─────┘ ``` -> 생성자 주입의 컴파일 에러가 오류 잡기 좋다.. +> 생성자 주입의 컴파일 에러가 오류 잡기 좋다.. ## 출처 - [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) \ No newline at end of file diff --git "a/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" "b/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" index 85ea3e9..964c654 100644 --- "a/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" +++ "b/Spring/\354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205 \353\260\251\353\262\225.md" @@ -2,13 +2,13 @@ # 요약 - [생성자 주입(권장) - 불변, 필수](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=1.%20%EC%83%9D%EC%84%B1%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Constructor%20Injection%29) - [수정자 주입 - 선택, 변경](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=2.%20%EC%88%98%EC%A0%95%EC%9E%90%20%EC%A3%BC%EC%9E%85%28Setter%20Injection%29) - - [필드 주입 - 테스트 용이](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=3.%20%ED%95%84%EB%93%9C%20%EC%A3%BC%EC%9E%85%28Field%20Injection%29) + - [필드 주입 - 테스트용](bear://x-callback-url/open-note?id=8C4454B9-D369-4539-8BF5-47A2A4E8D2A7-2996-000020E440BDD277&header=3.%20%ED%95%84%EB%93%9C%20%EC%A3%BC%EC%9E%85%28Field%20Injection%29) # 1. 생성자 주입(Constructor Injection) - - 생성자를 통해 의존 관계를 주입하는 방법 - - 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨 - -> 객체 생성 시, 개발자가 설정한 그대로 의존 관계가 주입됨 - - 때문에 주입받은 객체가 ::변하지 않거나::, 반드시 객체의 주입이 ::필요한 경우::에 강제하기 위해 사용할 수 있다 -> **불변,** **필수**(강제) +- 생성자를 통해 의존 관계를 주입하는 방법 +- 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨 +-> 객체 생성 시, 개발자가 설정한 그대로 의존 관계가 주입됨 +- 때문에 주입받은 객체가 ::변하지 않거나::, 반드시 객체의 주입이 ::필요한 경우::에 강제하기 위해 사용할 수 있다 -> **불변,** **필수**(강제) ``` @Service public class UserServiceImpl implements UserService { @@ -21,7 +21,7 @@ public class UserServiceImpl implements UserService { } ``` - - 생성자 1개만 있을 경우 @Autowired 생략해도 자동 주입 됨 +- 생성자 1개만 있을 경우 @Autowired 생략해도 자동 주입 됨 ``` @Service public class UserServiceImpl implements UserService { @@ -38,9 +38,9 @@ public class UserServiceImpl implements UserService { # 2. 수정자 주입(Setter Injection) - - 필드 값을 변경하는 수정자 메서드인 Setter를 사용해 의존 관계를 주입하는 방법 - - 주입받는 객체가 변경될 가능성이 있는 경우에 사용(사용해본적은 없는데, 필요한 경우도 드물다고 함..) - - 수정이 가능하기에 **선택**, **변경** 가능성이 있는 의존 관계에 사용 +- 필드 값을 변경하는 수정자 메서드인 Setter를 사용해 의존 관계를 주입하는 방법 +- 주입받는 객체가 변경될 가능성이 있는 경우에 사용(사용해본적은 없는데, 필요한 경우도 드물다고 함..) +- 수정이 가능하기에 **선택**, **변경** 가능성이 있는 의존 관계에 사용 ``` @Service public class UserServiceImpl implements UserService { @@ -57,11 +57,11 @@ public class UserServiceImpl implements UserService { > 주입할 대상이 없어도 동작하게 하려면 `@Autowired(required = false)`로 지정 -## . 필드 주입(Field Injection) - - 필드에 의존 관계를 바로 주입하는 방법 - - **단점**(사용하지 말자!) - - 외부에서 변경이 불가능 - - DI 프레임워크가 반드시 필요(순수 자바 테스트에서는 사용 불가능) +# 3. 필드 주입(Field Injection) +- 필드에 의존 관계를 바로 주입하는 방법 +- **단점**(사용하지 말자!) + - 외부에서 변경이 불가능 + - DI 프레임워크가 반드시 필요(순수 자바 테스트에서는 사용 불가능) ``` @Service @@ -79,8 +79,8 @@ public class UserServiceImpl implements UserService { # 4. 일반 메서드 주입(Method Injection) - - 일반 메서드를 통해서 주입하는 방법 - - 한번에 여러 필드를 주입할 수 있지만, 일반적으로 사용X +- 일반 메서드를 통해서 주입하는 방법 +- 한번에 여러 필드를 주입할 수 있지만, 일반적으로 사용X ``` @Service From 8c1aca7009bc2eb472fddff2cf16b459b7bc0e52 Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Tue, 21 Dec 2021 18:05:54 +0900 Subject: [PATCH 06/10] =?UTF-8?q?docs:=20=EC=9D=98=EC=A1=B4=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=A3=BC=EC=9E=85=20=EB=B0=A9=EB=B2=95.md=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20#6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Spring/.DS_Store | Bin 0 -> 6148 bytes ...\274\354\236\205 \353\260\251\353\262\225.md" | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 Spring/.DS_Store diff --git a/Spring/.DS_Store b/Spring/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Tue, 21 Dec 2021 18:13:38 +0900 Subject: [PATCH 07/10] =?UTF-8?q?docs:=20=EC=83=9D=EC=84=B1=EC=9E=90=20?= =?UTF-8?q?=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=B4?= =?UTF-8?q?=EC=95=BC=ED=95=98=EB=8A=94=20=EC=9D=B4=EC=9C=A0.md=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...0\353\212\224 \354\235\264\354\234\240.md" | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git "a/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" index 12e382a..ed7a1ca 100644 --- "a/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" +++ "b/Spring/\354\203\235\354\204\261\354\236\220 \354\243\274\354\236\205\354\235\204 \354\202\254\354\232\251\355\225\264\354\225\274\355\225\230\353\212\224 \354\235\264\354\234\240.md" @@ -5,16 +5,18 @@ - [final키워드 작성으로 실수를 줄이고 Lombok과의 연계가 좋다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=3.%20final%20%ED%82%A4%EC%9B%8C%EB%93%9C%20%EC%9E%91%EC%84%B1%20%EB%B0%8F%20Lombok%EA%B3%BC%EC%9D%98%20%EA%B2%B0%ED%95%A9) - [순환 참조 에러를 사전에 방지한다](bear://x-callback-url/open-note?id=B5467B00-E1D6-4C5B-8FA4-83B1A3B2975E-1500-00000B9786F1BC1D&header=4.%20%EC%88%9C%ED%99%98%20%EC%B0%B8%EC%A1%B0%20%EC%97%90%EB%9F%AC%20%EB%B0%A9%EC%A7%80) + # 1. 객체의 불변성 확보 - - 대부분 의존 관계 주입은 애플리케이션 종료시점까지 변하면 안됨! - - Setter를 열어두는 것은 좋은 설계 방법이 아님(누군가 실수로 변경할 수 있음) - -> OCP(Open/closed principle) 위배 - - 생성자 주입은 생성 시 딱 1번만 호출됨으로 불변하게 설계할 수 있음 - - final 키워드 설정 가능(불변임으로) +- 대부분 의존 관계 주입은 애플리케이션 종료시점까지 변하면 안됨! +- Setter를 열어두는 것은 좋은 설계 방법이 아님(누군가 실수로 변경할 수 있음) +-> OCP(Open/closed principle) 위배 +- 생성자 주입은 생성 시 딱 1번만 호출됨으로 불변하게 설계할 수 있음 +- final 키워드 설정 가능(불변임으로) + # 2. 테스트 코드의 작성 ## 생성자 주입이 아닐 경우 - - 필드 주입을 사용한다면 테스트 환경은 실제 코드의 DI 프레임워크 위에서 동작하지 않고, 순수한 자바 코드로 동작 -> **Null Point Exception 에러 발생, 테스트 하는 것이 불가능** +- 필드 주입을 사용한다면 테스트 환경은 실제 코드의 DI 프레임워크 위에서 동작하지 않고, 순수한 자바 코드로 동작 -> **Null Point Exception 에러 발생, 테스트 하는 것이 불가능** ### 실제 코드 ``` @@ -41,14 +43,16 @@ public class UserServiceTest { } ``` -> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생 +> DI 프레임워크가 없는 순수한 자바 코드 테스트임으로 의존 관계 주입이 누락되어 UserRepository가 null인 NPE발생 - - 위의 문제를 해결하기 위해선 Setter를 사용하면 되지만**, 싱글톤 패턴을 해칠 수 있다.** 또한 수정자 주입과 다를 바가 없으면서 수정자 주입 역시 **OCP 위배**한다는 문제가 있음 +- 위의 문제를 해결하기 위해선 Setter를 사용하면 되지만**, 싱글톤 패턴을 해칠 수 있다.** 또한 수정자 주입과 다를 바가 없으면서 수정자 주입 역시 **OCP 위배**한다는 문제가 있음 + +> OCP(Open/closed principle) : 개방-폐쇄 원칙, 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다. ## 생성자 주입일 경우 - - 의존 관계 주입이 누락될 경우 **컴파일 오류**가 발생 - - 어떤 값을 필수로 주입해야하는 지 확실하게 알 수 있음! +- 의존 관계 주입이 누락될 경우 **컴파일 오류**가 발생 +- 어떤 값을 필수로 주입해야하는 지 확실하게 알 수 있음! ### 실제 코드 ``` @@ -79,21 +83,21 @@ public class UserServiceTest { } ``` -> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository` +> 컴파일 오류 발생 : `java: constructor UserServiceImpl in class (패키지명).UserServiceImpl cannot be applied to given types; required: (패키지명).UserRepository` # 3. final 키워드 작성 및 Lombok과의 결합 ## final 키워드 작성 - - 생성자 주입은 final 키워드 사용 가능 - -> 값 설정 누락 시 컴파일 시점에 오류 발생 - - 누락된 의존성 확인이 빠름! +- 생성자 주입은 final 키워드 사용 가능 +-> 값 설정 누락 시 컴파일 시점에 오류 발생 +- 누락된 의존성 확인이 빠름! ## Lombok과의 결합 - - `@RequiredArgsConstructor` - -> final이 붙은 필드(변수)를 모두 모아 생성자를 자동으로 생성 - - 필드 주입보다 더 간결한 코드! +- `@RequiredArgsConstructor` +-> final이 붙은 필드(변수)를 모두 모아 생성자를 자동으로 생성 +- 필드 주입보다 더 간결한 코드! -> **최종 코드** +> **최종 코드** ``` @Service @RequiredArgsConstructor @@ -105,9 +109,8 @@ public class UserServiceImpl implements UserService { # 4. 순환 참조 에러 방지 - ## 필드 or 수정자 주입의 경우 - - 예시 (닭은 알을 낳고, 알은 닭으로 부화하고) +- 예시 (닭은 알을 낳고, 알은 닭으로 부화하고) ``` @Component public class Chicken { @@ -130,10 +133,10 @@ public class Egg { } ``` -> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생 +> 두 메소드는 서로를 순환하며 호출하다가, 메모리에 CallStack이 쌓여 StackOverFlow 에러를 발생 ## 생성자 주입의 경우 - - 애플리케이션 구동 시점(객체 생성 시점)에 컴파일 오류를 발생시켜 순환 참조 에러를 방지 +- 애플리케이션 구동 시점(객체 생성 시점)에 컴파일 오류를 발생시켜 순환 참조 에러를 방지 ``` Description: The dependencies of some of the beans in the application context form a cycle: @@ -144,7 +147,7 @@ Description: The dependencies of some of the beans in the application context fo └─────┘ ``` -> 생성자 주입의 컴파일 에러가 오류 잡기 좋다.. +> 생성자 주입의 컴파일 에러가 오류 잡기 좋다.. ## 출처 - [스프링 핵심 원리 - 기본편 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard) \ No newline at end of file From 50dd7b73d1ccbbf91fae608a666b73f672ca3f00 Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Thu, 23 Dec 2021 18:52:23 +0900 Subject: [PATCH 08/10] =?UTF-8?q?create:=20[Database]=20=EC=9D=B8=EB=8D=B1?= =?UTF-8?q?=EC=8A=A4=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=9D=B4=EC=9C=A0=20#12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...(\354\236\245\353\213\250\354\240\220).md" | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 "Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" diff --git "a/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" "b/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" new file mode 100644 index 0000000..852ee47 --- /dev/null +++ "b/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" @@ -0,0 +1,82 @@ +# 인덱스를 사용하는 이유(장단점) +## 요약 +> 인덱스는 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조입니다. +> 사용 시 테이블 조회 속도를 높여 DB 성능을 향상시키며, Full Scan하지 않아 시스템 부하를 줄여줍니다. +> 하지만 항상 정렬된 상태로 유지해야하기에 추가적인 쓰기작업이 필요하며 이를 저장하기 위한 저장공간이 필요합니다. 때문에 잘못 사용할 경우 성능 저하의 역효과를 발생시킵니다. + + +## 인덱스(Index)란? +- 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조. +- 추가적인 쓰기 작업과 저장공간을 활용 +-> 이를 관리하기 위해 DB에 ~~약 10%에 해당하는~~ 저장공간 필요 +- **PK는 자동으로 Index가 생성됨** -> NHN 기출 +![인덱스 구조](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/index_structure.png?raw=true) + +> 인덱스 없이 조회하면 모든 튜플(레코드)를 검색하지만 인덱스를 사용한다면 인덱스를 탐색하고 일치할 시에 해당 튜플로 데이터를 검색. -> 속도 **up** + + +## 인덱스 관리 + - Index를 항상 **최신의 데이터를 정렬된 상태로 유지**해야 원하는 값을 탐색 할 수 있음 + - INSERT, UPDATE, DELETE(데이터 추가, 수정, 삭제) 수행 시 정렬 필요! -> 부하**UP** + - INSERT, UPDATE, DELETE 시 추가적인 연산 필요 + -> 부하를 최소화하기 위해 데이터 삭제라는 개념에서 인덱스를 사용하지 않는다 라는 작업으로 대신함 + - INSERT : 새로운 데이터에 대한 인덱스 추가 + - DELETE : 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업 진행 + - UPDATE : 기존의 인덱스를 사용하지 않음 처리, 갱신된 데이터에 대한 인덱스 추가 + + +## 인덱스의 장단점 +### 장점 +- 테이블을 조회하는 속도와 그에 따른 성능을 향상 +- 전반적인 시스템의 부하를 줄임(Full Scan을 안해서) + +### 단점 +- 인덱스를 관리하기 위해 DB의 ~~약 10%에 해당하는~~ 추가적인 저장공간 필요 +- 인덱스를 관리하기 위해 추가 작업 필요 +- 잘못 사용할 경우 성능 저하의 역효과 발생 + + +## 인덱스를 사용하는 이유 +### 조건 검색 Where 절의 효율성 +- 인덱스 테이블은 데이터들이 정렬되어 저장되어 있기 때문에 해당 조건(where)에 맞는 데이터를 빠르게 찾아낼 수 있음 + +### 정렬 Order by 절의 효율성 +- 이미 정렬되어 있기 떄문에 order by에 의한 Sort과정을 피할 수 있음 + +### MIN, MAX의 효율적인 처리 가능 +- MIN값과 MAX값을 레코드의 시작값과 끝 값 한 건씩만 가져오면 되기에 Full Scan보다 효율적 + + +## 인덱스 자료구조 +### 해시테이블 +- key : 데이터(= 컬럼의 값) +- value : 데이터의 위치 +- 장점 + - 빠른 데이터 탐색에 유용 + - 시간 복잡도 O(1) +- 단점 + - 등호 연산에만 특화 + - DB는 부등호(>, <) 연산이 많아서 **사용 부적합** +![인덱싱_해쉬](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_hash.png?raw=true) + +## B+ Tree +- 대부분의 DB 인덱싱 자료구조 +- 특징 + - 리프노드에만 인덱스와 함께 데이터를 갖고있고, 나머지 노드들은 인덱스만을 가짐 + - 리프노드들은 연결리스트로 이루어짐 -> 탐색이 0번노드부터 일어나는 연결리스트에 비해 시간 효율이 좋음!(log2(N)) + - 데이터 노드의 크기는 인덱스 노드와의 크기와 같지 않아도 됨 +- 예시 + - 인덱스 +![인덱싱_B+Tree1](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_b%2Btree1.jpeg?raw=true) + + - B+ Tree +![인덱싱_B+Tree2](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Database/indexing_b%2Btree2.jpeg?raw=true) + +> BTree : 모든 노드에 데이터를 담음 +> 리프노드 : 자식이 없는 노드. 잎이라고도 함 +> B+ Tree 알고리즘에 대해서는 추후 정리할 예정입니다. + + +- 출처 + - [Database 인덱스(index)란? - MangKyu’s Diary](https://mangkyu.tistory.com/96) + - [자료구조 그림으로 알아보는 B+Tree](https://velog.io/@emplam27/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-B-Plus-Tree) \ No newline at end of file From 099bccdae27c3d9e870cf6ac90b3885939394f5f Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Sun, 26 Dec 2021 15:39:43 +0900 Subject: [PATCH 09/10] =?UTF-8?q?update=20:=20[Database]=20=EC=9D=B8?= =?UTF-8?q?=EB=8D=B1=EC=8A=A4=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=9D=B4=EC=9C=A0=20#12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...(\354\236\245\353\213\250\354\240\220).md" | 72 ++++++++++++++----- 1 file changed, 55 insertions(+), 17 deletions(-) diff --git "a/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" "b/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" index 852ee47..a970245 100644 --- "a/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" +++ "b/Database/\354\235\270\353\215\261\354\212\244\353\245\274 \354\202\254\354\232\251\355\225\230\353\212\224 \354\235\264\354\234\240(\354\236\245\353\213\250\354\240\220).md" @@ -15,14 +15,17 @@ > 인덱스 없이 조회하면 모든 튜플(레코드)를 검색하지만 인덱스를 사용한다면 인덱스를 탐색하고 일치할 시에 해당 튜플로 데이터를 검색. -> 속도 **up** -## 인덱스 관리 - - Index를 항상 **최신의 데이터를 정렬된 상태로 유지**해야 원하는 값을 탐색 할 수 있음 - - INSERT, UPDATE, DELETE(데이터 추가, 수정, 삭제) 수행 시 정렬 필요! -> 부하**UP** - - INSERT, UPDATE, DELETE 시 추가적인 연산 필요 - -> 부하를 최소화하기 위해 데이터 삭제라는 개념에서 인덱스를 사용하지 않는다 라는 작업으로 대신함 - - INSERT : 새로운 데이터에 대한 인덱스 추가 - - DELETE : 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업 진행 - - UPDATE : 기존의 인덱스를 사용하지 않음 처리, 갱신된 데이터에 대한 인덱스 추가 +## 인덱스를 사용하는 이유 +- 인덱스 테이블은 데이터들이 정렬되어 있음! -> **정렬과 연관지어 기억하자** + +### 조건 검색 Where 절의 효율성 +- 인덱스 테이블은 데이터들이 정렬되어 저장되어 있기 때문에 해당 조건(where)에 맞는 데이터를 빠르게 찾아낼 수 있음 + +### 정렬 Order by 절의 효율성 +- 이미 정렬되어 있기 떄문에 order by에 의한 Sort과정을 피할 수 있음 + +### MIN, MAX의 효율적인 처리 가능 +- MIN값과 MAX값을 레코드의 시작값과 끝 값 한 건씩만 가져오면 되기에 Full Scan보다 효율적 ## 인덱스의 장단점 @@ -36,15 +39,21 @@ - 잘못 사용할 경우 성능 저하의 역효과 발생 -## 인덱스를 사용하는 이유 -### 조건 검색 Where 절의 효율성 -- 인덱스 테이블은 데이터들이 정렬되어 저장되어 있기 때문에 해당 조건(where)에 맞는 데이터를 빠르게 찾아낼 수 있음 - -### 정렬 Order by 절의 효율성 -- 이미 정렬되어 있기 떄문에 order by에 의한 Sort과정을 피할 수 있음 - -### MIN, MAX의 효율적인 처리 가능 -- MIN값과 MAX값을 레코드의 시작값과 끝 값 한 건씩만 가져오면 되기에 Full Scan보다 효율적 +## 인덱스 관리 + - Index를 항상 **최신의 데이터를 정렬된 상태로 유지**해야 원하는 값을 탐색 할 수 있음 + - INSERT, UPDATE, DELETE(데이터 추가, 수정, 삭제) 수행 시 정렬 필요! -> 부하**UP** + - INSERT, UPDATE, DELETE 시 추가적인 연산 필요 + -> 부하를 최소화하기 위해 데이터 삭제라는 개념에서 **인덱스를 사용하지 않는다** 라는 작업으로 대신함 + - INSERT : 새로운 데이터에 대한 인덱스 추가 + - DELETE : 삭제하는 데이터의 인덱스를 사용하지 않는다는 작업 진행 + - UPDATE : 기존의 인덱스를 사용하지 않음 처리, 갱신된 데이터에 대한 인덱스 추가 + + +## 인덱스 생성 전략 +- 조건절에 자주 등장하는 컬럼(호출 빈도가 높음) +- 같거나 크고, 작음으로 자주 사용되는 컬럼(where 또는 order by에서 쓰이는 컬럼) +- 중복되는 데이터가 최소한인 컬럼(분포도가 좋다 = 데이터가 서로 다르고 넓게 퍼져 있다) +- 조인 조건으로 자주 사용되는 컬럼 ## 인덱스 자료구조 @@ -77,6 +86,35 @@ > B+ Tree 알고리즘에 대해서는 추후 정리할 예정입니다. + +## TMI : 결합 인덱스 +- 두 개 이상의 컬럼을 합쳐서 인덱스를 만드는 것 +- 단일 컬럼으로는 분포도가 나쁘지만, 여러 개의 컬럼을 합친다면 좋은 분포도를 가지며, where절에서 and 조건에 많이 사용되는 컬럼을 결합 인덱스로 생성함 + +### 결합 인덱스 컬럼 생성 전략 +- where절에서 and 조건으로 자주 결합되고, 결합할 시 분포도가 좋아지는 컬럼 +- 다른 테이블과 조인의 연결고리로 자주 사용되는 컬럼 +- order by에서 자주 사용되는 컬럼 +- 하나 이상의 키 컬럼 조건으로 같은 테이블의 컬럼들이 자주 조회될 때 + +### 예시 +- 결합 인덱스 생성 예시 +`create index emp_pay_idx on emp_pay(급여년월, 급여코드, 사원번호);` +- 결합 인덱스 사용 예시 +``` +select * from emp_pay where 급여년월 = '202107'; +select * from emp_pay where 급여년월 = '202107' and 급여코드 = '정기급여'; +select * from emp_pay where 급여년월 = '202107' and 급여코드 = '정기급여' and 사원번호 = '20210401'; +``` + +> 단 급여코드만을 검색할 때는 결합 인덱스의 첫 번째 컬럼인 급여년월의 조건식이 없기 때문에 결합 인덱스로 조회하지 않음! -> 급여년월, 급여코드, 사원번호의 순서대로 조회 + - 결합 인덱스 효율성 감소 + 1. LIKE 검색 : 2021%같이 검색할 경우 2021에 해당하는 모든 급여코드, 정기급여로 생성된 결합 인덱스를 조회해서 B*Tree에서 조회하기 어려움 + 2. 결합 인덱스 칼럼 순서(이하 급여년월(1), 급여코드(2), 사원번호(3) 컬럼을 숫자로 말하겠습니다) + - 1, 3 / 2 / 2, 3 / 3 으로 조회할 경우 결합 인덱스 순서대로 조회하지 않아서 Full Scan이 발생합니다 + + - 출처 - [Database 인덱스(index)란? - MangKyu’s Diary](https://mangkyu.tistory.com/96) + - [DB 데이터베이스 인덱스(Index) 란 무엇인가?](https://coding-factory.tistory.com/746) - [자료구조 그림으로 알아보는 B+Tree](https://velog.io/@emplam27/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-B-Plus-Tree) \ No newline at end of file From 51def2e7505f517513bbd098e9b4bf8b8f70f3aa Mon Sep 17 00:00:00 2001 From: leeejuhyeong Date: Sun, 6 Mar 2022 18:39:28 +0900 Subject: [PATCH 10/10] create: [Spring] Spring MVC #71 --- ...1\354\236\221 \353\260\251\354\213\235.md" | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 "Spring/Spring MVC \353\217\231\354\236\221 \353\260\251\354\213\235.md" diff --git "a/Spring/Spring MVC \353\217\231\354\236\221 \353\260\251\354\213\235.md" "b/Spring/Spring MVC \353\217\231\354\236\221 \353\260\251\354\213\235.md" new file mode 100644 index 0000000..68c9fbd --- /dev/null +++ "b/Spring/Spring MVC \353\217\231\354\236\221 \353\260\251\354\213\235.md" @@ -0,0 +1,157 @@ +# Spring MVC 동작 방식 +## 요약 +- Spring MVC는 DespatcherServlet, HandlerMapping, HandlerAdapter, ViewResolver로 동작한다 +- Spring MVC Annotation을 알아보자 + +## Spring MVC 핵심 구성 요소 +### DispatcherServlet +- 스프링 부트 구동 시 DispatcherServlet을 서블릿으로 자동등록(urlPatterns=“/“) +- 클라이언트로부터 어떠한 요청이 들어오면 Tomcat과 같은 서블릿 컨테이너가 요청을 받음 -> 이 모든 요청을 DispatcherServlet이 받게 됨 +- 즉, HTTP 프로토콜로 들어오는 모든 요청을 처리 -> 장점 +> 모든 요청을 가장 먼저 받기 때문에 Front Controller이라고도 함 + +### HandlerMapping +- 클라이언트의 요청을 처리할 컨트롤러 탐색 +- URL에 매핑된 핸들러(컨트롤러) 조회 + +### HandlerAdapter +- 실제 핸들러를 실행시키며, 핸들러의 처리 결과를 ModelAndView로 변환 + +### ViewResolver +- 컨트롤러 처리 결과를 JSP를 이용해서 생성하기 위해 사용 +- View의 논리 이름을 물리 이름으로 바꾸고 렌더링 역할을 담당하는 뷰 객체 반환 + +> Handler(핸들러)? : 웹 요청을 실제로 처리하는 객체, Spring MVC입장에서 @Controller 객체나 Controller 인터페이스를 구현한 객체 모두를 말함. + +### 스프링 MVC 동작 순서 +![스프링 MVC 동작](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Spring/%E1%84%89%E1%85%B3%E1%84%91%E1%85%B3%E1%84%85%E1%85%B5%E1%86%BCMVC%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A1%E1%86%A8.jpg?raw=true) + +### RestController +![RestController 동작](https://github.com/leeejuhyeong/images/blob/main/no-study-no-future/Spring/restcontroller%E1%84%83%E1%85%A9%E1%86%BC%E1%84%8C%E1%85%A1%E1%86%A8.jpg?raw=true) + +- 1 ~ 5는 Spring MVC와 동일 +- 6. 컨트롤러가 ResponseEntity를 반환 +- 7. HandlerAdapter가 반환받은 ResponseEntity를 통해 Response 처리 진행 +- 8. 서버의 응답을 클라이언트로 반환 + +## 요청의 흐름 +### Servlet +- 서블릿 호출 시 HttpServlet이 제공하는 service() 메서드 호출 +- service()를 시작으로 여러 메소드가 실행, DispatcherServlet.doDispatch()가 호출 + +### DispatcherServlet +``` +protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpServletRequest processedRequest = request; + HandlerExecutionChain mappedHandler = null; + boolean multipartRequestParsed = false; + + try { + ModelAndView mv = null; + Exception dispatchException = null; + + try { + processedRequest = checkMultipart(request); + multipartRequestParsed = (processedRequest != request); + + // 1. 핸들러 조회 + mappedHandler = getHandler(processedRequest); + if (mappedHandler == null) { + noHandlerFound(processedRequest, response); + return; + } + + // 2. 핸들러 어뎁터 조회 + HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); + + // 3. 헨들러 어댑터 실행 -> 4. 핸들러 어댑터를 통해 핸들러 실행 -> 5. ModelAndView 반환 + mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); + } + catch (Exception ex) { + dispatchException = ex; + } + + processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); + // ........이하 생략 + } +} + +private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, + @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, + @Nullable Exception exception) throws Exception { + + boolean errorView = false; + // 7. 뷰 렌더링 호출 + render(mv, request, response); +} + +protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception { + // Determine locale for request and apply it to the response. + Locale locale = + (this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale()); + response.setLocale(locale); + + View view; + String viewName = mv.getViewName(); + // 8. 뷰 렌더링 + view.render(mv.getModelInternal(), request, response); +} + + +``` + +## Spring MVC Annotation +### @RequestMapping +- HandlerMapping과 HandlerAdapter의 역할 +- 요청 정보를 매핑, 해당 URL 호출되면 이 메소드가 호출 + +### @GetMapping, @PostMapping, @PutMapping, @DeleteMapping +- Rest API 형식의 CRUD(c = p, r = g, u = p, d = d) +- @RequestMapping의 세부 url 매핑 + +### @RequestBody +- **Json(application/json)형태**의 HTTP Body 내용을 Java Object로 변환 +- 데이터는 MessageConvert를 통해 Java객체로 변환 +- 객체의 기본 생성자를 통해 객체를 생성하고, 내부적으로 Reflection을 사용해 값을 할당하므로 값을 주입하기 위한 **생성자나 Settr가 필요 없음** +> 데이터를 Java 객체로 변환하기 때문에 값 주입 생성자나, Setter가 필요 없음 + +### @RequestParam +- 1개의 HTTP 요청 파라미터를 받기 위해 사용, 파라미터 이름으로 바인딩 +- @RequestParam(“userid”) String userID -> request.getparameter(“userid”) +- 선언 시 필수적으로 보내야하며, 필수 변수가 아니라면 required = false로 설정 가능 + +### @ModelAttribute +- **multipart/form-data 형태**의 HTTP Body 내용과 HTTP 파라미터의 값들을 **생성자나 Setter를 통해** 주입해줌 +- HTTP Body 데이터와 HTTP 파라미터들을 Setter를 통해 1대1로 객체에 바인딩 +- Reflection으로 검증하기 때문에 모든 값을 받는 생성자가 없다면, 이외의 값은 Setter로 주입됨 +> 데이터를 1대1로 객체에 바인딩하기 때문에 값 주입 생성자나, Setter가 필요 + +### @RequestPart +- multipart/form-data 형태의 요청이 올 때 사용 +- File과 DTO를 같이 받을 수 있음 +``` +@PostMapping("") +public String insertUser( + @RequestPart(value = "file") MultipartFile multipartFile, + @RequestPart(value = "userInfo") UserInfo userInfo) { +} +``` + +### @PathVariable +- URL의 파라미터를 매핑 + +### @ResponseBody +- 해당 메소드의 결과를 ModelAndView가 아닌 JSON으로 반환 + +### @RestController +- 컨트롤러의 모든 메소드를 View가 아닌 Json으로 반환 + + + + + +## 출처 +- [스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 - 인프런 | 강의](https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard) +- [SpringDispatcher-Servlet(디스패처 서블릿)이란? 디스패처 서블릿의 개념과 동작 과정 - MangKyu’s Diary](https://mangkyu.tistory.com/18) +- [Spring MVC 기본 어노테이션과 Lombok 정리하기 :: Gyun’s 개발일지](https://devlog-wjdrbs96.tistory.com/401) +- [Spring Annotation 정리](https://velog.io/@gillog/Spring-Annotation-%EC%A0%95%EB%A6%AC) \ No newline at end of file