From da796c5576a9467f8b32044b8523e0e82675c981 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 26 Sep 2023 21:40:04 +0900 Subject: [PATCH 01/11] =?UTF-8?q?1=EC=A3=BC=EC=B0=A8=20=EA=B3=A0=ED=83=9C?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1주차 고태현 --- "week01/1\354\243\274\354\260\250.md" | 30 -- .../\352\263\240\355\203\234\355\230\204.md" | 471 ++++++++++++++++++ 2 files changed, 471 insertions(+), 30 deletions(-) delete mode 100644 "week01/1\354\243\274\354\260\250.md" create mode 100644 "week01/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week01/1\354\243\274\354\260\250.md" "b/week01/1\354\243\274\354\260\250.md" deleted file mode 100644 index 95ebbae..0000000 --- "a/week01/1\354\243\274\354\260\250.md" +++ /dev/null @@ -1,30 +0,0 @@ -## COW SPRING 2기 PRE-ONBOARDING 학습 과제 - -### 자바의 필수 개념들을 차근차근 살펴보자. - -* 자바의 primitive Type과 Reference Type은 어떤 차이가 있나요? - - -* 자바의 접근 제어자에 대해 설명해주세요. - - -* static 키워드에 대해 설명해주세요. - - -* final 키워드에 대해 설명해주세요. - * ++ 상속 관련된 내용도 포함할 것! - -* 오버로딩(Overloading)과 오버라이딩(Overriding)에 대해 설명해주세요. - - -* 추상 클래스와 인터페이스는 각각 무엇이고, 어떤 차이를 가지는지 설명해주세요 - * 반드시 추상 클래스와 인터페이스의 사용 목적을 명시해주세요. - - -* Java Enum에 대해 설명해주세요. - - -* 객체지향이란 무엇일까요? 객체지향을 지키면 어떤 이점을 얻을 수 있나요? - - -* 자바 객체지향의 4대 특성에 대해 각각 설명해주세요. \ No newline at end of file diff --git "a/week01/\352\263\240\355\203\234\355\230\204.md" "b/week01/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..a00e58d --- /dev/null +++ "b/week01/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,471 @@ +# [1WEEK] JAVA 기본 + +## COW SPRING 2기 PRE-ONBOARDING 학습 과제 + +## Primitive Type과 Reference Type의 차이점 + +--- + +> 자바의 데이터 타입 → Primitive Type / Reference Type +> + +**원시 타입(Primitive Type)**은 컴퓨터 과학에서 프로그래밍 언어가 제공하는 자료형 중 하나로 실제 데이터 값을 저장하는 타입이다. + +- Primitive Type 특징 + - 8가지의 타입이 있음(boolean, char, byte, short, int, long, float, double) + - 사용 전 선언을 해줘야함 + - 비객체 타입으로, **NULL값**을 가질 수 없음. + - 스택(Stack) 메모리에 저장됨. + +**참조 타입(Reference Type)**은 기본형 타입을 제외한 타입들이 모두 참조형 타입 / 메모리 번지 값을 통해 객체를 참조하는 타입이다 + +- Reference Type 특징 + - java.lang.Object 클래스를 상속하는 모든 클래스 + - 주소값을 메모리 Heap에 저장 + - 클래스 타입(class Type), 인터페이스 타입(interface Type), 배열 타입(array Type), 열거 타입(enum type) + - 객체이기에 NULL이 존재 + - NullPointException이 발생할 수 있으므로 변수값을 넣어줘야함 + - 참조하는 변수가 없으면 GC가 제거함 + +차이점 + +1. NULL 포함 가능 여부 + - Primitive Type은 객체가 아니므로 null을 담을 수 없지만, Reference Type은 객체로 참조함으로 null을 담을 수 있다. +2. 제너릭 타입에서 사용 가능 여부 +- 제너릭은 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법 EX) ArryList list + - Primitve Type은 불가능하지만, Reference Type은 가능하다 + - int는 원시 / Integer는 래퍼 클래스로 객체이다. + +## JAVA의 접근 제어자 + +--- + +> 접근 제어자(Access Modifier) : 클래스와 클래스의 멤버(필드, 메소드, 생성자)를 사용할 때, 접근할 수 있는 범위를 지정해주는 것 +> + +접근 제어자는 Private < Default < Protected < Public 순으로 많은 접근을 허용함. + +1. Private + - 같은 클래스안에 있는 멤버들만 접근 가능 +2. Default + - 같은 패키지안의 클래스에서만 접근이 가능 +3. Protected + - 같은 패키지안의 모든 클래스와, 다른 패키지의 **자식 클래스**에서 잡근 가능 +4. Public + - 모든 클래스에서 접근이 가능 + +## static 키워드 + +--- + +> static(정적) 고정된이라는 의미, 정적 변수와 정적 메소드를 만들 수 있음. +> +- 특징 + - 클래스가 메모리에 로드될떄, 스태틱(static) 영역에 생성 → heap 영역이 아니라 gc의 관리를 못 받음 + - 객체 생성 없이 사용됨 + - static 메서드 내에서 인스턴스 변수를 사용할 수 없음 + + ![Untitled](https://github.com/COW-edu/COW-Spring-2/assets/68328998/41eb2d88-593a-46a5-a409-960c81b5066b) + +- 사용 목적 + - 전역변수나 전역함수를 만들기 위해 사용 + - 공유멤버가 필요할 때 사용 + +BOOK 클래스 정의 + +```java +public class Book { + + static int price = 1000; // static 변수 + + public static void showPrice() { // static 메소드 + System.out.println("가격:" + price); + } +} +``` + +```java +public class HelloWorld { + public static void main(String[] args) { + + Book.price = 2000; // 객체 생성없이 클래스명으로 바로 사용 + Book.showPrice(); // 객체 생성없이 클래스명으로 바로 사용 + + Book b1 = new Book(); // 객체 생성후 사용 + b1.price = 4000; // 인스턴스 이름으로도 사용가능하나 클래스명으로 사용을 추천함 + b1.showPrice(); // 인스턴스 이름으로도 사용가능하나 클래스명으로 사용을 추천함 + } +} +``` + +## final 키워드 + +--- + +> 변수, 메서드 또는 클래스에 사용됨 / 무언가를 제한한다는 의미 +> +1. final 변수 +- final로 선언된 변수는 수정 불가 + +```java +final String hello = "hello world"; +hello = "see u next time"; // compile ERROR +``` + +1. final arguments(인자) +- 인자로 받은 값을 변경 불가 + +```java +public void func(final int number) { + number = 2; + System.out.println(number); + // compile error! +} +``` + +1. final 클래스 +- 다른 클래스가 상속할 수 없음 + +```java +final class MJ { + final String hello; + MJ() { + hello = "hello world"; + } +} + +class MMJ extends MJ() { + // compile error! +} +``` + +1. final 메소드 +- Override가 되지 않도록 함 + +```java +class MJ { + final String hello = "hello world"; + + final String getHello() { + return hello; + } +} +``` + +```java +class MJ extends MMJ { + + @Override + String getHello() { // compile error ! + return "See you MJ"; + } +} +``` + +## 오버로딩(Overloading)과 오버라이딩(Overriding) + +--- + +### 오버로딩(Overloading) + +> 같은 이름의 매서드를 여러개 가지면서 매개변수의 유형과 개수가 다르도록 하는 기술 +> + +조건 + +- 메소드의 이름이 같고, 매개변수의 개수나 타입이 달라야함. +- 리턴 값만 다른 것은 오버로딩 X + +```java +class OverloadingTest{ + void cat(){ + System.out.println("매개변수 없음"); + } + void cat(int a, int b){ + System.out.println("매개변수:"+a+","+b); + } + void cat(String c){ + System.out.println("매개변수:"+c); + } + +} + +public class Overtest{ + public static main(String[] args){ + + OverloadingTest ot = new OverloadingTest(); + + ot.cat(); + ot.cat(2,3); + ot.cat("hello"); + } + } +} +``` + +사용하는 이유 + +1. 같은 기능을 하는 메소드를 하나의 이름으로 사용할 수 있음 + - 대표적인 메소드가 println / 인자로 다앙한 타입을 받아 출력해 줌 +2. 메소드의 이름을 절약할 수 있음 + - 매개변수의 따라 메소드를 만들게 될 경우 메소드 네이밍함에 있어 고민을 가중시킴. + - ex ) println을 매개변수에 따라 제작하면, printlnInt, printlnDouble, printlnString 등 + +### 오버라이딩(Overriding) + +> 상위 클래스가 가지고 있는 매서드를 하위 클래스가 재정의해서 사용 +> + +조건 + +- 오버라이딩하고자 하는 메소드의 이름, 매개변수, 리턴 값이 모두 같아야함 +- 부모 클래스의 메소드보다 접근 제어자를 더 좁은 점위로 변경 가능 +- 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없음 + +```java +class Parent { + void display() { + System.out.println("부모 클래스의 display() 메소드입니다."); + } +} + +class Child extends Parent { + void display() { + System.out.println("자식 클래스의 display() 메소드입니다."); + } +} + + + +public class Inheritance { + public static void main(String[] args) { + + Parent pa = new Parent(); + pa.display(); + + Child ch = new Child(); + ch.display(); + + Parent pc = new Child(); + pc.display(); // Child cp = new Parent(); + } +} +``` + +```java +부모 클래스의 display() 메소드입니다. +자식 클래스의 display() 메소드입니다. +자식 클래스의 display() 메소드입니다 +``` + + + +## 추상 클래스와 인터페이스 + +--- + +### 추상 클래스(abstract class) + +> 추상 메소드 → 자식 클래스에서 반드시 오버라이딩해야만 사용할 수 있음 / 추상 클래스 → 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스 +> + +**추상화** + +- 복잡한 자료, 모듈, 시스템 등으로부터 핵심적인 개념 또는 기능을 간추려 내는 것 +- 알고는 있지만 정확하게 표현하기 힘든 것들을 중요한 부분이나 특징점을 잡아 설명하는 것 + +```java +abstract class Animal { + abstract void cry(); +} + +class Cat extends Animal { + void cry() { + System.out.println("냐옹냐옹!"); + } +} + +class Dog extends Animal { + void cry() { + System.out.println("멍멍!"); + } +} + + +public class Polymorphism { + public static void main(String[] args) { + + Cat c = new Cat(); + Dog d = new Dog(); + c.cry(); + d.cry(); + } +} +``` + +```java +냐옹냐옹! +멍멍! +``` + +**특징** + +- 추상 클래스는 인스턴스, 즉 객체를 만들 수 없음(new 사용 불가) +- 추상 메서드를 선언했다면 자식 클래스는 반드시 구현이 강제됨 +- static이나 final이 아닌 필드를 가질 수 있음 + - → 상속을 통해 구현해야하기 떄문 + + +**사용목적** + +- 공통으로 가지는 메소드와 필드가 많아 중복 멤버 통합 +- public 이외의 접근자 선언이 필요할 때 +- non-static, non-final 필드 선언이 필요한 경우 +- 구현 세부 정보의 일부 기능만 지정했을 때 +- 부모 클래스를 상속하여 부모 클래스가 가진 기능들을 구현해야할 때 + +### 인터페이스(Interface) + +> 추상 클래스가 미완성 설계도 / 인터페이스는 기본 설계도 +> + +```java +interface Animal { + public abstract void cry(); +} + +class Cat implements Animal { + public void cry() { + System.out.println("냐옹냐옹!"); + } +} + + + +class Dog implements Animal { + public void cry() { + System.out.println("멍멍!"); + } +} + +public class Polymorphism { + public static void main(String[] args) { + Cat c = new Cat(); + Dog d = new Dog(); + c.cry(); + d.cry(); + } +} +``` + +```java +냐옹냐옹! +멍멍! +``` + +→ extends 키워드 대신 implements라는 ‘구현’ 키워드를 사용하는 것은, 상속은 클래스간의 부모 - 자식관계를 연관 시키는데 의미가 중점이 되지만, 구현은 클래스를 확장 시켜 다양히 이용하는데 중점 + +**다중상속** + +- 한 클래스가 한 번에 두 개 이상의 클래스를 상속 받는 경우 + +********특징******** + +- static, default, private 제어자를 붙여 구체적인 메서드를 가질 수 있음 +- 모든 메서드는 public abstract로 정의 +- 모든 필드는 public static final 상수 + +사용 목적 + +- 기능을 정의해야 하지만 그 구현 방식이나 대상에 대해 추상화할 때 +- 서로 관련성이 없는 클래스들을 묶어 주고 싶을 때 +- 다중 상속(구현)할 때 +- 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장 + +--- + +### 차이점 + +- 추상 클래스는 단일상소 / 인터페이스는 다중 상속 +- 추상 클래스는 일반 변수, 생성자, 일반 메서드, 추상 메서드 모두 가질 수 있음 / 인터페이스는 추상 메서드만 가질 수 있음 +- 추상 클래스는 확장 / 인터페이스는 구현 + +## JAVA Enum + +--- + +### Enum(열거형) + +> Enumeration로 열거형이라고 불리며, 서로 연관된 상수들의 집합 +> + +**왜 사용하는가?** + +- 상수가 많아질 수록 가독성이 떨어지고, 어떤 것에 관한 상수인지 파악하기 힘듦 +- final static을 이용하여 정의하는 문제점을 해결 + +**예시 코드** + +```java +public enum Week { + MONDAY, TUSEDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY +} +``` + +**Enum method** + +![Untitled 2](https://github.com/COW-edu/COW-Spring-2/assets/68328998/c9d11a7d-6147-4468-aa83-b763915ea2c0) + +## 객체지향 + +--- + +### 객체지향 프로그래밍 + +> 컴퓨터 프로그래밍 패러다임 중 하나로 프로그래밍에서 필요한 데이터를 추상화 시켜 **상태와 행위**를 가진 객체로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 것 +> + +**객체지향 장점** + +1. 재사용성 + - 상속을 통해 코드의 재사용성을 높힘 +2. 생산성 향상 + - 잘 설계된 클래스를 만들어서 독립적인 객체를 사용함으로써 생산성을 높힘 +3. 자연적인 모델링 + - 일생상활에서 쓰는 개념을 그대로 객체라는 구조로 표현(패러다임)하여 생각한것을 그대로 구현 +4. 유지보수의 우수성 + - 프로그램을 변경할 때 수정, 추가를 하더라도 캡슐화를 통해 주변 코드에 영향이 적음 + +## 객체지향 4대 특성 + +--- + +특징 + +1. 추상화(Abstraction) + - 객체에서 공통된 속성과 행위를 추출하는 것 + - 공통의 속성과 행위를 찾아서 타입을 정의하는 과정 + - 추상화는 불필요한 정보는 숨기고 중요한 정보만 표한함으로써 프로그램을 간단하게 만드는 것 + + + + - 클래스 : 같은 특성을 지닌 여러 객체의 집합의 개념 + - 객체 : 실체 / 유일무이한 사물 + +1. 캡슐화(Encapsulation) + - 데이터 구조와 데이터를 다루는 방법들을 결합 시켜 묶는 것 + - 낮은 결합도를 유지할 수 있도록 설계하는 것 + + + +1. 상속(Inheritance) + - 클래스의 속성과 행위를 하위 클래스에 물려주거나 하위 클래스가 상위 클래스의 속성과 행위릘 물려받는 것 + - 새로운 클래스가 기존의 클래스의 데이터와 연산을 이용하게 함 + + + +1. 다형성(polymorphism) + - 하나의 변수명, 함수명이 상황에 따라 다른 의미로 해석될 수 있는 것 + - 어떠한 요소에 여러 개념을 넣어 놓는 것 + + \ No newline at end of file From 56f90f6742cc9ca88e238085a32448a7d590cf09 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 3 Oct 2023 20:22:52 +0900 Subject: [PATCH 02/11] =?UTF-8?q?[2=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week02/2\354\243\274\354\260\250.md" | 45 ---------------- .../\352\263\240\355\203\234\355\230\204.md" | 52 +++++++++++++++++++ 2 files changed, 52 insertions(+), 45 deletions(-) delete mode 100644 "week02/2\354\243\274\354\260\250.md" create mode 100644 "week02/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week02/2\354\243\274\354\260\250.md" "b/week02/2\354\243\274\354\260\250.md" deleted file mode 100644 index d73fc19..0000000 --- "a/week02/2\354\243\274\354\260\250.md" +++ /dev/null @@ -1,45 +0,0 @@ -### 2주차 학습 PR - -1주차에서 객체지향이 무엇인지 함께 고민해보고, 좋은 코드와 나쁜 코드, SOLID까지 함께 살펴보았는데요, - -세션 시간에 소개해 드렸던 로또 미션을 직접 구현해 보시면서, 직접 객체지향 설계와 구현을 경험해보실 시간입니다! - -이번 주 학습 PR에서는, 여러분들께서 로또 미션을 구현하시면서 - -여러분들이 설계부터 구현까지 하셨던 모든 고민, 경험, 회고 등등을 자유롭게 작성해주시면 됩니다! - -예를 들자면, - -- 요구사항 정의 -- 설계에 대한 고민 - - 디렉토리 구조는 어떻게 나눴는가? - - 클래스(객체)는 어떻게 설계하였고 무슨 역할을 하는지? - - 만약 별도의 디자인 패턴이나 아키텍처를 적용하셨다면..? - - 왜 해당 패턴/아키텍처를 사용해서 설계하였는지? - - 결과적으로 어떤 효과/성능개선이 있었나..? -- 구현에 대한 고민 - - 내 코드에서 이거 잘 짠것 같다..? - - 이 부분 고민 많이 했어요! - - 이거 좀 고민된다 A처럼 짜는게 좋을까, B처럼 짜는게 좋을까? - - 만약 A처럼 짰다면? → 왜 A처럼 짰는지? - - 구현에 대한 명확한 이유 - -굉장히 여러 가지가 나올 수 있겠네요! 적힌 내용은 예시일 뿐이며, **정답은 절대 없습니다!** 여러분들 생각대로, 정말 자유롭게 적어주시면 좋을 것 같아요 ㅎㅎ - -(그렇지만 내가 요런 고민했다는 티 팍팍 내주시면 너무 좋습니다!!!!💯) - -자세한 요구사항은 README 파일에 모두 적혀 있습니다! - -**→ 적힌 요구사항은 모두 꼼꼼히 읽어보시고, 꼭 지켜주시면 좋을 것 같아요!!** - -https://github.com/COW-edu/practice-oop-lotto - -예시로 참고하시면 좋을 것 같아, 제가 적었던 회고 글 링크 남겨둘게요!🙃 - -https://youwjune.tistory.com/29 - -### TIPS -* 시간이 짧아 SOLID 원칙만 소개해 드렸지만, 좋은 코드, 객체지향 코드를 위한 컨벤션, 원칙 등은 정말 많습니다! - * 관련 포스트를 많이 찾아보시면서 차차 적용해 나가셔도 좋을 것 같아요 ㅎ -* 만약 설계가 잘 되지 않는다면, 처음부터 너무 완벽하게 하려고 하지 않으셔도 됩니다! - * 차차 고민을 거듭해 가시면서, 좋은 코드로 리팩토링해보는 경험들도 다 밑거름이 되어줄 거에요✨ \ No newline at end of file diff --git "a/week02/\352\263\240\355\203\234\355\230\204.md" "b/week02/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..37e3c88 --- /dev/null +++ "b/week02/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,52 @@ +# [2WEEK] + +### 요구 기능 정리 & 기본 설계 구조 + +![KakaoTalk_20231002_005310938](https://github.com/COW-edu/COW-Spring-2/assets/68328998/b5ad747b-2058-47a4-829c-e439eb3252ed) + + + +### 설계 단계와 구현하면서 했던 메모 + +- 제네릭 타입 / 클래스 → 예제나 쓰이는 방법 +- 로또 클래스를 제네릭 타입으로 사용하여서 난수 생성을 했는데 → controller에서 로또를 어떤 관점으로 볼 것인지 이 부분(로또(list객체)에 대한 생성자 처리 방법) +- controller와 service의 역할분담 경계 어디까지 허용 되는지 validate는 controller단계에서 필터링 해주는 게 옳다고 생각하는데 어쩔 수 없는 로직상 service에서도 해줘야하는 경우가 생김 + - controller → 형식적 validation + - service → 의미적 validateion + - → 구조면에서 역할과 의미가 달라질 수 있음 + - [https://www.couchcoding.kr/blogs/couchcoding/[Spring] Controller%2C Service는 왜 분리해야할까%3F](https://www.couchcoding.kr/blogs/couchcoding/%5BSpring%5D%20Controller%2C%20Service%EB%8A%94%20%EC%99%9C%20%EB%B6%84%EB%A6%AC%ED%95%B4%EC%95%BC%ED%95%A0%EA%B9%8C%3F) +- exception과 error 메세지 차이 + - [https://choiblack.tistory.com/39](https://choiblack.tistory.com/39) + +### 구현에 대한 고민 + +- 오랜만에 진행한 객체 설계여서 생각보다 서칭하는데 많은 시간을 투자했습니다. 하지만 머리속에 그려지는 것들을 실제로 다 끄집어 내지 못한 거 같아 아쉬움이 많이 남고, 구현에 급급하다 보니 몇 기능들에 대해서는 아직 구현 못한 것들이 있습니다. 추후 주차에 점차 보완하여 좀 더 객체지향적이게 디벨롭 하고 싶습니다. + +### 2주차 학습 PR + +1주차에서 객체지향이 무엇인지 함께 고민해보고, 좋은 코드와 나쁜 코드, SOLID까지 함께 살펴보았는데요, + +세션 시간에 소개해 드렸던 로또 미션을 직접 구현해 보시면서, 직접 객체지향 설계와 구현을 경험해보실 시간입니다! + +이번 주 학습 PR에서는, 여러분들께서 로또 미션을 구현하시면서 여러분들이 설계부터 구현까지 하셨던 모든 고민, 경험, 회고 등등을 자유롭게 작성해주시면 됩니다! + +예를 들자면, + +- 요구사항 정의 +- 설계에 대한 고민 + - 디렉토리 구조는 어떻게 나눴는가? + - 클래스(객체)는 어떻게 설계하였고 무슨 역할을 하는지? + - 만약 별도의 디자인 패턴이나 아키텍처를 적용하셨다면..? + - 왜 해당 패턴/아키텍처를 사용해서 설계하였는지? + - 결과적으로 어떤 효과/성능개선이 있었나..? +- 구현에 대한 고민 + - 내 코드에서 이거 잘 짠것 같다..? + - 이 부분 고민 많이 했어요! + - 이거 좀 고민된다 A처럼 짜는게 좋을까, B처럼 짜는게 좋을까? + - 만약 A처럼 짰다면? → 왜 A처럼 짰는지? + - 구현에 대한 명확한 이유 + + +굉장히 여러 가지가 나올 수 있겠네요! 적힌 내용은 예시일 뿐이며, **정답은 절대 없습니다!** 여러분들 생각대로, 정말 자유롭게 적어주시면 좋을 것 같아요 ㅎㅎ + +(그렇지만 내가 요런 고민했다는 티 팍팍 내주시면 너무 좋습니다!!!!💯) \ No newline at end of file From 981753d89f53bf09336f1d9befe5bfa1873a7b49 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 10 Oct 2023 20:26:29 +0900 Subject: [PATCH 03/11] =?UTF-8?q?[3=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week03/3\354\243\274\354\260\250.md" | 45 --- .../\352\263\240\355\203\234\355\230\204.md" | 266 ++++++++++++++++++ 2 files changed, 266 insertions(+), 45 deletions(-) delete mode 100644 "week03/3\354\243\274\354\260\250.md" create mode 100644 "week03/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week03/3\354\243\274\354\260\250.md" "b/week03/3\354\243\274\354\260\250.md" deleted file mode 100644 index f19c798..0000000 --- "a/week03/3\354\243\274\354\260\250.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 3주차 학습 PR -학습 PR 역시 로또 리팩토링에 도움이 되는 내용들로 구성되어 있습니다. -해당 개념들을 학습한 뒤, 본인의 로또 코드에 적용까지 해 보신다면..? 비로소 본인 것이 됩니다 ㅎㅎ - -아래 `*` 은 여러분들의 학습을 위한 **최소한의** 가이드라인입니다. -꼭 깊이있는 학습 후에 꼼꼼하게 기록해주세요💯 - -## 일급 컬렉션이란? - -* 일급 컬렉션이란? - -* 일급 컬렉션은 왜 사용하는가? 어떤 장점이 있는지? - -+ 불변 객체..방어적 복사도 함께 찾아보시면 좋을 것 같아요! -+ https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/ - -## MVC 패턴이란? - - -* MVC는 왜 사용하는지? - -* MVC 패턴은 왜 등장했는가? 등장 배경? - -## Java의 Stream이란? - -* Stream의 특징? 장점? - * 병렬 처리 - * 작업 분류 - * lazy Evaluation - * 내부 반복 방식 - * for문과의 차이점? - -* 중간 연산 메서드 - -* 최종 연산 메서드 - -## 제네릭이란? - - -## Optional이란? - - -## References - -* \ No newline at end of file diff --git "a/week03/\352\263\240\355\203\234\355\230\204.md" "b/week03/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..76e7bdd --- /dev/null +++ "b/week03/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,266 @@ +# [3WEEK] 3주차 학습 PR + +## 일급 컬렉션이란? + +--- + +> Collection을 Wrapping하면서 그 외의 다른 멤버 변수가 없는 상태 +> +- 일급 컬렉션 사용이유 + - 비지니스에 종속적인 자료구조 + + ```java + public class Cars { + // 멤버 변수가 하나밖에 없다는게 중요!! + private List carList; + + public Cars(List carList) { + validateCarName(carList); + validateDuplicateName(carList); + this.carList = carList; + } + ... + } + ``` + + - Collection의 불변성을 보장 + - final 키워드는 불변이 아니라 재할당만을 금지함 + - 따라서 add, remove함수로 변경이 가능 + + ```java + public class Cars { + // 멤버 변수가 하나밖에 없다는게 중요!! + private List carList; + + public Cars(List carList) { + this.carList = carList; + } + + public int getCarListSize() { + return carList.size(); + } + } + ``` + + - 상태와 행위를 한 곳에서 관리 + - 값과 로직이 함께 존재 + - 중복된 메서드의 생성 문제를 해결 + - 이름이 있는 컬렉션 + - 단순한 변수명에 불과하여 의미부여가 어렵다 + + ```java + Freshman freshman = new Freshman(~~); + Sophomore sophomore = new Sophomore(~~); + Junior junior = new Junior(~~); + Senior senior = new Senior(~~); + ``` + +- 불변객체(lmmutabel Object) + - 객체 생성 후 내부 상태가 변하지 않는 객체 + - 장점 + - 쓰레드에 안전하여 멀티 쓰레드 환경에서 동기화를 고려하지 않음 + - 불변객체를 필도르 사용할 때 방어적 복사가 필요없음 + - 내부가 변하지 않으므로, Map Key와 Set요소로 사용 + - GC의 성능을 높힘 + - 생성 방법 + - setter 메소드를 사용하지 no + - 필드에 final과 private를 선언해라 + - 클래스를 final로 선언하여 Overriding을 막아라 + - 객체를 생성하기 위한 생성자 혹은 정적 팩토리 메소드를 추가 + - 인스턴스 필드에 가변객체가 포함된다면 방어적 복사를 이용하여 전달 +- 방어적 복사 + - 내부의 객체를 반환할 때, 객체의 복사본을 만들어서 반환하는 것 + - 이를 이용하면, 복사한 외부의 객체를 변경해도 원본 내부 객체가 변경되지 않는다. +- 얕은 복사 + - 원본 객체를 복사할 때, 새로운 객체를 만들지만 원본 객체의 ‘주소 값을’ 참조함 + - 원본이랑 복사한 객체에 서로 영향 +- 깊은 복사 + - 원본 객체를 복사할 때, 새로운 객체를 만들고 원본 객체의 모든 값을 복사해서 원본 객체로부터 독립적인 객체 생성 + - 복사한 객체가 독립이므로 영향 끼치지 않음 +- [https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/](https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/) + +## MVC패턴이란? + +--- + +> Model - View - Controller 구조로 사용자가 Controller를 조작하면 Model에서 데이터를 가져와 View에 표현 하는 것 +> +- MVC는 왜 사용하는지? + - 여러 개발자가 역할을 나눠 개발이 가능 + - 역할 분리 분활이 가능하다는 뜻 + - 중복 코드를 없앨 수 있고, 확장성이 유연한 코딩 가능 + - 웹, 앱으로 배포 방법이 다르면 view부분만 수정하면 된다. + - 각 컴포넌트별로 나뉘어져 있어 디버깅과 테스트에 용이 + - 코드의 양이 많아져도 유지 보수가 편하고 확장에도 용이 +- MVC 패턴은 왜 등장했는가? 등장 배경? + - 시작은 좋은 코드를 만들기 위해, 어떤 방식으로 코드를 나누고 묶어줘야 할까? 어떤 방식으로 코드를 추상화해야 할까? + - 로 시작하여 다음은 추상화를 하려하니 객체들의 맡고있는 역할을 나뉘어줘야 한다. + - 즉 GUI를 가진 소프트웨어를 객체 지향적으로 잘 구조화 하기 위해서. + +## 자바의 Stream이란? + +--- + +> JAVA 8에 추가된 기능으로 선언형 컬렉션 데이터 처리, 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다. +> + +정의 : 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소 + +```java +// 차량 목록 +List cars = Arrays.asList( + new Car("아반테", 20000000), + new Car("쏘나타", 30000000), + new Car("그랜저", 40000000) +); + +List lowPriceCarNames = cars.stream() + .filter(c -> c.getPrice() <= 30000000) // 3000만원 이하 차량 필터링 + .sorted((c1, c2) -> c2.getPrice().compareTo(c1.getPrice())) // 비싼 차량부터 정렬 + .map(Car::getName) // 자동차 이름 필터링 + .collect(Collectors.toList()); + +System.out.println(lowPriceCarNames); +// 출력 결과 : [쏘나타, 아반테] +``` + +- tream의 특징? 장점? + - 간결하고 읽기 쉬운 코드 + - 데이터 처리를 위해 코드가 간결해진다. + - 병렬 처리(Parallel Operation) + - 하나의 작업을 분할해서 각각의 코어가 병렬적 처리 + - 대규모 데이터 세트의 성능 향상 + - 작업 분류 + - lazy Evaluation(지연연산) + - 실제로 필요할 때까지 작업이 실행되지 않아, 메모리 사용량이 감소되므로 성능은 향상된다. + - 내부 반복 방식 + - 반복자를 이용하여 명시적으로 반복하는 컬레겻ㄴ과 다르게 스트림은 내부 반복 기능을 제공 + - for문과의 차이점? + - for문은 에러 위치를 바로 알 수 있음 + - stream은 지연 연산을 통해 실행되기에 발생 위치를 추적해야 함 + - stream은 최적화가 잘 이루어지지 않아서 오버헤드가 잘 발생한다. +- 중간 연산 메서드 + - skip(), limit() + + ```java + Stream stream1 = Stream.of("1", "2", "3", "4", "5", "6","7","8","9","10"); + stream1.skip(3).limit(5).forEach(System.out::print); //45678 + // 처음 5개의 요소를 건너뛰고, 스트림 요소를 3개로 제한 + ``` + + - filter(), distinct() + + ```java + Stream stream2 = Stream.of("1", "1", "1", "2", "3", "4"); + stream2.distinct().filter(i -> i.equals("4")).forEach(System.out::print); //4 + // distinct() : 중복 제거 / filter() : 조건에 맞지 않는 요소 제거 + ``` + + - sorted() + + ```java + // Comparator의 default 메서드인 comparing 사용 + Stream stream3 = Stream.of("dd", "aa", "CC", "cc", "x"); + stream3.sorted(Comparator.comparing((i) -> i.length())).forEach(System.out::print); + // Comparator로 스트림을 정렬한다. + ``` + + - peek() + + ```java + //peek + int[] intArr = {1, 2, 3, 4, 5}; + + int sum = Arrays.stream(intArr) + .peek(s -> System.out.print(s))//12345 + .sum(); + System.out.println(); + System.out.println(sum);//15 + + // 연산과 연산 사이에 올바르게 처리되었는지 확인 + ``` + + - map() + + ```java + Member[] members = { + new Member("김"), + new Member("최"), + new Member("박"), + new Member("이") + }; + + Stream memberStream = Stream.of(members); + + memberStream.map(member -> member.getName()) + .forEach(System.out::println); + + // 스트림 원하는 필드만 뽑거나 특정 형태로 반환 + ``` + +- 최종 연산 메서드 + +![Untitled](%5B3WEEK%5D%203%E1%84%8C%E1%85%AE%E1%84%8E%E1%85%A1%20%E1%84%92%E1%85%A1%E1%86%A8%E1%84%89%E1%85%B3%E1%86%B8%20PR%203d4307894a564a9084051bd433a97dab/Untitled.png) + +[[Java] 자바 스트림 collect() 정리 및 사용 예제](https://abcdefgh123123.tistory.com/424) + +## 제너릭이란? + +--- + +> 데이터의 타입을 클래스 내부에서 지정하는 것이 아닌 외부에서 사용자에 의해 지정되는 것 +> + +객체<타입>객체명 = new 객체<타입>(); + +장점 + +- 제너릭을 사용하면 잘못된 타입이 들어올 것을 컴파일 단계에서 방지 +- 클래스 외부에서 타입을 지정하기 때문에 따로 타입 체크를 해줄 필요가 없다 +- 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다. + +```java +class ExClassGeneric { + private T t; + + public void setT(T t){ + this.t = t; + } + + public T getT() { + return t; + } +} +``` + +## Optional이란? + +--- + +> JAVA 8에서 Optional 클래스를 이용해 NullPointException을 방지한다. null이 올 수 있는 값을 감싸는 wrapper 클래스이다. +> + +```java +public String findPostCode() { + // 위의 코드를 Optional로 펼쳐놓으면 아래와 같다. + Optional userVO = Optional.ofNullable(getUser()); + Optional
address = userVO.map(UserVO::getAddress); + Optional postCode = address.map(Address::getPostCode); + String result = postCode.orElse("우편번호 없음"); + + // 그리고 위의 코드를 다음과 같이 축약해서 쓸 수 있다. + String result = user.map(UserVO::getAddress) + .map(Address::getPostCode) + .orElse("우편번호 없음"); +} +``` + +## References + +--- + +[[Java] Collection 복사 - 복사 방법(방어적 복사, 얕은 복사, 깊은 복사) 및 상황별 최적의 복사 방법](https://ksh-coding.tistory.com/77) + +[[JAVA] Stream, 스트림과 병렬처리](https://ict-nroo.tistory.com/43) + +[[Java] 자바 스트림 중간 연산, 최종 연산](https://abcdefgh123123.tistory.com/423) \ No newline at end of file From 5313bd99802578adfc289326955a2fbe58018b07 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 10 Oct 2023 20:42:54 +0900 Subject: [PATCH 04/11] =?UTF-8?q?[3=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week03/\352\263\240\355\203\234\355\230\204.md" | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git "a/week03/\352\263\240\355\203\234\355\230\204.md" "b/week03/\352\263\240\355\203\234\355\230\204.md" index 76e7bdd..7c7867d 100644 --- "a/week03/\352\263\240\355\203\234\355\230\204.md" +++ "b/week03/\352\263\240\355\203\234\355\230\204.md" @@ -200,7 +200,8 @@ System.out.println(lowPriceCarNames); - 최종 연산 메서드 -![Untitled](%5B3WEEK%5D%203%E1%84%8C%E1%85%AE%E1%84%8E%E1%85%A1%20%E1%84%92%E1%85%A1%E1%86%A8%E1%84%89%E1%85%B3%E1%86%B8%20PR%203d4307894a564a9084051bd433a97dab/Untitled.png) +![Untitled](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/5f87fa8c-ff52-4a4b-af83-c76864a7fdc5) + [[Java] 자바 스트림 collect() 정리 및 사용 예제](https://abcdefgh123123.tistory.com/424) From 5c3ebbbd92c9fc5f4f74c2a5a2d3601200f6d5f6 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 17 Oct 2023 22:47:28 +0900 Subject: [PATCH 05/11] =?UTF-8?q?[4=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week04/4\354\243\274\354\260\250.md" | 328 +++++++++++++++++++++++++- 1 file changed, 315 insertions(+), 13 deletions(-) diff --git "a/week04/4\354\243\274\354\260\250.md" "b/week04/4\354\243\274\354\260\250.md" index ecbc830..388cb50 100644 --- "a/week04/4\354\243\274\354\260\250.md" +++ "b/week04/4\354\243\274\354\260\250.md" @@ -1,21 +1,323 @@ -# 4주차 학습 PR +# [4WEEK] 4주차 학습 PR -이번 주의 메인 테마는 테스트입니다. -단위 테스트와 테스트 툴인 JUnit5, AssertJ를 공부하고, 로또 미션에 충분한 테스트를 작성해주세요! -많은 예시 코드를 보시면 금방 감이 오실 겁니다! +## 테스트 코드 -* 테스트 코드란? 테스트 코드는 왜 작성하는지? +--- -* 단위 테스트란? +> 소프트웨어의 기능과 동작을 테스트하는 데 사용되는 코드 +> +- 종류 + - 단위 테스트(Unit Test) + - 통합 테스트(Integration Test) + - 시스템 테스트(System Test) -* JUnit5, AssertJ란? +- 왜 테스트 코드를 사용하는 가? -* BDD란? + 테스트 코드를 사용하는 가장 큰 이유는 ‘자신감?’ 이다. -* private method test + - **내가 무엇을 만들고 있는지 정확히 인지** + - 테스트 코드를 작성함으로써 요구사항의 기능적인 항목들 정리 + - **리팩토링을 진행할 때 부담 덜기** + - 코드 수정 후에도 기능이 정상적으로 작동하는지 검증 가능 + - **결합도와 의존성이 낮은 코드 지향** + - 의존성이 높은 부분을 개선 가능 + - **디버깅 비용 절감** + - 테스트 코드를 통해 오류를 줄일 수 있고, 빠르게 대처할 수 있는 내성력 + - 개발에 집중하여 생산성 향상에 도움 + - 테스트 자동화 -* @ParameterizedTest -* 참고하면 좋을 것 같은 링크 -* https://youtu.be/mIO4Rbe_M74?feature=shared -* https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/ \ No newline at end of file +## 단위 테스트(Unit Test) + +--- + +> 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트 +> +- 모듈은 api에서 하나의 기능 또는 메소드 + +```java +@DisplayName("자동차가 전진한다") +@Test +public void moveCar() { + // given + Car car = new Car("dani"); + + // when + car.move(4); + + // then + assertThat(car.getPosition()).isEqualTo(1); +} + +@DisplayName("자동차가 멈춘다") +@Test +public void stopCar() { + // given + Car car = new Car("dani"); + + // when + car.move(3); + + // then + assertThat(car.getPosition()).isEqualTo(0); +} +``` + +- 통합 테스트(Integration Test) + - 단위 테스트보다 더 큰 동작을 달성하기 위해 여러 모듈들을 모아 이들이 의도대로 협력하는지 확인하는 테스트 + - 따라서 외부 라이브러리, DB에 접근하여 다양한 환경에서 코드가 작동하는지 검증 + - BUT, 통합 테스트가 프로그램 전체가 완전히 작동하는지 검증하는 것은 아님 + - 단위 테스트에서 발견하지 못한 어려운 버그 발견 + - EX) 환경버그 CPU 환경에 따라 발생되는 것들 + + ```java + @SpringBootTest + class SubwayApplicationTests { + @Test + void contextLoads() { + } + } + ``` + +- 인수 테스트(Acceptance Test) + - 사용자 스토리에 맞춰 수행하는 테스트 + - 비지니스에 초점 + - 요구사항대로 잘 작동하는지 검증하는 것 + + ```java + public static ExtractableResponse 회원_생성_요청(MemberRequest memberRequest) { + return RestAssured + .given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(memberRequest) + .when().post("/api/members") + .then() + .extract(); + } + ``` + + +## JUnit5 + +--- + +> 유닛 테스트 프레임 워크 +> +- JUnit5 = Junit Platform + JUnit Jupiter + JUnit Vintage + - Junit Platform : JVM에서 돌아가는 테스트 프레임워크 테스트를 발견하고, 실행하고, 결과를 보고한다. + - JUnit Jupiter : 새로운 프로그래밍 모델, 확장 / 여러 메소드 제공 + - JUnit Vintage : 테스트 코드를 실행할 수 있도록 해주는 테스트 엔진 + + - JUunit5 주요 어노테이션 + + ![Untitled](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/da3fe266-79ec-48e7-9ae4-2173a9ecf43b) + + + +- Assert methods + - assertEquals() / 기대 값과 동일한지 확인 + + ```java + assertEquals(int expected, int actual, String message?) + assertEquals(float expected, float actual, float delta?, String message?) + ``` + + - assertSame() / 두 객체가 동일한지 확인할 때 사용 + + ```java + assertSame(Object expected, Object actual, String message?) + ``` + + - assertTrue() / 값이 true인지 확인 + + ```java + assertTrue(boolean condition, String message?) + ``` + + - assertNull() / 값이 null인지 확인 + + ```java + assertNull(Object actual, String message?) + ``` + + - assertTtimeout() / 지정한 시간 내에 테스트가 끝나지 않으면 테스트를 실패시키는 메소드 + + ```java + assertTimeout(Duration timeout, Executable executable, String message?) + ``` + + +## AssertJ + +--- + +> aseertion을 제공하는 자바 라이브러리 +> +- AssertJ를 쓰는 이유? + - 가독성 + + ```java + // 1. + assertEquals(a, b); + + // 2. + assertThat(a).isEqualTo(b); + ``` + + - 자세한 실패 메세지로 실패 원인 파악 용이 + + ```java + java.lang.AssertionError: + Expecting actual: + "ash" + to contain: + "o" + ``` + + - 다양한 검증 메서드 제공으로 인한 편리함 + + ```java + // JUnit + assertTrue(winners.containsAll(List.of("애쉬", "스플릿")) && winners.size() == 2); + assertArrayEquals(winners.toArray(), new String[]{"애쉬", "스플릿"}); + assertTrue(winners.containsAll(List.of("애쉬", "스플릿"))); + + // AssertJ + assertThat(winners).containsExactlyInAnyOrder("애쉬", "스플릿"); + assertThat(winners).containsExactly("애쉬", "스플릿"); + assertThat(winners).contains("애쉬", "스플릿"); + ``` + + - 메서드 체이닝 + + ```java + assertThat(score) + .isPositive() + .isGreaterThan(60) + .isLessThanOrEqualTo(75); + ``` + + +## BDD + +--- + +> Behavior-driven Development, 제품이나 서비스의 행동에 초점을 맞춘 개발 방법론 +> +- BDD 개발 절차 + - Given -When -Then + - Given : 시나리오 상에서 주어진 환경 // 올바른 이메일과 비밀번호를 입력한 상태 + - When : 사용자가 어떤 행위를 하는 것 // 유저가 로그인 버튼을 눌렀을 때 + - Then : 그에 따른 어떠한 결과 // 다음 화면으로 이동한다. +- TDD(Test Driven Devlopment) : 테스트를 먼저 작성하고 나서, 테스트가 정상적으로 돌아갈 때 까지 테스트를 하면서 코드를 작성 + +## Private method test + +--- + +Private method는 보통 외부 클래스에서 접근이 불가능하여 테스트 클래스에서 접근이 불가능하다. + +따라서 private 메서드들을 테스트 해야겠다 생각이 든다면 설계 단계에서 문제가 있을 가능성이 높으므로 다시 돌아봐야 한다. + +- private 메서드들을 테스트하는 경우 + - 설계가 잘못된 경우 + - private 메서드가 많은 곳에 결합되어 있는 경우 + - non deterministic(비결정적인) 로직 + - 외부 리소스 의존 로직 + - 시간이 많이 걸리는 로직 + +## @Parameterized Test + +--- + +> 여러 arument를 이용해 테스트를 여러번 돌릴 수 있는 테스트를 할 수 있는 기능 +> + +```java +@ParameterizedTest +@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) +void palindromes(String candidate) { + assertTrue(StringUtils.isPalindrome(candidate)); +} +``` + +- ValueSource + - argument가 하나인 테스트에 사용할 수 있음 + - short, byte, int, long, float, double, char, boolean, String, java.lang.Class에서 사용 + + ```java + @ParameterizedTest + @ValueSource({new Car(1000, "현대차")}) // 여기서 에러가 난다 + void valueSourceTest(car car) { + + } + ``` + +- EnumSource + - Enum을 argument로 보내는 것 + + ```java + public enum Planet { + EARTH, + MARS, + JUPITER; + } + ``` + + ```java + @ParameterizedTest + @EnumSource(names = {"MARS", "JUPITER"}) + void enumSourceTest(Planet planet) { + + // MARS, JUPITER만 각각 들어오게 된다 + + } + + @ParameterizedTest + @EnumSource(mode = EXCLUDE, names = {"MARS", "JUPITER"}) + void enumSourceTest(Planet planet) { + // EARTH만 들어온다 + } + ``` + +- MethodSource + - 테스트 클래스 내의 메소드 혹은 외부 클래스의 메소드가 반환하는 값을 source로 삼는 것 + + ```java + @ParameterizedTest + @MethodSource("parameterProvider") + void methodSourceTest(String argument) { + + // apple, banana가 각각 들어온다 + + } + + static Stream parameterProvider() { + return Stream.of("apple", "banana"); + } + ``` + +- CsvSource + - 분리된 문자열을 테스트 메소드의 파라미터로 넣는 것 + + ```java + @ParameterizedTest + @CsvSource({ + "apple, 1", + "banana, 2", + "'lemon, lime', 3" + }) + void csvSourceTest(String fruti, int rank) { + // (apple, 1) (banana, 2) ("lemon, lime", 3)이 각각 들어온다 + } + ``` + + +## Reference Link + +--- + +- [https://youtu.be/mIO4Rbe_M74?feature=shared](https://youtu.be/mIO4Rbe_M74?feature=shared) +- [https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/](https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/) // 테스트 +- [https://wecandev.tistory.com/168](https://wecandev.tistory.com/168) // Junit5 +- [https://lannstark.tistory.com/52](https://lannstark.tistory.com/52) // Parameterized Test \ No newline at end of file From 81876fd609e342b7da53554d8480608ae7d7790c Mon Sep 17 00:00:00 2001 From: grgr589 Date: Fri, 3 Nov 2023 11:05:56 +0900 Subject: [PATCH 06/11] =?UTF-8?q?[4=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week04/4\354\243\274\354\260\250.md" | 21 -- .../\352\263\240\355\203\234\355\230\204.md" | 323 ++++++++++++++++++ 2 files changed, 323 insertions(+), 21 deletions(-) delete mode 100644 "week04/4\354\243\274\354\260\250.md" create mode 100644 "week04/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week04/4\354\243\274\354\260\250.md" "b/week04/4\354\243\274\354\260\250.md" deleted file mode 100644 index ecbc830..0000000 --- "a/week04/4\354\243\274\354\260\250.md" +++ /dev/null @@ -1,21 +0,0 @@ -# 4주차 학습 PR - -이번 주의 메인 테마는 테스트입니다. -단위 테스트와 테스트 툴인 JUnit5, AssertJ를 공부하고, 로또 미션에 충분한 테스트를 작성해주세요! -많은 예시 코드를 보시면 금방 감이 오실 겁니다! - -* 테스트 코드란? 테스트 코드는 왜 작성하는지? - -* 단위 테스트란? - -* JUnit5, AssertJ란? - -* BDD란? - -* private method test - -* @ParameterizedTest - -* 참고하면 좋을 것 같은 링크 -* https://youtu.be/mIO4Rbe_M74?feature=shared -* https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/ \ No newline at end of file diff --git "a/week04/\352\263\240\355\203\234\355\230\204.md" "b/week04/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..388cb50 --- /dev/null +++ "b/week04/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,323 @@ +# [4WEEK] 4주차 학습 PR + +## 테스트 코드 + +--- + +> 소프트웨어의 기능과 동작을 테스트하는 데 사용되는 코드 +> +- 종류 + - 단위 테스트(Unit Test) + - 통합 테스트(Integration Test) + - 시스템 테스트(System Test) + +- 왜 테스트 코드를 사용하는 가? + + 테스트 코드를 사용하는 가장 큰 이유는 ‘자신감?’ 이다. + + - **내가 무엇을 만들고 있는지 정확히 인지** + - 테스트 코드를 작성함으로써 요구사항의 기능적인 항목들 정리 + - **리팩토링을 진행할 때 부담 덜기** + - 코드 수정 후에도 기능이 정상적으로 작동하는지 검증 가능 + - **결합도와 의존성이 낮은 코드 지향** + - 의존성이 높은 부분을 개선 가능 + - **디버깅 비용 절감** + - 테스트 코드를 통해 오류를 줄일 수 있고, 빠르게 대처할 수 있는 내성력 + - 개발에 집중하여 생산성 향상에 도움 + - 테스트 자동화 + + +## 단위 테스트(Unit Test) + +--- + +> 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트 +> +- 모듈은 api에서 하나의 기능 또는 메소드 + +```java +@DisplayName("자동차가 전진한다") +@Test +public void moveCar() { + // given + Car car = new Car("dani"); + + // when + car.move(4); + + // then + assertThat(car.getPosition()).isEqualTo(1); +} + +@DisplayName("자동차가 멈춘다") +@Test +public void stopCar() { + // given + Car car = new Car("dani"); + + // when + car.move(3); + + // then + assertThat(car.getPosition()).isEqualTo(0); +} +``` + +- 통합 테스트(Integration Test) + - 단위 테스트보다 더 큰 동작을 달성하기 위해 여러 모듈들을 모아 이들이 의도대로 협력하는지 확인하는 테스트 + - 따라서 외부 라이브러리, DB에 접근하여 다양한 환경에서 코드가 작동하는지 검증 + - BUT, 통합 테스트가 프로그램 전체가 완전히 작동하는지 검증하는 것은 아님 + - 단위 테스트에서 발견하지 못한 어려운 버그 발견 + - EX) 환경버그 CPU 환경에 따라 발생되는 것들 + + ```java + @SpringBootTest + class SubwayApplicationTests { + @Test + void contextLoads() { + } + } + ``` + +- 인수 테스트(Acceptance Test) + - 사용자 스토리에 맞춰 수행하는 테스트 + - 비지니스에 초점 + - 요구사항대로 잘 작동하는지 검증하는 것 + + ```java + public static ExtractableResponse 회원_생성_요청(MemberRequest memberRequest) { + return RestAssured + .given() + .contentType(MediaType.APPLICATION_JSON_VALUE) + .body(memberRequest) + .when().post("/api/members") + .then() + .extract(); + } + ``` + + +## JUnit5 + +--- + +> 유닛 테스트 프레임 워크 +> +- JUnit5 = Junit Platform + JUnit Jupiter + JUnit Vintage + - Junit Platform : JVM에서 돌아가는 테스트 프레임워크 테스트를 발견하고, 실행하고, 결과를 보고한다. + - JUnit Jupiter : 새로운 프로그래밍 모델, 확장 / 여러 메소드 제공 + - JUnit Vintage : 테스트 코드를 실행할 수 있도록 해주는 테스트 엔진 + + - JUunit5 주요 어노테이션 + + ![Untitled](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/da3fe266-79ec-48e7-9ae4-2173a9ecf43b) + + + +- Assert methods + - assertEquals() / 기대 값과 동일한지 확인 + + ```java + assertEquals(int expected, int actual, String message?) + assertEquals(float expected, float actual, float delta?, String message?) + ``` + + - assertSame() / 두 객체가 동일한지 확인할 때 사용 + + ```java + assertSame(Object expected, Object actual, String message?) + ``` + + - assertTrue() / 값이 true인지 확인 + + ```java + assertTrue(boolean condition, String message?) + ``` + + - assertNull() / 값이 null인지 확인 + + ```java + assertNull(Object actual, String message?) + ``` + + - assertTtimeout() / 지정한 시간 내에 테스트가 끝나지 않으면 테스트를 실패시키는 메소드 + + ```java + assertTimeout(Duration timeout, Executable executable, String message?) + ``` + + +## AssertJ + +--- + +> aseertion을 제공하는 자바 라이브러리 +> +- AssertJ를 쓰는 이유? + - 가독성 + + ```java + // 1. + assertEquals(a, b); + + // 2. + assertThat(a).isEqualTo(b); + ``` + + - 자세한 실패 메세지로 실패 원인 파악 용이 + + ```java + java.lang.AssertionError: + Expecting actual: + "ash" + to contain: + "o" + ``` + + - 다양한 검증 메서드 제공으로 인한 편리함 + + ```java + // JUnit + assertTrue(winners.containsAll(List.of("애쉬", "스플릿")) && winners.size() == 2); + assertArrayEquals(winners.toArray(), new String[]{"애쉬", "스플릿"}); + assertTrue(winners.containsAll(List.of("애쉬", "스플릿"))); + + // AssertJ + assertThat(winners).containsExactlyInAnyOrder("애쉬", "스플릿"); + assertThat(winners).containsExactly("애쉬", "스플릿"); + assertThat(winners).contains("애쉬", "스플릿"); + ``` + + - 메서드 체이닝 + + ```java + assertThat(score) + .isPositive() + .isGreaterThan(60) + .isLessThanOrEqualTo(75); + ``` + + +## BDD + +--- + +> Behavior-driven Development, 제품이나 서비스의 행동에 초점을 맞춘 개발 방법론 +> +- BDD 개발 절차 + - Given -When -Then + - Given : 시나리오 상에서 주어진 환경 // 올바른 이메일과 비밀번호를 입력한 상태 + - When : 사용자가 어떤 행위를 하는 것 // 유저가 로그인 버튼을 눌렀을 때 + - Then : 그에 따른 어떠한 결과 // 다음 화면으로 이동한다. +- TDD(Test Driven Devlopment) : 테스트를 먼저 작성하고 나서, 테스트가 정상적으로 돌아갈 때 까지 테스트를 하면서 코드를 작성 + +## Private method test + +--- + +Private method는 보통 외부 클래스에서 접근이 불가능하여 테스트 클래스에서 접근이 불가능하다. + +따라서 private 메서드들을 테스트 해야겠다 생각이 든다면 설계 단계에서 문제가 있을 가능성이 높으므로 다시 돌아봐야 한다. + +- private 메서드들을 테스트하는 경우 + - 설계가 잘못된 경우 + - private 메서드가 많은 곳에 결합되어 있는 경우 + - non deterministic(비결정적인) 로직 + - 외부 리소스 의존 로직 + - 시간이 많이 걸리는 로직 + +## @Parameterized Test + +--- + +> 여러 arument를 이용해 테스트를 여러번 돌릴 수 있는 테스트를 할 수 있는 기능 +> + +```java +@ParameterizedTest +@ValueSource(strings = { "racecar", "radar", "able was I ere I saw elba" }) +void palindromes(String candidate) { + assertTrue(StringUtils.isPalindrome(candidate)); +} +``` + +- ValueSource + - argument가 하나인 테스트에 사용할 수 있음 + - short, byte, int, long, float, double, char, boolean, String, java.lang.Class에서 사용 + + ```java + @ParameterizedTest + @ValueSource({new Car(1000, "현대차")}) // 여기서 에러가 난다 + void valueSourceTest(car car) { + + } + ``` + +- EnumSource + - Enum을 argument로 보내는 것 + + ```java + public enum Planet { + EARTH, + MARS, + JUPITER; + } + ``` + + ```java + @ParameterizedTest + @EnumSource(names = {"MARS", "JUPITER"}) + void enumSourceTest(Planet planet) { + + // MARS, JUPITER만 각각 들어오게 된다 + + } + + @ParameterizedTest + @EnumSource(mode = EXCLUDE, names = {"MARS", "JUPITER"}) + void enumSourceTest(Planet planet) { + // EARTH만 들어온다 + } + ``` + +- MethodSource + - 테스트 클래스 내의 메소드 혹은 외부 클래스의 메소드가 반환하는 값을 source로 삼는 것 + + ```java + @ParameterizedTest + @MethodSource("parameterProvider") + void methodSourceTest(String argument) { + + // apple, banana가 각각 들어온다 + + } + + static Stream parameterProvider() { + return Stream.of("apple", "banana"); + } + ``` + +- CsvSource + - 분리된 문자열을 테스트 메소드의 파라미터로 넣는 것 + + ```java + @ParameterizedTest + @CsvSource({ + "apple, 1", + "banana, 2", + "'lemon, lime', 3" + }) + void csvSourceTest(String fruti, int rank) { + // (apple, 1) (banana, 2) ("lemon, lime", 3)이 각각 들어온다 + } + ``` + + +## Reference Link + +--- + +- [https://youtu.be/mIO4Rbe_M74?feature=shared](https://youtu.be/mIO4Rbe_M74?feature=shared) +- [https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/](https://tecoble.techcourse.co.kr/post/2021-05-25-unit-test-vs-integration-test-vs-acceptance-test/) // 테스트 +- [https://wecandev.tistory.com/168](https://wecandev.tistory.com/168) // Junit5 +- [https://lannstark.tistory.com/52](https://lannstark.tistory.com/52) // Parameterized Test \ No newline at end of file From 7a800aecca63862c9ef633c01c586c043fd8798d Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 7 Nov 2023 16:11:36 +0900 Subject: [PATCH 07/11] =?UTF-8?q?[7=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week07/7\354\243\274\354\260\250.md" | 24 -- .../\352\263\240\355\203\234\355\230\204.md" | 313 ++++++++++++++++++ 2 files changed, 313 insertions(+), 24 deletions(-) delete mode 100644 "week07/7\354\243\274\354\260\250.md" create mode 100644 "week07/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week07/7\354\243\274\354\260\250.md" "b/week07/7\354\243\274\354\260\250.md" deleted file mode 100644 index cd83de7..0000000 --- "a/week07/7\354\243\274\354\260\250.md" +++ /dev/null @@ -1,24 +0,0 @@ -## 7주차 학습 PR - -### 싱글톤 패턴이란? - - -### 싱글톤 컨테이너란?(feat.싱글톤의 단점..?) - - -### Java의 POJO란 무엇인가?(feat.Spring의 Bean) - - -### 스프링의 사용 이유, 장점이나 특징(이거 중요!!) - - -### 스프링에서 사용되는 어노테이션 10개 이상 정리하기 --> 세션을 맡아주셨던 경호님께서 이때 어노테이션 한번에 정리해두니 그렇게 편했다고.. - - -### controller - service - repository란? - - -### (선택) 지난 세션에서 추가적으로 궁금했던 것들 자유롭게 기록 -지난 세션이나 학습 pr을 공부하시면서 어 그럼 이건 뭐지..? 하는 궁금증이 생겨난다면, -더 깊이있게 학습하시고 소제목(###)을 추가적으로 달아서 정리해보세요!! \ No newline at end of file diff --git "a/week07/\352\263\240\355\203\234\355\230\204.md" "b/week07/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..02229b7 --- /dev/null +++ "b/week07/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,313 @@ +# [7WEEK] 7주차 학습 PR + +## 싱글톤 패턴이란? + +--- + +> 객체의 인스턴스가 오직 1개만 생성되는 패턴 +> +- 싱글톤 객체가 사용 되는 경우 + - 프로그램 내에서 하나의 객체만 존재 + - 프로그램 내에서 여러 부분에서 해당 객체를 공유 + +- 싱글톤 패턴을 사용하는 이유 + - 메모리 측면의 이점 + - 한개의 인스턴스만 static메모리 영역에 할당하여 메모리 낭비를 막을 수 있음 + - 속도 측면의 이점 + - 이미 생성된 인스턴스를 활용하여 속도 측면에 이점bb + - 데이터 공유가 쉽다 + - 전역으로 선언되기 때문에 공유는 쉽지만, 동시성 문제가 발생할 수 있어 유의해야함 + + +### 싱글톤 생성 CODE + +```java +public class Singleton { + + private static Singleton instance = new Singleton(); + + private Singleton() { + // 생성자는 외부에서 호출못하게 private 으로 지정해야 한다. + } + + public static Singleton getInstance() { + return instance; + } + + public void say() { + System.out.println("hi, there"); + } +} +``` + +- 싱글톤 패턴의 단점 + - 통시성 문제를 해결해야함 + - → syncronized 키워드를 사용함 + - 테스트가 어렵다 + - 인스턴스의 상태를 초기화 시켜주지 않으면 온전한 테스트가 이루어지기 어려움 + - 클라이언트가 구체 클래스에 의존하게 됨(feat. new키워드) + - SOLD원칙 중 DIP, OCP원칙을 위반할 가능성이 높음 + +## 싱글톤 컨테이너란? + +--- + +> 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤으로 관리하는 것 / 스프링 빈이 싱글톤으로 관리되는 빈 +> +- 싱글톤 컨테이너 특징 + - 스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 싱글톤으로 관리됨 +- 스프링 컨테이너는 싱글톤 컨테이너 역할을 함 + - 싱글톤 레지스트리 +- 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 됨 +- DIP, OCP. 테스트. private 생성자로 부터 자유로운 싱글톤 사용 가능 + +### 싱글톤 컨테이너 code + +```java +@Test + @DisplayName("스프링 컨테이너와 싱글톤") + void springContainer() { + ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); + + // 1. 조회: 호출할 때마다 같은 객체 반환 + MemberService memberService1 = ac.getBean("memberService", MemberService.class); + + // 2. 조회: 호출할 때마다 같은 객체 반환 + MemberService memberService2 = ac.getBean("memberService", MemberService.class); + + // 참조값이 같은 것 확인 + System.out.println("memberService1 = " + memberService1); + System.out.println("memberService2 = " + memberService2); + + // memberService1 == memberService2 + assertThat(memberService1).isSameAs(memberService2); + } +``` + +- 싱글톤 컨테이너 장점 + - 이미 만들어진 객체를 공유하여 효율적으로 재사용 가능 + +- 싱글톤 주의 점 + - 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기에, 무상태(stateless)로 설계해야함 + - 특정 클라이언트에 의존적인 필드가 있으면 안됌 + - 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됌 + - 가급적 읽기만 가능 + - 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, TreadLocal 등을 사용 + + [[주요 개념] Stateful 과 Stateless](https://wooono.tistory.com/366) + + +## Java의 POJO + +--- + +> POJO(Plain Old Java Object) 순수한 오래된 자바 / 자바로 생성하는 순수한 객체 +> +- POJO 규칙 + - 특정 규약에 종속되지 않는다. + - 자바와 꼭 필요한 API외에는 종속되어선 안된다. + - 특정 환경에 종속적이지 않는다. + - 웹이라는 환경 정보나 웹 기술을 담고 있는 클래스나 인터페이스를 사용해선 안된다. + - 객체 지향적 원리에 충실해야 한다. + - 상속, 캡슐화, 다형성, 추상화 + +- 장점 + - 간결하고 깔끔하게 코드를 작성 가능 + - 간편하게 테스트 + - 객체지향적인 설계를 자유롭게 적용 + +- POJO를 지킨 CODE + - extends , implements 받아 메서드를 구현한 것이 아닌 기본적인 기능만 가진 자바 객체 + +```java +public class MyPojo { +    private String name; +    private int age; +     +    public String getName() { +     return name; +    } +    public String getAge() { +     return age; +    } +    public void setName(String name) { +     this.name = name; +    } +    public void setAge(int age) { +     this.age = age; +    } +} +``` + +- Bean : 스프링 컨테이너에 의해 관리되는 재사용 가능한 소프트웨어 컴포넌트 + - bean은 pojo이다 + 1. 모든 객체 변수는 private 제한자를 가지며 getter와 setter 함수를 통해 접근 가능 + 2. 아무런 입력값을 받지 않는 생성자가 존재 + +## 스프링의 사용이유 + +--- + +> 자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크 +> +- 프레임워크란? + - 프로그램의 기초를 구축할 수 있는 코드의 집합 + - 프로그램의 기본 뼈대와 틀을 정하고, 살을 붙이기 위해 코드를 작성 + +- 특징 + - 컨테이너 역할 + - java 객체의 LifeCycle을 관리하며, 스프링 컨테이너로부터 필요한 객체를 가져와 사용 + - DI 지원 + - 설정 파일이나 어노테이션을 통해 객체간 의존관계를 설정 + - AOP(Aspect Oriented Programming, 관점 지향 프로그래밍)지원 + - 트랜젝션, 로깅, 보안과 같은 모듈들을 실제 핵심 모듈에서 분리해 적용 + - POJO 지원 + - 컨테이너에 저장되는 객체는 특정한 인터페이스를 구현하거나, 특정 클래스를 상속 받지 않아도 됨 + +- 장점 + - 개발자의 수준과 실력에 상관없이 일정 수준의 품질을 기대 + - 담당자 혹은 개발자가 도중에 바뀌더라도, 유지보수에 대한 리스크를 줄일 수 있음 + +## 스프링에서 상용되는 어노테이션 + +--- + +> 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종 +> +- @Componet + - Bean 등록할 때 사용 + + ```java + @Component(value="myman") + public class Man { + public Man() { + System.out.println("hi"); + } + } + ``` + +- @Bean + - 외부 라이브러리와 같은 것들을 Bean으로 등록 +- @Controller + - Cotroller의 역할을 한다고 명시 + + ```java + @Controller // 이 Class는 Controller 역할을 합니다 + @RequestMapping("/user") // 이 Class는 /user로 들어오는 요청을 모두 처리합니다. + public class UserController { + @RequestMapping(method = RequestMethod.GET) + public String getUser(Model model) { + // GET method, /user 요청을 처리 + } + } + ``` + +- @RequestMapping + - URI의 요청과 Annotation value 값이 일치하면 해당 클래스나 메소드가 실행 + + ```java + @Controller // 이 Class는 Controller 역할을 합니다 + @RequestMapping("/user") // 이 Class는 /user로 들어오는 요청을 모두 처리합니다. + public class UserController { + @RequestMapping(method = RequestMethod.GET) + public String getUser(Model model) { + // GET method, /user 요청을 처리 + } + @RequestMapping(method = RequestMethod.POST) + public String addUser(Model model) { + // POST method, /user 요청을 처리 + } + @RequestMapping(value = "/info", method = RequestMethod.GET) + public String addUser(Model model) { + // GET method, /user/info 요청을 처리 + } + } + ``` + +- @RequestParam + - URL에 전달되는 파라미터를 메소드의 인자와 매칭시켜, 파라미터를 받아 처리 + + ```java + @Controller // 이 Class는 Controller 역할을 합니다 + @RequestMapping("/user") // 이 Class는 /user로 들어오는 요청을 모두 처리합니다. + public class UserController { + @RequestMapping(method = RequestMethod.GET) + public String getUser(@RequestParam String nickname, @RequestParam(name="old") String age { + // GET method, /user 요청을 처리 + // https://naver.com?nickname=dog&old=10 + String sub = nickname + "_" + age; + ... + } + } + ``` + +- @RequestBody + - Body에 전달되는 데이터를 메소드의 인자와 매칭시켜 데이터를 받아 처리 + + ```java + @Controller // 이 Class는 Controller 역할을 합니다 + @RequestMapping("/user") // 이 Class는 /user로 들어오는 요청을 모두 처리합니다. + public class UserController { + @RequestMapping(method = RequestMethod.POST) + public String addUser(@RequestBody User user) { + // POST method, /user 요청을 처리 + String sub_name = user.name; + String sub_old = user.old; + } + } + ``` + +- @ResponseBody + - 메소드에 리턴되는 값이 view로 출력되지 않고 HTTP Response Body에 직접 쓰여짐 +- @Autowired + - Bean 객체를 주입하기 위한 것 +- @GetMapping + - RequestMapping과 똑같은 역할 + + ```java + @Controller // 이 Class는 Controller 역할을 합니다 + @RequestMapping("/user") // 이 Class는 /user로 들어오는 요청을 모두 처리합니다. + public class UserController { + @GetMapping("/") + public String getUser(Model model) { + // GET method, /user 요청을 처리 + } + + //////////////////////////////////// + // 위와 아래 메소드는 동일하게 동작합니다. // + //////////////////////////////////// + + @RequestMapping(method = RequestMethod.GET) + public String getUser(Model model) { + // GET method, /user 요청을 처리 + } + } + ``` + +- @Configuration + - 1개 이상의 Bean을 등록할때 설정 +- @Repository + - DAO 클래스에서 사용 +- @SpringBootAppliation + - @Configuration, @EnableAutoConfiguration, @ComponentScan 3가지를 하나의 애노테이션으로 합친 것이다 + +## Controller - Service - Repository란? + +--- + +> MVC패턴 → Model : DB와 연동하여 사용자가 입력한 데이터나 사용자에게 출력할 데이터 handle / View : 사용자에게 시각적으로 보여주는 부분 / Controller : 데이터를 어떻게 처리할지 알려주는 역할 +> +- Controller + - Model or View에 대해 알고 있다 + - Model과 View는 서로 모른다 + - Controller는 이에 중재자 + +- Service + - Business Logit포함 + - 도메인 객체들이 협력 요청 + - Cotroller와 Domain 추상화 계층 제공 + - 사용자로부터 전달받은 데이터를 가공하여 처리 + +- Repository + - Entitiy에 의해 DB에 접근하는 메서드를 사용하기 위한 인터페이스 + - JPA를 사용하면 기본적인 CRUD를 제공 \ No newline at end of file From 44ff359b7a2eeabeec535313bd4ed0adf5d35da4 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 14 Nov 2023 19:45:55 +0900 Subject: [PATCH 08/11] =?UTF-8?q?[8=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week08/8\354\243\274\354\260\250.md" | 10 -- .../\352\263\240\355\203\234\355\230\204.md" | 124 ++++++++++++++++++ 2 files changed, 124 insertions(+), 10 deletions(-) delete mode 100644 "week08/8\354\243\274\354\260\250.md" create mode 100644 "week08/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week08/8\354\243\274\354\260\250.md" "b/week08/8\354\243\274\354\260\250.md" deleted file mode 100644 index c553a92..0000000 --- "a/week08/8\354\243\274\354\260\250.md" +++ /dev/null @@ -1,10 +0,0 @@ -# 8주차 학습 PR - -안녕하세요! 여러분 벌써 8주차라니, 15주차까지니까 벌써 반 정도 왔네요?? -이번 학습 PR은 심플하게 문항 딱 하나만 준비했습니다! -그러니 가능하면 딥하게!! 준비해주셔야 합니다~ 다음 세션 주제이기도 해요 ㅎ - -## HTTP 요청이 들어왔을 때 요청을 받고 응답하기 까지의 전 과정을 설명해주세요. -* 필수 포함 단어(필터, 인터셉터, dispatcherServlet) - -## (선택) 혹시 위 질문에 대한 답을 찾다가 새로운 개념들을 발견하면 정리해볼까요?? diff --git "a/week08/\352\263\240\355\203\234\355\230\204.md" "b/week08/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..9a4859a --- /dev/null +++ "b/week08/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,124 @@ +# [8WEEK] 8주차 학습 PR + +## HTTP 요청 과정 + +--- + +> HTTP(HypterText Transfer Protocol) : 하이퍼텍스트 문서를 교환하기 위해 만들어진 protocol / request(요청)과 response(응답)으로 이루어져있음 +> + +**Request Message** + +![Untitled 1](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/93da251f-64b1-463e-9ac4-4ed0a6aac571) + + +- start line + - HTTP Method : GET, POST, PUT, DELETE 등 + - Request target : request가 전송되는 목표 주소 + - HTTP version +- headers + - Host : 서버 호스트 이름과 포트번호 + - User-agent : 클라이언트 프로그램 정보 + - Referer : 바로 직전에 머물렀던 웹 링크 + - Accept : 처리 가능한 미디어 타입 + - Authorization : 인증 토큰 + - Cookie : key-value로 표현 +- body + - 요청 데이터를 담고있는 부분 + - 전송하는 데이터가 없다면 body는 비어있다 + +**Spring 구조** + +![Untitled 2](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/26f34e65-b27c-4d3f-b61e-579269b7b529) + +![Untitled 3](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/660aacde-b3bd-4a4c-90f5-8f24a4c877a0) + + +Spring MVC는 위와 같은 다이어그램의 구조로 작동하게 된다. + +- 웹 서버(Web Server) + - 인터넷을 기반으로 클라이언트에게 웹 서비스를 제공하는 컴퓨터 + - 클라이언트의 입장 : 웹 서버에 주소(url)을 가지고 통신(http)에 맞게 내용물(html)을 응답 받음 + - 서버 입장 : 클라이언트의 요청을 기다리고, 웹 요청(http)에 대한 데이터를 만들어서 응답, 이때 응답은 정적인 데이터로 한정 + - 아파치, Microsoft IIS, Nginix +- WAS(Web Application Server) + - 웹 어플리케이션을 실행시켜 필요한 기능을 수행하고 그 결과를 웹 서버에게 전달하는 미들웨어 + - php, jsp, asp와 같은 언어를 이용해 동적인 페이지를 만들어내는 서버 + - DB연동, 비지니스 로직처리가 가능 + - Tomcat, JEUS, IBM WebSphere + - 웹 서버 + 웹 컨테이너 + - 웹 컨테이너 : jsp, servlet을 실행시킬 수 있는 소프트웨어 + - servlet : 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 프로그래밍 기술 + + ![Untitled](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/ad18c4f6-e650-4bd5-bcc8-c8c0bdb25c34) + + + - 자바 클래스이므로 생명주기가 있음 +- Filter + - WAS를 걷쳐 들어온 Request는 Serlvet Filter라고 불리우는 low레벨의 무언가를 로깅하거나 감지를 담당함 + - Dispatcher Servlet(Spring의 앞단)에 도달하기 전에 처리 되므로 Web단에서 처리됨 + - Servlet Container로써 관리됨 + + ```java + public interface Filter { + + public default void init(FilterConfig filterConfig) throws ServletException {} + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException; + + public default void destroy() {} + } + ``` + + - init() : 객체를 조기화 → 서비스에 추가 → doFilter를 통해 처리 + - doFilter() : FilterChain의 doFilter 통해 다음 대상으로 요청을 전달 + - destroy() : 서비스에 있는 객체 필드 제거 → 자원 반환 + +- 디스패처 서블릿(Distpatcher Serlvet) + - 스프링단에 존재하는 서블릿 컨테이너에서 HTTP 프로토콜로 들어오는 모든 요청을 받아 적합한 컨트롤러에 위힘하는 프론트 컨트롤러 + - Handler Mapping을 통해 적절한 컨트롤러를 찾아줌 + - 프론트 컨트롤러(Front Controller) : + - 공통의 로직을 각 컨트롤러에게 분산 시켜줌 + +- 인터셉터(Interceptor) + - Spring이 제공하는 기술 + - 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조 or 가공할 수 있는 기능 + - 스프링단에서 작동 + +- 핸들러 매핑(Handler Mapping) + - 우선순위에 따라 요청 url에 맞는 Controller(핸들러)를 찾음 + - 0순위 → @RequestMapping + - 1순위 → 스프링 빈 등록 이름 + +- 핸들러 어댑터(Handler Adapter) + - 등장의 이유 : 요청에 따른 Controller(Handler)가 다를 수 있기에 상황에 맞는 컨트롤러와 연결 시키기 위하여 Adapter개념이 적용됨 + - ex) 해외 여행을 가게 되면 전기 규격이 다르기에 일본에서는 돼지코를 사용하여 전압을 맞춰준다. + - 0순위 → 어노테이션 기반의 핸들러 + - 1순위 → HttpRequestHandler 인터페이스 + - 2순위 Controller 인터페이스 + +- 뷰 리졸버(ViewResolver) + - 사용자가 요청한 정보를 랜더링(html) 하는 역할 + - 컨트롤러와 핸들러 어댑터를 통해 ModelAndView 반환 받음 + - 해당 view를 랜더링하여 view로 반환 + - 반환된 view는 forward를 통해 jsp을 통해 응답함 + +1. WAS로 거친 요청이 이곳에 온다. +2. Dispatcher Serlvet이 해당 요청을 받는다. +3. Handler Mapping으로 요청이 넘어가기전 인터셉터를 거친다 +4. Handler Mapping을 통해 요청에 해당하는 핸들러를 반환받아 +5. 핸들러 어댑터 목록에서 조회함 +6. 조회한 핸들러를 핸들러 어댑터를 통해 controller 메소드를 실행 +7. 가공된 데이터를 ModelAndView로 반환 됨 +8. 뷰 리졸버에서 해당 ModelAndView를 view로 랜더링함 +9. jsp를 통해 클라이언트 요청에 대한 응답을 보내줌 + +## 미션 하면서 알게된 거 + +- @RestController + - 위 어노테이션을 사용하면 하위 메소드들은 @ResponseBody를 갖게된다. + +## API Documentation +- https://documenter.getpostman.com/view/18378325/2s9YXmYLBq + From 5dce254d60cc36184d625f5276fe4b2ff9b8caf4 Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 21 Nov 2023 22:59:21 +0900 Subject: [PATCH 09/11] =?UTF-8?q?[9=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\352\263\240\355\203\234\355\230\204.md" | 106 +++++++++--------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git "a/week08/\352\263\240\355\203\234\355\230\204.md" "b/week08/\352\263\240\355\203\234\355\230\204.md" index 9a4859a..28176aa 100644 --- "a/week08/\352\263\240\355\203\234\355\230\204.md" +++ "b/week08/\352\263\240\355\203\234\355\230\204.md" @@ -13,19 +13,19 @@ - start line - - HTTP Method : GET, POST, PUT, DELETE 등 - - Request target : request가 전송되는 목표 주소 - - HTTP version + - HTTP Method : GET, POST, PUT, DELETE 등 + - Request target : request가 전송되는 목표 주소 + - HTTP version - headers - - Host : 서버 호스트 이름과 포트번호 - - User-agent : 클라이언트 프로그램 정보 - - Referer : 바로 직전에 머물렀던 웹 링크 - - Accept : 처리 가능한 미디어 타입 - - Authorization : 인증 토큰 - - Cookie : key-value로 표현 + - Host : 서버 호스트 이름과 포트번호 + - User-agent : 클라이언트 프로그램 정보 + - Referer : 바로 직전에 머물렀던 웹 링크 + - Accept : 처리 가능한 미디어 타입 + - Authorization : 인증 토큰 + - Cookie : key-value로 표현 - body - - 요청 데이터를 담고있는 부분 - - 전송하는 데이터가 없다면 body는 비어있다 + - 요청 데이터를 담고있는 부분 + - 전송하는 데이터가 없다면 body는 비어있다 **Spring 구조** @@ -37,27 +37,27 @@ Spring MVC는 위와 같은 다이어그램의 구조로 작동하게 된다. - 웹 서버(Web Server) - - 인터넷을 기반으로 클라이언트에게 웹 서비스를 제공하는 컴퓨터 - - 클라이언트의 입장 : 웹 서버에 주소(url)을 가지고 통신(http)에 맞게 내용물(html)을 응답 받음 - - 서버 입장 : 클라이언트의 요청을 기다리고, 웹 요청(http)에 대한 데이터를 만들어서 응답, 이때 응답은 정적인 데이터로 한정 - - 아파치, Microsoft IIS, Nginix + - 인터넷을 기반으로 클라이언트에게 웹 서비스를 제공하는 컴퓨터 + - 클라이언트의 입장 : 웹 서버에 주소(url)을 가지고 통신(http)에 맞게 내용물(html)을 응답 받음 + - 서버 입장 : 클라이언트의 요청을 기다리고, 웹 요청(http)에 대한 데이터를 만들어서 응답, 이때 응답은 정적인 데이터로 한정 + - 아파치, Microsoft IIS, Nginix - WAS(Web Application Server) - - 웹 어플리케이션을 실행시켜 필요한 기능을 수행하고 그 결과를 웹 서버에게 전달하는 미들웨어 - - php, jsp, asp와 같은 언어를 이용해 동적인 페이지를 만들어내는 서버 - - DB연동, 비지니스 로직처리가 가능 - - Tomcat, JEUS, IBM WebSphere - - 웹 서버 + 웹 컨테이너 - - 웹 컨테이너 : jsp, servlet을 실행시킬 수 있는 소프트웨어 - - servlet : 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 프로그래밍 기술 + - 웹 어플리케이션을 실행시켜 필요한 기능을 수행하고 그 결과를 웹 서버에게 전달하는 미들웨어 + - php, jsp, asp와 같은 언어를 이용해 동적인 페이지를 만들어내는 서버 + - DB연동, 비지니스 로직처리가 가능 + - Tomcat, JEUS, IBM WebSphere + - 웹 서버 + 웹 컨테이너 + - 웹 컨테이너 : jsp, servlet을 실행시킬 수 있는 소프트웨어 + - servlet : 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 프로그래밍 기술 - ![Untitled](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/ad18c4f6-e650-4bd5-bcc8-c8c0bdb25c34) + ![Untitled](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/ad18c4f6-e650-4bd5-bcc8-c8c0bdb25c34) - 자바 클래스이므로 생명주기가 있음 - Filter - - WAS를 걷쳐 들어온 Request는 Serlvet Filter라고 불리우는 low레벨의 무언가를 로깅하거나 감지를 담당함 - - Dispatcher Servlet(Spring의 앞단)에 도달하기 전에 처리 되므로 Web단에서 처리됨 - - Servlet Container로써 관리됨 + - WAS를 걷쳐 들어온 Request는 Serlvet Filter라고 불리우는 low레벨의 무언가를 로깅하거나 감지를 담당함 + - Dispatcher Servlet(Spring의 앞단)에 도달하기 전에 처리 되므로 Web단에서 처리됨 + - Servlet Container로써 관리됨 ```java public interface Filter { @@ -70,39 +70,44 @@ Spring MVC는 위와 같은 다이어그램의 구조로 작동하게 된다. public default void destroy() {} } ``` + + - init() : 객체를 조기화 → 서비스에 추가 → doFilter를 통해 처리 + - doFilter() : FilterChain의 doFilter 통해 다음 대상으로 요청을 전달 + - destroy() : 서비스에 있는 객체 필드 제거 → 자원 반환 - - init() : 객체를 조기화 → 서비스에 추가 → doFilter를 통해 처리 - - doFilter() : FilterChain의 doFilter 통해 다음 대상으로 요청을 전달 - - destroy() : 서비스에 있는 객체 필드 제거 → 자원 반환 - 디스패처 서블릿(Distpatcher Serlvet) - - 스프링단에 존재하는 서블릿 컨테이너에서 HTTP 프로토콜로 들어오는 모든 요청을 받아 적합한 컨트롤러에 위힘하는 프론트 컨트롤러 - - Handler Mapping을 통해 적절한 컨트롤러를 찾아줌 - - 프론트 컨트롤러(Front Controller) : - - 공통의 로직을 각 컨트롤러에게 분산 시켜줌 + - 스프링단에 존재하는 서블릿 컨테이너에서 HTTP 프로토콜로 들어오는 모든 요청을 받아 적합한 컨트롤러에 위힘하는 프론트 컨트롤러 + - Handler Mapping을 통해 적절한 컨트롤러를 찾아줌 + - 프론트 컨트롤러(Front Controller) : + - 공통 + - 의 로직을 각 컨트롤러에게 분산 시켜줌 - 인터셉터(Interceptor) - - Spring이 제공하는 기술 - - 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조 or 가공할 수 있는 기능 - - 스프링단에서 작동 + - Spring이 제공하는 기술 + - 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조 or 가공할 수 있는 기능 + - 스프링단에서 작동 + - 핸들러 매핑(Handler Mapping) - - 우선순위에 따라 요청 url에 맞는 Controller(핸들러)를 찾음 - - 0순위 → @RequestMapping - - 1순위 → 스프링 빈 등록 이름 + - 우선순위에 따라 요청 url에 맞는 Controller(핸들러)를 찾음 + - 0순위 → @RequestMapping + - 1순위 → 스프링 빈 등록 이름 + - 핸들러 어댑터(Handler Adapter) - - 등장의 이유 : 요청에 따른 Controller(Handler)가 다를 수 있기에 상황에 맞는 컨트롤러와 연결 시키기 위하여 Adapter개념이 적용됨 - - ex) 해외 여행을 가게 되면 전기 규격이 다르기에 일본에서는 돼지코를 사용하여 전압을 맞춰준다. - - 0순위 → 어노테이션 기반의 핸들러 - - 1순위 → HttpRequestHandler 인터페이스 - - 2순위 Controller 인터페이스 + - 등장의 이유 : 요청에 따른 Controller(Handler)가 다를 수 있기에 상황에 맞는 컨트롤러와 연결 시키기 위하여 Adapter개념이 적용됨 + - ex) 해외 여행을 가게 되면 전기 규격이 다르기에 일본에서는 돼지코를 사용하여 전압을 맞춰준다. + - 0순위 → 어노테이션 기반의 핸들러 + - 1순위 → HttpRequestHandler 인터페이스 + - 2순위 Controller 인터페이스 + - 뷰 리졸버(ViewResolver) - - 사용자가 요청한 정보를 랜더링(html) 하는 역할 - - 컨트롤러와 핸들러 어댑터를 통해 ModelAndView 반환 받음 - - 해당 view를 랜더링하여 view로 반환 - - 반환된 view는 forward를 통해 jsp을 통해 응답함 + - 사용자가 요청한 정보를 랜더링(html) 하는 역할 + - 컨트롤러와 핸들러 어댑터를 통해 ModelAndView 반환 받음 + - 해당 view를 랜더링하여 view로 반환 + - 반환된 view는 forward를 통해 jsp을 통해 응답함 1. WAS로 거친 요청이 이곳에 온다. 2. Dispatcher Serlvet이 해당 요청을 받는다. @@ -117,8 +122,7 @@ Spring MVC는 위와 같은 다이어그램의 구조로 작동하게 된다. ## 미션 하면서 알게된 거 - @RestController - - 위 어노테이션을 사용하면 하위 메소드들은 @ResponseBody를 갖게된다. + - 위 어노테이션을 사용하면 하위 메소드들은 @ResponseBody를 갖게된다. ## API Documentation -- https://documenter.getpostman.com/view/18378325/2s9YXmYLBq - +- https://documenter.getpostman.com/view/18378325/2s9YXmYLBq \ No newline at end of file From d670e53c66694c92b5994a1f871c928c349a5adc Mon Sep 17 00:00:00 2001 From: grgr589 Date: Tue, 21 Nov 2023 22:59:52 +0900 Subject: [PATCH 10/11] =?UTF-8?q?[9=EC=A3=BC=EC=B0=A8]=20=EA=B3=A0?= =?UTF-8?q?=ED=83=9C=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C?= =?UTF-8?q?=EC=B6=9C=ED=95=A9=EB=8B=88=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\352\263\240\355\203\234\355\230\204.md" | 251 ++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 "week09/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week09/\352\263\240\355\203\234\355\230\204.md" "b/week09/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..c18b36d --- /dev/null +++ "b/week09/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,251 @@ +# [9WEEK] 9주차 학습 PR + +## HTTP 요청 과정 + +--- + +> HTTP(HypterText Transfer Protocol) : 하이퍼텍스트 문서를 교환하기 위해 만들어진 protocol / request(요청)과 response(응답)으로 이루어져있음 +> + +**Request Message** + +![Untitled 1](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/93da251f-64b1-463e-9ac4-4ed0a6aac571) + + +- start line + - HTTP Method : GET, POST, PUT, DELETE 등 + - Request target : request가 전송되는 목표 주소 + - HTTP version +- headers + - Host : 서버 호스트 이름과 포트번호 + - User-agent : 클라이언트 프로그램 정보 + - Referer : 바로 직전에 머물렀던 웹 링크 + - Accept : 처리 가능한 미디어 타입 + - Authorization : 인증 토큰 + - Cookie : key-value로 표현 +- body + - 요청 데이터를 담고있는 부분 + - 전송하는 데이터가 없다면 body는 비어있다 + +**Spring 구조** + +![Untitled 2](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/26f34e65-b27c-4d3f-b61e-579269b7b529) + +![Untitled 3](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/660aacde-b3bd-4a4c-90f5-8f24a4c877a0) + + +Spring MVC는 위와 같은 다이어그램의 구조로 작동하게 된다. + +- 웹 서버(Web Server) + - 인터넷을 기반으로 클라이언트에게 웹 서비스를 제공하는 컴퓨터 + - 클라이언트의 입장 : 웹 서버에 주소(url)을 가지고 통신(http)에 맞게 내용물(html)을 응답 받음 + - 서버 입장 : 클라이언트의 요청을 기다리고, 웹 요청(http)에 대한 데이터를 만들어서 응답, 이때 응답은 정적인 데이터로 한정 + - 아파치, Microsoft IIS, Nginix +- WAS(Web Application Server) + - 웹 어플리케이션을 실행시켜 필요한 기능을 수행하고 그 결과를 웹 서버에게 전달하는 미들웨어 + - php, jsp, asp와 같은 언어를 이용해 동적인 페이지를 만들어내는 서버 + - DB연동, 비지니스 로직처리가 가능 + - Tomcat, JEUS, IBM WebSphere + - 웹 서버 + 웹 컨테이너 + - 웹 컨테이너 : jsp, servlet을 실행시킬 수 있는 소프트웨어 + - servlet : 동적 웹 페이지를 만들 때 사용되는 자바 기반의 웹 프로그래밍 기술 + + ![Untitled](https://github.com/TaetaetaE01/Procedural_Project/assets/68328998/ad18c4f6-e650-4bd5-bcc8-c8c0bdb25c34) + + + - 자바 클래스이므로 생명주기가 있음 +- Filter + - WAS를 걷쳐 들어온 Request는 Serlvet Filter라고 불리우는 low레벨의 무언가를 로깅하거나 감지를 담당함 + - Dispatcher Servlet(Spring의 앞단)에 도달하기 전에 처리 되므로 Web단에서 처리됨 + - Servlet Container로써 관리됨 + + ```java + public interface Filter { + + public default void init(FilterConfig filterConfig) throws ServletException {} + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException; + + public default void destroy() {} + } + ``` + + - init() : 객체를 조기화 → 서비스에 추가 → doFilter를 통해 처리 + - doFilter() : FilterChain의 doFilter 통해 다음 대상으로 요청을 전달 + - destroy() : 서비스에 있는 객체 필드 제거 → 자원 반환 + +- 디스패처 서블릿(Distpatcher Serlvet) + - 스프링단에 존재하는 서블릿 컨테이너에서 HTTP 프로토콜로 들어오는 모든 요청을 받아 적합한 컨트롤러에 위힘하는 프론트 컨트롤러 + - Handler Mapping을 통해 적절한 컨트롤러를 찾아줌 + - 프론트 컨트롤러(Front Controller) : + - 공통의 로직을 각 컨트롤러에게 분산 시켜줌 + +- 인터셉터(Interceptor) + - Spring이 제공하는 기술 + - 디스패처 서블릿(Dispatcher Servlet)이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조 or 가공할 수 있는 기능 + - 스프링단에서 작동 + +- 핸들러 매핑(Handler Mapping) + - 우선순위에 따라 요청 url에 맞는 Controller(핸들러)를 찾음 + - 0순위 → @RequestMapping + - 1순위 → 스프링 빈 등록 이름 + +- 핸들러 어댑터(Handler Adapter) + - 등장의 이유 : 요청에 따른 Controller(Handler)가 다를 수 있기에 상황에 맞는 컨트롤러와 연결 시키기 위하여 Adapter개념이 적용됨 + - ex) 해외 여행을 가게 되면 전기 규격이 다르기에 일본에서는 돼지코를 사용하여 전압을 맞춰준다. + - 0순위 → 어노테이션 기반의 핸들러 + - 1순위 → HttpRequestHandler 인터페이스 + - 2순위 Controller 인터페이스 + +- 뷰 리졸버(ViewResolver) + - 사용자가 요청한 정보를 랜더링(html) 하는 역할 + - 컨트롤러와 핸들러 어댑터를 통해 ModelAndView 반환 받음 + - 해당 view를 랜더링하여 view로 반환 + - 반환된 view는 forward를 통해 jsp을 통해 응답함 + +1. WAS로 거친 요청이 이곳에 온다. +2. Dispatcher Serlvet이 해당 요청을 받는다. +3. Handler Mapping으로 요청이 넘어가기전 인터셉터를 거친다 +4. Handler Mapping을 통해 요청에 해당하는 핸들러를 반환받아 +5. 핸들러 어댑터 목록에서 조회함 +6. 조회한 핸들러를 핸들러 어댑터를 통해 controller 메소드를 실행 +7. 가공된 데이터를 ModelAndView로 반환 됨 +8. 뷰 리졸버에서 해당 ModelAndView를 view로 랜더링함 +9. jsp를 통해 클라이언트 요청에 대한 응답을 보내줌 + +## 미션 하면서 알게된 거 + +- @RestController + - 위 어노테이션을 사용하면 하위 메소드들은 @ResponseBody를 갖게된다. + +## API Documentation +- https://documenter.getpostman.com/view/18378325/2s9YXmYLBq + + + +## DispatcherServlet 동작과정 + +- DispatcherServlet계층구조 + +![Untitled 4](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/f3fda7ca-7ff9-4c87-a760-7912bef5eea5) + +1. HttpServlet | DispatcherServlet의 상위 객체인 HttpSerlvet의 service으로 요청이 들어온다 + +![Untitled 5](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/7319a89a-993c-44a6-bcc7-231529184fe4) + +1. FrameworkServlet | http 메소드에 따른 호출을 해준다 + +![Untitled 6](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/8dd01b27-f647-456c-9bb5-c66da011c034) + +1. HttpServlet | http 메소드를 분류하고 do메소드로 실행, but ‘PATHCH’는 doPatch메소드가 없어 processRequest를 호출하고 메소드에 따라 필요한 처리와 do메소드를 호출한다. + +```java +String method = req.getMethod(); +// 요청에 대한 http 메소드를 분류한다 +``` + +![Untitled 7](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/eb649c61-e0cf-4759-ad46-139c920a69e7) + +![Untitled 8](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/831f1e18-cfed-4636-8d1a-dc37cc0d48f1) + +1. FrameworkServlet | 오버라이딩 된 각 do 메소드는 processRequest를 통해 공동퇸 request 과정 후 doService 호출 + +![Untitled 9](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/5b8be262-ba41-4e55-bbf6-3b8e4ff36498) + +1. DispatcherServlet | 자식 클래스인 DispatcherServlet에서 doSerivce 실행 + +```java +try { + doDispatch(request, response); + } +// doDispatch는 http 요청을 컨트롤러로 위힘하는 메소드 +``` + +![Untitled 10](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/d3493644-b6ae-4829-b6bc-d12588fbcd2f) + +1. DispatcherServlet | doDispatch() 속 + 1. 요청에 매핑되는 HandlerMapping + 2. 요청을 처리할 HandlerAdapter 조회 + 3. HandlerAdapter를 통해 컨트롤러 메소드 호출 + +![Untitled 11](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/3dc1d6e5-fa27-4b41-83bb-3510b677a0a5) + +- 요청에 매핑되는 HandlerMapping + - HandlerExecutionChain조회 + - HandlerExecutionChain = HandlerMethod + Interceptor + - HandlerMethod ⇒ 매팽되는 컨트롤러의 메소드, 컨트롤러 빈 이름, 빈 팩토리 등 저장 + - 리턴되는 것이 HandlerExecutionChain인 이유는 공동의 로직을 처리하기 위한 Interceptor가 존재하기 때문 + +```java +mappedHandler = getHandler(processedRequest); + if (mappedHandler == null) { + noHandlerFound(processedRequest, response); + return; + } +``` + +- getHandler() + +```java +@Nullable + protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { + if (this.handlerMappings != null) { + for (HandlerMapping mapping : this.handlerMappings) { + HandlerExecutionChain handler = mapping.getHandler(request); + if (handler != null) { + return handler; + } + } + } + return null; + } +``` + +- 요청을 처리할 HandlerAdapter 조회 + - 조회 후 HandlerAdapter 생성 + +```java +HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); +``` + +- getHandlerAdapter() + +```java +protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { + if (this.handlerAdapters != null) { + for (HandlerAdapter adapter : this.handlerAdapters) { + if (adapter.supports(handler)) { + return adapter; + } + } + } + throw new ServletException("No adapter for handler [" + handler + + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler"); + } +``` + +- HandlerAdapter를 통해 컨트롤러 메소드 호출 + - 컨트롤러 메소드 호출 전 → 적합한 파라미터를 만들어야함 + - 컨트롤러 메소드 호출 후 →메세지 컨버터를 통해 ResponseEntity Body를 찾아 Json 직렬화 + +```java +mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); +``` + +- AbstractHandlerMethodAdapter | handle() + +![Untitled 12](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/96c9f9f6-e3ad-44d7-9ef1-06872d66f675) + +- RequestMappingHandlerAdapter | handlerInternal() + +![Untitled 13](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/6f27bf73-779c-4edd-a5b9-524aa64662b7) + +- RequestMappingHandlerAdapter | invokeHandlerMethod() + +![Untitled 14](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/efdba465-69b3-4b33-bdf7-f748d04fa2a6) + +- RequestMappingHandlerAdapter | getModelAndView() + - invoke 함수로 매핑된 컨트롤러를 ModelAndView로 반환 + +![Untitled 15](https://github.com/COW-edu/practice-oop-lotto/assets/68328998/93c31954-2435-4ae0-bed6-c5928aff27a5) \ No newline at end of file From 73bf6f4000ba9ef37c1b205319d3a1980fb7e143 Mon Sep 17 00:00:00 2001 From: TaetaetaE01 Date: Tue, 28 Nov 2023 22:42:43 +0900 Subject: [PATCH 11/11] =?UTF-8?q?[10=EC=A3=BC=EC=B0=A8]=EA=B3=A0=ED=83=9C?= =?UTF-8?q?=ED=98=84=20=ED=95=99=EC=8A=B5=20PR=20=EC=A0=9C=EC=B6=9C?= =?UTF-8?q?=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week10/10\354\243\274\354\260\250.md" | 18 --- .../\352\263\240\355\203\234\355\230\204.md" | 149 ++++++++++++++++++ 2 files changed, 149 insertions(+), 18 deletions(-) delete mode 100644 "week10/10\354\243\274\354\260\250.md" create mode 100644 "week10/\352\263\240\355\203\234\355\230\204.md" diff --git "a/week10/10\354\243\274\354\260\250.md" "b/week10/10\354\243\274\354\260\250.md" deleted file mode 100644 index 867b71b..0000000 --- "a/week10/10\354\243\274\354\260\250.md" +++ /dev/null @@ -1,18 +0,0 @@ -# 10주차 학습 PR - -이번 주는 살짝 쉬어가는 느낌으로 실습 PR은 별도로 없고, -H2 Database를 설치해오시면 좋을 것 같습니다! - -## Indexing이란? -(clustering index, secondary index) - - -## DB의 Relationship(1:1, 1:m, n:m) - - - -## JPA 엔티티의 생명 주기 - - - -## @Id, @GeneratedValue \ No newline at end of file diff --git "a/week10/\352\263\240\355\203\234\355\230\204.md" "b/week10/\352\263\240\355\203\234\355\230\204.md" new file mode 100644 index 0000000..4eada70 --- /dev/null +++ "b/week10/\352\263\240\355\203\234\355\230\204.md" @@ -0,0 +1,149 @@ +# [10WEEK] 10주차 학습 PR + +## DB Indexing 이란? + +--- + +> 데이터베이스분야에 있어서 테이블에 대한 동작 속도를 높여주는 자료구조를 일컫는다. +> + +### 요약 + +1. 테이블에 대한 검색의 속도를 높여주는 자료구조 +2. 색인이고 메모리 영역의 일종의 목차를 생성하는 개념 +3. 따라서 이런 목차를 이용하여 검색 범위를 줄여 속도를 높일 수 있음 + +- 인덱스 종류 + - B-tree Index + - Bitmap Index + - IOT Index + - Clustered Index + +- 동작방법 + - 해당 테이블을 생성ㅎ시 생성하고 싶은 인덱스 컬럼 지정 + - 생성 후 인뎃스 조회 시, where 절이 포함된 쿼리로 조회 + - 인덱스로 저장된 key-value값을 참조해서 결과 출력 + +- 특징 + - index를 사용하면 검색 속도의 향상효과 + - 시스템 부하를 다운, 시스템 전체 성능향상에 기여 + - but, index를 위한 추고 공간 필요 + - 데이터가 많이 있다면 생성에 많은 시간 소요 + - insert, update, delete가 자주 발생시 성능이 하락 + +### clustering index + +: 페이지를 알고 있어서 바로 해당 페이지를 펼치는 것과 같음 + +- 방법 + - 데이블의 데이터를 지정된 컬럼에 대해 물리적으로 데이터를 재배열 + - 데이터가 테이블에 삽입되는 순서에 상관없이 index로 생성되어 있는 칼럼을 기준으로 정렬 + - index page를 key-value와 page-number로 구성 + - 데이터의 키값으로 페이지 번호를 검색하여 찾음 + - 루트 페이지와 리프 페이지로 구성 + - 리프 페이지는 데이터 그 자체 + - 물리적으로 정렬되어 있어 검색 속도가 빠르지만 입력/수정/삭제 속도는 느리다 + +### Secondary Index + +: 중복항목을 포함할 수 있는 인덱스, 다른 인덱스를 돕는 보조 인덱스 + +- 특징 + - 데이터 블록에서 행이 실제로 구서오디는 방식에 영향일 미치지 않음 + - 여러개의 인덱스를 가질 수 있음 + +## DB Relationship + +--- + +> 엔티티와 엔티티 사이의 관계, 즉 관리하고자 하는 업무 영역내의 특정한 두 개의 엔티티 사이에 존재하는 많은 관게 중 특별히 관리하고자 하는 직접적인 관계를 의미 +> + +- 왜래키 + - 관계는 외래키로 구현되어 참조 무결성으로 데이터 정합성 유지의 역할을 함 + +1. 1:1 관계 + 1. 어느 쪽 당사자의 입장에서 상대를 보더라도 반드시 단 하나씩과 관게를 가지는 것 + 2. 특징 + 1. 현시렝서 매우 드물게 나타나는 형태 + 2. 업무의 흐름에 다라 데이터가 설계된 형태에서 많이 나타남 + 3. 엔티티 수직 분할시에 많이 나타남 +2. 1:m 관계 + 1. 가장 흔하게 나타나는 매우 일반적인 형태. 마치 부모와 자식과의 관계처럼 계층적인 구조 + 2. 특징 + 1. 가장 흔하게 나타나는 관계 형태 + 2. 참조할 정보는 나에게 반드시 하나만 존재해야함 +3. n:m 관계 + 1. 말 그대로 다대다 관계이다 + 2. 특징 + 1. 관계를 가진 양쪽 당사자 모두에서 1:m 관계가 존재할 때 나타나는 모습 + 2. 선택 사양은 양쪽 모두가 선택적인 것이 기본형 + +## JPA 엔티티의 생명주기 + +--- + +> ORM 기술 표준으로 사용되는 인터페이스의 모음. 실제적으로 구현된것이 아니라 구현된 클래스와 매핑을 해주기 위해 사용되는 프레임 워크 +> + +- JPA의 내부 동작 + - EntityManagerFactory가 요청마다 EntityManger를 생성해주고, EntityManger는 커넥션 풀을 통해 디비에 접근 + +- 비영속(new/transient) + - 순수한 객체 상태이며, 영속성 컨텍스트와 관련이 없는 상태 + + ```java + Member member = new Member(); + ``` + + +- 영속(managed) + - EntityManager를 통해 엔티티를 영속성 컨텍스트에 저장되어 영속성 컨텍스트가 관리하는 상태 + + ```java + em.persist(member); // 객체 저장 + ``` + +- 준영속(detached) + - 영속성 컨텍스트에 저장되었다가 분리된상태 + + ```java + em.detach(member); // 특정 엔티티를 분리 + + em.close(); // 영속성 컨텍스트 닫기 + em.clear(); // 영속성 컨텍스트 초기화 + ``` + + +- 삭제 + - 엔티티를 영속성 컨텍스트와 데이터베이스에서 삭제한 상태 + + ```java + em.remove(member); + ``` + + +## @id, @GeneratedValue + +--- + +> id는 Primary Key와 같은 의미를 가지며 어노테이션으로 표기 +> +- @id + + ```java + @Id + @Column + prvate String code; + ``` + +- @GeneratedValue + - 구분이 가능한 유일한 값을 가지고 있어야 하고 데이터 경합으로 인해 발생되는 데드락 같은 현상을 방지 하기 위해 Long을 사용 + - 데드락 : 동일한 시점에 요청이 유입 되었을 대 데이터베이스는 테이블 혹은 레코드 lock을 걸어 데이터가 변경되지 않도록 막아 놓고 다른 작업을 함 + + ```java + @Id + @SequenceGenerator(name="seq", sequeneceName="jpa_sequence") + @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq") + private Long id; + ``` \ No newline at end of file