본문 바로가기

Spring

Spring 개발일지 - 전반적인 Spring MVC 구조를 살펴보자!

Developer OS - MacOS 12.4

Chipset - Apple M1 Max

IDE - Eclipse IDE

Language - Java

FrameWork - Spring

 

이 글은 JSP + Servlet으로 개발하다 Spring을 처음 배우시는 분에게 추천합니다! (필자도 동일)

블로그를 만들고 처음으로 글을 쓰는것 같아요. 그동안 저는. jsp + Servlet 조합으로만 개발을 하다가 규모가 있는 회사에 들어가려면 Spring이 필요하다는(사실 Spring Boot를 대부분 쓰긴 하지만) 사실을 깨닫고 Java 기초부터 차근차근 다시 공부하다 드디어! 한국 웹 시장에서 뺄 수 없는 Spring을 공부하게 되었습니다. 근데... 후.. 만만치 않더군요.. 백문이 불여일타! 우선 만들어보자고요!

프로젝트 생성하기!

  1. Pachage Explorer 오른쪽 클릭 -> New -> Spring Legacy Project
  2. Project name 입력 후 Templates은 Spring MVC Project 선택
  3. Top Level Package Name 입력

대부분의 Top Level Pachage Name은 com. 회사명. PJT명 이런 식으로 작명합니다

기본 페이지도 봤으니 이제 Spring Web MVC에 구동방법을 살펴봅시다!

제가 직접 적은 건데..ㅎㅎ;; 우선 한번 봅시다!

1. 클라이언트가 http:/localhost:8080/create.do로 Dispatcher Servlet에 요청을 보냅니다.

web.xml에 작성되어있는 Dispatcher Servlet을 한번 봐봅시다~

web.xml

(이미지 편집하다가 빵꾸뚤렸네요ㅋㅋㅋ) - web.xml

<context-param></context-param>

web.xml은 자동으로 생성이 되는데 <context-param>에 자동으로 작성된 어노테이션(주석)을 번역해보면

모든 서블릿 및 필터에서 공유하는 루트 스프링 컨테이너의 정의입니다.

말 그대로 web-Application에 있는 Servlet들이 공유하는 전역 변수입니다. 서블릿이 공유하고 참고하는 자소서(?) 같은 친구의

context-param의 이름과 값을 서술해줍니다.

web.xml에서 context-param에 작성된 root-context.xml(스프링 환경설정) 파일로 이동합니다.

root-context.xml

현재는 작성된 이 없습니다. 공통적으로 사용되는 bean을 등록해서 그때그때 사용하시면 됩니다~

어노테이션을 번역해보면 다음과 같습니다.

루트 컨텍스트: 다른 모든 웹 구성요소에 표시되는 공유 리소스를 정의합니다.

<listner></listner>

여기에도 작성된 어노테이션을 번역해보면

우리는 컨테이너 모든 Servlets과 필터에 의해 공유를 만듭니다.

리스너는 어떤 이벤트가 발생했을 때 listner-class에 있는 객체가 호출되면 그 호출을 처리하는 객체를 서술합니다.

그리고 log-4j를 사용하신다면!! listner-class에 log-4j에 관련된 listner-class를 작성하셔야 합니다.

log-4j도 기회가 되면 한번 자세하게 다뤄보도록 하죠!

<servlet></servlet>

<servlet></servlet>

응용 프로그램 요청을 처리합니다.

이곳은 Alias 즉, 별명을 서술하는 곳입니다.

<Servlet-name>은 Servlet-class와 연결됩니다 아래에 작성한 servlet-mapping할 때 servlet-name과 동일해야 합니다!

<Servlet-class>는 패키지 경로를 입력하는 곳입니다.

<init-param>은 <context-param>과 같은 의미입니다. 그렇지만 context-param은 Servlet끼리 사용하지만, init-param은 Servlet안에 지역변수처럼 이용됩니다. 필자의 경우 bean설정 파일을 여기 적힌 servlet-context.xml에 작성하게 됩니다.

위 사진은 제가 인텔리제이에서 webMVC를 생성한 건데 UI가 확실히 깨끗하죠? 역시 돈이 최고다

여기서는 dispatcher-servlet.xml을 참조하고 있네요~ 그렇다는 건 인텔리제이에서 코딩할 때는 dispatcher-servlet.xml에 bean을 생성하면 되겠군요!

<load-on-startup>은 0 이상 값이 들어가면 자동으로 인스턴스가 생성됩니다. 0에 가까운 숫자로 선언이 됩니다. 우선은 이 정도로만 기억해두면 될 것 같아요.

 

<servlet-mapping>

위에서 작성한 <servlet-name>과 맞춰서 정의해야 합니다. 

 

<url-pattern>

servlet-mapping은 url-pattern에 하나씩 servlet-name을 정의할 수 있습니다. /(루트)뿐 아니라 실무에서는 *. do 등으로 지정하게 됩니다. 여기에 url 태그를 작성하면 모든 url요청에 대해 서블릿이 요청을 처리합니다. /*를 사용하면 톰캣에. jsp를 다 무시하게 되기 때문에 /를 사용하는 게 맞다고 합니다.

 

2. web.xml에서 작성한 DispatcherServlet의 설정을 기록하는 servlet-context.xml로 이동합니다.

아까 web.xml에서 작성한<servlet> 관련된 Bean들이 모인 공간입니다. 위에서부터 차근차근 살펴보죠.

 

<annotation-driven />

스프링에서 @(어노테이션) 사용을 가능하게 해 줍니다. 스캔한 패키지 내부에 Controller를 로딩합니다.

아래 어노테이션을 해석해보죠.

스프링 MVC @컨트롤러 프로그래밍 모델을 활성화합니다.

<resources />

정적파일에 대한 경로를 설정해둡니다. resources파일에 정적파일 위치를 정해두면 DispatcherServlet과 Controller에 갔다가 .jsp를 거쳐서 보여주지만, 이렇게 정적파일 위치를 지정해두면 바로 접근 가능하게됩니다! 

${webappRoot}/resources 디렉토리의 정적 리소스를 효율적으로 제공하여 /resources/**에 대한 HTTP GET 요청을 처리합니다.

<beans:bean/>

perfix와 suffix에 등록된 값을 참조하여 /WEB-INF/views/'파일명'.jsp가 실행됩니다.

번역에서 더 자세하게 말해줬네요! 아까 말씀드린 return "jsp파일명"을 써놓은 @Controllers가 

@Controllers가 /WEB-INF/views 디렉토리의 .jsp 리소스에 렌더링하기 위해 선택한 보기를 확인합니다.

<context:component-scan/>

어떤 클래스가 컴포넌트(요소)를 가지고 있는지 해당 패키지에 있는 파일을 bean으로 등록하는 역할을 합니다.

스캔 대상인 요소를 확인하는 주석입니다.

 

3. @RequestMapping("/") 요청에 해당하는 home 메서드 실행

SpringMVC를 처음 생성하면 이런 모습으로 생성될거에요. view에 home.jsp와 HomeController.java가 있을거에요.

기본적으로 localhost:8080/(프로젝트명 / 설정으로 제거가능) 즉, 루트(/) 로 접속하면 뜨는 기본 프로젝트 화면입니다.

 

HomeController.java

Default Controller java file

어노테이션(@)에 대해 알아봅시다.

@Controller - 컨트롤러임을 나타내며, bean으로 자동으로 등록됩니다.

@RequestMapping - 직역해석하면 요청맵핑(감싸기) 어노테이션입니다. 요청 URL에 대한 메소드의 맵핑이 가능합니다.

기본적으로 value = "/"로 잡혀있는데, 저의경우 첫 화면은 "index.do"로 많이 맵핑하는 편입니다 :)

method는 GET으로 받는다고 적혀있습니다. 기본적으로 GET이기때문에 method부분은 제거해도 무관합니다!

HTTP GET/ POST 요청에대해 더 알고싶다면, https://www.youtube.com/watch?v=0jV7xOUcKog를 참고하세요! 테코톡 엄청납니다.... 진짜 우리 모두 힘내서 우아한형제들 입사해보아요(?)

 

5. public String home(Locale, Model model)에 대해 알아봅시다.

Locale은 Java의 나라 및 언어의 정보를 담고있는 자바의 Class입니다! (별로 안중요하고 몰라도 괜춘합니다.)

Model은 서블릿 해보신분은 request, session에 정보를 담아서 .jsp에 넘겨준 기억이 있으실지도..! (대표적으로 request.setAttribute()같은거..) 몰라도 괜찮아요! 근데 앞으로 이거 엄청많이 쓰게될거에요!

위에서 보면 addAttribute를 이용해서 model객체에 등록하고있네요. 앞에오는건 "변수명", 뒤에오는건 데이터 이렇게요.

 여기서는 formatDate라는 String자료형을 serverTime이라는 변수로 model에 저장하고있네요! :)

 

6. return에 대해 알아봅시다.

마지막! return home! return을 호출하면, VIEW에서 home을 찾에서 리턴해줍니다.

쉽게말해서 Spring에 view라는 친구가 home뒤에 .jsp를 붙여서 맵핑한 url명으로 return해준다고 이해하면 될것같네요!

home.jsp

아까 우리가 model 객체에 addAttribute()해서 넘긴 serverTime이라는 친구를 JSTL로 출력하고있어요.

JSTL은 나중에 기회가되면 포스팅해볼게요!

(Eclipse의 경우 JSTL1.2.jar 파일이 기본적으로 생성되는데, Intellij는 Spring에 직접 JSTL.jar을 다운받고 lib파일에 직접 넣어주셔야해요.. 이거때문에 2시간동안 500에러 잡았습니다.)

이제 기본적인것도 봤는데 톰캣 끼우시고~ 서버 Run하셔서~ 웹브라우저에 띄워봅시다~

 

localhost:8080/ 혹은 localhost:8080/path(톰캣지정 path명)/으로 접속합니다.(클라이언트가 요청)

Tomcat Default Page /

우왕 h1태그로 Hello world!랑 아까 model로 넘겨준 serverTime 잘 뜨고있...는데 한글이 깨졌네요..? 이건 web.xml에 utf-8파일 설정을 안해줘서그래요.. 아래에 다음과 같은 코드를 추가해봅시다!

<filter> 
    <filter-name>encodingFilter</filter-name> 
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 
    <init-param> 
       <param-name>encoding</param-name> 
       <param-value>UTF-8</param-value> 
    </init-param> 
    <init-param> 
       <param-name>forceEncoding</param-name> 
       <param-value>true</param-value> 
    </init-param> 
 </filter> 
 <filter-mapping> 
    <filter-name>encodingFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
 </filter-mapping>

UTF-8 설정 후의 index.do

UTF-8 포멧이 제대로 적용된걸 확인가능합니다 :)

 

web.xml에서 자꾸 에러가 떠요.. 이상 없는데..

팁! 자꾸 web.xml에 뭐 안건드렸는데 Eclipse에서 빨간색 X 에러가 뜬다면 이클립스가 멍청해서 web-app부분에 java를 대문자 JAVA로 변경해주세요! 이상한 에러가 잡힐거에요.

 

localhost:8080뒤에 아무것도 안붙히고싶어요 혹은 이름을 바꾸고싶어요

서버 더블클릭 -> 아래 Modules클릭 -> Edit..버튼 클릭 -> 원하는 Path명 입력!

 

긴 글 읽으시느라 수고많았습니다! 전반적인 Spring Web MVC에 대해 알아보았습니다.

이걸로 Spring Web MVC 맛을 보았습니다! 아직 @(어노테이션), Maven, Mybatis등을 알아보지 못했지만 이런 기본적인 동작법을 모르면 Spring 공부하는데 애를먹습니다.. 아직 저도 공부하는 단계이기에 잘못된점, 부족한점 댓글 남겨주시면 감사하겠습니다. 감사합니다!