[23기_황신애] spring tutorial 미션 제출합니다. #4
[23기_황신애] spring tutorial 미션 제출합니다. #4shinae1023 wants to merge 7 commits intoCEOS-Developers:shinae1023from
Conversation
Add detailed explanations about Spring Beans, their lifecycle, and dependency injection.
Add detailed explanation of Spring MVC, Servlets, and Tomcat.
README.md
Outdated
|
|
||
| ## 1. POJO란? | ||
|
|
||
| **POJO (Plain Old Java Objection) : 특정 기술이나 프레임워크에 종속되지 않은 순수한 자바 객체** |
There was a problem hiding this comment.
Object가 Objection으로 오타가 난 것 같아요! 😆
Object로 살짝 수정해 주시면 완벽할 것 같아요!
| ### 3) 스프링과 POJO의 관계 | ||
|
|
||
| 스프링 프레임워크의 가장 큰 목표 : POJO를 이용한 엔터프라이즈 애플리케이션 개발 | ||
|
|
||
| 개발자는 비즈니스 로직에만 집중해서 순수한 POJO 클래스를 작성하고, 스프링은 그 뒤에서 다음과 같은 기술로 기능을 덧붙여줌 | ||
|
|
||
| - **IoC/DI :** 순수한 객체 상태로 있으면 필요한 의존성(객체)을 알아서 주입 | ||
| - **AOP :** 비즈니스 로직에만 집중해서 개발하면 트랜잭션이나 로깅 같은 공통 기능을 밖에서 감싸줌 | ||
| - **PSA :** 인터페이스만 보고 개발하면 뒤에서 기술이 바뀌어도(DB, 서버 등) 코드 변화 없음 |
There was a problem hiding this comment.
단순히 POJO의 정의만 적은 게 아닌, 스프링의 핵심 3대 요소가 POJO와 어떻게 연결되는지도 얘기해주셔서 이해하기 더 쉬웠습니다! 깔끔하고 느좋 정리 감사합니다!
|
|
||
| 1. **extends 하지 않기:** 특정 규약(Framework)의 클래스를 상속받지 않음 | ||
| 2. **implements 하지 않기:** 특정 규약의 인터페이스를 구현하지 않음 | ||
| 3. **종속되지 않기:** 특정 환경에 종속적인 어노테이션이나 라이브러리가 비즈니스 로직에 침투하지 않음 |
There was a problem hiding this comment.
실무에서 자주 쓰는 @service, @RestController나 JPA의 @entity 같은 어노테이션이 붙은 클래스들은 엄밀히 따지면 특정 기술에 종속된 것이기 때문에 완벽한 POJO라 부르기 힘들 것 같은데 스프링에서는 이를 POJO 지향적인 개발이라고 부르는 이유가 뭘지 나중에 같이 얘기 나눠봐요!!
| ### **5-3) @Repository가 없어도 되는 이유** | ||
|
|
||
| 1. **자동 프록시 생성 (Proxy Mechanism)** | ||
| - **동적 생성** : 개발자가 인터페이스만 선언하면, 스프링 데이터 JPA가 런타임에 해당 인터페이스의 구현체(프록시 객체)를 자동으로 만들어줌. | ||
| - **자동 등록** : 이 과정에서 생성된 프록시 객체를 스프링이 알아서 빈으로 등록하기 때문에 별도의 어노테이션이 필요 없음. | ||
| 2. **@EnableJpaRepositories의 역할** | ||
| - **스캔 기능** : 스프링 부트 메인 클래스 등에 (보이지 않게) 설정된 `@EnableJpaRepositories`가 특정 패키지 내에서 `Repository` 인터페이스를 상속받은 모든 인터페이스를 찾아냄. | ||
| - **타입 기반 탐색** : 어노테이션이 있냐 없냐보다, `JpaRepository`를 상속받았느냐를 기준으로 빈 등록 대상을 결정함. | ||
| 3. **@NoRepositoryBean의 정체** | ||
| - **정의** : "이 인터페이스는 실제 리포지토리 빈으로 만들지 마라"고 스프링에게 알리는 표식 | ||
| - **방지책** : 스프링 데이터 JPA는 리포지토리 인터페이스를 스캔할 때, 해당 인터페이스가 실제 데이터베이스와 연결된 리포지토리인지 아니면 단순히 기능을 물려주기 위한 중간 인터페이스인지 구분해야 함. | ||
| - JpaRepository에 붙어 있는 이유 | ||
| - **공통 인터페이스 보호** : `JpaRepository`는 모든 엔티티에 공통으로 쓰이는 메서드(`save`, `findAll` 등)를 정의한 인터페이스일 뿐, 특정 엔티티(예 : User, Order)를 위한 리포지토리가 아님 | ||
| - **오류 방지** : 만약 여기에 `@NoRepositoryBean`이 없다면, 스프링은 `JpaRepository` 자체를 빈으로 만들려고 시도하다가 "이건 어떤 엔티티용 리포지토리야?"라며 에러 발생 |
There was a problem hiding this comment.
JPA를 처음 쓸 때 인터페이스만 만들고 동작하는게 신기했는데, @NoRepositoryBean의 역할과 스프링 데이터 JPA의 자동 프록시 생성 메커니즘을 이렇게 뜯어볼 수 있어 너무 좋았습니다! 프레임워크의 내부 동작을 짚고 넘어가 주셔서 튜토리얼 복습에 큰 도움이 되었습니다~!
|
|
||
| - **소스 :** 과거에는 XML을 많이 썼지만, 현재는 자바 설정 클래스(`@Configuration`)와 어노테이션(`@Component`, `@Autowired`)을 주로 사용 | ||
| - **역할 :** 이 가이드북을 해석해서 어떤 객체를 싱글톤으로 만들지, 어떤 구현체를 주입할지 결정 | ||
| 4. BeanFactory vs ApplicationContext |
There was a problem hiding this comment.
스프링 컨테이너의 역할에 대해서 잘 설명해주셨습니다! 근데 4. BeanFactory vs ApplicationContext 이 부분의 제목 포맷팅이 살짝 깨진 것 같아서 리뷰 남깁니다! 설명 너무 잘 읽었습니다~!
| ### 2-1) 싱글톤을 무상태로 설계하는 이유 | ||
|
|
||
| - 상태 유지 설계의 문제점 | ||
| - **공유 필드 발생**: 여러 스레드가 동시에 값을 변경하면 데이터가 뒤섞임 | ||
| - **예상치 못한 결과**: 사용자 A의 주문 금액이 사용자 B에 의해 덮어씌워지는 사고 발생 | ||
|
|
||
| ```java | ||
| @Component | ||
| public class StatefulService { | ||
|
|
||
| private int price; // 상태를 유지하는 필드 (문제 발생 지점) | ||
|
|
||
| public void order(String name, int price) { | ||
| System.out.println("name = " + name + " price = " + price); | ||
| this.price = price; // 여기서 특정 사용자의 상태를 필드에 저장함 | ||
| } | ||
|
|
||
| public int getPrice() { | ||
| return price; // 저장된 필드 값을 반환함 | ||
| } | ||
| } | ||
| ``` |
There was a problem hiding this comment.
싱글톤 빈의 무상태 설계 중요성을 명확하게 설명해주신 것 같습니다!
읽다가 만약 싱글톤 빈 내부에서 프로토타입 빈을 주입받아 사용한다면, 해당 프로토타입 빈은 매 요청마다 새로 생성 될 지, 혹은 싱글톤처럼 처음에 생성된 하나만 계속 유지 될 지 궁금증이 생겼습니다.
백엔드 기술 면접에서도 많이 나오는 내용이라고 봤었던 것 같은데 같이 공부해보면 좋을 것 같아요!
There was a problem hiding this comment.
싱글톤 빈의 무상태 설계 중요성을 명확하게 설명해주신 것 같습니다! 읽다가 만약 싱글톤 빈 내부에서 프로토타입 빈을 주입받아 사용한다면, 해당 프로토타입 빈은 매 요청마다 새로 생성 될 지, 혹은 싱글톤처럼 처음에 생성된 하나만 계속 유지 될 지 궁금증이 생겼습니다. 백엔드 기술 면접에서도 많이 나오는 내용이라고 봤었던 것 같은데 같이 공부해보면 좋을 것 같아요!
감사합니다! 흐음 그냥 생각해봤을땐 처음에 생성된 하나만 계속 유지되어야 맞을거 같은데! 좀 더 공부해보고 정리한 내용 나중에 반영해볼게요~
| // ... | ||
| } | ||
| ``` | ||
|
|
There was a problem hiding this comment.
POJO인 경우와 아닌 경우를 코드 예시를 들어 설명해주시니 이해하기가 쉬웠습니다!
| - **코드의 단순화 :** 프레임워크 관련 코드가 사라져 가독성이 좋아짐 | ||
| - **테스트 난이도 하락 :** 환경의 영향을 받지 않으므로 JUnit 등을 이용해 빠르게 단위 테스트 가능 | ||
| - **객체지향적 설계 :** 특정 기술의 제약이 없으므로 객체지향 설계(상속, 다형성 등)를 적용하기 쉬움 | ||
|
|
There was a problem hiding this comment.
저는 이번 README에 POJO에 관해서는 넣지 않았는데 신애님 덕분에 한 번 더 복기 할 수 있어서 좋았습니다!
|
|
||
| - 가장 권장되는 방식 | ||
|
|
||
| ### 3-3) 생성자 주입이 가장 권장되는 이유 |
There was a problem hiding this comment.
가장 권장되는 방식이 무엇인지만 알려주고 끝나는게 아닌 이유까지 자세하게 설명해줘서 해당 방식을 더 쉽게 이해하고 납득 할 수 있었습니다!
| 7. **인터셉터 후처리 (applyPostHandle)** : 로직 수행 후, 뷰 렌더링 전에 인터셉터의 `postHandle`을 실행함 | ||
| 8. **뷰 렌더링 (processDispatchResult)** : `ViewResolver`를 통해 논리적 뷰 이름을 실제 뷰 객체로 변환하고 화면을 생성하여 응답함 | ||
|
|
||
| **코드 구조** |
There was a problem hiding this comment.
단순하게 글로만 설명을 적은 것이 아닌 예시 코드도 넣어주셔서 훨씬 이해가 쉬웠습니다!
저도 앞으로 개념 설명할 때 예시 코드를 넣는 습관을 가져야겠네요..
Hoyoung027
left a comment
There was a problem hiding this comment.
리드미가 너무 잘 작성되어 있어서 저도 좋은 공부가 된 것 같습니다 👍
잘하시는만큼 조금 더 디테일 한 내용 몇가지를 리뷰로 남겨두었으니 공부해보시고 스터디원 분들과 이야기해보면 좋을 것 같아요~! 수고 많으셨습니다!!
| ```java | ||
| protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { | ||
| // 1. 핸들러 결정 | ||
| mappedHandler = getHandler(processedRequest); |
There was a problem hiding this comment.
mappedHandler의 자료형을 보시면 HandlerExecutionChain인데요, 여기에는 무엇이 담겨있는걸까요? 왜 Chain이라고 부르는걸까요?
한번 찾아보시면 좋을 듯 합니다!
|
|
||
| // 2. 핸들러 어댑터 결정 | ||
| HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); | ||
|
|
There was a problem hiding this comment.
mappedHandler로 핸들러를 찾았음에도 불구, Adapter가 추가로 필요한 이유는 뭘까요?
| // 6. 결과 처리 및 뷰 렌더링 | ||
| processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); | ||
| } | ||
| ``` |
There was a problem hiding this comment.
개인적으로 뷰 렌더링이 익숙한 표현은 아니었는데요, 프론트와 백의 역할이 구별되기 시작하면서 백엔드에서 화면을 그려내는 일을 더이상 하지 않게 되었기 때문인 듯 합니다.
그렇다면 여기에서 뷰 렌더링 로직은 어떻게 짜여져 있는걸까요??
@RestController, @Controller의 동작 차이를 알아보시면 좋을 것 같습니다!
감사합니다 !! |
감사합니다! doDispatcher() 에서 자료형의 이름에 주목하진 않았는데 덕분에 mvc에 대해서 좀 더 자세히 공부하는 기회가 되었습니다~ |
No description provided.