처음 스프링 프로젝트가 생성되면 아래와 그림과 같은 구조를 확인 하실 수 있습니다.

간단하게 구성을 설명 하겠습니다.


src/main/java 는 프로젝트에서 개발되는 모든 Java코의 경로가 됩니다.

개발자나 프로젝트의 기호에 따라 sql mapper, tiles 등 xml 의 경로가 포함되기도 합니다.


src/main/recoursec 는 서버가 작동될때 사용되는 파일들의 경로입니다.

DB 연동을 위한 sql mapper의 xml 파일, titles의 template.xml 파일, 다국어 지원을 위한 properties.xml 등이 포함됩니다.


src/test/java 와 src/test/resources 는 말 그대로 테스트용 경로입니다. 위 두 경로와 목적만 다릅니다.


JRE System Library 세팅된 자바 버전을 나타냅니다.


Maven Dependencies 는 pom.xml 에 등록된 라이브러리들이 표시 되어 있습니다.


src->webapp->resources 는 이미지, 자바스크립트 등 페이지를 구성하는 resources들의 경로입니다.

src->webapp->WEN-INF->spring  스프링을 구성하는 설정 파일들의 경로입니다.

src->webapp->WEB-INF->views 실제 페이지를 구성하는 jsp, html 등의 파일들의 경로입니다.





 아래부터 home.jsp 의 작동 원리를 설명 하겠습니다.





기존 Dynamic Web 프로젝트는 jsp 등 웹 파일에서 서버를 실행 하면 바로 해당 페이지에 접근을 할 수 있었습니다.

하지만 스프링에서는 보안을 위해 웹 파일들을 WEB-INF 안에 저장 하고 있습니다.

이유는 WEB-INF 는 직접 접근을 할 수 없기 때문입니다. 이러한 이유로 home.jsp 를 바로 실행 시키면 

아래처럼 404 에러가 발생합니다. 그렇기 때문에 우리는 컨트롤러를 통해 페이지를 호출 해야 합니다.

그림(스프링 작동 순서) 에서 부터 순서대로 설명 하겠습니다.





- 그림(스프링 작동 순서)




1. web.xml 은 프로젝트의 환경 설정을 해주는 파일입니다. 프로젝트가 실행되면 이 파일이 가장 먼저 실행 되고, 

DispatcherServlet이 해당 프로젝트로 들어오는 요청들을 낚아채고 핸들링을 해줍니다.

이 부분은 낚아챈 요청들을 servlet-context.xml 로 보내주는 부분입니다.





	
	
		contextConfigLocation
		/WEB-INF/spring/root-context.xml
	
	
	
	
		org.springframework.web.context.ContextLoaderListener
	

	
	
		appServlet
		org.springframework.web.servlet.DispatcherServlet
		
			contextConfigLocation
			/WEB-INF/spring/appServlet/servlet-context.xml
		
		1
	
		
	
		appServlet
		/
	







2. servlet-context 는 낚아챈 요청을 받아 <annotation-drive/> 란 태그를 사용하여 컨트롤러에서 어노테이션을 사용할 수 있게 해줍니다.

<context:component-scan base="com.프로젝트.패키지명"/> 태그는 어노테이션을 사용할 영역(패키지)를 설정 할 수 있게 해줍니다.

낚아챈 요청은 com.포르젝트.패키지명에  요청된 url에 맞게 맵핑이 됩니다.

  




	
	
	
	

	
	

	
	
		
		
	
	
	
	
	
	


  



3. @RequestMapping(value = "/", method=RequestMethod.GET) 에 있는 value 값을 참조하여 요청된 url과 맵핑을 합니다.

return 되는 값은 "home" 이지만, 과정 4에서 페이지 경로를 prefix(/WEB-INF/views/) , suffix(.jsp) 가 자동으로 완성해주기 때문에,

최종적으로 /WEB-INF/view/return값.jsp 가 호출이 됩니다.








localhost:8080 을 실행 해보시면 아래와 같은 결과가 나오게 됩니다.

@RequestMapping 에서 value값을 "Index" 라고 설정을 하게 되면, localhost:8080/Index 라는 url로 접근 하면 됩니다.




지난 2018년 1월에 국비지원 교육을 이수하며 까먹지 말자란 결심으로 스프링 프로젝트 생성 관련 포스팅을 했습니다.

1년이 지난 지금, 적어도 그때보다 더 많은 공부를 하고난 후, 지금 보니까 너무 형편 없는 포스트 였습니다...

그래서 지금의 지식으로 다시 한 번 스프링 프로젝트 생성 및 초기 설정을 진행 하려고 합니다.


 틀린 부분이 있으면 언제 지적 해주셨으면 좋겠습니다 






저는 이클립스 기반의 STS를 이용 해서 프로젝트를 생성 하겠습니다.

STS설치, JDK&Maven 설치 및 설정은 제가 작성한 포스트를 따라 해주시면 됩니다.




1-1. STS 설치는 아래 링크에서 필요한 버전을 다운 받아주세요, 저는 3.9.6 버전을 사용 설치 하였습니다.

https://spring.io/tools3/sts/legacy


1-2. JDK 다운 및 환경 변수 설정

https://gabrielyj.tistory.com/162?category=629044


1-3. Maven 다운 및 환경 변수 설정

https://gabrielyj.tistory.com/161?category=735500






모든 준비가 완료되었습니다. 바로 스프링 프로젝트 생성을 진행 하겠습니다. 

2-1. 이클립스 좌측 상단 File -> New -> spring 검색 후 Spring Legacy Project를 선택 해주세요.







2-2. 프로젝트 이름을 입력 한뒤, Templates 에서는 'Spring MVC Project'를 선택 하신다음, Configure tmeplates 에 들어가주세요.

저는 프로젝트를 2개 진행 할 수 있는 상황을 고려하여 Maven Repository 설치 경로를 local 로 잡겠습니다.






2-3. 설치된 Maven 폴더에 있는 setting.xml 파일을 열고, 그 안에 있는 <localRepository> 경로를 수정 합니다.

사용자가 원하는 경로를 설정 하실 수 있고, 그냥 default를 사용 하고 싶으시면 그대로 놔두고 바로 2.6 을 진행 해주세요.








2-4. Maven -> Installations -> Add 를 선택해서, 그림(2-4-2) 처럼 메이븐 설치 경로를 지정 해줍니다.



(그림 : 2-4-1)


(그림 : 2-4-2)







2-5. Maven -> User Settings -> Browse 를 선택해서, 2-3에서 수정한 setting.xml 을 선택 합니다.

그러면 자동으로 아래  Local Repository 가 세팅됩니다.

그리고 Apply and Close 를 하시고 Next를 합니다.


(그림 : 2-5-1)






2-6. 마지막으로 패키지 이름을 정해줍니다.

저는 보통 com.프로젝트.모듈.패키지 이런식으로 네이밍을 합니다.







2.7 생성된 프로젝트에서 맨 아래에 있는 pom.xml 파일을 열어서 스프링, 자바, 메이븐 버전 설정을 해야 합니다.





<Properties> 

<java-version> 은 현재 등록된 jdk 버전을 입력 해주시면 됩니다.

<org.springframework-version> 은 사용하고 싶은 스프링 버전을 입력 해주시면 됩니다.

하지만 스프링 버전별로 최소 요구 자바 버전이 다르고 잘 못된 버전을 입력 하시면 에러가 발생하니 주의 해주세요!


<plugin>

<version> 설치된 메이븐의 버전

<source> <target> 설치된 자바의 버전을 입력 해주시면 됩니다.






이번 포스트에서는 pom.xml 까지만 설정 하고 

그 다음 포스트에서 web.xml 과 servlet-context.xml 등 다른 내용을 진행 하겠습니다.


스프링 프로젝트에 톰캣을 설정하려고 합니다.

참고하시는 분들의 PC에 이미 톰캣이 설치 되어 있다고 가정하겠습니다.(in Program Files or anywhere)





이클립스에서 프로젝트를 생성 하듯이 File -> New -> server 검색을 하고 다음 버튼을 눌러주세요.









준비하신 톰캣의 버젼에 맞게 선택 해주세요. 저는 8.0버전이라 Tomcat v8.0 Server를 선택 하였습니다. 그리고 다음 버튼을 눌러주세요.










Tomcat Installation Directory 는 준비하신 톰캣 폴더로 정해주시고,

JRE에는 해당 프로젝트에서 사용하실 jdk 로 정해주시면 됩니다. 그리고 Finish 버튼을 눌러주세요.








서버 생성은 완료 되었고 웹 서버 사용이 필요하신 프로젝트를 서버 작동을 위해 포함 해주세요.









그리고 생성된 서버의 server.xml 파일에서 path를 "/" 로 바꿔주세요.

물론 사용하시는 분에 따라서 해당 내용은 변경되야 할 필요가 있습니다.





실무에서 두개 이상의 프로젝트를 진행하다 보면 각 프로젝트가 환경이 다를 수 있습니다.

저도 기존에 작업하던 프로젝트 말고 새로운 프로젝트를 진행 하고 있습니다.

그래서 Maven의 라이브러리 들이 충돌 되지 않도록 각 프로젝트(워크스페이스) repository를 다르게 설정 하였습니다.


아래 과정은 기존 default 경로(c:/user/.m2/repository)가 아닌 자신이 원하는 경로에 maven을 설정하는 내용 입니다.



1. 설치된 Maven 폴더->config-> setting.xml 파일을 열어줍니다.

그리고 중간쯤에 있는 <localRepository> 부분의 주석을 그위로 이동한 뒤, 원하는 경로명을 입력 해줍니다.








2. 프로젝트가 아닌 워크스페이스의 Preferences -> Maven -> Installations 에서 Add버튼 클릭

(자료.1) 아래 (자료.2) 처럼 위에서 수정하신 setting.xml 이 존재하는 경로를 등록 해줍니다.

setting.xml 수정하신 경로는 maven 설치 경로와 똑같습니다.


(자료.1)



(자료.2)






3. 마지막으로  Preferences -> Maven -> User Settings 항목에서 User Settings 부분에 

모든 과정을 마친 setting.xml 를 등록 해줍니다. 그러면 그 아래 항목인 Local Repository 에 

입력한 로컬 경로가 자동으로 표시 됩니다.




처음 스프링 프로젝트를 생성한 다음 pom.xml 에 있는 Maven 버전을 수정 해야 합니다.

cmd 창에서 mvn -v 명령어를 입력 하시면 아래와 설치된 해당 maven의 정보가 출력 됩니다.










pom.xml 파일에 입력된 내용 중 <version>에 설치된 maven 의 버젼을 입력 해주시고,

그 아래 <source> 와 <target>에는 설치된 자바 버젼을 입력 해주시면 됩니다.







스프링에서 라이브러리를 자동으로 관리해주는 Maven을 사용하기 위해

메이븐을 설치 및 환경 변수 설정을 해줘야 합니다.


아래 링크로 이동 후 다운로드 해주세요.


http://maven.apache.org/download.cgi








빨간 박스의 압축 파일을 다운로드 한 다음 C드라이브의  Program Files에 복사 후 붙여넣어 주세요.

그 다음에는 환경 변수 설정을 해야 합니다.









위에 처럼 변수 이름은 MAVEN_HOME 으로 설정 하신 다음,

변수 값으로는 폴더가 존재하는 경로를 넣어주면 됩니다.(C드라이브에 붙여넣은 폴더 경로)


그다음 다운로드와 설정이 완료 됬는지 확인 하기 위해서 cmd창을 열으신다음

mvn -version 

위 명령어를 입력 하세요.

아래 처럼 나오면 다운 및 설정에 성공한 것이고, 실패 했다면 처음부터 다시 실행 해주세요 :) 





스프링 프로젝트에 이미지를 업로드 하려고 하는데, 자꾸만 500에러가 발생합니다..


org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException


에러의 원인을 파악하지 못 했었는데, 제가 바인딩에 개념이 없었습니다...


form에 인코딩 타입 enctype="multipart/form-date" 해주시면 파일 업로드가 가능한데,

input="file" 의 name은 컨트롤러의 MultipartFile 객체가 선언되는 이름과 같아야 합니다.

예를들어, <input type="file" name="thumnail_file" /> 이라면,

컨트롤러에서 MultipartFile thumnail_file 이 되야 합니다.


*500 NullpointerException 에러는 이 에러 말고도 다양하게 발생됩니다.



public ModelAndView fileUpload(HttpServletRequest request, MultipartFile thumnail_file) throws Exception {
   // write something
}


스프링 프로젝트에 MariaDB 와 Mybatis를 연동 후 테스트 까지 해보겠습니다.

테스트 진행은 Maria DB의 테이블 및 테스트 칼럼이 샘플이 존재해야 합니다.

* 저는 testdb 테이블에 age 란 int형 칼럼이 존재 합니다.


첫 번째로, pom.xml 에 아래 dependency를 복사 및 붙여넣기 하세요.


*Mysql 과 Maria DB의 차이 ↓

http://gabrielyj.tistory.com/119?category=732269


		
		
			org.mariadb.jdbc
			mariadb-java-client
			1.1.7
		

		
		
			org.mybatis
			mybatis
			3.3.1
		

		
		
			org.mybatis
			mybatis-spring
			1.2.4
		

		
		
			org.springframework
			spring-jdbc
			${org.springframework-version}
		



그 다음 WEB-INF폴더 -> spring폴더 -> root-context.xml 파일을 열어준뒤,

Namespace 메뉴를 클릭합니다.

(아래를 참고하고 aop, context, jdbc, mybatis-spring을 추가해주세요)






Namespaces에서 추가가 완료되면,

아래 내용을 root-context.xml 에 추가 해주세요.

url 의 jdbc:mysql:// 이후로는 사용하시는 IP와 포트 번호를 입력 해주시고,

username 과 password 는 각각 ID와 PW를 입력 해주시면 됩니다.

* 로컬 DB를 사용하시는분은 (jdbc:mysql://localhost:8080/DB이름) 을 입력 하시면 됩니다. 

* 혹시 localhost 인데 포트번호가 8080 아니면 해당되는 포트번호를 꼭 입력 하셔야 합니다.



   
   
      
      
      
      
      
   

   
   
  



그 다음 Java Resources 폴더-> src/main/resources 폴더 내부에

mappers 패키지 생성 후 그 안에 testMapper.xml 을 생성하고,

그 외부에 mybatis-config.xml 파일을 추가로 생성합니다.






testMapper.xml (DB 쿼리문을 작성하는 부분입니다.)








	


mybatis-config.xml (이 부분은 테스트 하는 동안 수정할 필요 없습니다.입력만 잘해주세요.)










그 다음 추가로 Java Resources 폴더-> src/main/resources 폴더 내부에

mybatisUtil 이란 패키지를 생성하고,

인터페이스 TService 와 클래스 TServiceImpl를 생성해줍니다.

이 부분은 컨트롤러와 mapper 사이를 연결해주는 부분입니다.


SqlSession을 Inject 해주고,

namespace 에는 *Mapper.xml 내에서 사용하는 이름과 똑같아야 합니다.




인터페이스 TService (in mybatisUtil package)

package mybatisUtil;
public interface TService {
	public int test();
}


클래스 TServiceImpl (in mybatisUtil package)

package mybatisUtil; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Service; @Service public class TServiceImpl implements TService { @Inject private SqlSession sqlSession; private static final String namespace = "my.mappers.testMapper"; @Override public int test() { return sqlSession.selectOne(namespace + ".selectTest"); } }




이제 다시 root-context.xml 로 돌아가서 아까 입력 안한 2, 3번째 부분을 완성니다.

주의할 점은, mapperLocations 부분 부터

Mapper, Service, ServiceImpl 이 일치하지 않으면, 404에러 발생합니다.

404에러가 발생하면 꼭 *Mapper.xml 부터 절차적으로 확인 해보세요!




   
   
      
      
      
   

   
   

      
   

   




이렇게 DB연동 작업은 끝났습니다.

마지막으로 controller 에서 실행을 하면 됩니다.


Service 부분을 @Autowired 어노태이션을 입력 하여 TService 를 등록 해주시고,

ModelAndView형 메소드를 만들어 그 안에 test() 메소드를 실행 해줍니다.

*저는 바로 int 형으로 반환을 받고 뿌려주기 위해 int 형으로 선언 하였습니다.

그리고 addObject 메소드를 이용하여 mav 객체에 담아주고,

setViewName 메소드를 이용해 호출되는 페이지명도 담아줍니다.

* test.jsp 를 불러올것이기 때문에 test를 담았습니다.




package controller;

import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import mybatisUtil.TService;

@Controller
public class TestController {
	
	@Autowired
	private TService tDAO;
	
	@RequestMapping(value = "/test.do")
	public ModelAndView portList(ModelAndView mav) throws ServletException {
		
		int test = tDAO.test();
		
		mav.addObject("test", test);
		mav.setViewName("test");
		return mav;
	}
}



마지막으로 아래를 참고하여 test.jsp 를 생성해줍니다.

그 다음 EL문을 이용하여 ${test}를 입력 합니다

* 위에서 addObject 할 때 이름을 'test'로 했기 때문에 ${test}


그리고 !!!


http://localhost:8080/프로젝트명/test.do   <- 접속하세요

이 부분이 말끔히 실행되려면, servlet-context.xml 부분의

preffix="/" suffix=".jsp" 입니다.

그래서 위에 setViewName 으로 넘어온 test가 /test.jsp 가 됩니다.


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




Insert title here


	${test}






최종 결과 : 저는 DB에 입력된 age 값이 '10' 이였습니다.

 





Could not publish server configuration for Tomcat v8.5 Server at localhost.

Multiple Contexts have a path of 프로젝트명



해당 오류는 servelt.xml 에 등록된 프로젝트의 경로가 중복 설정되어 있을때 발생 합니다.


해결 방법 :





'Project Explorer' OR 'Navigation' 에서 위에처럼 사용 Server 의 web.xml 에 들어갑니다.

 




그러면 맨 밑에 프로젝트명과 경로가 입력 되어 있습니다.

보통 위 빨간색으로 표시된 path 부분이 중복 설정되어 있어 에러가 발생 하기 때문에,

해당 프로젝트명과 일치하는 경로명을 입력해 주시고 재 실행 하시면 됩니다.

*/PortfolioPage 와 /JunPage는 제가 사용하는 프로젝트명이므로,

 자신이 설정한 프로젝트명으로 입력 하셔야 합니다.






처음 스프링을 공부 했을때, 왜 home.jsp가 실행되지 않는지 이해를 못 했습니다.

근데 사실 아주 간단하지 않은 간단한 구조를 갖고 있었습니다.


home.jsp 에서 바로 실행을 하게 되면 아래와 같이 404 에러가 발생 합니다.

왜냐하면, WEB-INF는 보안의 이유때문에 직접 접근이 불가능 합니다.

해당 폴더에는 프로젝트의 환경 설정을 해주는 중요한 파일들이 존재하게 됩니다.


예를들어, DB 를 사용한다면 WEB-INF폴더에  저장된 DB의 ID, PW가

적나라게 드러나기 때문입니다.






그렇다면 어떻게 접근 해야 할까요?

스프링 프로젝트의 기본 home.jsp 작동 원리를 이해 하시려면,

밑의 프로젝트 구조를 알아야 합니다.







webapp 의 WEB-INF 폴더 안에는 web.xml 이란 파일이 존재합니다.

*web.xml 은 프로젝트의 환경 설정을 해주는 파일

프로젝트가 실행되면 web.xml 이 가장 먼저 실행되고, 그 다음 

DispatcherServlet이 해당 프로젝트로 들어오는 요청들을 낚아채고 핸들링 해줍니다.

그 낚아챈 요청들은 servlet-context.xml로 보내주게 됩니다.






그렇게 요청을 받은 servlet-context.xml 은

① : <annotation-driven /> 란 태그를 사용하여 @(어노태이션)을 사용할 수 있고,

그 어노태이션의 사용 위치는(패키지명:Home_Test)

② : <context:component-scan base-package="aaa.bbb.(패키지명)" />

해당 패키지명 내부의 클래스들입니다.(클래스명:HomeController.java)









@RequestMapping의 value가 "/" 인데 이것의 의미는 프로젝트명 이후에

아무런 주소없이 실행을 시키면 해당 메소드를 실행 시키라는 뜻입니다.

addAttribute는 model객체에 "serverTime"이란 이름으로 현재 시간을 담은것이고,

return "home"은 위의 servlet-context.xml에서 설정한

preffix와 suffix를 앞 뒤에 붙여준다는 뜻입니다.



즉!!! http://localhost:8080/Home_Test/ 이렇게 주소창에 실행을 시키면


1. web.xml 실행 후 servelt-context 가 요청 낚아챔


2. servlet-context에서 어노태이션의 사용 여부 및 위치를 확인 후 값 전달

* /Home_Test/ 라서 "/"요놈만 넘어가는 중입니다,

  ex) Home_Test/home.jsp 라면 home.jsp 가 넘어갑니다.


3. Homecontroller의 @Controller가 확인되며, mapping 값인 "/"인 home 메소드가 실행

* return 값 "home"은 다시 servlet-context.xml 로 넘어갑니다.


4. servlet-context.xml 이 return 값 'home'에 preffix와 suffix를 붙여 줌

* preffix(/WEB-INF/views) + home + suffix(.jsp) = /WEB-INF/views/home.jsp


5. home.jsp 가 실행됨

* 실제론 (http://localhost:8080/Home_Test/WEB-INF/views/home.jsp) 가 실행 됩니다.





+ Recent posts