Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8주차] 박수현 #23

Merged
merged 19 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion week06/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ Spring 프레임워크를 통해 더 나은 객체지향 설계와 코딩을 할

keywords : Dispatcher Servlet, interceptor, handler

---
---
99 changes: 99 additions & 0 deletions week06/[6주차] 박수현.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
## 프레임워크란?
프레임워크는 애플리케이션 개발에 필요한 기본 구조를 제공하는 소프트웨어 환경으로 개발자가 효율적이고 일관된 코드를 작성할 수 있도록 돕는다.
표준에 맞게 설계된 소프트웨어 구성 요소가 포함되어 협업할 때 발생할 수 있는 오류를 개선할 수 있다. 게다가 반복되는 작업을 줄일 수 있어서 개발 시간을 단축할 수 있다.
하지만 프레임워크는 제작자가 만든 구조에서 크게 벗어날수가 없기에 개발자가 자유롭거나 유연하게 만들기가 힘든 단점도 지니고 있다.
프레임워크의 예로는 스트럿츠, 스프링, 앵귤러, 장고 등이 있다.
---

## 스프링의 장점 / 사용이유
스프링은 어떤 장점이 있기 때문에 사용하는 프레임워크일지 함께 알아보자. 다음은 스프링의 장점이다.
*POJO 기반* - 스프링은 POJO(Plain Old Java Object)를 기반으로 개발되어 유연성과 테스트 용이성이 높다.
*의존성 주입 (DI)* - 객체 간의 의존성을 스프링이 관리하여 결합도를 낮추고 코드의 재사용성을 높인다.
*AOP 지원* - 관점 지향 프로그래밍(AOP)을 지원하여 횡단 관심사를 모듈화할 수 있다.
*경량화* - 필요한 모듈만 선택적으로 사용할 수 있어 효율적이다.
*트랜잭션 관리* - 일관된 트랜잭션 관리 기능을 제공하여 데이터 처리의 신뢰성을 높인다.
*활발한 커뮤니티* - 많은 자료와 지원으로 개발 시 도움을 받을 수 있다.
---

## AOP란?
AOP(Aspect Oriented Programming)는 관점 지향 프로그래밍이란 뜻으로 특정 관점에서 필요한 핵심적인 로직과 부가적인 로직으로 모듈화하여 개발하는 프로그래밍 기법이다. 객체지향 프로그래밍의 단점인 의존성 및 횡단 관심사를 보완하기 위해 고안되었다. 횡단 관심사는 예외 처리나 로깅과 같이 여러 클래스에 공통적으로 필요한 부분이지만 핵심 로직과 직접적인 관련은 적은 기능을 의미한다. 때문에 핵심 로직 코드에 부가 로직이 섞여 코드의 복잡성과 중복이 늘어나는 문제가 생기는데 스프링은 AOP를 이용하여 코드 중복을 줄이고, 코드 가독성과 유지보수성을 높일 수 있다. AOP는 컴파일 시, 클래스 로딩 시, 런타임 시 등에 적용할 수 있다.
---

## 싱글톤이란?
싱글톤(Singleton)은 클래스의 인스턴스가 애플리케이션에서 하나만 생성되도록 보장하는 디자인 패턴이다. 싱글톤은 클래스 인스턴스를 생성할 때마다 다른 메모리 주소가 할당되어 메모리가 낭비되는 문제를 해결하기 위해 고안되었다. 하지만 싱글톤 패턴을 사용하면 중복하여 인스턴스 생성되는 것을 막고 하나의 객체를 여러 곳에서 공유해 일관적으로 데이터를 사용할 수 있으며 메모리 사용을 최적화할 수 있다. 하지만 싱글톤 패턴에는 몇 가지 문제점이 있다.
1. 멀티스레드 환경에서의 안전성: 싱글톤을 구현할 때 여러 스레드가 동시에 인스턴스를 생성하려고 하면 의도와 다르게 여러 인스턴스가 생성될 수 있다.
2. 유연성 부족: 싱글톤 클래스는 하나의 인스턴스만 가지기 때문에 특정 테스트 환경에서는 다른 인스턴스를 생성하거나 교체하기 어렵다.
3. 의존성 증가: 클래스가 싱글톤 인스턴스에 강하게 결합될 경우 모듈 간 의존성이 커져 테스트와 확장이 어려워질 수 있다.
이외에도 상속과 테스트 하기가 어려워진다는 점등이 있다.
---

## 싱글톤 컨테이너란?
이러한 문제점을 해결하기 위해 스프링의 싱글톤 컨테이너가 등장했다. 스프링은 객체를 싱글톤 컨테이너에서 관리하며 애플리케이션 시작 시 필요한 객체들을 싱글톤으로 생성하고 관리하는 컨테이너 역할을 수행한다. 스프링의 싱글톤 컨테이너는 멀티스레드 환경에서도 안전하게 싱글톤을 보장하며 객체의 의존성 주입과 유연한 설정이 가능해 다양한 환경에서 테스트 및 확장할 수 있다. 스프링에서 싱글톤 컨테이너는 빈 객체들을 싱글톤 방식으로 생성 및 관리하는 역할을 한다. 스프링 컨테이너는 기본적으로 모든 빈을 싱글톤으로 관리하여 매번 같은 객체를 반환함으로써 자원을 절약하고 일관성을 유지한다.
---

## Spring에서 Bean 관리 방법
스프링에서 객체 간의 의존관계를 관리하기 위해 Bean이 사용된다. 다음은 스프링에서 빈이 어떻게 관리되는지에 대한 주요 요소들이다.

1. 스프링 컨테이너
스프링 컨테이너는 빈을 생성하고, 소멸시키며, 필요한 의존성을 빈에 주입하는 기능을 제공한다. 주로 ApplicationContext가 대표적인 스프링 컨테이너 인터페이스로 사용된다. 애플리케이션 실행 시, 컨테이너는 빈을 로드하고 초기화하여 빈들을 중앙에서 관리한다.

2. 빈 정의
스프링에서는 빈을 정의하기 위해 XML 설정 파일, 자바 기반의 어노테이션, 자바 설정 클래스 등 다양한 방법을 제공한다.
XML 설정 파일: 예전에는 XML 파일에 <bean> 태그를 사용해 빈을 정의하는 방식이 주로 사용되었다.
자바 어노테이션: @Component, @Service, @Repository, @Controller 같은 어노테이션을 사용해 클래스에 빈을 자동으로 등록할 수 있다.
자바 설정 클래스: @Configuration과 @Bean을 사용하여 자바 클래스에서 빈을 정의할 수 있으며, 이는 설정을 코드 기반으로 관리할 수 있어 가독성과 유지보수성을 높인다.

3. 빈 스코프
스프링은 빈의 생명주기를 관리하기 위해 다양한 **스코프(scope)**를 제공한다. 스코프는 빈의 생성과 사용 범위를 지정하는 역할을 한다.

싱글톤(Singleton): 애플리케이션 전체에서 하나의 인스턴스만 유지한다.
프로토타입(Prototype): 빈을 요청할 때마다 새로운 인스턴스를 생성한다.
요청(Request): HTTP 요청마다 하나의 빈 인스턴스를 생성하고 요청이 끝나면 소멸한다.
세션(Session): HTTP 세션 동안 하나의 인스턴스를 유지한다.
애플리케이션(Application): 서블릿 컨텍스트 생명주기와 동일하게 빈을 관리한다.

4. 의존성 주입(DI)
스프링에서는 빈 간의 의존성을 관리하기 위해 **의존성 주입(DI, Dependency Injection)**을 사용한다. DI를 통해 객체 간의 결합도를 낮추고 테스트와 확장을 쉽게 할 수 있다. 스프링은 세 가지 주요 DI 방식을 지원한다.

생성자 주입: 생성자를 통해 의존성을 주입하는 방식으로, 필수적인 의존성을 강제할 수 있어 가장 추천되는 방식이다.
세터 주입: 세터 메서드를 통해 의존성을 주입하는 방식으로, 선택적 의존성 주입에 유용하다.
필드 주입: 필드에 직접 의존성을 주입하는 방식으로 가장 간단하지만, 테스트가 어렵고 순환 참조가 발생할 수 있어 권장되지 않는다.
이처럼 스프링은 빈을 효율적으로 관리하고, 객체 간의 결합도를 낮추어 유연하고 유지보수하기 쉬운 애플리케이션을 개발할 수 있도록 돕는다.
---

## Layered Architecture
레이어드 아키텍처는 애플리케이션을 계층으로 나누어 구성하는 아키텍처로 각 계층이 독립적으로 개발되거나 유지보수될 수 있다. 일반적으로 3개의 계층으로 나뉜다.
*프레젠테이션 계층* - 클라이언트의 요청을 비즈니스 계층으로 전달하는 역할을 담당한다.
*비즈니스 계층* - 비즈니스 로직을 구현하는 부분으로 시스템이 처리해야하는 역할을 맡는다.
*데이터 액세스 계층* - 데이터베이스에서 데이터를 저장하거나 업데이트하거나 읽는 역할을 담당하는 부분이다.
레이어드 아키텍쳐는 주로 단순하기에 소규모의 시스템을 구축할 때 쓰이지만 시스템이 확장될수록 유지보수하거나 테스트하기 어려워지는 단점이 존재한다.
---

## 스프링 어노테이션란? / 어노테이션 종류 10가지 이상 찾아보기
어노테이션은 '주석'이라는 뜻으로 스프링 어노테이션은 코드에 특별한 의미나 기능을 수행하도록 지시하는 기술이다. 스프링에서 어노테이션을 사용하면 코드가 더 직관적으로 표현할 수 있고 설정 파일 없이도 많은 기능을 간결하게 구현할 수 있다. 스프링 컨테이너는 어노테이션을 통해 빈을 등록하거나 의존성을 주입하는 등의 역할을 수행하며 각 어노테이션이 붙은 코드에 대해 지정된 기능을 실행한다.

1. @Bean - 메서드의 반환값을 빈으로 등록한다. 주로 @Configuration 클래스 안에서 사용되어 빈 팩토리를 통해 관리되는 객체를 생성하고 반환한다.

2. @Component - 스프링 컨테이너가 자동으로 인식하여 관리하는 일반적인 빈을 나타낸다. 특정한 역할을 가지지 않은 클래스에 사용되고 주로 @ComponentScan을 통해 스캔된다.

3. @Controller - 컨트롤러 클래스에 사용되며, 웹 애플리케이션에서 요청을 처리하고 응답을 생성하는 역할을 한다. MVC 패턴에서 Controller 역할을 수행하도록 스프링이 인식한다.

4. @Service - 비즈니스 로직을 처리하는 서비스 클래스에 사용된다. 실제 기능을 수행하는 계층의 로직을 캡슐화하여 표현하고 다른 계층에서 호출하는 핵심 로직을 포함한다.

5. @Repository - 데이터 접근 계층의 클래스에 사용되고 주로 데이터베이스와의 상호작용을 관리한다. @Repository를 사용하면 예외 처리가 자동으로 변환되어 데이터 계층에서의 에러를 일관되게 관리할 수 있다.

6. @Autowired - 스프링 컨테이너에서 자동으로 의존성을 주입하도록 한다. 필요한 빈을 컨테이너에서 찾아 주입하여 생성자 및 필드, 세터 메서드 등에 적용될 수 있다.

7. @Qualifier - @Autowired와 함께 사용되어 같은 타입의 빈이 여러 개 있을 때 특정 빈을 선택하여 주입할 수 있도록 한다.

8. @Scope - 빈의 스코프를 지정하여 빈의 생명주기를 설정할 수 있다. 기본적으로 싱글톤(singleton) 스코프가 사용되며 필요에 따라 프로토타입(prototype), 요청(request), 세션(session) 등의 스코프를 설정할 수 있다.

9. @Configuration - 설정 클래스로 사용되고 내부에서 정의된 @Bean 메서드를 통해 빈을 구성한다. 스프링 컨테이너는 @Configuration 클래스를 초기화하여 빈을 생성하고 관리한다.

10. @RequestMapping - URL 요청을 특정 메서드와 매핑하여 웹 요청을 처리할 메서드를 지정한다. @GetMapping, @PostMapping 등의 세부 매핑 어노테이션도 존재하여 HTTP 메서드에 따라 매핑을 더욱 세밀하게 할 수 있다.
---

## Spring Framework 구조와 동작 방식
스프링 프레임워크는 Dispatcher Servlet을 중심으로 구조화되어 있다. 클라이언트 요청이 들어오면 Dispatcher Servlet이 이를 받아 Handler Mapping을 통해 해당 요청을 처리할 핸들러(컨트롤러)를 찾는다. 요청 전/후에 Interceptor가 배치되어 특정 로직을 실행할 수 있다. Handler는 비즈니스 로직을 처리하고 결과를 Dispatcher Servlet에 반환하며 이후 View Resolver가 뷰를 결정하여 최종 응답을 제공한다.

---
3 changes: 3 additions & 0 deletions week07/parksuehyun-crud-api/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/gradlew text eol=lf
*.bat text eol=crlf
*.jar binary
37 changes: 37 additions & 0 deletions week07/parksuehyun-crud-api/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/
37 changes: 37 additions & 0 deletions week07/parksuehyun-crud-api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.5'
id 'io.spring.dependency-management' version '1.1.6'
}

group = 'practice'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
useJUnitPlatform()
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading