[BE] 스프링 기초

김주언·2022년 6월 16일
0

TODO LIST

목록 보기
2/18
post-thumbnail

1. 서버?

서버란 프로그램이라고 생각하면 됨
그런데 이 프로그램은 특정 포트의 소켓을 열어놓고 그 소켓에 클라이언트가 연결할때까지 무한 대기하는 것
그러다가 클라이언트가 연결하면 해당 클라이언트 소켓에서 요청을 받아와 수행하고 응답을 작성해서 전달한다.

예를 들어 서버에서 클라이언트의 요청을 읽을때나 클라이언트로의 응답을 보낼 때 FTP 프로토콜을 사용하면 FTP 서버가 되고 HTTP 프로토콜을 쓰면 HTTP 서버가 되는 것

아무튼 서버는 네트워크 기능 을 수행하는 프로그램!!

1.1 정적 웹 서버

HTTP 서버 중에서도 리소스 파일을 리턴하는 서버

HTTP GET /file.html 요청을 받았을 때, 정적 웹서버는 지정된 디렉터리에서 file.html파일을 HTTP response 바디에 넣어서 클라이언트에게 전송한다. 이 때 해당 파일에 아무 작업도 하지 않아서 정적인 것

아파치나 Nginx가 정적 웹 서버이다. 아파치나 Nginx를 설치 후 지정된 경로에 원하는 리소스 파일을 두면 알아서 웹서버가 리소스 파일을 전송해줘서 클라이언트가 접근할 수 있게됨

1.2 동적 웹 서버

파일을 있는 그대로 전송하지 않고 어떠한 작업을 거친 후 전송한다. 클라이언트가 요청에 요청 매개변수를 보내면 이를 활용하거나 등 다양한 작업이 가능하다.

  1. 클라이언트는 요청에 매개변수와 값을 전송 (name = test)
  2. 서버가 요청과 매개변수에 맞는 작업 수행
  3. 작업이 완료된 html파일 클라이언트에게 전송

따라서 정적 웹 서버는 클라이언트가 어떤 요청을 해도 똑같은 결과를 반환하지만, 동적 웹 서버는 클라이언트에 따라, 또 매개변수나 요청의 종류에 따라 결과가 다르게 나타난다

그래서 각 요청별, 매개변수별 로직을 작성해주는 것이 백엔드 개발!

그런데, 사용자 요구에 따라 로직은 항상 변하기 때문에, 일정 규격이 정확한(??) 서버 (아파치나 Nginx)는 사용할 수가 없다. 그러면 서버 프로그램 작성해주기 위해서 처음부터 끝까지 소켓 프로그래밍, HTTP 파싱, 스레드 풀 관리 등 다 해야하나??

그러면 난 백엔드 공부 안햇음

암튼 그래서 동적 웹 서버 구현 도와주는 자바 프로그램이 있다. 그게 바로 서블릿 엔진
아파치 톰캣이 서블릿 엔진에 속함

1.3 자바 서블릿 엔진 / 컨테이너

서블릿 엔진 또는 컨테이너는 서버 프로그램.
서블릿 엔진 설치 후, 서블릿 엔진에 클래스 파일과 해당 클래스 파일을 어떤 요청에서 실행하는지 설정해준다.

클래스 파일 작성 시 서블릿 엔진이 이해가능한 형태로 작성해야하는데, 이는 javax.servlet.http.HttpServlet을 상속하는 클래스들이다. HttpServlet을 상속받는 클래스를 작성해 특정 형식에 맞춰서 전달한다.
서블릿 엔진을 이용하면 서버를 처음부터 구현하지 않아도 비즈니스 로직 구현이 가능하다.

스프링부트는 내부적으로 서블릿 엔진을 사용하기 위해 서블릿을 상속 및 구현해준다.


2. 스프링 프레임워크

스프링은 오픈 소스 경량 프레임워크

  • 오픈소스 : 소스코드가 공개되어 있다.
  • 프레임워크 : 확장하여 사용가능한 코드
    - 확장하여 사용한다 ?
    • 프레임워크가 제공하는 라이브러리 사용
    • 프레임워크가 제공하는 클래스나 인터페이스를 상속 및 구현하여 코드를 프레임워크의 일부로서 실행하는것

2.1 의존성 주입

2.1.1 의존?

public class TestClass {
	private final TestPersistence persistence;
    
    public TestService() {
    	this.persistence = new TestPersistence();
    }
    
    public void create(...) {
    	//...
        persistence.create(...)
    }

}

위 클래스가 어떤 특정 기능을 수행한다고 가정할 때, 이 특정 기능 수행을 위해서 TestPersistence 를 사용하고 있다. 따라서 이 클래스는 만약 TestPersistence이 없으면 제 기능을 하지 못하게 되는 것.

즉, TestClassTestPersistence에 의존한다.

위 코드는 TestPersistence에 의존하는 TestClassTestPersistence 객체를 생성하고 관리하고 있다.

이러면 나중에 persistence가 바뀌면

  • 모든 코드를 일일히 수정해줘야 한다
  • 유닛 테스트가 힘들다

이러한 문제를 해결하기 위해서 의존성 주입을 하게되는 것이다

2.1.2 의존성 주입

해당 클래스가 의존하는 다른 클래스를 외부에서 주입시키는 것

의존성 주입은 디자인패턴의 한 종류로서, 이 패턴을 사용함으로써 제어역전 (IoC)구현이 가능하다!

  1. 생성자를 이용한 주입방법
public class TestClass {
	// 인터페이스 
	private final ITTestPersistence persistence;
    
    public TestService(ITTestPersistence persistence) {
    	this.persistence = persistence;
    }
    
    public void create(...) {
    	//...
        persistence.create(...)
    }

}

이렇게 하면 TestClass가 자신이 의존하고 있는 클래스 객체를 생성하지 않고 외부에서 넘겨받게 된다.
TestService 객체 생성 시 ITTestPersistence 구현부를 넘겨줌으로써 의존주입하는 것

ITTestPersistence는 인터페이스임!!

메인코드는 아래와 같다.

public static void main(String[] args) {
	ITTestPersistence persistence = new TestPersistence();
    TestService service = new TestService(persistence);
}



  1. Setter를 이용한 주입방법

Test 클래스

public class TestClass {
	// 인터페이스 
	private final ITTestPersistence persistence;
    
    public void setITTestService(ITTestPersistence persistence) {
    	this.persistence = persistence;
    }
    
    public void create(...) {
    	//...
        persistence.create(...)
    }

}

메인 코드

public static void main(String[] args) {
	ITTestPersistence persistence = new TestPersistence();
    TestService service = new TestService();
    service.setITTestService(persistence)
}

이렇듯 의존성 주입은 두가지 방법이 존재한다. 그리고 이러한 의존성 주입을 대신 해주는 것이 의존성 주입 컨테이너이며, 의존성 주입 컨테이너 중 하나가 스프링 프레임워크!

그래서 스프링 프레임워크를 사용하면 new 키워드를 사용해 일일히 생성하는 작업이 현저히 줄어든다. 스프링 프레임워크의 IoC 컨테이너 객체 (= ApplicationContext)가 대신 해주기 때문에~~

2.2 스프링부트 사용 이유

스프링부트 쓰면 Stand-alone급의 스프링 기반 앱 구동을 쉽게 할 수 있다.

Stand-alone?
애플리케이션 구동 시 다른 애플리케이션 필요 하지 않다는 뜻

아파치 톰캣은 웹 서버/서블릿 컨테이너가 필요하기 때문에 스탠드 얼론이 아니다. 아파치톰갯은 war파일을 톰캣에 배포해야한다.

반면에 스프링부트는 임베디드 톰캣이나 제티와 같은 웹 서버를 앱 실행시 함께 제공한다.
즉, 스프링부트 애플리케이션 실행 = 웹서버 실행

또 스프링부트는 자동으로 설정해주는 부분이 많아서 귣

3. 스프링 프레임워크와 디스패처 서블릿

3.1 서블릿 기반 서버

웹 애플리케이션은 보통 자바 서블릿 기반으로 한다.
자바 서블릿 기반 서버의 동작은 아래와 같다.
(서브 클래스는 javax.servlet.http.HttpServlet을 상속받는 클래스들이다)

서버는 HTTP 요청을 받으면 해당 요청을 해석하여 지정된 서블릿 클래스를 실행한다.
HttpServlet 서브 클래스들은 아래와 같은 순서로 동작하게 된다.

  1. 요청 받아서 파라미터 해석 - doGet()
  2. 비즈니스 로직 수행 -process()
  3. 응답 작성 - response.setContentType(), etc ...

막상 중요한건 2번인데 1 / 3번을 반복해서 작성하게 된다. 시러잉

3.2 스프링부트의 디스패처 서블릿

스프링부트는 어노테이션과 서브클래스 사용하여 반복작업을 줄여준다~~

스프링부트 DispatcherServelt이라는 서브 클래스 덕분에 서블릿 클래스 작성할 필요가 없다
대신에 어노테이션과 인터페이스를 사용하여 스프링이 개발자가 작성한 비즈니스 로직 이해할 수 있도록 클래스를 구현해야한다.

아무튼 스프링 사용하면

  1. HttpServlet 상속받을 필요가 없다.
  2. doGet 오버라이딩 하지 않아도 된다
  3. HttpServletRequest를 직접 파싱하지 않아도 된다.
  4. HttpServletResponse 작성하지 않아도 된다.

4. 스프링부트

4.1 메인 메서드와 @SpringBootApplitcation

스프링부트를 사용하면 다양한 어노테이션을 사용해 많은 설정 작업을 간단히 할 수 있다. @SpringBootApplitcation 는 해당 클래스가 스프링부트를 설정하는 클래스임을 의미한다.
또한 이 어노테이션이 달린 클래스가 속한 패키지를 베이스 패키지로 인식한다.

스프링은 의존성 주입 컨테이너로서의 역할을 수행한다. 스프링은 베이스 패키지와 하위 패키지에서 자바 빈을 찾아서 스프링의 의존성 주입 컨테이너 객체(ApplicationContext)에 등록한다.
그리고 애플리케이션 실행 중 특정 객체를 사용해야할 때 해당 객체가 다른 클래스에 의존중이라면 그 의존중인 클래스를 찾아서 연결해준다.

자동으로 연결해주는 작업은 @Autowired 가 담당한다.

그렇다면 스프링은 ApplicationContext에 등록해야하는 자바 빈을 어떻게 찾을까?

4.2 @Component

@Component 는 스프링에게 해당 클래스를 자바 빈으로 등록할 것을 알려준다.
하지만 @Component이 설정되었다고 해서 무조건 스프링이 검색해서 등록할 수는 없고, @ComponentScan 이 필요하다.
그리고 @SpringBootApplitcation이 내부적으로 @ComponentScan을 가지고 있기 때문에 추가적으로 설정해주지 않아도 된다.

4.3 @Bean

스프링에게 자동으로 객체를 찾아서 생성하는 것을 맡기고 싶지 않을때는 @Bean을 사용한다.
이 어노테이션을 사용하면 스프링이 객체를 생성할 때의 방식과 매개변수 전달 방식을 설정할 수 있다.

profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글