본문 바로가기

IT 공부

김영한 강의 정리 - 스프링 핵심 원리 기본편

김영한 강사님의 기본편을 아주 간략하게 정리하고자 한다

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢

www.inflearn.com

 

 


 

 

📚 SpringBoot 이란 ?

 

간단하게 이야기하자면 단독으로 스프링 애플리케이션을 생성하고 실행시킬 수 있게 해주고,

Tomcat과 같은 웹서버 설치 및 기타 설정을 자동으로해주는 프레임 워크이다

 

📚 Spring 이란 ?

 

자바 기반의 프레임워크로 객체지향적인 개발을 할 수 있게 도와주는 프레임 워크

 

 

📚 객체 지향 프로그래밍이란 ?

 

객체 지향 프로그래밍은 컴퓨터 명령어의 시각이 아닌 객체들의 모임으로 파악하는 것??

 

잘 이해가 되지 않는 부분이 있다

 

조금 더 간단하게 이야기 하자면 현실의 사물에 빗대어 객체로 표현한다면 조금 이해하기 편하다

 

 

📚 다형성 이란 ?

 

공장에서 부품을 갈아끼우면 다른 상품을 만들어 낼 수 있듯이 객체를 갈아끼우면 다른 결과물을 출력해내는 것

 

* 간단하게 남자 배우라는 역활에 어떤 배우(강동원, 장동건)가 오던 교체가 가능하다는 것 / 이것이 현실 세계의 다형성

 

역할과 구현을 분리하는 것이 중요

 

* 역할 - 인터페이스

* 구현 - 해당 인터페이스를 구현한 클래스

 

📚 객체 지향 설계의 5가지원칙(SOLID) 란 ?

 

앞 글자를 한 글자씩 따와서 SOLID 라고 한다

 

SRP : 단일 책임 원칙

OCP : 개방 폐쇄 원칙

LSP : 리스코프 치환 원칙

ISP : 인터페이스 분리 원칙

DIP : 의존관계 역전 원칙

 

 

[SRP : 단일 책임 원칙]

 

하나의 클래스는 하나의 책임만 가져야한다

 

- 하나의 기능만을 가져야한다고 이해하면 편하다

 

 

[OCP : 개방 폐쇄 원칙]

 

소프트웨어의 요소는 확장에는 열려있고 변경에는 닫혀 있어야 한다

 

즉, 코드의 변경없이 확장 할 수 있는 코드 작성을 위해 다형성을 이용하는 것이 좋다

 

 

[LSP : 리스코프 치환 원칙]

 

프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다

 

- 하위 클래스는 인터페이스 규약을 지켜야한다

* 엑셀 = 앞으로 가는 것, 뒤로 가는 기능으로 규약을 깨뜨리면 안된다

 

 

[ISP : 인터페이스 분리 원칙]

 

특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 좋다

 

기능에 맞게 인터페이스를 분리해서 사용하는 게 좋다

 

- 인터페이스가 명확해지고, 대체 가능성이 높아짐

 

 

[DIP : 의존 관계 역전 원칙]

 

프로그래머는 역할에 의존해야지 구현에 의존해서는 안된다

 

결국 인터페이스에 의존해서 개발해야한다는 것이다 / 이는 기능 교체에 유리해진다

 

 

 

📚 스프링의 DI 란 ?

 

스프링은 DI와 DI 컨테이너로 OCP(개방 폐쇄 원칙), IDP(인터페이스 분리원칙) 기능하게 지원 해준다

 

DI : Dependency Injection / 의존 관계

 

 

 

📚 코드를 짤 때 주의할 점

 

OCP : 개방 폐쇄 원칙

DIP : 의존관계 역전 원칙

 

코드를 작성 하기 전 항상 생각하고 설계를 잘해야한다

 

특히 SOLID의 법칙 중 OCP, DIP를 꼭 주의해서 코드를 작성할 수 있도록 해야한다

 

인터페이스로 구현체를 받아 올 수 있도록 설계하고,

해당 기능에서 변경이 일어나도 바로 처리가 될 수 있도록 코드가 작성 되는 것이 중요하다

 

이러한 의존성을 낮추기 위해서 필요한 것이 DI 라고 생각 된다

 

 

📚 테스트 코드 작성 법

 

@Test
void createOrder(){

    // given
    Long memberId = 1L;
    Member member = new Member(memberId, "memberA", Grade.VIP);
    memberService.join(member);

    // when
    Order order = orderService.createOrder(memberId, "itemA", 10000);

    // then
    Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);

}
 

Test 클래스에서 작성하면 된다

반드시 @Test 어노테이션이 있어야만 JUnit5에서 인식하여 실행된다

 

given / when / then

 

은 테스트 할 때 사용하는 방법인데

 

given : 테스트 데이터를 셋팅

when : 실제 기능 실행

then : 결과값 비교

 

하는 방식으로 테스트를 진행하면 된다

 

 

@BeforeEach
public void beforeEach(){
    AppConfig appConfig = new AppConfig();
    memberService = appConfig.memberService();
    orderService = appConfig.orderService();
}

 

@BeforeEach는 테스트를 시작하기 전 실행하는 Before 메소드 이다

 

 

 

📚 싱글톤 패턴 사용 이유 ?

 

싱글톤을 사용하지 않으면 공통된 객체를 만들 때 마다 다 사용해야된다

 

그렇기에 객체를 1개만 생성해서 공유하도록 설계한다

 

* 싱글톤 패턴 : 객체의 인스턴스가 오직 1개만 생성

 

[ 예제 ]

 

// 1. static 영역에 객체를 딱 1개만 생성한다
private static final SingletonService instance = new SingletonService();


// 2. 해당 인스턴스 조회 기능
public static SingletonService getInstance(){
    return instance;
}

// 3. 외부에서 new 할 수 없게 private로 막아둠
private SingletonService(){

}

// 4. 사용
public void logic(){
    System.out.println("싱글톤 객체 로직 호출");
}

 

위와 같은 방법으로 싱글톤을 구현할 수 있다

 

 

SingletonService singletonService2 = SingletonService.getInstance();

 

 

싱글톤 객체를 불러와야할 때는 위와 같은 방식으로 불러 올 수 있다

 

우리는 스프링을 사용하면 스프링 컨테이너에서 자동으로 객체를 싱글톤으로 관리해주기에 크게 신경을 쓸 필요는 없

 

 

 

📚 @Component  ?

 

해당 어노테이션이 등록되어 있는 클래스는 스프링 부트에서 빌드 단계에 전부 체크하게 된다

 

@Component는 다시 말하자면 빌드 시 체크해라 라는 어노테이션으로 이해하면 편하다

 

조금 더 상세하게 보면 

 

@Controller : 스프링 MVC 컨트롤러로 인식

@Service : 개발자들 인식처리 (실제로 뭔가 처리가 일어나지는 않음)

@Repository : 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환처리됨

 

 

📚 의존 관계 주입 방법 ?

 

1. 생성자 주입

2. 수정자 주입(setter 주입)

3. 필드 주입

4. 일반 메서드 주입

 

 

📚 의존 관계 주입시 생자 주입을 해야하는 이유 ?

 

* 기존의 업무에서 나는 보통 필드 주입을 통해서 의존 관계를 주입해 왔는데 이 방법이 추천하지 않는 방법이라는 것을 알았다

 

[생성자 주입 추천 이유]

생성자 주입을 하면 생성 시 한번만 생성되면 컨테이너 에서 관리하므로 불변하게 설계 가능

 

 

private final MemberService memberService;
private final OrderService orderService;

public OrderServiceTest(MemberService memberService, OrderService orderService) {
    this.memberService = memberService;
    this.orderService = orderService;
}

 

위와 같은 방식으로 생성자 주입을 진행하면 된다

 

생성자 주입을 하면 컴파일 단계에서 모든 에러를 한 번 걸러줄 수 있기에 굉장히 유용하고 빠르다!

(컴파일에서 걸러지는 이유는 바로 final로 해당 객체에 데이터가 있는지를 바로 체크해준다)

 

 

@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
    

 

위의 코드의 생성자 부분을 Lombok의 @RequireedArgsConstrucor로 자동 생성되게 할 수 있다

 

 

📚 의존관계는 언제 어떻게 ?

 

편리하게 의존 주입을 해주기에 기본적으로 자동 의존 주입을 사용하자

 

단, 직접 등록하는 기술(config) 들은 수동 등록하는 것이 좋다

 

또한

 

다형성을 많이 사용하는 비지니스 로직은 수동 등록을 고민해볼 수 있다

 

 

📚 스프링 빈의 라이프사이클

 

[ 싱글톤 ]

 

스프링 컨테이너 생성 - 스프링 빈 생성 - 의존 관계 주입 - 초기화 콜백 - 사용 - 소멸전 콜백 - 스프링 종료

 

 

📚 스프링 빈의 라이프사이클 콜백 설정

 

초기화 콜백 : @PostConstruct

소멸전 콜백 : @PreDestroy

 

 

📚 빈(Bean) 스코프란 ?

 

[ 스코프란? ]

 

Bean이 존재할 수 있는 범위를 의미한다

 

[ 스코프의 종류 ]

 

싱글톤 : 기본 스코프로써 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프

 

프로토 타입 : 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하는 매우 짧은 스코프

(초기화 콜백은 호출하지만 종료 콜백은 호출하지 않음)

 

웹 관련 스코프 :

request : 웹 쵸어이 들어오고 나갈때 까지 유지되는 스코프

session : 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프

application : 웹의 서블릿 컨텍스와 같은 범위로 유지되는 스코프

 

 

 

 

📚 후기

 

실무적인 부분 보다는 굉장히 기본에 충실한 강의

 

중요한 기능이면서도 중요하지 않은 기능들도 작동 원리에 대해서 알 수 있었고

 

기존에 알고 있던 지식들 중 틀린 지식들을 바로잡을 수 있는 강의였다