Spring Di, Servlet

박규민·2024년 10월 20일
post-thumbnail

Spring Di

Spring Di란?

Di는 Dependency injection으로 의존성 주입의 뜻을 갖고 있다.
Java의 여러 소프트웨어 설계 패턴 중 하나로,
객체 간의 의존성을 외부에서 주입받는 방식을 의미한다.

Di를 사용하면 객체 간의 의존성을 직접 생성하지 않고, 외부에서 주입할 수 있다.
이를 통해 객체 간의 결합도를 줄이고 유지보수성을 향상시킬 수 있다.

  • 기존의 일반적인 방식
    : 객체들은 서로 의존되어 있다

다음과 같은 커피 원두 클래스가 있다고 가정하자

public static class CoffeeBeans{
	public void grind(){
    	System.out.println("기본 원두로 갈고 있습니다");
        }
    }

커피 머신 클래스도 존재한다

public static class CoffeeMachine{
	private CoffeeBeans coffeeBeans;
    
    public CoffeeMachine(){
    	this.coffeeBeans = new CoffeeBeans();
    }
    
    public void brew(){
		coffeeBeans.grind();
        System.out.println("기본 원두로 커피를 내립니다.");
    }
}

이 경우 brew를 통해 커피를 내리려면 커피머신에서 커피원두라는 필드값을 이전에 정의했던 CoffeeBeans클래스에서 가져와야 한다.

이렇게 코드를 작성하는 스타일을 '강한 결합(Tight Coupling)'이라고 한다.
이렇게 되면 오로지 '기본 원두'만을 갈 수 있는 '원두 일체형' 커피 머신이 된다.
만약, 디카페인 원두를 사용하고 싶다면 CoffeeBeans 클래스 뿐만 아니라 CoffeeMachine 클래스도 수정해야한다.

이에 반해, '느슨한 결합(Loose Coupling)'은 원두 분리형 커피머신이 된다.

우선, CoffeeBeans를 인터페이스로 정의하고

public interface CoffeeBeans {
	void grind();
    }

이후, CoffeeBeans 인터페이스를 구현하는 구현체 클래스를 만든다

public static class RegularCoffeeBeans implements CoffeeBeans
	@Override
    public void grind(){
    	System.out.println("기본 원두로 갈고 있습니다");
    }
}

이렇게 구현한다면, 다시 디카페인 원두를 사용하고 싶을 때 훨씬 간단해진다.
커피 원두 인터페이스를 다시 상속받아, 디카페인이라는 구현체 클래스를 정의해주면 된다.

public static class DecafCoffeeBeans implements CoffeeBeans{
	@override
    public void grind(){
    	System.out.println("디카페인 원두로 갈고 있습니다");
    }
}

이렇게 분리형 장치는 전체를 이루는 장치들을 각 역할에 따라 부품화한다.
이처럼 모듈화 소프트웨어 시스템을 구축하는 데에도 중요한 역할을 한다.

의존성 주입은 의존성을 외부에서 주입받아 유연한 개발을 도와준다
Spring은 이런 의존성 주입을 자동화 해줘, 개발자의 부담을 줄여준다

Spring의 의존성 주입 방식

  1. 생성자 주입(Constructor Injection)
  2. Setter 주입(Stter Injection)
  3. 필드 주입(Field Injection)

1) 생성자 주입 (⭐️)
: 객체가 생성될 때 생성자를 통해 필요한 의존성을 주입받는 방식
: 생성자 인수를 통해 필요한 객체를 받아와서 객체가 생성될 때 모든 의존성이 명확하게 설정된다
: 또한, 객체의 불변성을 보장해준다

@Service
public class MemberSignupService {
	private final Member Repository memberRepository;
    
    @Autowired
    public MemberSignupService(final MemberRepository memberRepository){
    	this.memberRepository = memberRepository;
    }
    
    /*나머지 로직들*/
}

2) Setter 주입
: Setter 주입은 런타임에 의존성을 주입, 의존성이 없더라도 객체가 생성된다

    1.주입 받으려는 빈의 생성자를 호출, 빈을 찾거나 빈 팩토리에 등록
    2.생성자 인자에 사용하는 빈을 찾거나 생성
    3. Setter의 인자로 주입 

@Service
public class MemberSignupService {
	private final MemberRepository memberRepository;
    
    @Autowired
    public void setMemberSignupService(final MemberRepository memberRepository){
    	this.memberRepository = memberRepository;
    }
    
    /* 나머지 로직들 */
    
}

: 선택적 의존성이 있을 때 유용하다.
: 대신 필수적 의존성이 주입되어야 할 때 이를 강제할 수 없다.

3)Field 주입
: 필드 주입 방식 역시 Setter 주입 방식과 마찬가지로
런타임에 의존성 주입, 의존성이 없더라도 객체가 생성될 수 있다.

   1. 주입받으려는 빈의 생성자를 호출하여 빈을 찾거나 빈 팩토리에 등록
   2. 생성자 인자에 사용하는 빈을 찾거나 생성
   3. 필드에 주입
   
@Service
public class MemberSignupSerivce{
	@Autowired
    private MemberRepository memberRepository;
    
  /* 나머지 로직들*/
}

: 코드가 깔끔하고 단순해지지만 필드에 직접 주입되어 테스트 중에 의존성을 주입하는 것이 어렵다
: 명시적으로 드러나는 의존성이 없어, 의존성 구조를 이해하기 어렵다
-> 의존성 관계가 드러나지 않아 Bean들 간의 순환 참조 문제가 발생할 수 있다

Spring Servlet

Spring Servlet이란?

Spring MVC 패턴에서 Controller에 해당하는 부분이다
Spring Servlet은 스프링 프레임워크에서 웹 애플리케이션을 구축할 때 사용하는 핵심적인 구성 요소로, 주로 Spring MVC의 일부로서 작동한다. Spring Servlet은 클라이언트의 HTTP 요청을 처리하고 적절한 응답을 제공하기 위해 서블릿(Servlet)을 사용한다.

서블릿(Servlet)이란?

웹 애플리케이션에서 클라이언트의 요청을 처리하고, 그에 대한 응답을 생성하는 중요한 구성요소이다.
즉, 자바에서 웹 애플리케이션을 만들 때 HTTP 요청을 처리하는 역할을 한다.

  1. HTTP Request에 사용자의 Id/Pw가 들어가면
  2. HTTP Response로는 로그인 후 페이지가 전송되어야 한다
  3. 이때, 로그인 정보를 받아 확인후 다음 페이지를 보내는 것이 Servlet이다.
  4. 웹서버는 요청을 WAS(Web Application Server)에게 넘기고, WAS는 요청에 따른 Servlet을 실행한다. Servlet은 요청에 대한 응답을 클라이언트에게 보낸다.

Servlet Container란?

Servlet을 관리해주는 컨테이너 역할이다.
Servlet이 어떤 역할을 수행하는 매뉴얼이라면,
Servelt Container는 해당 메뉴얼을 보고 직접 핸들링한다.

서블릿 컨테이너는 클라이언트의 요청을 받아주고 응답할 수 있도록, 웹서버와 Socket으로 통신한다.

  • Web server
    : HTTP 요청을 받아들이고, 해당 요청에 대한 응답을 제공하는 서비스
    : 요청이 들어오면 이를 서블릿 컨테이너에 전달, 서블릿 컨테이너가 동적 요청을 처리한 결과를 다시 웹 서버를 통해 클라이언트에게 전달하는 방식으로 작동한다.
  • Socket
    : 네트워크 통신을 위한 EndPoint, 서버-클라이언트 통신을 가능하게 한다.
    : 클라이언트와 서버가 데이터를 주고받기 위해 열려있는 연결 포트
    : TCP / UDP 소켓으로 나뉜다

Spring의 DispatcherServlet이란?

Spring에서 가장 중요한 서블릿은 DispatcherServlet이다.
이는 FrontController 패턴을 구현한 서블릿, 모든 HTTP 요청을 받는다.
요청은 적절한 컨트롤러로 전달하고, 로직을 실행 후 응답을 생성해준다.

@Controller
public class MyController {
	
    @GetMapping("/umc")
    public String hello(Model model){
    	model.addAttribute("message", "UMC Spring");
        return "greeting";
    }
}
  1. 요청 : 클라이언트가 /umc URL을 통해 HTTP 요청이 들어오면 DispatcherServlet으로 전달된다.
  2. Handler Mapping : DispatcherServlet은 해당 HTTP Request를 처리할 수 있는 적합한 Controller를 찾는다.
  3. Controller은 요청을 처리하기 위해 hello() 메서드를 호출, 맞는 비즈니스 로직을 실행 후 결과를 반환한다.
  4. 반환된 결과는 ViewResolver를 통해 적절한 view로 렌더링 해줘, HTTP Response로 HTML 혹은 JSON의 형태로써 전달된다.
profile
말도 할 줄 아는 Potato임니다

0개의 댓글