Skip to content

[21기_박정하] spring tutorial 미션 제출합니다. #1

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

Open
wants to merge 2 commits into
base: mirupio
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .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
43 changes: 43 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
*#
*.iml
*.ipr
*.iws
*.jar
*.sw?
*~
.#*
.*.md.html
.DS_Store
.attach_pid*
.classpath
.factorypath
.gradle
.metadata
.project
.recommenders
.settings
.springBeans
.vscode
/code
MANIFEST.MF
_site/
activemq-data
bin
build
!/**/src/**/bin
!/**/src/**/build
build.log
dependency-reduced-pom.xml
dump.rdb
interpolated*.xml
lib/
manifest.yml
out
overridedb.*
target
.flattened-pom.xml
secrets.yml
.gradletasknamecache
.sts4-cache

.idea
27 changes: 27 additions & 0 deletions HELP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Read Me First
The following was discovered as part of building this project:

* The original package name 'com.ceos21.spring-boot' is invalid and this project uses 'com.ceos21.spring_boot' instead.

# Getting Started

### Reference Documentation
For further reference, please consider the following sections:

* [Official Gradle documentation](https://docs.gradle.org)
* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/3.4.3/gradle-plugin)
* [Create an OCI image](https://docs.spring.io/spring-boot/3.4.3/gradle-plugin/packaging-oci-image.html)
* [Spring Web](https://docs.spring.io/spring-boot/3.4.3/reference/web/servlet.html)

### Guides
The following guides illustrate how to use some features concretely:

* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)

### Additional Links
These additional references should also help you:

* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle)

154 changes: 154 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,156 @@
# spring-tutorial-21st
CEOS back-end 21st spring tutorial project

# 1주차 미션
## Spring
: java 기반 백엔드 프레임워크

## Spring이 지원하는 기술들
### 1. IoC(=Inversion of Control) 제어의 역전
#### 개념
- 개발자가 객체를 직접 **생성, 관리**하지 않고, **Spring**이 함
이를 위해, **'Spring Container'** 존재

#### 존재 이유
- 기존 : **개발자**가 직접 객체를 생성하고, 관리하고, 의존성을 해결
- IoC 적용 후 : 이 일들을 **Spring**이 맡아주기 때문에 **코드가 간결**해지고, **유지보수가 쉬워짐**

#### 구현 방식
- **DI(=Dependency Injection) 의존성 주입**

#### 장점

1. **결합도 낮춤**
- 객체 간의 강한 **의존성 제거** -> 코드의 **유연성, 재사용성** 높임
ex) new를 사용하지 않고, 인터페이스 기반으로 의존성을 주입

2. **유지 보수 용이**
- 객체를 변경할 때 코드 전체를 수정할 필요 없이 설정 파일(applicationContext.xml)이나 어노테이션(@Autowired, @Inject)을 수정하면 됨

2. **객체 생성 및 생명 주기 관리 자동화**
- Spring이 객체를 생성하고 소멸시켜줘서, **개발자는 비즈니스 로직에 집중**할 수 있음

3. **테스트 용이성**
- 실제 객체 대신 가짜(Mock) 객체 등을 활용한 **단위테스트 작성**이 쉬워짐


### 2. AOP(=Aspect-Oriented Programming) 관점 지향 프로그래밍
#### 개념
- **핵심 로직**과 **부가 기능**을 **분리**하는 프로그래밍 방식

#### 존재 이유
- 여러 클래스에서 반복적으로 등장하는 **공통 기능을 모듈화**해서 여러 클래스에서 쉽게 **재사용**

#### 장점
1. **코드 중복 제거**

2. **유지보수성 향상**
- 공통 기능이 한 곳에 모여 있어 수정이 필요할 때 여러 곳을 수정할 필요 없음

3. **핵심 로직과 보조 기능을 분리**
- 핵심 로직을 방해하지 않으면서 부가적인 기능을 쉽게 추가 가능
ex) 로깅, 보안, 트랜잭션 처리

### 3. PSA(=Portable Service Abstraction) 휴대 가능한 서비스 추상화
#### 개념
- 다양한 기술 스택을 **추상화**하여 일관된 방식(**통합된 인터페이스**)으로 사용할 수 있도록 제공

#### 존재 이유
- 여러 기술의 **차이**를 개발자가 직접 처리하지 않도록 하기 위해

#### 장점
1. **기술 스택 변경 용이**
ex) JDBC에서 JPA로 전환해도 코드를 크게 수정하지 않아도 됨

2. **일관된 개발 방식 제공**
- Spring이 제공하는 공통 API를 사용

3. **기술 종속성 제거**
- 특정 기술에 의존하지 않고 개발
ex) JDBC, Hibernate, JPA, JMS 등

## Spring Bean
#### 개념
- **Spring Container**에 의해 관리되는 객체

#### 특징
1. **Spring Container가 직접 관리**
- **Application** 또는 **BeanFactory**가 생성, 소멸 관리

2. **Singleton 기본 적용**
- Spring Container 내에서 하나의 Bean은 하나만 생성됨
- 기본 설정 : @Scope("singleton"), 필요하면 변경 가능 : @Scope("prototype")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

와아 singleton에 대한 내용을 함께 조사해주셨군요! @Scope("singleton")@Scope("prototype")의 차이는 무엇이 있나요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

두 어노테이션은 Bean의 생성범위에서 차이가 있는데요! 각 특징을 정리해보았씁니다..

  • @scope("singleton")

    • Spring의 기본 스코프(Default Scope)
    • Bean이 한 번만 생성되어 Spring 컨테이너 내에서 공유됨
    • 같은 Bean을 여러 번 주입받아도 항상 같은 인스턴스를 참조
    • 메모리 사용량이 적고 성능이 좋음, 하지만 상태를 가지면 동시성 문제 발생 가능
  • @scope("prototype")

    • 요청할 때마다 새로운 객체를 생성
    • 각 요청마다 독립적인 Bean 인스턴스를 반환
    • 상태 정보를 가지는 Bean을 사용할 때 유용
    • 하지만 매번 새 인스턴스를 생성하므로 메모리 사용량이 증가

따라서 singleton은 공유할 수 있는 stateless 객체에 적합하고, prototype은 각 요청마다 새로운 인스턴스가 필요할 때 적합합니다!


3. **Lazy Initialization 가능**
= 필요할 때만 생성됨
- 기본 설정 : Container가 로드될 때 Bean 미리 생성, 필요하면 변경 가능 : @Lazy -> 생성 미룸
Comment on lines +84 to +86

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지연로딩과 즉시로딩 차이가 뭔가요?!
N+1 문제에 대해서도 공부하면 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

둘은 JPA에서 연관된 엔티티를 조회할 때 언제 데이터를 불러올 것인지를 결정합니다.

  • 즉시 로딩(Eager Loading)
    fetch = FetchType.EAGER (기본값: @manytoone, @OnetoOne)

    • 연관된 엔티티를 즉시 조회하는 방식
    • 엔티티를 조회하면 연관된 모든 엔티티를 한 번에 가져옴
  • 지연 로딩(Lazy Loading)
    fetch = FetchType.LAZY (기본값: @onetomany, @manytomany)

    • 실제 데이터를 사용할 때까지 연관된 엔티티를 조회하지 않음
    • N+1 문제
      • 지연 로딩으로 인해 발생하는 성능 문제
      • 하나의 쿼리(N)에 대해 추가적으로 N개의 쿼리가 실행됨
        ex) Order 엔티티를 조회할 때 Customer 엔티티가 지연 로딩일 경우 => Order마다 추가적으로 Customer를 가져오는 N개의 추가 쿼리 발생

잘 몰랐던 개념인데 정리하면서 새롭게 알게 되었어요!! 질문 감사합니다 ㅎㅎ


#### 존재 이유
- 의존성 주입을 위해

#### 구현 방식
1. **어노테이션 기반**
= @Componet 계열 어노테이션 사용
- @Component, @Service, @Repository, @Controller 등 사용 -> 자동 Bean 등록

2. **Java Config**

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어노테이션 기반 자동 등록과 비교했을 때, `@Bean을 사용했을 때의 장점이 뭐가 있을까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bean을 사용했을 때의 장점은 여러가지가 있습니다..

  1. 외부 라이브러리 객체 등록 가능
    • @component내부에서 만든 클래스에만 적용할 수 있지만, @bean외부 라이브러리에서 제공하는 클래스도 직접 등록할 수 있음.
      ex) JDBC datasource
  2. 세밀한 설정 가능
    • @component기본 생성자나 @Autowired를 통한 자동 주입을 해야하지만, @bean직접 객체를 생성하고 세부 설정을 조정할 수 있음.
  3. 생성 순서 및 의존성 명확하게 관리 가능
    • @component 스캔 방식에서는 클래스 간의 의존성이 복잡할 경우 순서를 명확히 보장하기 어렵지만, @bean을 사용하면 필요한 Bean을 메서드 호출을 통해 직접 전달할 수 있음

한마디로 "간편한 것은 @component이지만 세밀한 커스텀을 위해서는 @bean을 사용한다"라고 보면 될 것 같습니다!

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seoahS01
스프링 튜토리얼도 올렸습니다......바보같이 readme만 제출해야하는 건줄 알고 있었어요 ㅠ.ㅠ....죄송합니다

= @Bean 사용
- @Configuration 클래스 내부에서 @Bean 메서드 사용 -> 직접 Bean 등록

### Spring Bean의 라이프사이클
#### 1. 객체 생성
- @Component, @Bean 사용
-> Spring이 Bean을 자동 생성

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@component@bean 의 차이점을 처음에는 몰라서 찾아본 적이 있는데, Component는 class 단위로 Bean은 메서드 단위로 한다고 해요! (아마 다 아실 것 같지만요 ㅎ)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 그 기준으로 나뉜다는 것은 뭔가 들어본 것 같으면서도 잊고 있었어요...!! ㅎㅎ 감사합니당ㅎ

#### 2. 의존성 주입
- @Autowired, @Inject, @Resource 사용
-> 의존성 자동 주입
Comment on lines +105 to +107

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 세개의 차이점이 뭔가요 !
각각이 Bean을 찾는 순서에 대해서도 찾아보면 좋을 것 같네요 ~!

저도 잘 몰라서 찾아봤습니당 ㅎㅎ
https://wooj-coding-fordeveloper.tistory.com/68

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

셋의 차이를 정확하게 정리해준 아주 유용한 글이군요...! 좋은 자료 감사합니당 ㅠ.ㅠ

정리하자면... 세가지 경우에 따라서 알맞게 선택해서 쓰면 될 것 같네요! ㅎㅎ

  • Spring 전용 프로젝트
    @Autowired (Spring의 추가 기능 지원 가능)
  • Spring이 아닌 다른 프레임워크와 호환 필요
    @Inject (Java 표준)
  • 특정 이름의 빈을 지정해야 할 때
    @resource(name = "beanName")


#### 3. 초기화
- @PostConstruct 또는 init-method 속성 사용
- InitializingBean 인터페이스 구현 -> afterPropertiesSet() 메서드 호출
-> Bean이 생성된 후 실행할 초기화 로직을 수행

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 빈 라이프 사이클을 초기화 / 사용 / 소멸 정도로만 찾아봤는데 각 구현 및 로직과 함께 명시 해 주어서 더 좋은 것 같아요


#### 4. 사용
-> Bean 사용하면서 애플리케이션이 로직 수행

#### 5. 소멸
- @PreDestroy 또는 destroy-method 속성 사용
- DisposableBean 인터페이스 구현 -> destroy() 메서드 호출
-> 애플리케이션 종료 시, Bean이 소멸되기 전 정리할 작업 수행

## Spring annotation

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어노테이션에 대해 자세히 설명해주셨군요👍

#### 개념
- Java에서 메타데이터를 제공하는 특수한 형태의 마커

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

처음에 메타 데이터가 무엇인지 감이 잘 안 잡혔는데
https://kr.teradata.com/glossary/what-is-metadata
에서 보니까 확실히 알 것 같더라고요! 참고 자료 남깁니다 :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 저도 감이 안 왔는데 이제 좀 알 것 같아요...ㅎㅎ
다른 데이터를 설명하는 데이터였군요...!! 감사합니당 !!!

#### 구현 방식
- **컴포넌트 스캔** : @Controller, @Service, @Repository (는 @Component 포함) -> spring bean으로 자동 등록
- Spring container라는 '통'에 @Controller붙은 것들을 '컨트롤러 객체'로 생성해서 넣어둠
- Spring container라는 '통'에 @Service붙은 것들을 '서비스 객체'로 생성해서 넣어둠
- Spring container라는 '통'에 @Repository붙은 것들을 '리포지토리 객체'로 생성해서 넣어둠
- **자동 의존관계 설정** : 생성자에 @Autowired 붙어 있으면 spring container에 있는 객체와 연결시켜줌


## 단위 테스트와 통합 테스트
### 단위 테스트 Unit Test
#### 개념
- 애플리케이션의 **개별 모듈**(클래스, 메서드 단위)만을 테스트
- 다른 모듈과의 의존성을 제거(Mocking) 하여 독립적으로 테스트

#### 존재 이유
- **빠르고 독립적**이므로 **주요 기능 검증**하는 데 유용

### 통합 테스트 Integration Test
#### 개념
- **여러 모듈**(서비스, 컨트롤러 등)이 실제로 연동되는지 테스트
- 데이터베이스, API, 파일 시스템 등과의 실제 연동 확인

#### 존재 이유
- **실제 환경과 유사**하게 동작을 검증하는 데 필요
Comment on lines +123 to +149

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻👍🏻 좋아요



## 느낀점
용어 자체는 익숙해도 정확히는 알지 못했던 개념들을 꼼꼼하게 정리할 수 있어서 좋았다. 이전 프로젝트에서 스프링 기술들을 한 번 경험한 후에 개념을 정리하니까 좀 더 기억에 잘 남고 재미있었다. 기술을 알고 쓰는 것과 모르는데 무턱대고 쓰는 것은 정말 차이가 클 것이기 때문에, 이번에 이렇게 이해한 개념들을 프로젝트에서 적용해볼 생각에 조금 설렌다. 또 '존재 이유' 위주로 공부하니까 이해가 더 잘되는 것 같아서 앞으로도 이런식으로 공부해야겠다.



33 changes: 33 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.3'
id 'io.spring.dependency-management' version '1.1.7'
}

group = 'com.ceos21'
version = '0.0.1-SNAPSHOT'

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

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
useJUnitPlatform()
}
7 changes: 7 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
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.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading