TIL(Today I Learned)

2023.06.15 TIL(web.xml, root-context.xml, servlet-context.xml 상세 설명)

jjonse 2023. 6. 15. 16:08

(1) web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	//모든 서블릿 및 필터에서 공유하는 루트 스프링 컨테이너의 정의
	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/root-context.xml</param-value>
	</context-param>
	
	<!-- Creates the Spring Container shared by all Servlets and Filters -->
    //모든 서블릿과 필터에서 공유하는 스프링 컨테이너를 만든다
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- Processes application requests -->
    //응용 프로그램 요청 처리
	//서블릿 등록
    //서블릿은 DispatcherServlet으로 되어있는데, 이 클래스에는 setContextConfigLocation 메소드가 존재한다.
    //config 설정 파일의 경로를 알려줄 수 있는 그런 메소드다.
    //init-param은 생성자 파라미터를 설정해준다. 
    //그래서 dispatcherServlet에 contextCOnfig 어쩌고는 /WEB-INF/ 어쩌고로 채워지는 것이다.
	<servlet>
		<servlet-name>appServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
		
	<servlet-mapping>
		<servlet-name>appServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

</web-app>

- 스프링 컨테이너 안에 객체들을 여러개 담을 수 있다.

- 이때, 이 객체들을 bean이라 표현한다.

- 스프링을 이용하면 관계 연결도 스프링이 다 해준다.

 

 

(2) root-context.xml

- 스프링 컨테이너안에는 어떠한 객체들(bean)이 있는지 확인할 수 있는 xml이다.

- 스프링 컨테이너를 만들기 위한 파일이다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<!-- Root Context: defines shared resources visible to all other web components -->
		
</beans>

 

 

(3) servlet-context.xml

- 이 xml은 디스패처 서블릿을 제공하기 위한 파일이다.

- 첫번째 설정은 Spring MVC @Controller를 활성화한다.

- annotation-driven 태그를 통하여 Controller를 활성화 할 수 있다.

 

$$ 정적 리소스란? $$

- 일반적인 완성된 파일 내용을 그대로 확인하는게 정적 리소스다.

 

$$렌더링이란? $$

- 화면을 만들어주는 작업을 뜻한다.

 

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

//디스패처 서블릿 컨텍스트 : 이 서플렛의 요청 처리 인프라를 정의
	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
    
	<!-- Enables the Spring MVC @Controller programming model -->
	//Spring MVC @Controller 프로그래밍 모델을 활성화한다
    <annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	//${webappRoot} 경로에 있는 고정적인 리소스를 효율적으로 제공하여 /resources/에 대한 HTTP GET 요청을 처리
    <resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	//@Controllers에서 렌더링을 위해 선택한 보기를 /WEB-INF/views 디렉토리의 .jsp 리소스를 해결한다.
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
    
    //component-scan을 진행하는 태그다.
    //
	<context:component-scan base-package="com.kh.app" />
	
	
	
</beans:beans>

 

 

(4) , IoC, DI란?

1. IoC : 제어의 역전. 제어할 부분을 스프링에게 넘기겠다는 뜻. 그동안 개발자가 모든 걸 다뤘지만 스프링이 웬만한 걸 다뤄준다.

- 예를 들어, MemberController에서 x = new MemberService();를 작성했다. 서비스에서는 new MemberDao();라는 표현을 사용했다.

- 개발자가 직접 객체를 생성하는 과정이 서블릿을 만들면서 있었다. 앞으로는 스프링을 사용할 때 이런 코드를 타이핑하지 않게 된다. 개발자가 직접 제어해서 객체를 생성할 필요가 없어진다. 

- 그럼 스프링에서는 어떻게 할까?
- MemberService라는 클래스가 있는데 스프링에 이 memberService를 객체로 만들어주라고 표시를 하면 된다. 

- 단순히 실행에 그치는게 아니라 dao까지 연결을 해준다.

- 결합도가 높다(구체적인 타입)을 알고 있다는 것은 무언가가 변경되었을 때 이를 다 변경해야 한다는 것을 뜻한다.

- 최대한 추상적으로 연결되어야 결합도가 낮아질 수 있다.

- 어떤 식으로 바뀌더라도 인터페이스를 활용하면 바꿀 필요가 없다.

- 그런데 문제가 있다. 연결은 바로 개발자가 한다. 변수이름이 x인데, x는 어떤 객체라고 코드 타이핑을 해야 한다. 

- 그것또한 일종의 연결인데, 이 또한 신경쓸게 있다는 말이다.

 

- 연결관계를 편하게 하려고 매니저가 등장한다. 매니저는 주방직원이 서빙직원이 필요하다고 한다. 서빙직원을 채용하는데, 김철수, 김영희 이런 애들이 서빙 직원으로 되어있으면 매니저가 연결을 해주는 것이다. 매니저가 알아서 다 관리를 해버리는 것이다. 개발자가 직접 코드를 쳐서 연결하는 것이 아니라 매니저가 직원들간의 관계를 파악하고 둘을 연결해준다. 

 

 

 

2. DI : 의존성 주입. 서로가 없으면 완성이 안되듯이 Controller는 service에 의존하고 service는 dao에 의존한다. 이렇게 서로 의존성을 주입한다.

즉, dependency를 연결해주는 것을 뜻한다.

 

 

(5) maven

- maven은 정확히 빌드 툴이다.

- 메이븐이 빌드를 할 때, 자기 마음대로 빌드를 하는 것이 아니라 pom.xml을 참조해서 빌드를 진행한다.

- 현재 프로젝트와 관련된 설정을 변경하고 싶다면 pom.xml에 가서 문서를 수정하면 된다.

- 메이븐이 pom.xml을 봐서 수정을 하게 된다. 

- 메이븐을 사용하지 않았다면 자기 컴퓨터에서 작업하던 거랑 김철수가 작업할 때랑 환경이 동일하지 않게 되는 문제가 있다.

- 이러한 문제가 있기 때문에 메이븐을 사용하는 것이 좋다. 

- lib도 pom.xml에서 관리한다.

 

 

(6) Dispatcher Servlet(디스패처 서블릿)

-  웹에서 특정 경로로 요청을 보내면 이는 web.xml의 appServlet을 호출한다. 

- appServlet이 하는 일? => 들어온 요청을 받고 method가 무엇인지 파악한다. 이에 맞춰서 특정 메소드를 파악한다.

- web.xml은 톰캣과 관련이 있다. 어떤 대장 서블릿(Dispatcher Servlet)을 하나 만든다. url-pattern이 '/'였음. 모든 요청을 받는 서블릿을 톰캣이 만들어 놓은 것이다.

- 클라이언트의 요청을 받아주는 대장서블릿이 바로 디스패처 서블릿이다. 

- 얘가 모든 요청을 받아서 클라이언트에 요청을 받고 요청된 uri, method를 체크하고 스프링 컨테이너의 여러개의 객체들 중에서 현재 요청을 처리할 수 있는 메소드를 찾아가게 만든다. 

- 예를 들어, 스프링 컨테이너 안에 세개의 메소드가 있는데 디스패처 서블릿이 uri, method와 매칭되는 해당 메소드를 부른다. 

- 디스패처 서블릿의 역할은 어떤 특정 컨트롤러를 호출하는 역할을 한다. 

- 불러지는 메소드는 home Controller의 home 메소드다. 왜냐하면 맵핑이 value = "/"로 되어있기 때문이다.

- 즉, 컨트롤러는 직접 포워딩을 하는 것이 아니라 어디로 포워딩 해달라고 알려주기만 하면 된다. 

- 디스패처 서블릿에 의해 어떤 jsp로 포워딩 해주는 것이다. 

 

 

 

$$자세한 것은 스프링 동작원리를 참고할 것 $$

 

 

 

 

(7) @Autowired

- 스프링이 알아서 자동으로 연결해주는 어노테이션. 올바른 객체를 찾아서 연결.

- 스프링 컨테이너에 있는 여러 개의 객체(bean)들 중에서 타입이 일치하는 것을 찾아서 연결해줌. 

- DAO는 DAO라 안하고 @Repository를 붙인다. 

- 어노테이션을 필드에 달아주면 필드인덱션이고, 생성자에 달아주면 생성자 인덱션이다.

- 필드에 달아주면 FINAL 키워드를 사용할 수 없기 때문에(FINAL을 달아줘야 더 안정적임) 주로 생성자로 어노테이션을 달아준다.

- 스프링은 생성자가 딱 하나일때는 @Autowired 키워드를 생략할 수 있다.(스프링이 알아서 달아주기 때문, 근데 가독성으로 인해 웬만하면 달아줌)

- 그런 어노테이션을 달아주면 빈으로써 스프링 컨테이너에 담겨진다.

 

(8) Mybatis Spring

- 스프링은 마이바티스를 쓸때, 중간에 어뎁터를 사용한다. 

- 스프링과 마이바티스가 다이렉트로 연결되어 있으면, 단계를 피하고 중간에 대리인을 한명 넣는다.

- 그 어뎁터를 통해서 데이터를 주고받을 수 있게 만들어놨다. 

- 스프링을 가지고 마이바티스를 쓰려면 중간다리 역할을 해주는 MyBatis Spring도 추가해줘야한다.(마찬가지로 Mybatis도)

- 스프링은 마이바티스를 직접 사용하지 않고 어댑터를 사용하기 때문에 sqlSession을 그대로 사용하는 것이 아니라 sqlSession template을 사용한다. 

 

(9) Controller, Service, Repository

- 이런 어노테이션이 달려있으면 스프링 컨테이너에 빈 객체로 생성된다. 

- 사실은 @Component라는 어노테이션을 달아야지 스프링 컨테이너에 빈으로 만들어진다.

- 하지만, Repository라고만 달아도 빈 객체로 만들어진다. 왜냐하면 Repository 어노테이션은 Component를 포함하고 있기 때문에 스프링 컨테이너에 자동으로 등록된다. 

- 같은 맥락으로 MemberService를 등록할때도 Service 어노테이션을 달아줘도 Service 어노테이션 안에 Component라는 어노테이션을 포함하고 있기 때문에 Service 어노테이션만 달아줘도 컨테이너에 등록된다.

- Controller도 마찬가지다.

 

 

(10) 마이바티스와 Spring 연결

- annotation을 직접 추가해서 service와 controller를 연결해주었지만 sqlSessionTemplate같은 경우에는 연결해주는 어노테이션이 없다.

- 그래서 해당 클래스파일을 찾아서 어노테이션을 연결해주어야 한다.

- 그렇다면 마이바티스 sqlSession을 Spring Container에 담아주는 방법이 무엇이 있을까?

- 스프링 컨테이너에 담기 위해서 스프링 컨테이너를 관리하는 xml문서에 찾아가서 직접 마이바티스를 등록해주면 된다.

- 그 xml 파일은 바로 'servlet-context.xml'이다.

 

 

- 톰캣 서버 안의 spring container에는 servlet바구니와 root 바구니가 있다. 

- root 바구니는 전역에서 사용할 수 있는 바구니고, servlet 바구니는 servlet 전용이다. 

- root는 전역 설정이니까 서블릿 측에서도 root의 것을 사용할 수 있다.

- servlet 바구니에서는 그 안의 것을 외부가 사용할 수 없다. 

- 각각의 바구니를 설정하는 타입이 따로따로 존재한다.

- 빈을 등록하는 것도 여기에서 할 수 있다.

- 빈을 등록하는 것은 annotation 방식, xml 방식 두 가지가 있다.

- 그럼 어떤 바구니에 담아야할까? 그렇다면 root 바구니에 담으면 된다. 누구나 사용할 수 있는 바구니이기 때문이다.

- 객체를 만들 때, SqlSessionTemplate은 기본 생성자가 없기 때문에 인자값으로 SqlSessionFactory를 전달해줘야한다.

- 생성자는

<bean class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0"></constructor-arg>
</bean>

이렇게 추가해주면 된다.

 

 

- 타입이 가장 첫번째 고려대상이다. 그래서 id도 같이 맞춰줘야 한다.