본문 바로가기
개발/Spring

스프링 RestTemplate Response XML

by Kingbbode 2016. 4. 10.

 공공데이터포탈의 공공 데이터를 활용하여 보았습니다.  공공 데이터는 JSON을 지원하는 API도 많지만 XML만 지원하는 API도 아직 많습니다. 저는 이번에 XML을 제공해주는 API를 사용하게 되었습니다.  RestTemplate를 사용하여 XML 데이터를 객체에 맵핑할 수 있는 많은 방법 중 제가 사용한 것은 jaxb를 사용한 XML 객체 맵핑입니다.

 XML 데이터를 다룰 때 알아두어야 할 개념!

 첫번째, 'OXM' 입니다. Object XML Mapping의 약자로 XML 데이터의 객체 맵핑을 다루는 개념입니다. 여기에서 특정 데이터를 XML 형태로 만드는 것을 마샬링(mashalling)이라고 하며 그 반대의 과정, 즉 XML 데이터를 특정 데이터로 만드는 것을 언마샬링(unmashalling)이라고 합니다. OXM의 개념을 알고 있으면 MarshallingHttpMessageConverter를 사용한 XML 객체 맵핑도 가능합니다.

 두번째, 'JAXB' 입니다. Java Architecture for XML Binding의 약자로 OXM을 쉽게 도와주는 도구와 같습니다. 마샬링, 언마샬링의 과정을 JAXB Annotation을 사용하여 직관적이고 쉽게 맵핑할 수 있도록 도와주고 있습니다. 저는 jaxb2RootElementHttpMessageConverter를 사용하여 JAXB Annotation으로 맵핑하였습니다. 

 주요 annotation을 알아야 사용 가능합니다. spring에서 이루어지는 annotaion을 통한 다른 객체 맵핑 방법이 비슷하듯 jaxb의 annotaion들도 전체적으로 비슷하였습니다.

<주요 JAXB Annotation>

@XmlAccessorType : XML 데이터를 어떤 방법으로 맵핑할지를 선언해줄 수 있는 annotaion으로 NONE을 사용할 시 XmlElement로 annotate된 객체만 맵핑시킵니다.

@XmlRootElement :  Class에 사용하는 annotation으로 해당 클래스가 XML 특정 노드의 루트라는 것을 뜻합니다. name을 사용하여 root를 명시할 수 있습니다.

@XmlElement : 변수에 사용하는 annotaion으로 해당 변수가 XML의 노드임을 뜻 합니다. XmlRootElement로 선언된 영역에서 해당 변수 이름과 맵핑하려는 XML 데이터 노드 이름이 같다면 굳이 명시해주지 않아도 됩니다.

@XmlElementWrapper : 해당 변수가 특정 노드들을 감싸고 있는 Wrapper란 것을 명시해주는 annotaion 입니다.


RestTemplate!

1
2
URI url = new URI(url + serviceKey);
response = restTemplate.exchange(url, HttpMethod.GET, entity, CustomResponse.class);
cs

 exchange를 이용하여 XML 데이터를 객체에 맵핑해보았습니다. 공공 API에 대한 간단한 팁을 드리자면 서비스키에 특수문자가 다수 들어가게 됩니다. restTemplate에서 URL 빌더나 String으로 서비스키가 포함된 url을 작성시 서비스키가 인코딩을 거치며 본 형태를 잃어버리게 됩니다. URI를 사용하여 안전하게 서비스키를 작성하였습니다.

 XML 객체 맵핑을 이해하기 좋게 샘플을 작성해보았습니다.

샘플1)
XML 데이터 형태 :
<response>
    <a>값</a>
</reponse>

자바 객체 :

1
2
3
4
5
6
7
8
9
10
11
12
13
@XmlRootElement(name = "response")
public class Response{    
    private String a;
 
    public String getA() {        
        return a;    
    }    
 
    public void setA(String a) {        
        this.a= a;
    }   
}
 
cs


샘플2)
XML 데이터 형태 : 
<response>
<item>
<a>값</a>
</item>
<response>

자바 객체 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@XmlRootElement(name = "response")
public class Response{    
    private Item item;
 
    public Item getItem(){
        return item;
    }
 
    public void setItem(Item item){
        this.item = item;    
    }
 
    @XmlRootElement(namme="item")
    public static class Item{
        private String a;
 
        public String getA() {        
            return a;    
        }    
 
        public void setA(String a) {        
            this.a= a;
        }  
    }
}
 
cs

샘플3)
XML 데이터 형태 : 
<response>
<items>
<item>
<a>값</a>
</item>
...
<item>
<a>값</a>
</item>
<items>
<response>

자바 객체 : 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@XmlRootElement(name = "response")
public class Response{
    private List<Item> items;    
    
    @XmlElementWrapper(name="items")
    @XmlElement(name="item")
    public List<Item> getItems(){
        return items;
    }
 
    public void setItems(List<Item> items){
        this.items = items;    
    }
 
    @XmlRootElement(namme="item")
    public static class Item{
        private String a;
 
        public String getA() {        
            return a;    
        }    
 
        public void setA(String a) {        
            this.a= a;
        }  
    }
}
 
cs


 샘플 1,2,3을 응용하면 여러가지 형태의 데이터를 받는 것이 가능합니다. 다음에 기회가 된다면 MarshallingHttpMessageConverter를 활용하여 XML 데이터 맵핑을 해보고 싶습니다. XML을 또 사용할 일이 있다면;;! 

댓글