diff --git a/pom.xml b/pom.xml
index a0fab39..785f9aa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,6 +94,12 @@
2.3.1
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ 2.10.5
+
+
javax.servlet
javax.servlet-api
diff --git a/src/main/java/cokr/xit/foundation/data/XML.java b/src/main/java/cokr/xit/foundation/data/XML.java
new file mode 100644
index 0000000..37f8372
--- /dev/null
+++ b/src/main/java/cokr/xit/foundation/data/XML.java
@@ -0,0 +1,150 @@
+package cokr.xit.foundation.data;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.function.Consumer;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
+
+import cokr.xit.foundation.AbstractComponent;
+
+/**XML 포맷/파싱 유틸리티.
+ * @author mjkhan
+ */
+public class XML extends AbstractComponent {
+ private XmlMapper xmlMapper;
+
+ /**XML 포맷/파싱에 사용하는 XmlMapper를 반환한다.
+ * @return XML 포맷/파싱에 사용하는 XmlMapper
+ */
+ public XmlMapper getXmlMapper() {
+ if (xmlMapper == null) {
+ xmlMapper = new XmlMapper();
+ xmlMapper.configure(ToXmlGenerator.Feature.WRITE_XML_DECLARATION, true);
+ }
+ return xmlMapper;
+ }
+
+ /**XML 포맷/파싱에 사용하는 XmlMapper를 설정한다.
+ * @param xmlMapper XML 포맷/파싱에 사용하는 XmlMapper
+ * @return 현재 XML 객체
+ */
+ public XML setXmlMapper(XmlMapper xmlMapper) {
+ this.xmlMapper = xmlMapper;
+ return this;
+ }
+
+ /**XML 포맷/파싱에 사용하는 XmlMapper의 동작을 설정한다.
+ * @param configurer XmlMapper 동작 설정 function
+ * @return 현재 XML
+ */
+ public XML configure(Consumer configurer) {
+ if (configurer != null)
+ configurer.accept(getXmlMapper());
+ return this;
+ }
+
+ /**XML 문자열을 파싱하여 주어진 클래스의 객체로 변환한다.
+ * @param 클래스 유형
+ * @param xml XML 문자열
+ * @param klass 클래스
+ * @return 문자열을 파싱하여 변환한 객체
+ */
+ public T parse(String xml, Class klass) {
+ try {
+ return getXmlMapper().readValue(xml, klass);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ public T parse(String xml, TypeReference typeRef) {
+ try {
+ return getXmlMapper().readValue(xml, typeRef);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ /**input의 내용을 파싱하여 주어진 클래스의 객체로 변환한다.
+ * @param 클래스 유형
+ * @param input XML input
+ * @param klass 클래스
+ * @return input을 파싱하여 변환한 객체
+ */
+ public T parse(InputStream input, Class klass) {
+ try {
+ return getXmlMapper().readValue(input, klass);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ public T parse(InputStream input, TypeReference typeRef) {
+ try {
+ return getXmlMapper().readValue(input, typeRef);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ /**주어진 객체를 XML 문자열로 변환한다.
+ * @param obj 객체
+ * @return 객체를 변환한 XML 문자열
+ */
+ public String stringify(Object obj) {
+ return stringify(obj, false);
+ }
+
+ /**주어진 객체를 XML 문자열로 변환한다.
+ * @param obj 객체
+ * @param indent 띄어쓰기 여부
+ * - 띄어쓰기를 적용하려면 true
+ * - 그렇지 않으면 false
+ *
+ * @return 객체를 변환한 XML 문자열
+ */
+ public String stringify(Object obj, boolean indent) {
+ if (obj instanceof String)
+ return (String)obj;
+
+ XmlMapper mapper = getXmlMapper();
+ ObjectWriter writer = !indent ? mapper.writer() : mapper.writerWithDefaultPrettyPrinter();
+
+ try {
+ return writer.writeValueAsString(obj);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ /**주어진 객체를 OutputStream에 저장한다.
+ * @param out OutputStream
+ * @param obj 객체
+ * @param indent 띄어쓰기 여부
+ * - 띄어쓰기를 적용하려면 true
+ * - 그렇지 않으면 false
+ *
+ */
+ public void write(OutputStream out, Object obj, boolean indent) {
+ XmlMapper mapper = getXmlMapper();
+ ObjectWriter writer = !indent ? mapper.writer() : mapper.writerWithDefaultPrettyPrinter();
+
+ try {
+ writer.writeValue(out, obj);
+ } catch (Exception e) {
+ throw runtimeException(e);
+ }
+ }
+
+ /**주어진 객체를 OutputStream에 저장한다.
+ * @param out OutputStream
+ * @param obj 객체
+ */
+ public void write(OutputStream out, Object obj) {
+ write(out, obj, false);
+ }
+}
\ No newline at end of file