Skip to content

[21기_최근호] spring tutorial 미션 제출합니다. #13

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 4 commits into
base: WithFortuna
Choose a base branch
from
Open
Changes from 1 commit
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
189 changes: 189 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,192 @@
# spring-tutorial-21st
CEOS back-end 21st spring tutorial project

# 1주차

## POJO

: 특정 프레임워크나 라이브러리에 의존하지 않는 순수 자바 코드

---

## Spring

: 자바 기반 객체지향적으로 서버 설계를 편리하게 도와주는 프레임워크. 주로 빈을 통해 객체를 관리하는 컨테이너 역할

- **객체지향 5원칙**
- **S**: Single Responsibility ⇒ 책임분리(AOP, 관점지향 프로그래밍)
- **O**: Open closed principle ⇒ 인터페이스에 의존하고 구현체에 의존하지 않는다(PSA, 서비스 추상화)
- **L**: 리스코프 치환법칙 ⇒ 상속할 때 주의해라. (자식은 부모의 기능을 온전히 수행 가능해야함)

**ex1)** 잘못된 상속: Rectangle로 Square 인스턴스를 받아도 밑변과 높이를 서로 다르게 설정이 불가능함
Rectangle ← Square

// 코드
Rectange rec = new Square();
rec.setHeight(10);
rec.setWidth(15); // !!!!!!!!!!!!오류 발생. width, height 모두 15로 설정됨.

**ex2)** 잘한 상속:
List ← ArrayList
← LinkedList

- **I**: Inversion of Control ⇒ 스프링 컨테이너가 객체 관리
- **D**: Dependency Injection ⇒ 관리 중인 객체를 삽입

---

**Q. 스프링이 POJO 프레임워크라고 함은 무슨 의미?**

⇒ 개발자의 선택에 따라 스프링에 의존할지 안할지 결정 가능 (POJO 객체를 쓸지 말지 선택 가능)

/** POJO 코드
* 스프링 없어도 돌아감
*/

@Service
public class MemberService {
private MemberRepository memberRepository;
//...
}

//NOT POJO
@Controller
public class MemberController {
@GetMapping("/members")
public String getMembers() {}
}

---

## AOP (Aspect Oriented Programming, 관점 지향 프로그래밍)

: 비즈니스 로직과 관리 로직 관심사를 분리

**ex)** Service 계층에서 (비즈니스 로직, 트랜잭션 관리 코드)를 분리

---

## PSA (Portable Service Abstraction)

: 특정 기술에 종속적이지 않은 설계 = 인터페이스에 의존하고 구현체에 의존 X

**ex)** 데이터 접근 기술 중 JPA, JDBC 로 변경하여도 코드의 변경은 최소화된다.
`PlatformTransactionManager`
- JpaTransactionManager (JPA)
- DataSourceTransactionManager (JDBC)

---

## Spring Boot

- 내장 톰캣
- 의존성 관리
- 설정 자동화
- 모니터링 (성능 측정, 메트릭 확인)

---

## 1. 스프링 빈

- **의미:** 스프링 컨테이너에서 생성과 소멸을 관리하는 **싱글톤 객체**
싱글톤 객체: 동일한 인스턴스로 같은 메모리 점유

Choose a reason for hiding this comment

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

싱글톤 객체의 설명을 보고 static 클래스와 spring bean의 차이점이 궁금해서 찾아보았는데 잘 설명되어있는 것 같아 첨부합니다~
싱글톤 vs 정적클래스

Copy link
Author

Choose a reason for hiding this comment

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

오.. 리뷰 보고나니까 저도 궁금해져서 링크 보고 왔습니다
싱글톤 객체 구현 방식이 꽤 다양하네요. 좋은 자료 감사합니다!


- **생명주기:**
객체 생성 → 의존성 주입 → 초기화 → 사용 중 → 소멸

**Q. @PostConstruct가 적용되는 시점은?**
⇒ 초기화 단계의 **마지막**에 호출된다.
객체가 생성(메모리 힙에 할당), 의존성이 주입되고 필요한 설정들도 끝난 초기화의 마지막 단계.
(이때 개발자가 원하는 추가 설정이 가능)

Choose a reason for hiding this comment

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

어떤 추가 설정이 가능한가요?

Copy link
Author

Choose a reason for hiding this comment

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

테스트데이터를 초기화하거나 간단한 캐싱작업에도 활용할 수 있다고 합니다
조금 더 공부해봐야겠네요.!


---

## 2. 스프링 빈 등록 방법

- `@Bean`을 사용한 직접 등록
- `@Component` 사용 (`@Service`, `@Repository`, `@Controller`)
- `@ComponentScan(basePackages = " ")`
: 지정 패키지(없다면 현재 패키지) 하위의 @Component를 찾으면 자동 빈 등록

---

## 3. 어노테이션

- **기능**
- 메타 데이터
ex) `@Override`
- 특정 기능을 가짐
ex) `@Component`, `@PostConstruct`

// 코드
@Target(ElementType.???) // TYPE, METHOD, FIELD
@Retention(RetentionPolicy.???) // RUNTIME, CLASS, SOURCE

Choose a reason for hiding this comment

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

저는 해당 부분을 조사할 때 @Retention 어노테이션의 기능이 헷갈렸어서, 혹시나 참고하시라고 제가 참고했던 글 남깁니다. 블로그의 댓글에 어떤 분이 잘 설명해주신 것 같아요.
retention어노테이션

Copy link
Author

Choose a reason for hiding this comment

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

RetentionPolicy.CLASS는 저도 이게 굳이 왜 필요한지 이해가 잘 안갔었는데 덕분에 배워갑니다 👍

public @interface CustomAnnotation {}

---

## 4. 스프링 Context 구조

- **BeanDefinitionRegistry**와 **BeanFactory** 상속관계

`DefaultListableBeanFactory` (클래스, 구현체)
→ *BeanFactory 인터페이스*
→ *BeanDefinitionRegistry 인터페이스*

`AnnotationConfigApplicationContext` (자식)
→ `GenericApplicationContext` (부모)
→ *BeanFactory 인터페이스*
→ *BeanDefinitionRegistry 인터페이스*

// 코드
public class GenericApplicationContext implements BeanFactory, BeanDefinitionRegistry {
private DefaultListableBeanFactory beanFactory;

public Object getBean() {
beanFactory.getBean(); // 위임
}
}
Comment on lines +136 to +148

Choose a reason for hiding this comment

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

BeanFactory와 BeanDefinitionRegistry의 관계를 잘 정리해주셨는데, Spring에서는 일반적으로 ApplicationContext를 더 많이 사용한다고 합니다. BeanFactoryApplicationContext의 차이는 무엇일까요?

Copy link
Author

@WithFortuna WithFortuna Mar 17, 2025

Choose a reason for hiding this comment

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

저도 궁금해서 찾아봤었는데

  • BeanFactory : 빈 생성, 관리 기능 //스프링 빈 Lazy 초기화
  • ApplicationContext: (빈 생성,관리기능) + AOP + 국제화 //스프링 빈Eager 초기화
    약간은 추상적지만.. 빈팩토리가 빈 관련된 기능만 제공한다면 앱컨텍스트는 거기에 더해서 상위기능들을 같이 제공하더라고요

Comment on lines +142 to +148

Choose a reason for hiding this comment

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

코드 예시 들어주신거 너무 좋은데요?
GenericApplicationContext가 직접 getBean()을 호출하지 않고, 내부적으로 DefaultListableBeanFactory에 위임하는 이유는 무엇인가요?

Copy link
Author

Choose a reason for hiding this comment

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

오 질문이 날카롭습니다..
GenericApplicationContext가 직접 getBean()함수를 구현하지 않고 별도의 구현체인 DefaultListableBeanFactory를 멤버변수로 두고 사용하는 방식이 저도 낯설더라고요.
일단 몇가지 이유를 찾아봤는데

  1. 결합도 낮추기
    : ApplicationContext(AC) 는 여러 상위 기능을 한꺼번에 제공해야합니다. 따라서 직접 구현하거나 상속하는 방식을 택한다면 AC가 너무 많은 책임을 지게 됩니다.
  2. 확장성 높이기
    : 새로운 빈팩토리가 필요하면 멤버변수를 교체만 하면 됩니다. 또 국제화와 같은 상위기능을 더하고 싶을 때에도 멤버로 추가하거나 빈으로 등록만 하면 되므로 확장하기가 쉽습니다!

보통 조합과 위임이라고 표현하는 것 같습니다


---

## 5. 테스트 코드

### 1. **단위 테스트**

: 외부 환경과는 분리된 순수한 코드 로직을 대상으로 검증

// 코드
@ExtendWith(MockitoExtension.class)
class MemberServiceTest {
@Mock
private MemberRepository memberRepository;

@InjectMocks
private MemberService memberService;

@Test
void findById() {
// given
Member member = new Member(...);
when(memberRepository.findById(1L))
.thenReturn(Optional.of(new Member("olaf")));

// when
Member findMember = memberService.findById(1L);

// then
Assertions.assertThat(findMember.getName()).isEqualTo("olaf");
}
}

---

### 2. **통합 테스트**

: API 요청, DB 연결과 같은 외부 환경을 포함하여 시스템의 전체적인 동작을 검증

// 코드
@SpringBootTest // 스프링 환경에서 통합테스트
@AutoConfigureMockMvc // API 호출 테스트
class ApiTest {
}