Recent Posts
Recent Comments
Adsense
Archives
Visitor
Today
Total
관리 메뉴

Annotation

전자정부프레임워크 xml & json 리턴받는 방법 (egov, spring 마샬링) 본문

Java

전자정부프레임워크 xml & json 리턴받는 방법 (egov, spring 마샬링)

devs 2015. 1. 28. 21:08

벌써 10월 말이네요..

그간 너무도 바빠서 포스팅을 또 미루고 미뤘습니다.

그건 그렇고 최근 사이트 유입경로를 살펴보니 구글이 압도적이었습니다.

물론 네이버에서 등록을 않해주니 아직 그럴수있다 생각하지만..네이버는 등록하기 너무 힘들어요 :(

최대한 네이버에서 강조하는 "양질의 컨텐츠" 를 제작하여 포스팅 해야겠습니다.

어쨋든..앞서 말씀드린 것처럼, 이번 포스팅 주제는 다음과 같습니다.



전자정부프레임워크 xml & json 리턴받기 (마샬링)



저는 아직 초보 개발자라서 마샬링이라는 단어를 전자정부프레임워크를 접하며 처음 들었습니다.

딱 들었을때는 철권 캐릭터중 "마샬로우" 가 생각났구요..;)

사전적 의미를 찾아보니


컴퓨터 과학에서 마샬링(marshalling, l을 하나만 사용하여 marshaling이라고도 표기)이란 한 객체의 메모리에서의 표현방식을 저장 또는 전송에 적합한 다른 데이터 형식으로 변환하는 과정이다. 또한 이는 데이터를 컴퓨터 프로그램의 서로 다른 부분 간에 혹은 한 프로그램에서 다른 프로그램으로 이동해야 할 때도 사용된다. 마샬링은 직렬화(serialization)와 유사하며 한 오브젝트, 여기서는 직렬화 된 오브젝트로 멀리 떨어진 오브젝트와 통신하기 위해 사용된다. 이는 복잡한 통신을 단순화 하기 위해, 기본 요소(primitives) 대신 통신을 위한 맞춤형 오브젝트를 사용한다. 마샬링의 반대 개념으로 언마샬링(unmarshalling)이 있다 (디마샬링-demarshalling-이라고도 불리며, 역직렬화-deserialization-와 유사하다).


라고 합니다...

역시나 언제 어디서든 사전적 의미로만 이해하려고하면 어려운것 같습니다. (저만그런가요?)

그치만 이번 포스팅에서는 사용법을 먼저 보시고, 그 결과물을 보시면 한번에 이해가 되실겁니다.

참고해주실 부분은 저번 포스팅(전자정부프레임워크 마이바티스 연동설정)과 마찬가지로

1. 저는 STS (Spring Tool Suite) 가 아닌, eGovFrameWork (전자정부프레임워크) 를 사용하였습니다.

2. 코어프로젝트가 아닌 eGovFrame Web Project에서 샘플소스를 생성해서 사용했습니다.

3. 마샬링 라이브러리는 JAXB 를 사용하였습니다.



1. 메이븐 빌드 후 설정경로 및 파일 확인


마샬링에 필요한 도구는

<dependency>
	<groupId>org.codehaus.jackson</groupId>
	<artifactId>jackson-core-asl</artifactId>
	<version>1.8.0</version>
</dependency>

<dependency>
	<groupId>org.codehaus.jackson</groupId>
	<artifactId>jackson-mapper-asl</artifactId>
	<version>1.8.0</version>
</dependency>
	
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-oxm</artifactId>
	<version>3.0.5.RELEASE</version>
</dependency>

 

이렇게 3개 입니다.

첫번째와 두번째는 json을 위한 라이브러리리구요.

마지막 세번째는 xml을 위한 라이브러리 입니다.

추가 하신 뒤, 메이븐 빌드를 하셨으면 이제 셋팅할 경로를 확인하겠습니다.


위의 사진을 참고해 주시고, 우리가 설정해야할 폴더 경로는 두곳입니다.



src/main/java/     (클래스 폴더입니다)

src/main/webapp/WEB-INF/     (어플리케이션 설정 폴더입니다)


그 중에서 설정해야 할 파일은 총 4개입니다.


- 클래스 폴더에서 두가지 -

MapController.java     (컨트롤러 입니다)

MapVO.java     (VO 입니다)

- 어플리케이션 설정폴더에서 두가지 -

dispatcher-servlet.xml     (스프링mvc 설정파일 입니다)

web.xml     (어플리케이션 설정파일 입니다)


이렇게 4개만 기억하고 계시면 되구요. 설명 순서는 밑에서부터 올라가겠습니다.



2. 어플리케이션 설정


web.xml을 열어주세요.

우리는 서버에 요청할때. 확장자를 구분해서 요청합니다.

스프링을 손대기 전에는 대부분 .jsp로 요청합니다.

그치만 우리는 스프링을 사용하면서 모든 요청은 DispacherServlet 님께서 관리하시기 때문에 확장자를 정확하게 구분하여 요청하여야 합니다.

확장자는 이미 web.xml에 기본설정으로 *.do로 서플릿 맵핑이 되어있을겁니다.

따라서 xml 과 json 확장자를 추가하여 요청받도록 하겠습니다.


<servlet-mapping>
	<servlet-name>action</servlet-name>
	<url-pattern>*.xml</url-pattern>
</servlet-mapping>
	
<servlet-mapping>
	<servlet-name>action</servlet-name>
	<url-pattern>*.json</url-pattern>
</servlet-mapping>

 

물론..꼭 요청 확장자명을 xml과 json으로 하지 않으셔두 됩니다.

*.spring

*.battlefield

*.egovframework

등등...마음대로 하셔도 됩니다..........만

편의를 위해 xml 요청은 xml로, json은 json으로 하겠습니다.



3. Dispacher-Servlet 에 빈과 마샬링 대상객체 등록



2번에서 web.xml에 요청받을 확장자를 추가하였으니 이제 빈과 마샬링 설정을 해야합니다.

/WEB-INF/config/egovframework/springmvc/ 에서 dispacher-servlet.xml을 열어주세요.

xml 스타일을 변경하기 위해, 우리는 xml 스키마를 추가해야 합니다.


xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd"


 맨 윗줄에서 xmlns:oxm을 추가해주시구요,

xsi:schemaLocation 부분에 http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd 을 추가해주세요.

기존에 spring-context, spring-beans 가 등록되어있으니 그뒤에 추가해주셔야 합니다.

그다음 적당한 부분에 다음 소스를 추가합니다.


 <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
	<!-- 마샬링 대상 확장자 및 타입 정의 -->
	<property name="mediaTypes">
		<map>
			<entry key="xml" value="application/xml" />
			<entry key="json" value="application/json" />
		</map>
	</property>
				
	<!-- 마샬링 빈 등록 -->
	<property name="defaultViews">
		<list>
   			<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
				<property name="marshaller" ref="marshaller" />
   			</bean>
	   			
   			<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
				<property name="prefixJson" value="false"/>
   			</bean>
		</list>
	</property>
</bean>


 첫번째 <마샬링 대상 확장자 정의> 주석부분을 해석하자면,

리턴될 미디어 타입을 지정해 주는 부분입니다.

entry부분을 봐주세요. key가 xml로 들어오면 value를 application/xml로 뱉어준다는 겁니다.

이 말은. 우리가 위에서 web.xml에 확장자 *.xml 과 *.json을 추가하였죠?

따라서 확장자 xml로 들어오면 문서타입을 xml로 설정한다는 말입니다.

결국 web.xml에서 요청 확장자명을 *.battlefield로 설정하셨다면,

이쪽에서도 key를 battlefiled로 설정하셔야 합니다.

그래야 ContentNegotiatingViewResolver 빈이 캐치합니다.

두번째 <마샬링 빈 등록> 부분은 더 볼것도 없습니다.

xml 마샬링을 위해 MarshallingView 빈을 등록하고,

MappingJacksonJsonView 는 json 문서로 마샬링 하기위한 빈입니다.

따로 설정하지 않고 복사하고 쓰시면 되겠습니다.


그리고 나서 적당한 부분에 아래 소스를 참고하여 작성해 주세요.


<oxm:jaxb2-marshaller id="marshaller">
	<oxm:class-to-be-bound name="egovframework.example.map.service.MapVO" />
</oxm:jaxb2-marshaller>

 

이부분은 마샬링을 시킬 대상을 적어주는 것입니다.

이글을 보고계신분이 만들어놓은 VO 객체의 주소를 정확히 적어주세요.

VO가 뭔데요? 라고 물으신다면..구글이나 네이버 검색을 추천하겠습니다. :)

여기까지 셋팅이 되셧으면 다음으로 넘어가겠습니다.



4. 마샬링 스타일 설정


마샬링 스타일설정이라는 제목이 좀 안맞게 들릴수도 있는데요.

그냥 컨트롤러와 VO 설정이라는 말입니다...

그럼 먼저 VO 쪽을 설정하겠습니다.


@XmlRootElement(name = "fields")
@XmlAccessorType(XmlAccessType.FIELD)
public class MapVO {

	@XmlElement(name = "gid")
	private String gid = "";
	@XmlElement(name = "content")
	private String content = "";
	@XmlElement(name = "title")
	private String title = "";
	
	public String getGid() {
		return gid;
	}
	public void setGid(String gid) {
		this.gid = gid;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	
}


어노테이션만 없으면 일반적으로 코딩하시던부분과 동일하기 때문에 코드 보시면 이해가 금방 되시리라 믿습니다.

그리고 위의 코드에 있는 어노테이션은 JAXB 레퍼런스를 참고해주시면 감사하겠구요.

짧은 설명으로 @XmlRootElement 어노테이션은 최상위 부모 노드명을 설정하는 어노테이션입니다.

그리고 일반 필드들은 @XmlElement 어노테이션으로 지정해주시면 되구요.

간단하죠? :)

다음 컨트롤러쪽을 설정하겠습니다.


@RequestMapping(value = "/map/info")
public String goToInfo(@ModelAttribute("mapVO") MapVO mapVO, Model md){

	return "/map/info";
}


 @RequestMapping 어노테이션으로 요청받을 url을 평소처럼 지정해주시되,

확장자는 적지 마셔야 합니다.

클라이언트에서 요청시 확장자를 구분하여 알아서 제어하기 때문에 컨트롤러에서는 요청명까지만 적어주셔야 합니다.

만약 info.do 라고 적어주시면 무조껀 .do 로밖에 요청을 받을 수 없습니다.

메소드 인자로는 @ModelAttribute를 사용하였는데, 여기서 중요한건 @ModelAttribute 어노테이션은 마샬링 할 때 주의를 하셔야 합니다.

@ModelAttribute 어노테이션으로 클래스를 지정하면

메소드 내부에서 model.addAttribute() 를 사용하여도 결과는 @ModelAttribute 에 지정된 클래스로 마샬링이 됩니다.

결국 클라이언트로부터 받은 인자들을 자동으로 클래스의 필드에 맵핑시키려면 @ModelAttribute 어노테이션을 빼주셔야 하구요,

메소드 내부에서 마샬링 시킬 클래스를 생성해서 모델에 던저야만 원하는 결과를 얻을 수 있습니다.

말이 좀 복잡하고 어려웠나요?

쉽게 풀이하자면

1. 나는 클라이언트로부터 받은 값을 바로 xml로 던저버리겠다. (@ModelAttribute 사용)

2. 내가 임의로 xml을 만들어 던저버리겠다. (@ModelAttribute 사용 하지않고 xml만들 클래스를 생성하여 모델에 추가)

하시면 되겠습니다.

결국 1번 같은 경우는 위의 소스처럼 코딩하시면 되구요.

2번같은 경우는 아래 소스처럼 코딩 하시면 됩니다.


@RequestMapping(value = "/map/info")
public String goToInfo(MapVO mapVO, Model md){
	
	resultXML xml = new resultXML();
	xml.setContent = mapVO.getContent();
	
	md.addAttribute("xml", xml);
	
	return "/map/info";
}


 이해 되시나요?

이해 되시길 바라며.....마지막 부분으로 넘어가겠습니다.



5. 테스트



테스트는 참 기대되는 단계중 하나죠.

에러를 뿜던가, 좋은 결과를 뿜던가..

위의 컨트롤러를 참고하여 테스트를 진행해봤습니다.


- XML 요청 -

127.0.0.1/map/info.xml?gid=1&content=Result&title=Marshalling


<?xml version="1.0" encoding="UTF-8"?>
<fields>
    <gid>1</gid>
    <content>Result</content>
    <title>Marshalling</title>
</fields>


 결과는 이렇게 나올것이구요.


- JSON요청 -

127.0.0.1/map/info.json?gid=1&content=Result&title=Marshalling

{
    "mapVO": {
        "content": "Result",
        "gid": "1",
        "title": "Marshalling"
    }
}


 JSON 결과도 역시 이렇게 잘 나왔습니다.

.do 는 생략해도 되겠죠?

예상하셨겠지만 .do는 뷰 리졸버를 통하여 해당하는 .jsp가 보이게 됩니다.



6. 마치며



사실 구지 마샬링을 통하여 XML 또는 JSON을 리턴받을 필요는 없습니다.

귀찮아서 그렇지 직접 만들어서 쓰셔도 상관없습니다.

하지만 그 귀찮음을 조금이나마 덜고 삽질을 줄이기위해 사용하는 것이니 알아두면 참 좋은 기술인건 분명합니다.

마샬링의 최대의 장점은 아래와 같다고 생각합니다.

우리가 순수 자바 문자열로 XML 을 리턴 받으려면

문자열을 일일이 만들어서 보내야하지만 마샬링작업은 객체를 사용하여 XML 을 만들어 보내줍니다.

따라서 우리는 컨트롤러에서 한개의 메소드로 세가지의 기능을 할 수 있습니다.

*.do 는 뷰로,

*.xml 은 XML로,

*.json 은 JSON으로.

이보다 얼마나 더 간편하고 좋을수 있을까요?

만약 이런 마샬링 작업이 아니라면..

요청별로, 더 세분화 하면 기능별로..메소드를 따로 두어 요청해서 받아야할 것입니다.

getMapXML(), getMapJSON, getMapView() 이런식으로 말이죠.

물론 너무 단정지어서 제가 이야기했지만 분명 저런 상황은 존재합니다.

얼핏 보기에 이번 포스팅이 설정할것도 많고 어렵게 느껴지실 수 있겠지만 전자정부프레임워크를 시작하면서 느낀건 딱 한가지 입니다.

XML 설정을 잘하자!

그 외에는 따로 어노테이션이나 설정이 어색해서 그렇지 대부분 비슷합니다.

어찌되었든 여기까지 읽어주시고 따라하시느라 매우 고생하셨습니다.

끝끝내 해도 안되시는 분이 있으면 쪽지 남겨주셔도 좋습니다.

소스가 필하신분도요 :)

설명에서 틀린부분이 있다면 꼭 저에게 알려주세요. 꼭이요.

감사합니다.



Comments