From a89806d13dafa758b213264f6814735df1b61571 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:39:20 +0900 Subject: [PATCH 01/13] =?UTF-8?q?Update=20and=20rename=20week01/1=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8.md=20to=20=ED=99=8D=EC=A0=95=EC=9A=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week01/1\354\243\274\354\260\250.md" | 30 --- "\355\231\215\354\240\225\354\232\260.md" | 213 ++++++++++++++++++++++ 2 files changed, 213 insertions(+), 30 deletions(-) delete mode 100644 "week01/1\354\243\274\354\260\250.md" create mode 100644 "\355\231\215\354\240\225\354\232\260.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/\355\231\215\354\240\225\354\232\260.md" "b/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..2bba9d0 --- /dev/null +++ "b/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,213 @@ +# 자바 기본 + +## Primitive Type과 Reference Type의 차이점 + +자바에서 데이터 타입은 크게 Primitive Type과 Reference Type으로 나눌 수 있다. + +**Primitive Type(원시 타입)** + +- 정수, 실수, 문자, 논리 리터널 등의 실제 데이터 값을 저장하는 타입이다. +- int, long, double, float, boolean, byte, short, char +- Java에서 기본 자료형은 반드시 사용하기 전에 선언되어야하며, 자료형의 길이는 운영체제에 독립적이며 변하지 않는다. +- Stack 메모리에 저장된다. + +**Reference. Type(참조 타입)** + +- 객체를 참조하는 타입으로 메모리 번지 값을 통해 객체를 참조하는 타입이다. +- Integer, Long, Double, Float, Boolean, Byte, Short, Char +- Java에서 최상위 클래스인 Object 클래스를 상속하는 모든 클래스를 말한다. +- Java에서 실제 객체는 Heap 메모리에 저장되며 참조 타입 변수는 스택 메모리에 실제 객체들의 주소를 저장하여 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다. + +************차이점************ + +- 원시 타입은 null 값을 담을 수 없는 반면에 참조 타입은 null을 입력 값으로 받을 수 있다. +- 원시 타입은 제네릭 타입에서 사용할 수 없는 반면에 참조 타입은 제네릭 타입에서 사용할 수 있다. + +## 접근 제어자 + +자바에서는 접근 제어자를 사용하여 클래스의 멤버(필드, 메서드, 내부 클래스)에 대한 접근 권한을 제어할 수 있다. 접근 제어자는 코드의 캡슐화와 데이터 은닉을 지원하며, 다른 클래스나 패키지에서 어떤 멤버에 접근할 수 있는지를 명시적으로 정의한다. + +1. **public** + - 가장 넓은 범위의 접근 제어자로, 어떤 클래스에서든 접근이 가능하다. 다른 패키지에서도 접근할 수 있다. +2. **protected** + - 같은 패키지 내의 클래스와 해당 클래스를 상속받은 서브클래스에서 접근 가능하다. 다른 패키지의 클래스에서는 접근이 제한된다. +3. **default** + - 접근 제어자를 명시하지 않는 경우, 해당 멤버는 기본적으로 같은 패키지 내에서만 접근이 가능하다. 다른 패키지에서는 접근할 수 없다. +4. **private** + - 가장 제한적인 범위의 접근 제어자로, 해당 멤버는 오로지 자신을 포함한 해당 클래스 내에서만 접근 가능하다. 서브 클래스도 접근할 수 없다. + +## static + +Java에서 Static 키워드를 사용하는 것은 메모리에 한 번 할당되어 프로그램이 종료될 때 해제되는 것을 의미한다. + +Static 키워드를 통해 생성된 정적멤버들은 Heap 영역이 아닌 Static영역에 할당된다. Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만 Garbage Collector의 관리 영역 밖에 존재하기에 Static 영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 된다. + +**************************************************정적(Static) 멤버 선언************************************************** + +```java +static int num = 0; +public static void static_method(){} +``` + +## final + +자바(Java)에서 final 키워드는 변수, 메서드, 클래스 등의 선언 앞에 사용된다. final은 다양한 컨텍스트에서 다른 의미를 가지며, 주로 해당 멤버나 클래스의 수정이나 재정의를 막는 데 사용된다. + +1. **Final 변수** + - final로 선언된 변수는 상수를 나타낸다. 즉, 한 번 초기화되면 값을 변경할 수 없다. + - 초기화는 변수를 선언할 때 또는 생성자에서 이루어져야 한다. + - 주로 상수 값이나 설정 값을 표현할 때 사용된다. +2. **Final 메서드** + - final로 선언된 메서드는 하위 클래스에서 재정의(오버라이딩)할 수 없다. + - 부모 클래스에서 정의된 메서드가 그대로 사용되어야 하며, 하위 클래스에서 변경할 수 없다. +3. **Final 클래스** + - final로 선언된 클래스는 더 이상 상속될 수 없다. 즉, 하위 클래스를 만들 수 없다. + - 주로 불변 클래스를 정의할 때 사용된다. 불변 클래스란 수정할 수 없는 객체를 나타낸다. +4. **Final 매개변수** + - 메서드나 생성자의 매개변수를 final로 선언할 수 있다. + - final 매개변수는 메서드 내에서 변결할 수 없으며, 주로 메서드 내에서 매개변수 값이 변경되지 않음을 보장할 때 사용된다. +5. **Final 변수와 상속** + - final로 선언된 변수는 재할당할 수 없지만, 상속 관계에서 주의해야 함. + - 부모 클래스의 final 변수는 하위 클래스에서 다시 선언하여 새로운 변수로 인식된다. + + ```java + public class Parent { + final int value = 10; + } + + public class Child extends Parent { + // 부모 클래스의 value와는 별개의 변수 + final int value = 20; + } + ``` + + +## Overloading, Overriding + +오버로딩과 오버라이딩 두 개념은 다형성을 구현하는 데 사용된다. + +1. **Overloading** + - 오버로딩은 같은 이름의 메서드 또는 생성자를 여러 개 정의하는 것을 의미한다. + - 오버로딩된 메서드는 매개변수의 타입, 개수 또는 순서가 서로 다를 수 있다. + - 호출 시 인자의 종류나 개수에 따라 적절한 오버로딩된 메서드가 선택되어 실행된다. + + ```java + public class Example { + public int add(int a, int b) { + return a + b; + } + + public double add(double a, double b) { + return a + b; + } + + public String add(String a, String b) { + return a + b; + } + } + ``` + +2. **Overriding** + - 오버라이딩은 상위 클래스(부모 크래스)의 메서드를 하위 클래스(자식 클래스)에서 재정의하는 것을 의미한다. + - 매서드 시그니처(메서드 이름, 매개변수 타입 및 반환 타입)는 동일해야 한다. + - 오버라이딩된 메서드는 상위 클래스의 메서드 대신 호출된다. 이렇게 하위 클래스에서 동일한 메서드 이름으로 다르게 동작하도록 할 수 있다. + + ```java + class Animal { + void makeSound() { + System.out.println("동물이 소리를 내고 있습니다."); + } + } + + class Dog extends Animal { + @Override + void makeSound() { + System.out.println("강아지가 짖고 있습니다."); + } + } + ``` + +- 오버로딩은 같은 클래스 내에서 메서드 이름이 같은 다수의 메서드를 가질 수 있으며, 메서드 호출 시 매개변수에 따라 어떤 메서드가 호출될지 결정됩니다. +- 오버라이딩은 상속 관계에서 발생하며, 상위 클래스의 메서드를 하위 클래스에서 덮어쓰는 것을 의미합니다. 오버라이딩된 메서드는 상위 클래스의 메서드를 대체하고 동일한 시그니처를 가져야 합니다. 호출 시 객체의 타입에 따라 오버라이딩된 메서드가 실행됩니다. + +## 추상 클래스와 인터페이스 + +****************추상 클래스 (Abstract Class)**************** + +- 추상 클래스는 일반 클래스와 별 다를 것이 없다. 단지, 추상 메서드를 선언하여 상속을 통하여 자손 클래스에서 완성하도록 유도하는 클래스이다. 그래서 미완성 설계도라고도 표현한다. +- 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없다. + +```java +abstract class 클래스이름 { + ... + public abstract void 메서드이름(); +} +``` + +**인터페이스 (Interface)** + +- 인터페이스는 기본 설계도이다. 인터페이스는 클래스에 특정 동작을 추가하고, 다양한 클래스 간에 공통 동작을 정의하기 위해 사용된다. +- 다중상속이 가능하다. + +```java +interface 인터페이스이름 { + public static final 상수이름 = 값; + public abstract void 메서드이름(); +} +``` + +**차이점** + +1. 인스턴스 생성 가능 여부 + - 추상 클래스는 인스턴스를 직접 생성할 수 있다. 즉, 객체를 만들 수 있다 + - 인터페이스는 직접 인스턴스를 생성할 수 없다. 즉, 객체를 만들 수 없으며, 인터페이스를 구현한 클래스의 인스턴스를 생성해야 한다. +2. 메서드 + - 추상 클래스는 추상 메서드(Abstract Method) 외에도 구현된 메서드(일반 메서드)를 포함할 수 있다. 추상 메서드는 하위 클래스에서 반드시 구현되어야 하지만, 일반 메서드는 구현되어 있어도 되고 하위 클래스에서 오버라이딩(재정의)할 수 있다. + - 인터페이스는 추상 메서드만을 선언할 수 있습니다. 모든 메서드는 추상이며, 이를 구현하는 클래스에서 반드시 모든 메서드를 구현해야 합니다. +3. 상속 + - 자바에서 클래스는 하나의 클래스만 상속할 수 있으므로, 추상 클래스는 다른 클래스를 상속받으면서 동시에 추상 클래스일 수 있습니다. + - 클래스는 하나의 클래스만 상속할 수 있지만, 인터페이스는 여러 인터페이스를 동시에 구현할 수 있으므로 다중 상속을 지원합니다. + +## Enum + +Java에서 `**Enum**`은 열거형(Enumeration)을 나타내는 데이터 형식으로, 관련된 상수를 그룹화하고 간편하게 사용할 수 있도록 지원하는 기능이다. + +```java +enum 이름 { + 상수1, + 상수2, + // ... +} +``` + +## 객체지향이란? + +객체 지향 프로그래밍 (Object-Oriented Programming, OOP)은 프로그래밍에서 필요한 데이터를 추상화 시켜 `상태와 행위를 가진 객체`로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다. + +객체지향 프로그래밍의 ******이점****** + +1. **모듈화(Modularity):** 객체지향 프로그래밍은 코드를 모듈화하고 클래스로 구성함으로써 코드의 유지보수성을 높인다. 각 클래스는 독립적으로 개발 및 테스트할 수 있어서 개발 과정을 단순화한다. +2. **재사용성(Reusability):** 상속과 다형성을 활용하여 코드를 재사용할 수 있다. 이미 구현된 클래스를 확장하여 새로운 클래스를 작성하거나, 다른 프로젝트에서 동일한 클래스를 사용할 수 있다. +3. **유지보수성(Maintainability):** 객체 지향 프로그래밍은 코드를 더 쉽게 이해하고 수정할 수 있도록 도와준다. 클래스와 객체의 캡슐화는 내부 구현을 숨기고 외부 인터페이스를 통해 상호작용하기 때문에 코드 변경이 다른 부분에 미치는 영향을 최소화한다. +4. **확장성(Scalability):** 객체지향 시스템은 요구 사항의 변화나 추가 기능의 구현에 대한 확장성을 가진다. 새로운 클래스나 객체를 추가하고 기존 코드를 수정하지 않고도 시스템을 확장할 수 있다. +5. **코드의 가독성과 이해도 향상:** 현실 세계 개념을 모델링하므로 코드는 비즈니스 로직을 이해하기 쉽고 자연스럽게 문서화된다. +6. **객체 재사용:** 객체를 독립적으로 개발하여 라이브러리로 사용하거나 다른 프로젝트에서 재사용할 수 있으므로 생산성이 향상된다. + +## 객체지향의 4대 특성 + +1. **캡슐화(Encapsulation):** + - 캡슐화는 데이터와 해당 데이터를 처리하는 메서드를 하나로 묶어 객체로 생성하는 것을 의미한다. + - 객체의 상태(데이터)는 private 접근 제어자를 사용하여 외부에서 직접 접근할 수 없게 제한된다. 따라서 정보 은닉(Information Hiding)을 실현한다. + - 오직 객체의 메서드를 통해서만 데이터에 접근할 수 있으므로 데이터의 무결성을 보호하고 부적절한 수정을 방지할 수 있다. +2. **상속(Inheritance):** + - 상속은 하위 클래스가 상위 클래스의 특성과 동작을 상속받아 재사용할 수 있도록 하는 메커니즘이다. + - 상속 관계를 형성하여 클래스 간 계층 구조를 생성하고, 공통 코드를 공유하여 코드의 재사용성을 향상시킨다. + - 상위 클래스는 기본적인 동작을 정의하고, 하위 클래스는 이를 확장하거나 변경할 수 있다. +3. **다형성(Polymorphism):** + - 다형성은 하나의 인터페이스나 메서드를 여러 클래스에서 다르게 구현하는 능력을 의미한다. + - 다형성을 통해 객체가 여러 형태를 가질 수 있고, 실행 시간에 객체의 실제 타입에 따라 다른 메서드가 호출된다. + - 다형성은 코드의 유연성을 높이고, 동적 바인딩을 통해 실행 시간에 적절한 메서드를 호출한다. +4. **추상화(Abstraction):** + - 추상화는 복잡한 시스템을 간소화하고 필수적인 기능만 포함하는 모델을 생성하는 과정이다. + - 추상 클래스와 인터페이스를 사용하여 현실 세계의 개념을 모델링하고, 중요한 세부 정보를 감추어 간결하고 이해하기 쉬운 인터페이스를 제공한다. + - 추상화를 통해 사용자는 객체의 핵심 기능에만 집중할 수 있으며, 세부 구현을 무시할 수 있다. From 48e23146bc3a4597efad8397b9581ce956bb717f Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:41:45 +0900 Subject: [PATCH 02/13] =?UTF-8?q?Delete=20=ED=99=8D=EC=A0=95=EC=9A=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "\355\231\215\354\240\225\354\232\260.md" | 213 ---------------------- 1 file changed, 213 deletions(-) delete mode 100644 "\355\231\215\354\240\225\354\232\260.md" diff --git "a/\355\231\215\354\240\225\354\232\260.md" "b/\355\231\215\354\240\225\354\232\260.md" deleted file mode 100644 index 2bba9d0..0000000 --- "a/\355\231\215\354\240\225\354\232\260.md" +++ /dev/null @@ -1,213 +0,0 @@ -# 자바 기본 - -## Primitive Type과 Reference Type의 차이점 - -자바에서 데이터 타입은 크게 Primitive Type과 Reference Type으로 나눌 수 있다. - -**Primitive Type(원시 타입)** - -- 정수, 실수, 문자, 논리 리터널 등의 실제 데이터 값을 저장하는 타입이다. -- int, long, double, float, boolean, byte, short, char -- Java에서 기본 자료형은 반드시 사용하기 전에 선언되어야하며, 자료형의 길이는 운영체제에 독립적이며 변하지 않는다. -- Stack 메모리에 저장된다. - -**Reference. Type(참조 타입)** - -- 객체를 참조하는 타입으로 메모리 번지 값을 통해 객체를 참조하는 타입이다. -- Integer, Long, Double, Float, Boolean, Byte, Short, Char -- Java에서 최상위 클래스인 Object 클래스를 상속하는 모든 클래스를 말한다. -- Java에서 실제 객체는 Heap 메모리에 저장되며 참조 타입 변수는 스택 메모리에 실제 객체들의 주소를 저장하여 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다. - -************차이점************ - -- 원시 타입은 null 값을 담을 수 없는 반면에 참조 타입은 null을 입력 값으로 받을 수 있다. -- 원시 타입은 제네릭 타입에서 사용할 수 없는 반면에 참조 타입은 제네릭 타입에서 사용할 수 있다. - -## 접근 제어자 - -자바에서는 접근 제어자를 사용하여 클래스의 멤버(필드, 메서드, 내부 클래스)에 대한 접근 권한을 제어할 수 있다. 접근 제어자는 코드의 캡슐화와 데이터 은닉을 지원하며, 다른 클래스나 패키지에서 어떤 멤버에 접근할 수 있는지를 명시적으로 정의한다. - -1. **public** - - 가장 넓은 범위의 접근 제어자로, 어떤 클래스에서든 접근이 가능하다. 다른 패키지에서도 접근할 수 있다. -2. **protected** - - 같은 패키지 내의 클래스와 해당 클래스를 상속받은 서브클래스에서 접근 가능하다. 다른 패키지의 클래스에서는 접근이 제한된다. -3. **default** - - 접근 제어자를 명시하지 않는 경우, 해당 멤버는 기본적으로 같은 패키지 내에서만 접근이 가능하다. 다른 패키지에서는 접근할 수 없다. -4. **private** - - 가장 제한적인 범위의 접근 제어자로, 해당 멤버는 오로지 자신을 포함한 해당 클래스 내에서만 접근 가능하다. 서브 클래스도 접근할 수 없다. - -## static - -Java에서 Static 키워드를 사용하는 것은 메모리에 한 번 할당되어 프로그램이 종료될 때 해제되는 것을 의미한다. - -Static 키워드를 통해 생성된 정적멤버들은 Heap 영역이 아닌 Static영역에 할당된다. Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만 Garbage Collector의 관리 영역 밖에 존재하기에 Static 영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 된다. - -**************************************************정적(Static) 멤버 선언************************************************** - -```java -static int num = 0; -public static void static_method(){} -``` - -## final - -자바(Java)에서 final 키워드는 변수, 메서드, 클래스 등의 선언 앞에 사용된다. final은 다양한 컨텍스트에서 다른 의미를 가지며, 주로 해당 멤버나 클래스의 수정이나 재정의를 막는 데 사용된다. - -1. **Final 변수** - - final로 선언된 변수는 상수를 나타낸다. 즉, 한 번 초기화되면 값을 변경할 수 없다. - - 초기화는 변수를 선언할 때 또는 생성자에서 이루어져야 한다. - - 주로 상수 값이나 설정 값을 표현할 때 사용된다. -2. **Final 메서드** - - final로 선언된 메서드는 하위 클래스에서 재정의(오버라이딩)할 수 없다. - - 부모 클래스에서 정의된 메서드가 그대로 사용되어야 하며, 하위 클래스에서 변경할 수 없다. -3. **Final 클래스** - - final로 선언된 클래스는 더 이상 상속될 수 없다. 즉, 하위 클래스를 만들 수 없다. - - 주로 불변 클래스를 정의할 때 사용된다. 불변 클래스란 수정할 수 없는 객체를 나타낸다. -4. **Final 매개변수** - - 메서드나 생성자의 매개변수를 final로 선언할 수 있다. - - final 매개변수는 메서드 내에서 변결할 수 없으며, 주로 메서드 내에서 매개변수 값이 변경되지 않음을 보장할 때 사용된다. -5. **Final 변수와 상속** - - final로 선언된 변수는 재할당할 수 없지만, 상속 관계에서 주의해야 함. - - 부모 클래스의 final 변수는 하위 클래스에서 다시 선언하여 새로운 변수로 인식된다. - - ```java - public class Parent { - final int value = 10; - } - - public class Child extends Parent { - // 부모 클래스의 value와는 별개의 변수 - final int value = 20; - } - ``` - - -## Overloading, Overriding - -오버로딩과 오버라이딩 두 개념은 다형성을 구현하는 데 사용된다. - -1. **Overloading** - - 오버로딩은 같은 이름의 메서드 또는 생성자를 여러 개 정의하는 것을 의미한다. - - 오버로딩된 메서드는 매개변수의 타입, 개수 또는 순서가 서로 다를 수 있다. - - 호출 시 인자의 종류나 개수에 따라 적절한 오버로딩된 메서드가 선택되어 실행된다. - - ```java - public class Example { - public int add(int a, int b) { - return a + b; - } - - public double add(double a, double b) { - return a + b; - } - - public String add(String a, String b) { - return a + b; - } - } - ``` - -2. **Overriding** - - 오버라이딩은 상위 클래스(부모 크래스)의 메서드를 하위 클래스(자식 클래스)에서 재정의하는 것을 의미한다. - - 매서드 시그니처(메서드 이름, 매개변수 타입 및 반환 타입)는 동일해야 한다. - - 오버라이딩된 메서드는 상위 클래스의 메서드 대신 호출된다. 이렇게 하위 클래스에서 동일한 메서드 이름으로 다르게 동작하도록 할 수 있다. - - ```java - class Animal { - void makeSound() { - System.out.println("동물이 소리를 내고 있습니다."); - } - } - - class Dog extends Animal { - @Override - void makeSound() { - System.out.println("강아지가 짖고 있습니다."); - } - } - ``` - -- 오버로딩은 같은 클래스 내에서 메서드 이름이 같은 다수의 메서드를 가질 수 있으며, 메서드 호출 시 매개변수에 따라 어떤 메서드가 호출될지 결정됩니다. -- 오버라이딩은 상속 관계에서 발생하며, 상위 클래스의 메서드를 하위 클래스에서 덮어쓰는 것을 의미합니다. 오버라이딩된 메서드는 상위 클래스의 메서드를 대체하고 동일한 시그니처를 가져야 합니다. 호출 시 객체의 타입에 따라 오버라이딩된 메서드가 실행됩니다. - -## 추상 클래스와 인터페이스 - -****************추상 클래스 (Abstract Class)**************** - -- 추상 클래스는 일반 클래스와 별 다를 것이 없다. 단지, 추상 메서드를 선언하여 상속을 통하여 자손 클래스에서 완성하도록 유도하는 클래스이다. 그래서 미완성 설계도라고도 표현한다. -- 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없다. - -```java -abstract class 클래스이름 { - ... - public abstract void 메서드이름(); -} -``` - -**인터페이스 (Interface)** - -- 인터페이스는 기본 설계도이다. 인터페이스는 클래스에 특정 동작을 추가하고, 다양한 클래스 간에 공통 동작을 정의하기 위해 사용된다. -- 다중상속이 가능하다. - -```java -interface 인터페이스이름 { - public static final 상수이름 = 값; - public abstract void 메서드이름(); -} -``` - -**차이점** - -1. 인스턴스 생성 가능 여부 - - 추상 클래스는 인스턴스를 직접 생성할 수 있다. 즉, 객체를 만들 수 있다 - - 인터페이스는 직접 인스턴스를 생성할 수 없다. 즉, 객체를 만들 수 없으며, 인터페이스를 구현한 클래스의 인스턴스를 생성해야 한다. -2. 메서드 - - 추상 클래스는 추상 메서드(Abstract Method) 외에도 구현된 메서드(일반 메서드)를 포함할 수 있다. 추상 메서드는 하위 클래스에서 반드시 구현되어야 하지만, 일반 메서드는 구현되어 있어도 되고 하위 클래스에서 오버라이딩(재정의)할 수 있다. - - 인터페이스는 추상 메서드만을 선언할 수 있습니다. 모든 메서드는 추상이며, 이를 구현하는 클래스에서 반드시 모든 메서드를 구현해야 합니다. -3. 상속 - - 자바에서 클래스는 하나의 클래스만 상속할 수 있으므로, 추상 클래스는 다른 클래스를 상속받으면서 동시에 추상 클래스일 수 있습니다. - - 클래스는 하나의 클래스만 상속할 수 있지만, 인터페이스는 여러 인터페이스를 동시에 구현할 수 있으므로 다중 상속을 지원합니다. - -## Enum - -Java에서 `**Enum**`은 열거형(Enumeration)을 나타내는 데이터 형식으로, 관련된 상수를 그룹화하고 간편하게 사용할 수 있도록 지원하는 기능이다. - -```java -enum 이름 { - 상수1, - 상수2, - // ... -} -``` - -## 객체지향이란? - -객체 지향 프로그래밍 (Object-Oriented Programming, OOP)은 프로그래밍에서 필요한 데이터를 추상화 시켜 `상태와 행위를 가진 객체`로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다. - -객체지향 프로그래밍의 ******이점****** - -1. **모듈화(Modularity):** 객체지향 프로그래밍은 코드를 모듈화하고 클래스로 구성함으로써 코드의 유지보수성을 높인다. 각 클래스는 독립적으로 개발 및 테스트할 수 있어서 개발 과정을 단순화한다. -2. **재사용성(Reusability):** 상속과 다형성을 활용하여 코드를 재사용할 수 있다. 이미 구현된 클래스를 확장하여 새로운 클래스를 작성하거나, 다른 프로젝트에서 동일한 클래스를 사용할 수 있다. -3. **유지보수성(Maintainability):** 객체 지향 프로그래밍은 코드를 더 쉽게 이해하고 수정할 수 있도록 도와준다. 클래스와 객체의 캡슐화는 내부 구현을 숨기고 외부 인터페이스를 통해 상호작용하기 때문에 코드 변경이 다른 부분에 미치는 영향을 최소화한다. -4. **확장성(Scalability):** 객체지향 시스템은 요구 사항의 변화나 추가 기능의 구현에 대한 확장성을 가진다. 새로운 클래스나 객체를 추가하고 기존 코드를 수정하지 않고도 시스템을 확장할 수 있다. -5. **코드의 가독성과 이해도 향상:** 현실 세계 개념을 모델링하므로 코드는 비즈니스 로직을 이해하기 쉽고 자연스럽게 문서화된다. -6. **객체 재사용:** 객체를 독립적으로 개발하여 라이브러리로 사용하거나 다른 프로젝트에서 재사용할 수 있으므로 생산성이 향상된다. - -## 객체지향의 4대 특성 - -1. **캡슐화(Encapsulation):** - - 캡슐화는 데이터와 해당 데이터를 처리하는 메서드를 하나로 묶어 객체로 생성하는 것을 의미한다. - - 객체의 상태(데이터)는 private 접근 제어자를 사용하여 외부에서 직접 접근할 수 없게 제한된다. 따라서 정보 은닉(Information Hiding)을 실현한다. - - 오직 객체의 메서드를 통해서만 데이터에 접근할 수 있으므로 데이터의 무결성을 보호하고 부적절한 수정을 방지할 수 있다. -2. **상속(Inheritance):** - - 상속은 하위 클래스가 상위 클래스의 특성과 동작을 상속받아 재사용할 수 있도록 하는 메커니즘이다. - - 상속 관계를 형성하여 클래스 간 계층 구조를 생성하고, 공통 코드를 공유하여 코드의 재사용성을 향상시킨다. - - 상위 클래스는 기본적인 동작을 정의하고, 하위 클래스는 이를 확장하거나 변경할 수 있다. -3. **다형성(Polymorphism):** - - 다형성은 하나의 인터페이스나 메서드를 여러 클래스에서 다르게 구현하는 능력을 의미한다. - - 다형성을 통해 객체가 여러 형태를 가질 수 있고, 실행 시간에 객체의 실제 타입에 따라 다른 메서드가 호출된다. - - 다형성은 코드의 유연성을 높이고, 동적 바인딩을 통해 실행 시간에 적절한 메서드를 호출한다. -4. **추상화(Abstraction):** - - 추상화는 복잡한 시스템을 간소화하고 필수적인 기능만 포함하는 모델을 생성하는 과정이다. - - 추상 클래스와 인터페이스를 사용하여 현실 세계의 개념을 모델링하고, 중요한 세부 정보를 감추어 간결하고 이해하기 쉬운 인터페이스를 제공한다. - - 추상화를 통해 사용자는 객체의 핵심 기능에만 집중할 수 있으며, 세부 구현을 무시할 수 있다. From 9024a9a8bbd0ff7d02b218abe51fd6be656ee4f3 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:43:08 +0900 Subject: [PATCH 03/13] =?UTF-8?q?week01=20Assignment=20=ED=99=8D=EC=A0=95?= =?UTF-8?q?=EC=9A=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit week01 Assignment 제출입니다! --- .../\355\231\215\354\240\225\354\232\260.md" | 213 ++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 "week01/\355\231\215\354\240\225\354\232\260.md" diff --git "a/week01/\355\231\215\354\240\225\354\232\260.md" "b/week01/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..0491dff --- /dev/null +++ "b/week01/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,213 @@ +# 자바 기본 + +## Primitive Type과 Reference Type의 차이점 + +자바에서 데이터 타입은 크게 Primitive Type과 Reference Type으로 나눌 수 있다. + +**Primitive Type(원시 타입)** + +- 정수, 실수, 문자, 논리 리터널 등의 실제 데이터 값을 저장하는 타입이다. +- int, long, double, float, boolean, byte, short, char +- Java에서 기본 자료형은 반드시 사용하기 전에 선언되어야하며, 자료형의 길이는 운영체제에 독립적이며 변하지 않는다. +- Stack 메모리에 저장된다. + +**Reference. Type(참조 타입)** + +- 객체를 참조하는 타입으로 메모리 번지 값을 통해 객체를 참조하는 타입이다. +- Integer, Long, Double, Float, Boolean, Byte, Short, Char +- Java에서 최상위 클래스인 Object 클래스를 상속하는 모든 클래스를 말한다. +- Java에서 실제 객체는 Heap 메모리에 저장되며 참조 타입 변수는 스택 메모리에 실제 객체들의 주소를 저장하여 객체를 사용할 때마다 참조 변수에 저장된 객체의 주소를 불러와 사용하는 방식이다. + +************차이점************ + +- 원시 타입은 null 값을 담을 수 없는 반면에 참조 타입은 null을 입력 값으로 받을 수 있다. +- 원시 타입은 제네릭 타입에서 사용할 수 없는 반면에 참조 타입은 제네릭 타입에서 사용할 수 있다. + +## 접근 제어자 + +자바에서는 접근 제어자를 사용하여 클래스의 멤버(필드, 메서드, 내부 클래스)에 대한 접근 권한을 제어할 수 있다. 접근 제어자는 코드의 캡슐화와 데이터 은닉을 지원하며, 다른 클래스나 패키지에서 어떤 멤버에 접근할 수 있는지를 명시적으로 정의한다. + +1. **public** + - 가장 넓은 범위의 접근 제어자로, 어떤 클래스에서든 접근이 가능하다. 다른 패키지에서도 접근할 수 있다. +2. **protected** + - 같은 패키지 내의 클래스와 해당 클래스를 상속받은 서브클래스에서 접근 가능하다. 다른 패키지의 클래스에서는 접근이 제한된다. +3. **default** + - 접근 제어자를 명시하지 않는 경우, 해당 멤버는 기본적으로 같은 패키지 내에서만 접근이 가능하다. 다른 패키지에서는 접근할 수 없다. +4. **private** + - 가장 제한적인 범위의 접근 제어자로, 해당 멤버는 오로지 자신을 포함한 해당 클래스 내에서만 접근 가능하다. 서브 클래스도 접근할 수 없다. + +## static + +Java에서 Static 키워드를 사용하는 것은 메모리에 한 번 할당되어 프로그램이 종료될 때 해제되는 것을 의미한다. + +Static 키워드를 통해 생성된 정적멤버들은 Heap 영역이 아닌 Static영역에 할당된다. Static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든지 참조할 수 있는 장점을 가지지만 Garbage Collector의 관리 영역 밖에 존재하기에 Static 영역에 있는 멤버들은 프로그램의 종료시까지 메모리가 할당된 채로 존재하게 된다. + +**************************************************정적(Static) 멤버 선언************************************************** + +```java +static int num = 0; +public static void static_method(){} +``` + +## final + +자바(Java)에서 final 키워드는 변수, 메서드, 클래스 등의 선언 앞에 사용된다. final은 다양한 컨텍스트에서 다른 의미를 가지며, 주로 해당 멤버나 클래스의 수정이나 재정의를 막는 데 사용된다. + +1. **Final 변수** + - final로 선언된 변수는 상수를 나타낸다. 즉, 한 번 초기화되면 값을 변경할 수 없다. + - 초기화는 변수를 선언할 때 또는 생성자에서 이루어져야 한다. + - 주로 상수 값이나 설정 값을 표현할 때 사용된다. +2. **Final 메서드** + - final로 선언된 메서드는 하위 클래스에서 재정의(오버라이딩)할 수 없다. + - 부모 클래스에서 정의된 메서드가 그대로 사용되어야 하며, 하위 클래스에서 변경할 수 없다. +3. **Final 클래스** + - final로 선언된 클래스는 더 이상 상속될 수 없다. 즉, 하위 클래스를 만들 수 없다. + - 주로 불변 클래스를 정의할 때 사용된다. 불변 클래스란 수정할 수 없는 객체를 나타낸다. +4. **Final 매개변수** + - 메서드나 생성자의 매개변수를 final로 선언할 수 있다. + - final 매개변수는 메서드 내에서 변결할 수 없으며, 주로 메서드 내에서 매개변수 값이 변경되지 않음을 보장할 때 사용된다. +5. **Final 변수와 상속** + - final로 선언된 변수는 재할당할 수 없지만, 상속 관계에서 주의해야 함. + - 부모 클래스의 final 변수는 하위 클래스에서 다시 선언하여 새로운 변수로 인식된다. + + ```java + public class Parent { + final int value = 10; + } + + public class Child extends Parent { + // 부모 클래스의 value와는 별개의 변수 + final int value = 20; + } + ``` + + +## Overloading, Overriding + +오버로딩과 오버라이딩 두 개념은 다형성을 구현하는 데 사용된다. + +1. **Overloading** + - 오버로딩은 같은 이름의 메서드 또는 생성자를 여러 개 정의하는 것을 의미한다. + - 오버로딩된 메서드는 매개변수의 타입, 개수 또는 순서가 서로 다를 수 있다. + - 호출 시 인자의 종류나 개수에 따라 적절한 오버로딩된 메서드가 선택되어 실행된다. + + ```java + public class Example { + public int add(int a, int b) { + return a + b; + } + + public double add(double a, double b) { + return a + b; + } + + public String add(String a, String b) { + return a + b; + } + } + ``` + +2. **Overriding** + - 오버라이딩은 상위 클래스(부모 크래스)의 메서드를 하위 클래스(자식 클래스)에서 재정의하는 것을 의미한다. + - 매서드 시그니처(메서드 이름, 매개변수 타입 및 반환 타입)는 동일해야 한다. + - 오버라이딩된 메서드는 상위 클래스의 메서드 대신 호출된다. 이렇게 하위 클래스에서 동일한 메서드 이름으로 다르게 동작하도록 할 수 있다. + + ```java + class Animal { + void makeSound() { + System.out.println("동물이 소리를 내고 있습니다."); + } + } + + class Dog extends Animal { + @Override + void makeSound() { + System.out.println("강아지가 짖고 있습니다."); + } + } + ``` + +- 오버로딩은 같은 클래스 내에서 메서드 이름이 같은 다수의 메서드를 가질 수 있으며, 메서드 호출 시 매개변수에 따라 어떤 메서드가 호출될지 결정됩니다. +- 오버라이딩은 상속 관계에서 발생하며, 상위 클래스의 메서드를 하위 클래스에서 덮어쓰는 것을 의미합니다. 오버라이딩된 메서드는 상위 클래스의 메서드를 대체하고 동일한 시그니처를 가져야 합니다. 호출 시 객체의 타입에 따라 오버라이딩된 메서드가 실행됩니다. + +## 추상 클래스와 인터페이스 + +****************추상 클래스 (Abstract Class)**************** + +- 추상 클래스는 일반 클래스와 별 다를 것이 없다. 단지, 추상 메서드를 선언하여 상속을 통하여 자손 클래스에서 완성하도록 유도하는 클래스이다. 그래서 미완성 설계도라고도 표현한다. +- 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없다. + +```java +abstract class 클래스이름 { + ... + public abstract void 메서드이름(); +} +``` + +**인터페이스 (Interface)** + +- 인터페이스는 기본 설계도이다. 인터페이스는 클래스에 특정 동작을 추가하고, 다양한 클래스 간에 공통 동작을 정의하기 위해 사용된다. +- 다중상속이 가능하다. + +```java +interface 인터페이스이름 { + public static final 상수이름 = 값; + public abstract void 메서드이름(); +} +``` + +**차이점** + +1. 인스턴스 생성 가능 여부 + - 추상 클래스는 인스턴스를 직접 생성할 수 있다. 즉, 객체를 만들 수 있다 + - 인터페이스는 직접 인스턴스를 생성할 수 없다. 즉, 객체를 만들 수 없으며, 인터페이스를 구현한 클래스의 인스턴스를 생성해야 한다. +2. 메서드 + - 추상 클래스는 추상 메서드(Abstract Method) 외에도 구현된 메서드(일반 메서드)를 포함할 수 있다. 추상 메서드는 하위 클래스에서 반드시 구현되어야 하지만, 일반 메서드는 구현되어 있어도 되고 하위 클래스에서 오버라이딩(재정의)할 수 있다. + - 인터페이스는 추상 메서드만을 선언할 수 있습니다. 모든 메서드는 추상이며, 이를 구현하는 클래스에서 반드시 모든 메서드를 구현해야 합니다. +3. 상속 + - 자바에서 클래스는 하나의 클래스만 상속할 수 있으므로, 추상 클래스는 다른 클래스를 상속받으면서 동시에 추상 클래스일 수 있습니다. + - 클래스는 하나의 클래스만 상속할 수 있지만, 인터페이스는 여러 인터페이스를 동시에 구현할 수 있으므로 다중 상속을 지원합니다. + +## Enum + +Java에서 `**Enum**`은 열거형(Enumeration)을 나타내는 데이터 형식으로, 관련된 상수를 그룹화하고 간편하게 사용할 수 있도록 지원하는 기능이다. + +```java +enum 이름 { + 상수1, + 상수2, + // ... +} +``` + +## 객체지향이란? + +객체 지향 프로그래밍 (Object-Oriented Programming, OOP)은 프로그래밍에서 필요한 데이터를 추상화 시켜 `상태와 행위를 가진 객체`로 만들고, 객체들간의 상호작용을 통해 로직을 구성하는 프로그래밍 방법이다. + +객체지향 프로그래밍의 ******이점****** + +1. **모듈화(Modularity):** 객체지향 프로그래밍은 코드를 모듈화하고 클래스로 구성함으로써 코드의 유지보수성을 높인다. 각 클래스는 독립적으로 개발 및 테스트할 수 있어서 개발 과정을 단순화한다. +2. **재사용성(Reusability):** 상속과 다형성을 활용하여 코드를 재사용할 수 있다. 이미 구현된 클래스를 확장하여 새로운 클래스를 작성하거나, 다른 프로젝트에서 동일한 클래스를 사용할 수 있다. +3. **유지보수성(Maintainability):** 객체 지향 프로그래밍은 코드를 더 쉽게 이해하고 수정할 수 있도록 도와준다. 클래스와 객체의 캡슐화는 내부 구현을 숨기고 외부 인터페이스를 통해 상호작용하기 때문에 코드 변경이 다른 부분에 미치는 영향을 최소화한다. +4. **확장성(Scalability):** 객체지향 시스템은 요구 사항의 변화나 추가 기능의 구현에 대한 확장성을 가진다. 새로운 클래스나 객체를 추가하고 기존 코드를 수정하지 않고도 시스템을 확장할 수 있다. +5. **코드의 가독성과 이해도 향상:** 현실 세계 개념을 모델링하므로 코드는 비즈니스 로직을 이해하기 쉽고 자연스럽게 문서화된다. +6. **객체 재사용:** 객체를 독립적으로 개발하여 라이브러리로 사용하거나 다른 프로젝트에서 재사용할 수 있으므로 생산성이 향상된다. + +## 객체지향의 4대 특성 + +1. **캡슐화(Encapsulation):** + - 캡슐화는 데이터와 해당 데이터를 처리하는 메서드를 하나로 묶어 객체로 생성하는 것을 의미한다. + - 객체의 상태(데이터)는 private 접근 제어자를 사용하여 외부에서 직접 접근할 수 없게 제한된다. 따라서 정보 은닉(Information Hiding)을 실현한다. + - 오직 객체의 메서드를 통해서만 데이터에 접근할 수 있으므로 데이터의 무결성을 보호하고 부적절한 수정을 방지할 수 있다. +2. **상속(Inheritance):** + - 상속은 하위 클래스가 상위 클래스의 특성과 동작을 상속받아 재사용할 수 있도록 하는 메커니즘이다. + - 상속 관계를 형성하여 클래스 간 계층 구조를 생성하고, 공통 코드를 공유하여 코드의 재사용성을 향상시킨다. + - 상위 클래스는 기본적인 동작을 정의하고, 하위 클래스는 이를 확장하거나 변경할 수 있다. +3. **다형성(Polymorphism):** + - 다형성은 하나의 인터페이스나 메서드를 여러 클래스에서 다르게 구현하는 능력을 의미한다. + - 다형성을 통해 객체가 여러 형태를 가질 수 있고, 실행 시간에 객체의 실제 타입에 따라 다른 메서드가 호출된다. + - 다형성은 코드의 유연성을 높이고, 동적 바인딩을 통해 실행 시간에 적절한 메서드를 호출한다. +4. **추상화(Abstraction):** + - 추상화는 복잡한 시스템을 간소화하고 필수적인 기능만 포함하는 모델을 생성하는 과정이다. + - 추상 클래스와 인터페이스를 사용하여 현실 세계의 개념을 모델링하고, 중요한 세부 정보를 감추어 간결하고 이해하기 쉬운 인터페이스를 제공한다. + - 추상화를 통해 사용자는 객체의 핵심 기능에만 집중할 수 있으며, 세부 구현을 무시할 수 있다. \ No newline at end of file From fb65e866befc730ec7313e82261bb84e68564fb7 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:10:01 +0900 Subject: [PATCH 04/13] Delete week02 directory --- "week02/2\354\243\274\354\260\250.md" | 45 --------------------------- 1 file changed, 45 deletions(-) delete mode 100644 "week02/2\354\243\274\354\260\250.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 From 053f77e965afa778b317a4a4692f4779dd6af4f1 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:11:14 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[2=EC=A3=BC=EC=B0=A8]=20=ED=99=8D?= =?UTF-8?q?=EC=A0=95=EC=9A=B0=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 [2주차] 홍정우 학습 PR 제출합니다. --- .../\355\231\215\354\240\225\354\232\260.md" | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 "week02/\355\231\215\354\240\225\354\232\260.md" diff --git "a/week02/\355\231\215\354\240\225\354\232\260.md" "b/week02/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..595af55 --- /dev/null +++ "b/week02/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,21 @@ +# COW - Week2 + +### 2주차 학습 PR + +- 요구사항 정의 + 1. Lotto + 1. 6자리의 번호를 입력받을 로또 객체가 필요하다. + 2. Lottos + 1. 여러 개의 로또를 구매할 시 여러 개의 로또를 관리하기 위한 Lottos 객체가 필요하다. + 3. Money + 1. 하나의 로또당 1000원임으로 Input으로 들어간 금액에 알맞는 로또를 제공 할 Money객체가 필요하다. + 4. WinningLotto + 1. 당첨 번호와 보너스 번호를 입력받을 WinningLotto 객체가 필요하다. + 5. Result + 1. 당첨 내역과 수익률을 출력할 Result 객체가 필요하다. + +- 구현에 대한 고민 + - 우선 객체를 파악하는 것에 많은 고민을 했다. 하나의 객체는 하나의 책임을 맡아야 함으로 객체의 역할을 정하여 책임을 부여하는 과정에서 많은 객체가 필요하다는 것을 알게 되었다. + - 로또 번호는 1~45의 범위를 가지고 로또를 구매하기 위한 돈도 1000원 단위로 팔아야하는 등 여러가지 제약 조건이 필요하여 예외 처리를 하는 것에도 많은 고민이 필요했다. + - 당첨 내역을 출력할 때 당첨 번호가 일치하는 횟수를 구하는 로직을 작성할 때 들여쓰기 depth가 3이 넘지 않도록 작성하는 것에 어려움을 겪었고 코드도 내가 생각한 것과 다르게 작성하여 디버깅하는 능력을 길러서 다시 해결을 시도해 볼 것이다. + - Enum을 많이 사용해보지 않아 어떤 방식으로 작동하는 지와 사용법에 미숙하여 이해를 하지 못하고 사용한 경향이 있는 것 같다. 다음 주차 PR 때는 이해를 최대한 하고 코드를 다시 작성해 볼 것이다. \ No newline at end of file From facae947a5a6333b7294de21b82516d9947423fd Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:00:59 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[3=EC=A3=BC=EC=B0=A8]=20=ED=99=8D?= =?UTF-8?q?=EC=A0=95=EC=9A=B0=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 --- .../\355\231\215\354\240\225\354\232\260.md" | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 "week03/\355\231\215\354\240\225\354\232\260.md" diff --git "a/week03/\355\231\215\354\240\225\354\232\260.md" "b/week03/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..f328a5a --- /dev/null +++ "b/week03/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,170 @@ +# Cow - Week3 + +## 일급 컬렉션 + +- 일급 컬렉션(First-class Collection)은 프로그래밍에서 컬렉션을 일급 객체(First-class Object)처럼 다루는 개념입니다. +- 콜렉션을 포함한 클래스는 반드시 다른 멤버 변수가 없어야 한다. + +**일급 컬렉션을 사용하는 이유와 장점** + +1. **불변성(Immutability)**: 일급 컬렉션은 불변 객체로 다룰 수 있다. 이것은 컬렉션을 변경할 수 없다는 것을 의미하며, 데이터의 무결성을 보장하고 다중 스레드 환경에서의 문제를 방지하는데 도움이 된다. + 1. final과의 차이점은 final은 불변을 만들어주는 것이 아니라, 재할당만 금지인 것으로 값 변경이 가능하다. +2. **함수 조합성(Function Composition)**: 일급 컬렉션을 사용하면 함수를 조합할 때 더 쉽게 데이터를 다룰 수 있다. +3. **상태와 행위를 한 곳에서 관리 :** 값과 로직이 함께 존재한다. +4. **가독성과 유지 보수성**: 일급 컬렉션을 사용하면 코드의 가독성을 높일 수 있다. 데이터 구조에 의미 있는 이름을 부여하고 이를 활용하여 코드를 작성하는 것이 가능하며, 이는 코드의 유지 보수를 쉽게 만들어 준다. +5. **에러 감소**: 일급 컬렉션을 사용하면 데이터를 처리하는 과정에서 발생하는 에러를 줄일 수 있다. 불변성과 유형 안정성(Type Safety)을 통해 코드를 안정적으로 유지할 수 있다. + +불변 객체(Immutable Object)와 방어적 복사(Defensive Copy)는 일급 컬렉션과 관련이 있다. 불변 객체는 객체의 상태를 변경할 수 없게 만드는 개념으로, 데이터의 불변성을 보장하기 위해 사용된다. 방어적 복사는 불변 객체를 활용하여 다른 객체로부터 데이터를 보호하고 복사본을 제공하는 기술이다. 이는 데이터 무결성을 유지하고 예기치 않은 부작용을 방지하는 데 도움이 된다. 이러한 개념은 일급 컬렉션과 함께 사용될 때 코드의 안정성과 신뢰성을 높일 수 있는 장점이 있다. + +****예제**** + +```java +Map map = new HashMap<>(); +map.put("1", "A"); +map.put("2", "B"); +map.put("3", "C"); +``` + +위의 코드를 아래처럼 Wrapping하는 것 + +```java +public class GameRanking { + + private Map ranks; + + public GameRanking(Map ranks) { + this.ranks = ranks; + } +} +``` + +## MVC + +****************MVC 패턴이란?**************** + +- MVC(Mode-View-Controller) 패턴은 소프트웨어 개발에서 사용되는 소프트웨어 아키텍처 패턴 중 하나로, 애플리케이션의 구성 요소를 세 가지 주요 역할로 분리하여 설계하는 방법. +- MVC 패턴을 활용함으로써 애플리케이션의 관심사를 분리하고 모듈화하여 유지 보수와 확장성을 개선할 수 있다. + +**MVC 패턴의 3가지 요소** + +1. **모델(Model)**: 모델은 애플리케이션의 데이터와 비즈니스 로직을 관리한다. 데이터의 상태를 저장하고 조작하며, 데이터 변경을 처리하고 필요한 정보를 제공한다. +2. **뷰(View)**: 뷰는 데이터를 시각적으로 표현하는 부분. 사용자 인터페이스(UI)를 담당하며, 모델의 데이터를 표시하고 사용자와 상호 작용하는 방법을 정의한다. +3. **컨트롤러(Controller)**: 컨트롤러는 사용자 입력을 처리하고 모델과 뷰 간의 상호 작용을 조정한다. 사용자의 요청을 받아 모델을 업데이트하고, 변경된 데이터를 뷰에 반영하는 역할을 한다. + +**MVC 패턴 사용 이유는?** + +1. **관심사 분리(Separation of Concerns)**: MVC는 애플리케이션의 다양한 측면(데이터 관리, UI 표현, 사용자 입력 처리)을 서로 분리하여 관리할 수 있게 하는 장점이 있다. 이로써 각 구성 요소를 독립적으로 개발하고 유지 보수할 수 있는 것이다. +2. **재사용성과 모듈화**: 각각의 MVC 구성 요소는 독립적으로 재사용할 수 있는 장점이 있다. 모델, 뷰, 컨트롤러를 다른 프로젝트에서도 활용할 수 있어 개발 생산성을 향상시킬 수 있다. +3. **유지 보수와 확장성**: 애플리케이션의 변경 사항을 더 쉽게 관리할 수 있다. 애플리케이션의 변화가 있을 때 다른 구성 요소에 영향을 주지 않고 해당 변경을 수행할 수 있게 된다. + +**************MVC 패턴의 등장 배경************** + +- 예전에는 자바 JSP와 서블릿만을 이용하여 웹 서비스를 개발하였다. 하지만 JSP의 경우 간단한 코드임에도 자바 코드와 HTML 코드가 복잡하게 얽혀 있어 가독성이 떨어질 뿐만 아니라 변경 생명 주기가 서로 다른 요소들이 결합(뷰 + 비즈니스 로직)되어 있다는 큰 문제가 있어 UI가 변경되어야 하는 시점에 비즈니스 로직도 함께 변경되어야 한다는 불편함이 있었다. 이러한 이유들을 타파하고자 등장하게 된 것이 MVC 패턴이다. +- 즉, 관심사의 분리를 통하여 애플리케이션의 다양한 측면을 서로 분리하여 관리하기 위하여 MVC 패턴이 등장한 것. + +## Java의 Stream이란? + +**Stream** + +- 자바 8에서 추가한 스트림(*Streams*)은 람다를 활용할 수 있는 기술 중 하나이다. + - 람다란? : 람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것이라고 할 수 있다. 람다 표현식에는 이름은 없지만, 파라미터 리스트, 바디, 반환 형식, 발생할 수 있는 예외 리스트는 가질 수 있다. + +Stream의 특징 및 장점 + +- 병렬 처리 + - Stream을 사용하면 데이터를 병렬로 처리할 수 있다. **`parallel()`** 메서드를 사용하여 스트림을 병렬 스트림으로 변환하고, 멀티코어 프로세서를 활용하여 빠른 처리가 가능하다. +- 작업 분류 + - Stream 연산은 파이프라인 방식으로 연결할 수 있다. 이것은 한 번에 하나의 요소만 처리하는 대신 여러 연산을 연결하여 데이터를 처리하는 것을 의미한다. +- lazy Evaluatuin + - Stream 연산은 지연 평가 방식으로 동작한다. 이것은 연산이 실제로 수행되기 전까지는 데이터를 읽거나 처리하지 않는다는 것을 의미한다. 이를 통해 필요한 연산만 수행할 수 있어 불필요한 연산을 피할 수 있다는 장점이 있다. +- 내부 방복 방식 + - Stream은 내부 반복을 사용하여 데이터를 처리한다. 이는 내가 명시적으로 루프를 작성하지 않아도 되고, 코드가 간결해지며 더 가독성이 높아지게 된다. +- for문과의 차이점 + - **`for`**문은 명시적으로 데이터 컬렉션을 반복하며 작업을 수행하는 반면, **`Stream`**은 내부적으로 데이터를 반복하고 작업을 수행한다. 이로 인해 코드가 더 간결해지고, 병렬 처리 등의 최적화도 가능하다. + +중간 연산 메서드 + +- **`filter(Predicate predicate)`**: 주어진 조건에 맞는 요소만 필터링한다. +- **`map(Function mapper)`**: 요소를 다른 형태로 변환한다. +- **`sorted()`**: 요소를 정렬한다. + +최종 연산 메서드 + +- **`forEach(Consumer action)`**: 각 요소에 대한 작업을 수행한다. +- **`collect(Collector collector)`**: 요소를 수집하여 새로운 컬렉션을 생성한다. +- **`count()`**: 요소의 개수를 반환한다. + +Stream 예제 + +```java +public static void main(String[] args) { + List fruit = Arrays.asList("apple", "banana", "cherry", "date", "fig"); + + // 중간 연산: 길이가 4 이상인 단어만 선택하고, 대문자로 변환 + List result = words.stream() + .filter(word -> word.length() >= 4) + .map(String::toUpperCase) + .collect(Collectors.toList()); + + // 최종 연산: 결과 출력 + result.forEach(System.out::println); + } +``` + +## Generic 이란? + +- 데이터의 타입을 일반화하는 것. +- 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법 + +**Generic의 장점** + +1. **타입 안정성** : 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다. +2. **코드** **재사용성** : 반환 값에 대한 타입 반환 및 타입 검사를 할 필요가 없다. +3. **표현력** : 제네릭을 사용하면 코드를 더 읽기 쉽고 표현력 있게 만들 수 있다 메서드나 클래스의 이름과 인터페이스가 제네릭 타입 매개변수를 사용하여 더 의미 있는 형태로 작성된다. + +**예제** + +```java +public class GenericClass { + private T value; + + public GenericClass(T value) { + this.value = value; + } + + public T getValue() { + return value; + } +} + +public static void main(String[] args) { + GenericClass stringGeneric = new GenericClass<>("Hello, Generic!"); + String value = stringGeneric.getValue(); // 형변환 필요 없음 + + GenericClass intGeneric = new GenericClass<>(42); + int intValue = intGeneric.getValue(); // 형변환 필요 없음 +} +``` + +## Optional이란? + +- **`null`** 값으로 인한 예외를 방지하고 코드를 더 안전하게 만드는데 도움을 주는 클래스 + +**특징** + +1. 값**의 존재 유무 표현**: 값이 존재할 수도 있고 없을 수도 있는 상황을 명확하게 v표현한다. 따라서 메서드의 반환값으로 사용하면 호출자에게 해당 메서드가 값을 반환하지 않을 수 있다는 사실을 알려준다. +2. **`null` 방지**: **`null`**을 직접 다루지 않아도 된다. **`null`**을 처리하는 부분에서 발생할 수 있는 예외를 방지하고 코드 안정성을 높인다. +3. **메서드 체이닝**: 메서드 체이닝을 통해 여러 연산을 연속적으로 수행할 수 있다. 이로 인해 코드가 더 간결하고 가독성이 높아진다. +4. **명시적 반환**: 메서드의 반환값이 항상 **`Optional`** 형태로 반환되므로, 해당 메서드가 값을 반환하지 않을 수 있다는 사실을 명시적으로 나타낼 수 있다. + +Reference + +https://tecoble.techcourse.co.kr/post/2021-04-26-defensive-copy-vs-unmodifiable/ + +https://jojoldu.tistory.com/412 + +https://hongchangsub.com/mvcpattern/ + +https://futurecreator.github.io/2018/08/26/java-8-streams/ + +https://madplay.github.io/post/java-streams-intermediate-operations \ No newline at end of file From 8e999ee69ea3a82ffacfb8c0df51dda78c351449 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Tue, 17 Oct 2023 01:24:22 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[4=EC=A3=BC=EC=B0=A8]=20=ED=99=8D?= =?UTF-8?q?=EC=A0=95=EC=9A=B0=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 --- .../\355\231\215\354\240\225\354\232\260.md" | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 "week04/\355\231\215\354\240\225\354\232\260.md" diff --git "a/week04/\355\231\215\354\240\225\354\232\260.md" "b/week04/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..207f2e9 --- /dev/null +++ "b/week04/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,173 @@ +# Cow - Week4 + +## 테스트 코드 + +**목적** + +- 테스트 코드는 소프트웨어의 기능, 성능, 안정성 및 신뢰성을 향상시키는 데 도움을 준다. 테스트를 통해 버그를 식별하고 수정할 수 있으며, 코드 변경이 기존 기능에 미치는 영향을 평가할 수 있다. +- 테스트 코드를 작성하면 소프트웨어에서 발생하는 문제를 식별하고 디버깅하는 데 도움을 준다. 문제가 발생할 때, 테스트를 실행하여 문제의 원인을 파악하고 수정할 수 있다. +- 소프트웨어는 시간이 지남에 따라 변경되는데, 테스트 코드는 이러한 변경을 안정적으로 관리하는 데 도움을 준다. 새로운 코드를 추가하거나 기존 코드를 수정할 때 테스트 코드를 실행하여 변경이 예기치 않은 부작용을 유발하는지 확인할 수 있다. +- 테스트 코드는 코드의 사용법과 기대 동작을 문서화하는 역할을 한다. 테스트 케이스는 소프트웨어의 예상 동작을 명확하게 정의하고, 이를 참조할 수 있는 문서로 사용할 수 있다. +- 테스트 코드는 여러 개발자가 협업하는 환경에서 특히 유용하다. 테스트 케이스를 공유하면 다른 팀원이 코드를 이해하고 변경 사항을 안전하게 진행할 수 있다. + +## 단위 테스트 + +- 단위 **테스트는 **응용 **프로그램에서 **테스트 **가능한 **가장 **작은 **소프트웨어를 **실행하여 **예상대로 **동작하는지 **확인하는 **테스트이다*.* + +******************특징과 목적****************** + +- 단위 테스트는 개별 단위를 독립적으로 테스트한다. 이는 테스트 케이스 간에 상호 작용이 없어야 하며, 다른 단위 테스트의 실패로 인해 현재 테스트 케이스가 실패하지 않아야 한다. +- 단위 테스트는 자동화되어야 한다. 개발자가 코드를 변경할 때마다 테스트를 수동으로 실행할 필요 없이 자동화된 테스트 스위트를 실행하여 결과를 얻을 수 있어야 한다. +- 단위 테스트는 주로 개발자 관점에서 코드의 기능과 동작을 확인하는 데 사용된다. 따라서 테스트는 코드의 각 부분에 대한 기대 동작을 정의하고 이를 확인할 수 있다. +- 단위 테스트는 빠르게 실행되어야 합니다. 코드 변경 사항을 신속하게 검증할 수 있어야 하며, 디버깅과 문제 해결을 단순화한다. +- 단위 테스트는 일반적으로 클래스 또는 메소드 수준으로 정해진다. + +## JUnit5, AssertJ + +- 자바 언어를 기반으로 한 테스트 프레임워크와 라이브러리 +- 소프트웨어 개발에서 단위 테스트 및 테스트 주도 개발(Test-Driven Development, TDD)를 지원하고 테스트 작성과 검증을 향상시키는데 사용된다. + +1. **JUnit5** + - JUnit 5는 플랫폼 아키텍처를 도입하여 다양한 테스트 실행 엔진을 지원한다. 즉, 다양한 환경에서 JUnit 테스트를 실행하는 유연성을 제공한다. + - Jupiter API의 주요 애노테이션에는 **`@Test`**, **`@BeforeEach`**, **`@AfterEach`**, **`@BeforeAll`**, **`@AfterAll`**, **`@DisplayName`**, **`@Nested`**, **`@ParameterizedTest`** 이 있다. + - JUnit 5는 확장 기능을 통해 사용자 정의 확장을 추가하고 테스트 라이프사이클을 커스터마이징하는 데 사용할 수 있다. 이를 통해 테스트 환경을 조정할 수 있다. + - JUnit 5는 매개변수화 테스트를 지원한다. 이를 통해 동일한 테스트 메서드를 다양한 입력 값과 예상 결과를 사용하여 여러 번 실행할 수 있다. + - **`@EnabledIf`** 및 **`@DisabledIf`**과 같은 애노테이션을 사용하여 조건부 테스트 실행을 구현할 수 있다. + +1. **AssertJ** + - AssertJ는 다양한 단언 메서드를 제공하여 다양한 유형의 데이터를 검증할 수 있다. + - AssertJ는 커스텀 단언을 작성하고 자체 도메인 특정 언어를 만들 수 있는 확장성을 제공한다. 이를 통해 테스트 코드를 도메인에 맞게 구성할 수 있다. + - 단언 구문은 빌더 패턴을 사용하여 연결되며, 자연스럽게 읽히는 문장을 생성한다. 이러한 구문은 테스트 결과를 이해하기 쉽게 만든다. + - AssertJ는 자료 구조를 검증하는 메서드를 제공한다. 예를 들어, 리스트의 크기를 확인하거나 맵에서 특정 키의 값과 일치하는지 확인할 수 있다. + - AssertJ는 실패한 테스트에 대한 유용한 오류 메시지를 생성하므로, 어떤 부분이 실패했는지 명확하게 파악할 수 있다. + +## BDD (****Behavior Driven Development)**** + +- 행동 주도 개발 +- 사용자의 행위까지 생각하고 테스트하며 개발한다. +- **테스트 코드의 목적 :** 서비스 유저 시나리오의 검증 +- **테스트 코드의 설계 중심 :** 서비스 사용자 행위 중심 +- **테스트 코드 설계 재료 :** 서비스 기획서 +- **적합한 프로젝트 :** 서비스 프로젝트 +- **장점 :** 설계 단계에서 누락된 기획을 확인할 수 있다. + +```java +Given + - 사용자가 처음에 페이지에 접속하고 나면, display 값이 0이다. +When + - 유저는 2를 클릭하고, 디스플레이에 2가 보여진다. + - 유저는 +를 클릭한다. + - 유저는 4를 클릭하고, 디스플레이에 4가 보여진다. + - 유저는 =를 클릭한다. +Then + - 디스플레이 값은 6이 된다. +``` + +## Private Method Test + +1. ****Java Reflection API를 이용한 메소드 호출**** + - Java에서 제공하는 리플렉션 API를 이용하는 방법. + - 리플렉션을 이용하면 정적으로 고정된 메소드의 코드를 메타정보로 추상화된 Method를 얻어낼 수 있으며 직접 호출 또한 가능하다. + +```java +@ExtendWith(MockitoExtension.class) +class PrivateTestClassTest { + + @InjectMocks + private PrivateTestClass target; + + @Test + void isPredifined가True_ReflectionAPI() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + // given + String name = "MangKyu"; + Method method = target.getClass().getDeclaredMethod("isPredefined", String.class); + method.setAccessible(true); + + // when + boolean result = (boolean)method.invoke(target, name); + + // then + assertThat(result).isTrue(); + } + +} +``` + +1. ****Spring의 ReflectionTestUtils를 이용한 메소드 호출**** + + ```java + @ExtendWith(MockitoExtension.class) + class PrivateTestClassTest { + + @InjectMocks + private PrivateTestClass target; + + @Test + void isPredifined가True_ReflectionTestUtils() { + // given + String name = "MangKyu"; + + // when + boolean result = ReflectionTestUtils.invokeMethod(target, "isPredefined", name); + + // then + assertThat(result).isTrue(); + } + + } + ``` + + **private method test를 지양해야 하는 이유** + + 1. **구현 세부 사항에 의존성**: private 메서드를 직접 테스트하려면 해당 메서드의 구현 세부 사항에 의존하게 됩니다. 이는 코드 변경 시 테스트 케이스의 실패 가능성을 높이고, 코드를 리팩터링할 때 불안정성을 초래할 수 있다. + 2. **테스트 대상의 변경에 민감함**: private 메서드를 직접 테스트하는 경우, private 메서드의 동작 변경이 테스트 코드에 영향을 미치며, 이로 인해 불필요한 테스트 코드의 수정이 필요할 수 있다. + 3. **테스트 케이스 가독성과 유지 관리 문제**: private 메서드를 테스트하려면 별도의 테스트 케이스를 작성하거나 리플렉션과 같은 복잡한 메커니즘을 사용해야 한다. 이는 테스트 코드의 가독성을 저하시키고, 테스트 스위트를 관리하기 어렵게 만든다. + 4. **목표 중심 테스팅**: 테스트 코드의 목표는 보통 public API를 통해 소프트웨어의 외부 동작을 검증하는 것이다. private 메서드는 일반적으로 내부 구현 세부 사항을 다루기 때문에 외부 사용자 관점에서 테스트해야한다. + +## @ParameterizedTest + +- **`@ParameterizedTest`**는 JUnit 5 테스트 프레임워크에서 제공하는 애노테이션 중 하나로, 매개변수화된 테스트를 생성하는데 사용된다. 이를 통해 동일한 테스트 메서드를 여러 다른 입력 값과 예상 결과를 사용하여 여러 번 실행할 수 있다. + +```java +int multiplyBy2(int number) { + return number * 2; +} + +@ParameterizedTest +@DisplayName("1 곱하기 2는 2") +void multiply1By2() { + assertThat(multiplyBy2(1)).isEqualTo(2); +} + +@ParameterizedTest +@DisplayName("2 곱하기 2는 4") +void multiply2By2() { + assertThat(multiplyBy2(2)).isEqualTo(4); +} +``` + +## DAO (Data Access Object) + +- 데이터베이스의 data에 접근하기 위한 객체 +- **DataBase에 접근 하기 위한 로직 & 비지니스 로직**을 분리하기 위해 사용한다. + +## DTO + +- • **`DTO(Data Transfer Object)`** 는 계층 간 데이터 교환을 하기 위해 사용하는 객체로, DTO는 로직을 가지지 않는 순수한 데이터 객체(getter & setter 만 가진 클래스). + +**유저가 입력한 데이터가 DB까지 전송되는 과정** + +- 유저가 자신의 브라우저에서 데이터를 입력하여 form에 있는 데이터를 DTO에 넣어서 전송합니다. +- 해당 DTO를 받은 서버가 DAO를 이용하여 데이터베이스로 데이터를 집어넣습니다. + +나의 궁금증 → 유저가 보낸 요청은 보통 파라미터, JSON Body로 전달되는데 그렇다면 DTO는 String같은 변수 값을 저장하고 있을텐데 View에게로 Server는 어떤 형식의 데이터를 전달할까? + +⇒ 객체를 JSON 형태로 파싱하여 전달. (이때, DTO에는 Getter가 있어야 함) + +## VO (Value Object) + +- **`VO(Value Object)`** 값 오브젝트로써 값을 위해 쓰인다. + +**DTO와의 차이점** + +- DTO는 setter을 가질 수 있어 값이 변할 수 있지만 VO는 값이 변해서는 안되고 값을 옮기는 Object로서의 역할이다. \ No newline at end of file From cb9bec2cfc1d4b43150d7f635ccba81da65a7ab4 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Tue, 7 Nov 2023 19:47:19 +0900 Subject: [PATCH 08/13] =?UTF-8?q?Update=20and=20rename=207=EC=A3=BC?= =?UTF-8?q?=EC=B0=A8.md=20to=20=ED=99=8D=EC=A0=95=EC=9A=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [7주차] 홍정우 학습 PR 제출합니다. --- "week07/7\354\243\274\354\260\250.md" | 24 -- .../\355\231\215\354\240\225\354\232\260.md" | 364 ++++++++++++++++++ 2 files changed, 364 insertions(+), 24 deletions(-) delete mode 100644 "week07/7\354\243\274\354\260\250.md" create mode 100644 "week07/\355\231\215\354\240\225\354\232\260.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/\355\231\215\354\240\225\354\232\260.md" "b/week07/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..ad946c4 --- /dev/null +++ "b/week07/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,364 @@ +# 7주차 학습 PR + +## 싱글톤 패턴이란? + +### Singleton 패턴 + +- 객체의 인스턴스가 오직 1 개만 생성되는 패턴을 의미한다. + +예제 코드 + +```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"); + } +} +``` + +### 싱글톤 패턴을 사용하는 이유 + +1. **메모리 측면** : 최소 한 번의 new 연산자를 통해서 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비를 방지할 수 있다. +2. **데이터 공유** : 싱글톤 인스턴스는 전역으로 사용되는 인스턴스이기 때문에 다른 클래스의 인스턴스들이 접근하여 사용할 수 있다. 이때, 동시성 문제에 대해 유의할 것 +3. **도메인 관점** : 인스턴스가 한 개만 존재하는 것을 보증 + +### 싱글톤 패턴의 문제점 + +1. **싱글톤 패턴을 구현하는 코드 자체가 많이 필요하다** : 멀티스레딩 환경에서 발생할 수 있는 동시성 문제 해결을 위해 synronized(스레드 간 동기화를 시켜 data의 thread-safe를 가능케하는 키워드) 키워드를 사용해야한다. +2. **테스트하기 어렵다** : 싱글톤 인스턴스는 자원을 공유하고 있기 때문에 테스트가 결정적으로 격리된 환경에서 수행 되려면 매번 인스턴스의 상태를 초기화 시켜주어야 한다. +3. **의존 관계상 클라이언트가 구체 클래스에 의존하게 된다** : new 키워드를 직접 사용하여 클래스 안에서 객체를 생성하고 있으므로, 이는 SOLID 원칙 중 DIP를 위반하고 또, OCP 원칙 또한 위반할 가능성이 높다. + +## 싱글톤 컨테이너 + +### 싱글톤 컨테이너 + +- 소프트웨어 디자인 패턴 중 하나로 “싱글톤”을 구현하기 위한 메커니즘이다. +- 특정 클래스의 인스턴스가 오직 하나만 존재하도록 보장하는 패턴으로, 여러 부분에서 동일한 객체 인스턴스를 공유하고자 할 때 사용된다. + +### 싱글톤 컨테이너의 특징 + +1. **단일 인스턴스** : 싱글톤 컨테이너는 특정 클래스의 인스턴스를 오직 하나만 생성하고 유지하기에 여러 부분에서 동일한 인스턴스에 접근할 수 있다. +2. **전역 접근** : 어디에서든 싱글톤 인스턴스에 접근할 수 있으므로 전역적인 상태나 기능을 공유할 수 있다. +3. **지연 초기화** : 인스턴스를 처음으로 요청할 때 생성하거나 초기화한다. 이를 통해 자원을 절약할 수 있고 애플리케이션 시작 시 모든 싱글톤을 미리 생성하지 않을 수 있다. +4. **스레드 안전성** : 여러 스레드에서 동시에 접근해도 안전하도록 구현될 수 있다. + +**구현 방법 : 의존성 주입 컨테이너와 함께 사용하는 것 ( Spring )** + +## POJO 프로그래밍 + +### POJO + +- Plain Old Java Object. 즉, Java로 생성하는 순수한 객체 +- IoC/DI, AOP, PSA를 통해서 달성할 수 있다. +- 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고, 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 의미한다. + +### 규칙 + +1. **Java나 Java의 스펙에 정의된 것 이외에는 다른 기술이나 규약에 얽매이지 않아야 한다.** + 1. 예제 코드 + + ```java + public class User { + private String userName; + private String id; + private String password; + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + } + ``` + + +1. **특정 환경에 종속적이지 않아야 한다.** + 1. 특정한 프레임워크에서만 동작이 가능하면 안된다는 의미 + 2. POJO는 환경에 독립적이어야 한다. 특히, 비즈니스 로직을 담고 있는 POJO 클래스는 웹 기반의 환경 정보나 웹 기술을 담고 있는 클래스 또는 인터페이스를 사용하면 안된다. + +### POJO 프로그래밍이 필요한 이유 + +- 특정 환경이나 기술에 종속적이지 않으면 재사용이 가능하고, 확장 가능한 유연한 코드를 작성할 수 있다. +- 저수준 레벨의 기술과 환경에 종속적인 코드를 제거하여 코드가 간결해지며 디버깅도 쉬워진다. +- 특정 기술이나 환경에 종속적이지 않기에 테스트가 단순해진다. +- **객체지향적인 설계를 제한없이 적용할 수 있다.** + +## Spring의 사용 이유, 장점이나 특징 + +- 스프링은 자바를 기반으로 하는 프레임워크이다. Spring을 사용하는 이유를 알기 위해서는 Spring의 특징을 알아야 한다. + +### Spring 특징 + +1. **POJO 기반의 구성 (Plain Old Java Object)** + - 특정한 라이브러리나 컨테이너의 기술, 개발 환경에 종속적이지 않음을 의미한다. + - 위에서 알아본 POJO의 특징으로 인해 자유롭게 객체지향적 설계를 구현할 수 있다. 즉, 개발자는 가장 일반적인 형태로 코드를 작성하고 실행할 수 있다. → 높은 생산성, 유연한 테스트 +2. **DI (Dependecy Injection, 의존성 주입)을 통한 객체 관계 구성** + - 의존성 주입은 제어의 역전이 일어나는 것을 전제로 스프링 내부의 객체들 간의 관계를 관리할 때 사용한다. + - 의존성 주입은 특정 개체에 필요한 객체를 외부에서 결정하여 연결시키는 것을 말한다. 자바에서는 인터페이스를 사용하여 의존적인 관계를 처리. + - 메소드나 객체(bean)의 호출 작업은 제어의 역전(IoC)을 통해 외부에서 이루어진다. (외부란 객체를 기준으로 봤을 때의 외부) + - 제어의 역행을 전제 조건으로 의존성 주입이 일어난다. + - 의존성을 가진 객체에 대해 스프링에서 의존성 주입이 발생하도록 함 + - 의존성 주입 특징으로 인해 개발자가 POJO 개발이 가능 + + +********컴포넌트 스캔과 자동 의존관계 설정******** + +- 스프링에서 컴포넌트 스캔(Bean Scanning)과 자동 의존관계 설정은 스프링 컨테이너가 자동으로 빈(Bean)을 검색하고 관리하며, 빈 간의 의존성을 자동으로 설정하는 기능이다. +1. **컴포넌트 스캔** + - **`@Component`**와 관련 어노테이션을 사용하여 클래스를 스프링 빈으로 등록한다. + - **`@Component`** 어노테이션은 스프링 컨테이너에 의해 검색되고 빈으로 등록된다. 다른 관련 어노테이션으로는 **`@Service`**, **`@Repository`**, **`@Controller`** 이 있음 + + **예제 코드** + + ```java + import org.springframework.stereotype.Service; + + @Service + public class UserService { + // 비즈니스 로직 + } + ``` + +2. **자동 의존관계 설정** + - 스프링은 컴포넌트 스캔을 사용하여 빈을 찾아 놓고, 자동 의존 관계를 설정한다. 이를 위해 **`@Autowired`** 어노테이션을 사용하여 필요한 의존성을 주입한다. + + **예제 코드** + + ```java + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + + @Controller + public class UserController { + private final UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + // 컨트롤러 로직 + } + ``` + + +**의존성 주입의 방법** + +1. 필드 주입 +2. setter 주입 +3. **생성자 주입 (권장)** +4. 메서드 주입 + +**생성자 주입 권장 이유** + +1. **명시성 및 명확성**: 생성자 주입은 의존성이 필수적이라는 것을 명확하게 나타내므로, 클래스의 사용자에게 해당 의존성이 반드시 필요하다는 정보를 전달한다. 이는 코드를 읽는 사람에게 명확한 API를 제공하며, 코드의 이해와 유지보수를 쉽게 만든다. +2. **불변성과 불변성 보장**: 생성자를 통한 의존성 주입은 한 번 설정되면 불변하며 변경 불가능하도록 만들 수 있다. 이는 클래스의 상태를 불변하게 유지하고 예측 가능한 동작을 제공. +3. **테스트 용이성**: 생성자 주입은 의존성을 주입하기 쉽게 만들어 테스트하기 용이하다. 의존성을 쉽게 대체하거나 모의 객체(Mock)를 주입하여 단위 테스트를 수행할 수 있다. +4. **순환 의존성 방지**: 생성자 주입을 사용하면 순환 의존성(서로 의존하는 빈들의 무한 루프)을 방지할 수 있다. 컨테이너는 생성자를 통해 의존성을 주입하므로 순환 의존성을 일찍 감지하고 예외를 발생시킬 수 있다. +5. **불필요한 setter 메서드 없음**: 생성자 주입을 사용하면 불필요한 setter 메서드가 없어지므로, 클래스의 상태가 변동 가능한 경우에도 의존성이 한 번 주입되면 변경할 수 없다는 장점이 있다. +6. **안정성 및 일관성**: 생성자 주입은 객체가 생성될 때 모든 의존성이 완전하게 주입되도록 보장한다. 이로 인해 객체가 생성된 후에 NullPointerException과 같은 예외를 방지하며 안정성을 높일 수 있다. + +**예제 코드** + +```java +import org.springframework.stereotype.Service; + +@Service +public class UserService { + private final UserRepository userRepository; + + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public String getUserInfo() { + // 사용자 정보를 조회하는 로직 + return "User Info from UserService"; + } +} +``` + +```java +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +@Controller +public class UserController { + private final UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + public String displayUserInfo() { + String userInfo = userService.getUserInfo(); + return "User Info: " + userInfo; + } +} +``` + +```java +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.example") +public class AppConfig { + // 다른 설정 및 빈 정의 +} +``` + +위 설정 클래스에서 "com.example" 패키지에서 스캔하여 **`UserService`**와 **`UserController`**를 빈으로 관리. + +이렇게 하면 스프링은 생성자 주입을 통해 의존성을 자동으로 주입하고, **`UserController`**를 통해 **`UserService`**에 액세스할 수 있다. + +1. **************AOP (관심지향 프로그래밍) 지원************** + - 로깅, 보안, 트랜잭션 관리 등과 같은 공통적인 관심사를 모듈화 하여 코드 중복을 줄이고 유지 보수성을 향상하는데 도움을 준다. + - 메소드나 객체의 기능을 핵심 관심사(Core Concern - 각 객체가 가져야 할 본래의 기능)와 공통 관심사(Cross-cutting Concern - 여러 객체에서 공통적으로 사용되는 코드)로 나누어 프로그래밍하는 것 + - 여러 개의 클래스에서 반복해서 사용하는 코드가 있다면 해당 코드를 모듈화하여 공통 관심사로 분리 + - **AOP 용어**: + - **Aspect(관점)**: AOP에서 모듈화된 관심사의 단위이다. 각 관점은 애플리케이션에서 특정한 기능(로깅, 보안 등)을 나타내며, 관점은 포인트컷과 어드바이스를 포함. + - **Pointcut(포인트컷)**: 관심사를 적용할 지점 또는 메서드를 선택하는 규칙. + - **Advice(어드바이스)**: 관심사를 언제 실행할지 정의한 코드 조각이다. + - **Join Point(조인 포인트)**: 어드바이스가 실행될 수 있는 특정 지점 또는 메서드 호출. + - **Weaving(위빙)**: 관점(Aspect)을 실제 애플리케이션 코드에 적용하는 과정 + - 주요 어노테이션 + - **@Aspect** : 해당 클래스를 Ascpect로 사용하겠다는 것을 명시 + - **@Before** : 해당 메서드가 실행되기 전에 Advice를 실행 + - **@AfterReturning** : 대상 메서드가 정상적으로 실행되고 반환된 후에 Advice를 실행 + - **@AfterThrowing** : 대상 메서드에서 예외가 발생했을 때 Advice를 실행 + - **@After** : 대상 메서드가 실행된 후에 Advice를 실행 + - **@Around** : 대상 메서드 실행 전, 후 또는 예외 발생 시에 Advice를 실행 + + 1. **편리한 MVC 구조** + 2. **WAS에 독립적인 개발 환경** + +**************************이러한 스프링의 특징으로 인해 프로그래머로 하여금 편리하게 개발할 수 있도록 한다. 즉, 비즈니스 로직에만 집중할 수 있게 해주는 것이다. 프로그래머는 해당 상황을 최적화시키기 위한 비즈니스 로직과 관련한 변수와 메소드를 개발하는데 집중할 수 있는 것이다.************************** + +## Spring 어노테이션 + +1. **@Component**: 클래스를 스프링 빈으로 등록. +2. **@Controller**: 웹 컨트롤러 클래스를 정의하며, 스프링 MVC에서 사용. +3. **@Service**: 비즈니스 로직을 수행하는 서비스 클래스를 정의하며, 스프링에서 서비스 빈으로 등록. +4. **@Repository**: 데이터 액세스 계층의 리포지토리 클래스를 정의하며, 스프링 데이터 액세스를 위해 사용된다. +5. **@Autowired**: 의존성 주입(Dependency Injection)을 수행할 때 사용하는 어노테이션으로, 생성자, 메서드, 또는 필드에 적용할 수 있다. +6. **@Configuration**: 스프링 빈 구성 클래스로, 스프링 애플리케이션 컨텍스트를 설정하는 클래스를 나타낸다. +7. **@Bean**: 메서드가 스프링 빈을 반환함을 나타내며, 스프링 컨테이너에서 해당 빈을 관리한다. +8. **@RequestMapping**: 스프링 MVC 컨트롤러에서 HTTP 요청과 메서드를 매핑하는데 사용하는 어노테이션이다. +9. **@Value**: 프로퍼티 값을 주입하거나 외부 설정 파일에서 값을 읽을 때 사용되는 어노테이션. +10. **@Scope**: 빈의 범위(싱글톤, 프로토타입 등)를 설정하는 어노테이션. +11. **@Qualifier**: 여러 개의 빈 중에서 어떤 빈을 주입할지 지정할 때 사용되는 어노테이션. +12. **@PostConstruct**: 빈이 초기화된 후에 실행해야 하는 메서드를 정의할 때 사용하는 어노테이션. +13. **@PreDestroy**: 빈이 파괴되기 전에 실행해야 하는 메서드를 정의할 때 사용하는 어노테이션. +14. **@Transactional**: 트랜잭션 관리를 위해 사용되는 어노테이션으로, 메서드나 클래스에 적용하여 트랜잭션 경계를 설정. +15. **@Aspect** : 해당 클래스를 Ascpect로 사용하겠다는 것을 명시 +16. **@Before** : 해당 메서드가 실행되기 전에 Advice를 실행 +17. **@AfterReturning** : 대상 메서드가 정상적으로 실행되고 반환된 후에 Advice를 실행 +18. **@AfterThrowing** : 대상 메서드에서 예외가 발생했을 때 Advice를 실행 +19. **@After** : 대상 메서드가 실행된 후에 Advice를 실행 +20. **@Around** : 대상 메서드 실행 전, 후 또는 예외 발생 시에 Advice를 실행 + +## Controller-Service-Repository + +Controller, Service, 그리고 Repository는 스프링 프레임워크에서 사용되는 주요 구성 요소입니다. 이러한 구성 요소는 스프링 애플리케이션을 모듈화하고 더 관리하기 쉽게 만드는 데 사용된다. + +1. **Controller**: + - Controller는 스프링 MVC (Model-View-Controller) 아키텍처에서 웹 요청을 처리하는 역할을 한다. + - 클라이언트로부터 HTTP 요청을 받아서 해당 요청을 처리하고, 응답을 생성하며 웹 페이지 또는 데이터를 클라이언트에 반환한다. + - `@Controller` 어노테이션을 사용하여 스프링에서 컨트롤러 클래스로 인식하도록 표시. + - 주로 웹 애플리케이션의 비즈니스 로직을 처리하는 곳으로, 요청에 따른 데이터를 서비스 레이어에서 가져와서 클라이언트에게 표시하는 역할을 한다. + + ```java + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Controller; + import org.springframework.web.bind.annotation.*; + + import java.util.List; + + @Controller + @RequestMapping("/users") + public class UserController { + private UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + @PostMapping + public void addUser(@RequestBody User user) { + userService.addUser(user); + } + + @GetMapping + public List getAllUsers() { + return userService.getAllUsers(); + } + } + ``` + +2. **Service**: + - Service는 비즈니스 로직을 구현하고 제공하는 컴포넌트로, 주로 비즈니스 로직을 처리하고 데이터 저장소와 상호 작용한다. + - 서비스 계층은 Controller와 Repository 사이에서 중간 계층 역할을 한다. + - `@Service` 어노테이션을 사용하여 스프링에서 서비스 클래스로 인식하도록 표시. + - 여러 서비스 메서드가 여러 번 호출되어야 하는 비즈니스 로직을 포함하며, 다양한 서비스 간의 통합을 관리. + + ```java + import org.springframework.beans.factory.annotation.Autowired; + import org.springframework.stereotype.Service; + import java.util.List; + + @Service + public class UserService { + private UserRepository userRepository; + + @Autowired + public UserService(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public void addUser(User user) { + userRepository.addUser(user); + } + + public List getAllUsers() { + return userRepository.getAllUsers(); + } + } + ``` + +3. **Repository**: + - Repository는 데이터 액세스 계층을 담당하며, 데이터베이스와의 상호 작용 및 데이터 저장 및 검색을 수행하는 역할을 한다. + - 주로 데이터베이스와의 상호 작용을 추상화하고 데이터 액세스 코드를 구현. + - `@Repository` 어노테이션을 사용하여 스프링에서 리포지토리 클래스로 인식하도록 표시. + - 데이터베이스 테이블과 객체 간의 매핑 및 데이터 액세스 메서드를 포함한다. From c8411d2e5b13c21457161433f28c4a5e5099b910 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Tue, 14 Nov 2023 23:03:19 +0900 Subject: [PATCH 09/13] =?UTF-8?q?docs=20:=20md=20=EC=9E=91=EC=84=B1?= 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 -- .../\355\231\215\354\240\225\354\232\260.md" | 169 ++++++++++++++++++ 2 files changed, 169 insertions(+), 10 deletions(-) delete mode 100644 "week08/8\354\243\274\354\260\250.md" create mode 100644 "week08/\355\231\215\354\240\225\354\232\260.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/\355\231\215\354\240\225\354\232\260.md" "b/week08/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..10ef3fe --- /dev/null +++ "b/week08/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,169 @@ +# 8주차 학습 PR +# Cow - Week8 + +--- + +## HTTP 요청이 들어왔을 때 요청을 받고 응답하기까지의 전 과정 + +--- + +### HTTP + +- HTTP(하이퍼텍스트 전송 프로토콜) 요청은 웹 브러우저 또는 다른 클라이언트가 웹 서버에게 보내는 메시지이다. + +### HTTP 메서드 + +- **GET** : 리소스를 요청할 때 사용되는 메서드. 주로 정보를 요청할 때 사용되며 URL에 데이터가 포함될 수 있지만 일반적으로 쿼리 매개변수를 사용 +- **POST** : 서버에 데이터를 제출할 때 사용되는 메서드. 주로 폼 데이터를 전송할 때 사용되며, 데이터는 요청 본문에 포함된다. +- **PUT** : 서버에 새로운 리소르를 생성하거나 업데이트할 때 사용되는 메서드. 요청 본문에 업데이트된 데이터를 포함한다. +- **DELETE** : 서버에서 리소스를 삭제할 때 사용되는 메서드 + +### URL (Uniform Resource Locator) + +- 요청의 대상이 되는 리소스의 위치를 지정한다. + +### 헤더 (Headers) + +- 요청에 대한 여러가지의 속성을 정의 + +### 요청 본문 (Request Body) + +- POST 또는 PUT과 같은 메서드에서 사용되며, 서버로 전송할 데이터를 포함한다. +- 주로 폼 데이터나 JSON 형식의 데이터가 여기에 포함된다. + +## HTTP Request → HTTP Response까지의 과정 + +1. **URL 입력** + - 목적지의 주소로 이해하면 편하다. + - 요청의 대상이 되는 리소스의 위치이다. +2. **DNS (Domain Name System)** + - IP 주소를 외우는 것은 어렵기에 Domain Name을 사용하는 것 + - 작동 원리 + 1. 웹 브라우저에 URL입력 + 2. Local DNS에게 Hostname에 대한 IP 주소 요청 + 3. Local DNS에 IP 주소가 없다면 다른 DNS Nave Server 정보를 응답 + 4. Root DNS 서버에게 Hostname에 대한 IP 주소를 요청 + 5. Root DNS 서버는 .com 도메인을 관리하는 TLD Nave Server 정보 응답 + 6. TLD에게 Hostname에 대한 IP 주소를 요청 + 7. TLD는 Hostname을 관리하는 DNS Server 정보 응답 + 8. 해당 URL의 도메인을 관리하는 DNS Server에게 Hostname에 대한 IP 주소를 요청 + 9. DNS Server는 Hostname에 대한 IP 주소 응답 + 10. Local DNS Server는 응답으로 받은 Hostname에 대한 IP 주소를 캐싱하고 IP 주소 정보로 HTTP 요청 + + 스크린샷 2023-11-14 오후 10 53 07 + +3. **HTTP 요청** + - URL을 입력함으로서 Domain Name에 요청했지만, 실제로는 DNS 서버를 통해 알아낸 IP주소와 입력한 URL 정보가 함께 요청으로 전달된다. + - URL 정보와 전달받은 IP 주소는 HTTP Protocal을 사용하여 HTTP Request Message 생성 + + 스크린샷 2023-11-14 오후 10 53 15 + + - HTTP 요청 Message는 TCP Protocol을 사용하여 인터넷을 거쳐 해당 IP 주소의 컴퓨터 Web Server로 전송 + - TCP Protocol : 인터넷에서 데이터를 안정적으로 전송하기 위한 프로토콜 중 하나. 데이터를 패킷으로 나누어 전송하고, 수신 측에서 패킷을 재조립하여 응용 프로그램에 전달하는 역할. +4. **Internet** + - 인터넷은 내 컴퓨터로 시작해 Router - Modem - ISP - Modem - Router의 경로를 거쳐 해당 IP 주소의 컴퓨터 Web Server로 도착하게 된다. + - Router(공유기) : 컴퓨터 네트워크 간에 데이터 패킷을 전송하는 네트워크 장치 + - Modem : 디지털 정보 전달을 위해 신호를 변조하여 송신하고 수신 측에서 원래의 신호로 복구하기 위해 복조하는 장치 + - ISP : 개인이나 기업체에게 인터넷 접속 서비스, 웹사이트 구축 및 웹호스팅 서비스를 제공하는 인터넷 서비스 제공 업체 +5. **Web Server** + - 목적 IP 컴퓨터의 Web Server에 도착 + - Web Server는 요청 URL 정보를 확인하고, 필요한 요청이 여기서 처리되면 돌려보낸다. + - **동작** + - Web Server는 HTTP 요청을 받고 바로 컨텐츠를 응답하거나, WAS에 요청을 전달 + - WAS에 요청이 전달되고, WAS에서 처리된 요청이 있다면 해당 컨텐츠를 응답 + - **기능** + - HTTP 요청이 들어오면 요청을 서비스하는 담당 + - 정적 컨텐츠 + - WAS를 거치지 않고 바로 컨텐츠 제공 + - 동적 컨텐츠 + - 동적 컨텐츠 제공을 위해 WAS에 요청 전달 +6. WAS +- **Web Server 에서 처리할 수 없는 요청은 WAS로 온다.** + +**동작** + +- Web Server 로부터 받은 요청과 관련된 Servlet을 메모리에 로딩 +- web.xml 을 참조하여 해당 Servlet 에 대한 Thread 생성 (Thread Pool 활용) +- HttpServletRequest, HttpServletResponse 객체를 생성하여 생성된 Servlet에 전달 + - Thread는 Servlet의 service() 호출 + - service() 는 요청에 맞는 doGet() or doPost() 호출 +- doGet() or doPost() 는 인자에 맞게 생성된 적절한 동적 컨텐츠를 Response 객체에 담아 WAS에 전달 +- WAS는 Response 객체를 HttpResponse 형태로 바꾸어 Web Server에 전달 +- 생성된 Thread를 종료하고, HttpServletRequest, HttpServletResponse 객체 제거 + +**Servlet란?** + +- 자바 언어를 기반으로 하는 서버 사이드 프로그래밍을 위한 표준 인터페이스 +- 동적인 웹 페이지를 생성하고 클라이언트 요청에 대한 응답을 처리하는 자바 클래스 +1. **Servlet Filter** + 1. **요청 및 응답 변형:** 필터는 클라이언트로부터의 HTTP 요청이나 서버에서 클라이언트로의 HTTP 응답을 가로채어, 이를 변형하거나 수정할 수 있다. 예를 들어, 요청에 대한 로깅, 요청 데이터의 압축, 인코딩의 변경, 헤더 조작 등을 수행할 수 있다. + 2. **인증 및 권한 부여:** 필터는 요청이나 응답을 가로채어 사용자의 인증 상태를 확인하고, 특정 리소스에 대한 권한을 확인하는 등의 보안 관련 작업을 수행할 수 있다. + 3. **로깅 및 감시:** 필터는 요청과 응답 데이터에 대한 로깅 작업을 수행하거나, 특정 동작이나 성능에 관한 감시를 수행할 수 있다. + 4. **캐싱 및 압축:** 필터는 요청이나 응답에 대한 캐싱, 데이터 압축, 쿠키의 추가 또는 제거 등과 같은 성능 최적화 작업을 수행할 수 있다. + + ```java + import javax.servlet.*; + import java.io.IOException; + + public class MyFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + // 초기화 작업 수행 + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + // 요청 전/후에 수행할 작업 + // 예: 요청 로깅, 요청 데이터 변형 등 + + // 다음 필터로 체인을 전달하거나, 필터 체인이 마지막인 경우 서블릿 또는 JSP로 요청 전달 + chain.doFilter(request, response); + + // 응답 전/후에 수행할 작업 + // 예: 응답 로깅, 응답 데이터 변형 등 + } + + @Override + public void destroy() { + // 필터 소멸 시 수행할 작업 + } + } + ``` + +2. **Dispatcher Servlet** + - Spring 프레임워크에서 클라이언트의 모든 요청을 처리하는 중앙 컨트롤러 역할을 하는 Servlet + - MVC 웹 애플리케이션에서 HTTP 요청을 처리하고, 적절한 컨트롤러에게 요청을 전달하여 처리 결과를 생성하고 응답을 생성하는 역할 + - 특징 + 1. **HTTP 요청의 중앙 집중 처리:** Dispatcher Servlet은 모든 클라이언트의 HTTP 요청을 중앙에서 관리하고, 이를 적절한 핸들러에게 전달. 이를 통해 애플리케이션의 구조가 단순화되고 유지보수성이 향상된다. + 2. **URL 패턴 기반의 핸들러 매핑:** Dispatcher Servlet은 URL 패턴을 기반으로 어떤 핸들러(컨트롤러)가 요청을 처리할지 결정. Spring MVC에서는 **`@RequestMapping`** 어노테이션 등을 사용하여 URL 패턴과 핸들러를 매핑한다. + 3. **뷰 리졸버와의 연동:** Dispatcher Servlet은 핸들러가 반환하는 뷰의 이름을 실제 뷰로 변환하는 뷰 리졸버와 연동하여 최종적으로 클라이언트에게 전달될 뷰를 결정한다 + 4. **Handler Interceptor 지원:** Dispatcher Servlet은 Handler Interceptor를 통해 컨트롤러 호출 전/후에 추가 작업을 수행할 수 있다. 예를 들어, 인증, 로깅, 트랜잭션 관리 등의 작업을 수행할 수 있다. + 5. **Spring IoC 컨테이너와의 통합:** Dispatcher Servlet은 Spring IoC 컨테이너와 연동되어 웹 애플리케이션에서 사용되는 빈들에 대한 관리를 Spring이 담당합니다. + + ```java + import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + + public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + + @Override + protected Class[] getRootConfigClasses() { + return null; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[]{MyWebConfig.class}; + } + + @Override + protected String[] getServletMappings() { + return new String[]{"/"}; + } + } + ``` + + 1. **Spring Interceptor** + - Servlet Filter와 동일하게 웹 공통 관심사를 처리 + - MVC 구조에 특화된 필터 기능 제공 + - Spring MVC에서 컨트롤러의 요청 처리 전.후 또는 응답 후에 특정한 동작을 수행할 수 있도록 하는 기능 From 24d9172165e72b7de974c0391ba0f3e122812721 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:58:35 +0900 Subject: [PATCH 10/13] =?UTF-8?q?docs=20:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week08/\355\231\215\354\240\225\354\232\260.md" | 3 +++ 1 file changed, 3 insertions(+) diff --git "a/week08/\355\231\215\354\240\225\354\232\260.md" "b/week08/\355\231\215\354\240\225\354\232\260.md" index 10ef3fe..90075ab 100644 --- "a/week08/\355\231\215\354\240\225\354\232\260.md" +++ "b/week08/\355\231\215\354\240\225\354\232\260.md" @@ -167,3 +167,6 @@ - Servlet Filter와 동일하게 웹 공통 관심사를 처리 - MVC 구조에 특화된 필터 기능 제공 - Spring MVC에서 컨트롤러의 요청 처리 전.후 또는 응답 후에 특정한 동작을 수행할 수 있도록 하는 기능 + +**API 문서** +- https://api.postman.com/collections/29836884-19215572-b5bf-4376-89ad-e19ce0295409?access_key=PMAT-01HF96M8C7JJ53M75NKBXDK7ZG From dde8ea47abe7018f1dd3b2bf0248a4d658f4c79a Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Wed, 15 Nov 2023 19:05:49 +0900 Subject: [PATCH 11/13] =?UTF-8?q?docs=20:=20API=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "week08/\355\231\215\354\240\225\354\232\260.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/week08/\355\231\215\354\240\225\354\232\260.md" "b/week08/\355\231\215\354\240\225\354\232\260.md" index 90075ab..21b802f 100644 --- "a/week08/\355\231\215\354\240\225\354\232\260.md" +++ "b/week08/\355\231\215\354\240\225\354\232\260.md" @@ -169,4 +169,4 @@ - Spring MVC에서 컨트롤러의 요청 처리 전.후 또는 응답 후에 특정한 동작을 수행할 수 있도록 하는 기능 **API 문서** -- https://api.postman.com/collections/29836884-19215572-b5bf-4376-89ad-e19ce0295409?access_key=PMAT-01HF96M8C7JJ53M75NKBXDK7ZG +- https://documenter.getpostman.com/view/29836884/2s9YXnzekG From 77abe546bd489b5d0993cd7191ad394947c1d6f1 Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Tue, 21 Nov 2023 19:33:27 +0900 Subject: [PATCH 12/13] =?UTF-8?q?docs=20:=20=ED=95=99=EC=8A=B5=20PR=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\355\231\215\354\240\225\354\232\260.md" | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 "week09/\355\231\215\354\240\225\354\232\260.md" diff --git "a/week09/\355\231\215\354\240\225\354\232\260.md" "b/week09/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..6a69ec3 --- /dev/null +++ "b/week09/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,358 @@ +# Cow - Week 9 + +--- + +## DispatcherServlet 동작 과정 + +--- + +- 디스패처 서블릿은 모든 요청을 가장 먼저 받는 프론트 컨트롤러이다. + +### Dispatcher-Servlet이란? + +- HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러로 정의할 수 있다. + +### Front Controller + +- 서블릿 컨테이너의 제일 앞에서 서버로 들어오는 클라이언트의 모든 요청을 받아서 처리해주는 컨트롤러로, MVC 구조에서 함께 사용되는 디자인 패턴이다. + +**************디스패터 서블릿의 계층 구조************** + +![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/2b3f86e8-7eb0-4259-86ee-9899e94142f2/4fcdd7cd-0077-467c-af04-31960369a112/Untitled.png) + +### HttpServlet + +- HTTP 서블릿을 구현하기 위한 J2EE 스펙의 추상 클래스 +- 특정 HTTP 메서드를 지원하기 위해서는 doX 메서드를 오버라이딩 해야 한다.(템플릿 메소드 패턴) +- doPatch는 지원하지 않음 + +### HttpServletBean + +- HttpServlet을 Spring이 구현한 추상 클래스 +- 스프링이 모든 유형의 서브릿 구현을 위해 정의한 공통 클래스 + +### FrameworkServlet + +- 스프링 웹 프레임워크의 기반이 되는 서블릿 +- doX 메서드를 오버라이딩하고 있으며, doX 요청들을 공통된 요청 처리 메서드인 processRequest로 전달 +- processRequest에서 실제 요청 핸들링은 추상 메서드 doService로 위임된다. + +## 디스패처 서블릿이 요청을 받아서 컨트롤러로 위임하는 과정 + +1. 서블리 요청/응답을 HTTP 서블릿 요청/응답으로 변환 + - HTTP 요청은 등록된 필터들을 거쳐 디스패처 서블릿이 처리하게 되는데, 가장 먼저 요청을 받는 부분은 부모 클래스인 HttpServlet에 구현된 service 메서드이다. + + ```java + public abstract class HttpServlet extends GenericServlet { + + ... + + @Override + public void service(ServletRequest req, ServletResponse res) + throws ServletException, IOException { + + HttpServletRequest request; + HttpServletResponse response; + + try { + request = (HttpServletRequest) req; + response = (HttpServletResponse) res; + } catch (ClassCastException e) { + throw new ServletException(lStrings.getString("http.non_http")); + } + service(request, response); + } + + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + ... + } + + ... + } + ``` + + - service에서는 먼저 Servlet 관련 Request/Response 객체를 Http 관련 Request/Response로 캐스팅해준다. 캐스팅 시에 에러가 발생하면 HTTP 요청이 아니므로 에러를 던진다. +2. Http Method에 따른 처리 작업 진행 + - HttpServletRequest 객체를 파라미터로 갖는 service 메소드를 호출하는데, HttpServlet에도 service가 있지만 자식 클래스인 FrameworkServlet에 service가 오버라이딩 되어 있어 자식의 메소드가 호출된다. + + ```java + public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { + + ... + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + HttpMethod httpMethod = HttpMethod.resolve(request.getMethod()); + if (httpMethod == HttpMethod.PATCH || httpMethod == null) { + processRequest(request, response); + } + else { + super.service(request, response); + // PATCH가 아닌 경우 처리하는 로직은 아래와 같다. + } + + ... + } + } + ``` + + ```java + public abstract class HttpServlet extends GenericServlet { + + ... + + protected void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // PATCH가 아닌 경우 처리하는 로직 + String method = req.getMethod(); + + if (method.equals(METHOD_GET)) { + ... // lastModifed에 따른 doGet 처리(요약함) + doGet(req, resp); + + } else if (method.equals(METHOD_HEAD)) { + long lastModified = getLastModified(req); + maybeSetLastModified(resp, lastModified); + doHead(req, resp); + + } else if (method.equals(METHOD_POST)) { + doPost(req, resp); + + } else if (method.equals(METHOD_PUT)) { + doPut(req, resp); + + } else if (method.equals(METHOD_DELETE)) { + doDelete(req, resp); + + } else if (method.equals(METHOD_OPTIONS)) { + doOptions(req,resp); + + } else if (method.equals(METHOD_TRACE)) { + doTrace(req,resp); + + } else { + ... // 에러 처리 + } + } + + ... + } + ``` + + - HttpServlet에서는 요청 메서드에 따라 필요한 처리와 doX 메서드를 호출한다. 그러면 doX 메서드를 오버라이딩하고 있는 자식 클래스인 FrameworkServlet로 요청이 이어진다. 즉, PATCH를 제외한 메서드들에 대해 템플릿 메서드 패턴이 적용된 것. + + ```java + public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware { + + ... + + @Override + protected final void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + processRequest(request, response); + } + + @Override + protected final void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + processRequest(request, response); + } + + ... + } + ``` + +3. 요청에 대한 공통 처리 작업 진행 + - 오버라이딩된 doX 메서드는 모두 request를 처리하는 processRequest 메서드를 호출하고 있다. + + ```java + protected final void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + ... // LocaleContextHolder 처리 등 생략 + + try { + doService(request, response); + } catch (ServletException | IOException ex) { + failureCause = ex; + throw ex; + } catch (Throwable ex) { + failureCause = ex; + throw new NestedServletException("Request processing failed", ex); + } finally { + ... // 후처리 진행 + } + } + + protected abstract void doService(HttpServletRequest request, HttpServletResponse response) + throws Exception; + ``` + + - processsRequest에서는 request에 대한 공통 작업을 진행한 후, DispatcherServlet의 doService를 호출하게 된다. + + ```java + public class DispatcherServlet extends FrameworkServlet { + + ... + + @Override + protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception { + logRequest(request); + + ... // flash map 등의 처리 진행 + + try { + doDispatch(request, response); + } finally { + ... // 후처리 진행 + } + } + + ... + + } + ``` + + - HTTP 요청을 컨트롤러로 위임해주는 doDispatch 호출 +4. 컨트롤러로 요청을 위임 + - doDispatch + 1. 요청에 맵핑되는 HandletMapping 조회 + 2. 요청을 처리 할 HandlerAdapter 조회 + 3. HandlerAdapter를 통해 컨트롤러 메서드 호출 + + ```java + protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpServletRequest processedRequest = request; + HandlerExecutionChain mappedHandler = null; + boolean multipartRequestParsed = false; + + WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); + + try { + ModelAndView mv = null; + Exception dispatchException = null; + + try { + processedRequest = checkMultipart(request); + multipartRequestParsed = (processedRequest != request); + + // 1. 요청에 패핑되는 HandlerMapping (HandlerExecutionChain) 조회 + mappedHandler = getHandler(processedRequest); + if (mappedHandler == null) { + noHandlerFound(processedRequest, response); + return; + } + + // 2. 요청을 처리할 HandlerAdapter 조회 + HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); + + ... + + // 3. HandlerAdapter를 통해 컨트롤러 메소드 호출(HandlerExecutionChain 처리) + mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); + + ... // 후처리 진행(인터셉터 등) + } catch (Exception ex) { + dispatchException = ex; + } catch (Throwable err) { + // As of 4.3, we're processing Errors thrown from handler methods as well, + // making them available for @ExceptionHandler methods and other scenarios. + dispatchException = new NestedServletException("Handler dispatch failed", err); + } + processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); + } catch (Exception ex) { + triggerAfterCompletion(processedRequest, response, mappedHandler, ex); + } catch (Throwable err) { + triggerAfterCompletion(processedRequest, response, mappedHandler, + new NestedServletException("Handler processing failed", err)); + } finally { + ... // 후처리 진행 + } + } + ``` + + 1. **클라이언트의 요청 수신:** + - 클라이언트가 HTTP 요청을 보내면, 서블릿 컨테이너는 해당 요청을 DispatcherServlet으로 보낸다. + 2. **HandlerMapping에게 요청 전달:** + - DispatcherServlet은 **HandlerMapping**을 통해 어떤 컨트롤러(Handler)가 요청을 처리할지 결정. **HandlerMapping**은 URL과 컨트롤러 사이의 매핑을 관리한다. + - 디스패처 서블릿이 HandlerMethod가 아닌 HandlerExecutionChain를 얻는 이유는 공통 처리를 위한 인터셉터가 존재하기 때문이다. + + ```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; + } + ``` + + 3. **HandlerAdapter에게 요청 전달:** + - 선택된 컨트롤러(Handler)에 대한 정보를 기반으로 DispatcherServlet은 **HandlerAdapter**에게 실제 요청을 처리할 수 있는지 확인하도록 전달. **HandlerAdapter**는 해당 컨트롤러를 실행하고, 결과를 DispatcherServlet에 반환한다. + + ```java + protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { + HttpServletRequest processedRequest = request; + HandlerExecutionChain mappedHandler = null; + boolean multipartRequestParsed = false; + + WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); + + try { + ModelAndView mv = null; + Exception dispatchException = null; + + try { + processedRequest = checkMultipart(request); + multipartRequestParsed = (processedRequest != request); + + // 1. 요청에 패핑되는 HandlerExecutionChain 조회 + mappedHandler = getHandler(processedRequest); + if (mappedHandler == null) { + noHandlerFound(processedRequest, response); + return; + } + + // 2. 요청을 처리할 HandlerAdapter 조회 + HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); + + ... + + // 3. HandlerAdapter를 통해 컨트롤러 메소드 호출(HandlerExecutionChain 처리) + mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); + + ... // 후처리 진행(인터셉터 등) + } catch (Exception ex) { + dispatchException = ex; + } catch (Throwable err) { + // As of 4.3, we're processing Errors thrown from handler methods as well, + // making them available for @ExceptionHandler methods and other scenarios. + dispatchException = new NestedServletException("Handler dispatch failed", err); + } + processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); + } catch (Exception ex) { + triggerAfterCompletion(processedRequest, response, mappedHandler, ex); + } catch (Throwable err) { + triggerAfterCompletion(processedRequest, response, mappedHandler, + new NestedServletException("Handler processing failed", err)); + } finally { + ... // 후처리 진행 + } + } + 출처: https://mangkyu.tistory.com/216 [MangKyu's Diary:티스토리] + ``` + + 4. **ViewResolver에게 뷰 정보 요청:** + - DispatcherServlet은 컨트롤러가 반환한 뷰 이름을 이용하여 **ViewResolver**에게 실제 뷰 객체를 찾을 수 있는지 확인하도록 요청한다. + 5. **뷰 실행:** + - 찾아진 뷰 객체를 사용하여 DispatcherServlet은 뷰를 실행하고, 뷰에서 클라이언트로 응답을 생성한다. \ No newline at end of file From 33ff7103133a38cc8fb16ede6bc1e2ceeb575eca Mon Sep 17 00:00:00 2001 From: Erichong7 <97429550+Erichong7@users.noreply.github.com> Date: Tue, 28 Nov 2023 18:30:16 +0900 Subject: [PATCH 13/13] =?UTF-8?q?docs=20:=20=ED=99=8D=EC=A0=95=EC=9A=B0.md?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= 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 -- .../\355\231\215\354\240\225\354\232\260.md" | 155 ++++++++++++++++++ 2 files changed, 155 insertions(+), 18 deletions(-) delete mode 100644 "week10/10\354\243\274\354\260\250.md" create mode 100644 "week10/\355\231\215\354\240\225\354\232\260.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/\355\231\215\354\240\225\354\232\260.md" "b/week10/\355\231\215\354\240\225\354\232\260.md" new file mode 100644 index 0000000..626c3d8 --- /dev/null +++ "b/week10/\355\231\215\354\240\225\354\232\260.md" @@ -0,0 +1,155 @@ +# Cow - Week9 + +## Indexing + +- 데이터베이스 분야에 있어서 테이블에 대한 동작 속도를 높여주는 자료구조 +- 테이블 내의 1개의 컬럼, 혹은 여러 개의 컬럼을 이용하여 생성될 수 있다. +- 고속의 검색 속도, 레코드 접근과 관련 효율적인 순서 매김 동작에 대한 기초를 제공 +- 인덱스를 저장하는 데 필요한 디스크 공간은 보통 테이블을 저장하는 데 필요한 디스크 공간보다 작다. + - 보통의 인덱스는 키 - 필드만 가지고 있고, 테이블이 다른 세부 항목들은 가지고 있지 않기 때문 +- 관계형 데이터베이스에서는 인덱스는 테이블 부분에 대한 하나의 사본이다. + +### Clustered + +스크린샷 2023-11-27 오전 11 00 16 + +- 클러스터 형 인덱스는 데이터가 테이블에 물리적으로 저장되는 순서를 정의한다. 즉, 클러스터 형 인덱스는 특정 컬럼을 기준으로 데이터들을 정렬시킨다. +- 테이블 데이터는 오직 한 가지의 방법으로만 정렬되기 때문에 오직 테이블 당 하나의 클러스터 형 인덱스만 존재할 수 있다. +- primary key의 제약 조건은 클러스터 된 인덱스를 자동으로 생성하기 때문에 우리가 일반적으로 테이블을 생성할 때 특정 컬럼에 primary key를 지정했다면, 자료가 자동으로 정렬된다. +- 장점 : 검색 속도를 향상 시킨다. +- 단점 : 새로운 데이터를 삽입할 때는 많은 비용이 소모된다. + +### Secondary Index + +스크린샷 2023-11-27 오전 11 02 43 + +- Primary key 이외의 필요한 정렬 기준이 있을 경우 사용한다. +- 테이블 당 여러 개를 가질 수 있다. +- Data Record가 정렬되어 있지 않다. +- Index가 Data Record의 모든 주소 값을 가지고 있어야 한다. +- unique 하지 않아도 된다. +- 데이터 레코드가 Index 순서대로 정렬되어 있지 않기 때문에 범위 조건으로 검색하게 되면 많은 I/O가 발생할 수 있다. + +## Relationship + +- 관계는 엔터티 간의 관련성을 의미한다. + +### 관계 차수 + +- Relation Cardinality는 두 개의 엔터티 간 관계에 참여하는 수를 의미 + +### 1:1 관계 + +- 완전 1:1 + - 하나의 엔터티에 관계되는 엔터티의 관계가 하나 있는 경우 + - 반드시 존재 +- 선택적 1:1 + - 하나의 엔터티에 관계되는 엔터티의 관계가 하나이거나 없을 수도 있다. + +### 1:M 관계 + +- 엔터티에 행이 하나 있을 때 다른 엔터티의 값이 여러 개 있는 관게 + +### N:M 관계 + +- 두 개의 엔터티가 서로 여러 개의 관계를 갖고 있는 것 +- 이러한 경우 JOIN 시에 문제가 발생할 수 있다. 따라서 1:M OR N:1로 바꿔줘야 한다. + +## JPA 엔터티의 생명 주기 + +### 비영속 + +- 영속성 컨텍스트와 전혀 관계가 없는 상태 +- 객체를 생성’만’한 상태 + +```java +// 객체를 생성한 상태 (비영속) +Member member = new Member(); +member.setId("member1"); +member.setUsername("회원1"); +``` + +### 영속 + +- 영속성 컨텍스트에 저장된 상태 +- 엔터티가 영속성 컨텍스트에 의해 관리되는 상태 +- 영속 상태가 된다고 바로 DB에 쿼리가 날라가지 않는다. 트랜잭션의 commit시점에 영속성 컨텍스트에 있는 정보들이 DB에 쿼리로 날라간다. + +```java +// 객체를 생성한 상태 (비영속) +Member member = new Member(); +member.setId("member1"); +member.setUsername("회원1"); +EntityManager entityManager = entityManagerFactory.createEntityManager(); +entityManager.getTransaction().begin(); +// 객체를 저장한 상태 (영속) +entityManager.persist(member); +``` + +### 준영속 + +- 영속성 컨텍스트에 저장되었다가 분리된 상태 +- 영속성 컨텍스트에서 지운 상태 + +```java +// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태 +entityManager.detach(member); +``` + +### 삭제 + +- 실제 DB 삭제를 요청한 상태 + +```java +// 객체를 삭제한 상태 +entityManager.remove(member); +``` + +## @Id / @GeneratedValue + +### @Id + +- PK를 나타내기 위하여 @Id 어노테이션을 사용 +- @Id 어노테이션은 기본타입, 기본 래퍼런스 유형, String, java.util.Date, java.sql.Date, java.math.BingDecimal, java.math.BigInteger 중 하나여야 한다. @Column 어노테이션을 지정하지 않으면 열 이름은 기본 키 속성 또는 필드의 이름으로 가정한다. + +```java +package com.example.jwptodolist.todo.domain; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "todos") +public class Todo { + + @Id + private Long id; + + protected Todo() { + } + + public Todo(final Long id) { + this.id = id; + } + + public Long getId() { + return id; + } +} +``` + +### @GeneratedValue + +엔터티의 기본키 생성 전략 + +- **TABLE** + - 데이터베이스에 키 생성 전용 테이블을 하나 만들고 이를 사용하여 기본키를 생성 +- **SEQUENCE** + - 데이터베이스의 특별한 오브젝트인 시퀸스를 사용하여 기본키를 생성 + - Sequence란 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트 +- **IDENTITY** + - 기본키 생성을 데이터베이스에 위임한다. + - 예를 들어 MySQL의 경우 AUTO_INCREMENT를 사용하여 기본키를 생성한다. +- **AUTO** + - JPA 구현체가 자동으로 생성 전략을 결정한다.