1부에서는 HttpServletResonse의 getWriter()를 통해 마샬링한 데이터를 바로 출력하는 예제,

 

2부에서는 마샬링한 데이터를 OutputStream에 저장후 InputStream으로 변환하여 언마샬링 하는 예제를 작성해 봤습니다.

 

이번에는 마샬링 결과를 파일로 저장후 InputStreamReader를 통해 File을 읽어와서 언마샬링 하는 예제를 작성해 보겠습니다.

 

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링 후 파일로 저장

import com.thoughtworks.xstream.XStream;

 

XStream xstream = new XStream();
final String xmlPath = "D:\\test.xml";
OutputStreamWriter osw =  

new OutputStreamWriter(new FileOutputStream(new File(xmlPath)), "utf-8");

 

UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
userBltnListCollections.setUserBltnList(list);
xstream.processAnnotations(UserBltnListCollections.class);
xstream.toXML(userBltnListCollections, osw); //마샬링한 데이터를 파일로 저장

-----------------------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)

  //(UserBltnListVO클래스는 일반적인 getter/setter를 포함한 Value Object Class임)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

-------------------------------------------------------------------------------------------------

- UserBltnListVO (ValueObject Class) 

 

import com.thoughtworks.xstream.annotations.XStreamOmitField

 

public class UserBltnListVO {
 
 //@XStreamAsAttribute로 지정시 속성으로 지정된다.
 //JAXB에서는 @XmlAttribute(name="xx")로 지정함 필드일 경우엔 마샬링시
 //JAXB와 마찬가지로 따로 지정할 필요는 없는것 같다.
 //JAXB는 마샬링시 모든 필드를 바인딩 하지만 XStream에서는
 //@XStreamOmitField가 지정된 필드는 제외시킨다. 
 
 @XStreamOmitField
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링후 데이터를 저장한 파일을 InputStreamReader로 읽어와서 언마샬링

InputStreamReader isr = new InputStreamReader(new FileInputStream(xmlPath),"utf-8");
UserBltnListCollections userBltnListCollectionsToUnMarshall = null;

//지정된 XStream 관련 Annotation을 처리한다.
xstream.processAnnotations(UserBltnListCollections.class);   
//마샬링된 파일을 InputStreamReader로 읽어와서 언마샬링 함
userBltnListCollectionsToUnMarshall = (UserBltnListCollections)xstream.fromXML(isr);   

-----------------------------------------------------------------------------------------------------------------

JAXB에서 마샬링된 XML을 언마샬링 할때는 File클래스로 저장 후 바로 읽어와서 언마샬링 하도록 했으나 이번엔 방식은

 

비슷하나 Stream을 통해서 저장하는 방식으로 바꿔봤습니다. 예제에서는 작은 파일이기 때문에 어떤 방법으로 처리해도

 

IO에 무리가 되지 않으나 XML크기가 크고 빈번한 요청이 일어나는 Task라면 어떤 방식으로 처리할것인가를 고민해야 할

 

것으로 보입니다. 여기까지 XStream을 통한 마샬링, 언마샬링 방법에 대해서 알아봤습니다. 개념은 조금 다를지 몰라도

 

결과적으로 봐선 XStream을 사용하는것이 더 좋을것 같습니다. 좀더 유연하다고나 할까요? 시간이 되면 List<Map>을

 

언마샬링 하는 예제를 작성해 보려고 합니다. 이경우엔 따로 구현을 해야되는 것으로 알고 있습니다. JAXB 사용방법

 

예제를 작성할때도 잠깐 언급했지만 DomParser사용할때에 비해서 이렇게 비교가 안될정도로 편하게 쓸 수 있게 만들어준

 

개발자 분들에게 항상 존경과 감사함을 느낍니다.

신고

1부에서는 HttpServletResonse의 getWriter()를 통해 마샬링한 데이터를 바로 출력하는 예제를 작성해 봤습니다.

 

이번에는 OutputStream으로 마샬링한 데이터를 저장하고 이를 InputStream으로 변환하여 언마샬링 처리하는 방법을

 

예제로 작성해보겠습니다. JAXB를 사용한 예제도 비슷하게 HttpUrlConnection을 통해 가져온 InputStream을

 

언마샬링 하는 예제가 있으니 참고하시기 바랍니다.

 

-----------------------------------------------------------------------------------------------------------------

※Object를 마샬링 후 OutputStream으로 저장한 후 InputStream으로 변환

  import com.thoughtworks.xstream.XStream;

 

  ByteArrayOutputStream ous = new ByteArrayOutputStream();
  ByteArrayInputStream ins = null;
  byte[] byteData= null;
  
  UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
  userBltnListCollections.setUserBltnList(list); //list는 List Collection클래스임
  
  XStream xstream = new XStream();    

  //지정된 XStream 관련 Annotation을 처리한다.
  xstream.processAnnotations(UserBltnListCollections.class); 

  //UnMarshalling시 InputStream을 처리하기 위해 OutputStream으로 저장
  xstream.toXML(userBltnListCollections, ous); 
  byteData = ous.toByteArray();
  ins = new ByteArrayInputStream(byteData); //InputStream으로 변환 

-----------------------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)

  //(UserBltnListVO클래스는 일반적인 getter/setter를 포함한 Value Object Class임)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

-------------------------------------------------------------------------------------------------

- UserBltnListVO (ValueObject Class) 

 

import com.thoughtworks.xstream.annotations.XStreamOmitField

 

public class UserBltnListVO {
 
 //@XStreamAsAttribute로 지정시 속성으로 지정된다.
 //JAXB에서는 @XmlAttribute(name="xx")로 지정함 필드일 경우엔 마샬링시
 //JAXB와 마찬가지로 따로 지정할 필요는 없는것 같다.
 //JAXB는 마샬링시 모든 필드를 바인딩 하지만 XStream에서는
 //@XStreamOmitField가 지정된 필드는 제외시킨다. 
 
 @XStreamOmitField
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

 - InputStream을 언마샬링

 UserBltnListCollections userBltnListCollectionsToUnMarshall = null;  

 //지정된 XStream 관련 Annotation을 처리한다.
 xstream.processAnnotations(UserBltnListCollections.class);

 //InputStream을 읽어서 바인딩될 Object에 저장  
 userBltnListCollectionsToUnMarshall =  (UserBltnListCollections) xstream.fromXML(ins);

-----------------------------------------------------------------------------------------------------------------

 

JAXB로 마샬링후 언마샬링 처리할때와 방식은 거의 비슷합니다. JAXB나 XStream둘 중 한가지라도 써보셨다면 결국

 

마샬링이나 언마샬링을 처리하는 부분의 약간의 차이, 어노테이션 이름 차이정도가 있으며 결국 맵핑을 얼마나 잘 시켜서

 

사용하느냐가 관건인 듯 싶습니다.

신고

XStream을 통한 마샬링, 언마샬링 처리에 대해서 알아보겠습니다. 최근 JAXB(Java Architecture for XML Binding)

 

API와 더불어 OXM(Object/Xml Mapping)에 많이 사용되고 있는 것 같네요. 스프링 프레임워크를 쓰시는 분들은

 

JAXB, XStream 모두 Spring OXM에 포함되어 있으므로 간단히 의존성 주입후 사용하시면 되겠습니다.

 

저는 따로 라이브러리를 받아서 사용 했습니다. 마샬링, 언마샬링 구현 방식은 JAXB와 거의 유사합니다만

 

가독성은 XStream이 더 간결했으며 대략적인 개념은 비슷한 라이브러리 들이지만 약간씩 차이가 있습니다.

 

개인적으로는 편의성만 보면 XStream이 쓰기 더 편하게 느껴집니다. 이제 간단한 예제부터 한번 보겠습니다.

 

대략적인 설명은 예제의 주석 부분을 보시면 이해 되실겁니다. 실습해보면서 나름 이해한 내용이라 잘못된 이해일수도

 

있습니다.

 

*JAXB를 통한 Marshalling, UnMarshalling 방법은 아래 링크들을 참고하시면 됩니다.

 

1부 : 파일을 통한 마샬링, 언마샬링 처리

2부 : HttpUrlConnection을 통해 얻어온 InputStream을 언마샬링

3부 : 마샬링된 데이터를 OutputStream에 저장하고 다시 InputStream으로 변환 후 언마샬링

 

 

※마샬링 후 출력

  import com.thoughtworks.xstream.XStream

 

  UserBltnListCollections userBltnListCollections = new UserBltnListCollections();
  userBltnListCollections.setUserBltnList(list);

 

  //마샬링시 xpp3 라이브러리의 종속성을 피하기 위해 DomDriver를 사용하도록 설정

  //할수 있다. 일부에선 속도저하가 심각하므로 꿈에서도 사용하지 말라는 소리가 있지만

  //그렇게 방대한 XML이 아니라면 상관 없을 듯 싶다.

  //ex) XStream xstream = new XStream(new DomDriver("utf-8"));


  XStream xstream = new XStream();

  //지정된 XStream관련 Annotation을 처리한다. 
  xstream.processAnnotations(UserBltnListCollections.class);
  xstream.toXML(userBltnListCollections, response.getWriter());   //출력

 

------------------------------------------------------------------------------------------------

 - UserBltnListCollections Class

  import com.thoughtworks.xstream.annotations.XStreamAlias;
  import com.thoughtworks.xstream.annotations.XStreamImplicit;

 

  //루트 Element의 별칭을 지정해줌

  //주의점 : 당연한 결과겠지만 마샬링시 필드명에 Alias를 지정하여 필드명 변경등이

  //있을경우 언마샬링시에도 XStreamAlias를 사용해서 일치하게 설정해야 한다.
  @XStreamAlias(value="userBltnList")
  public class UserBltnListCollections {
 
  //하위 필드(Collection)에 대해 XStreamImplicit Annotation으로 지정함
  //(XAJB의 경우 @XmlElement(name="bltnList")로 지정함)
  @XStreamAlias(value="bltnList")
  @XStreamImplicit(itemFieldName="bltnList")
  private List<UserBltnListVO> userBltnList = null;
  
  public List<UserBltnListVO> getUserBltnList() {
   if(userBltnList==null){
    userBltnList = new ArrayList<UserBltnListVO>();
  }
   return userBltnList;
  }

  public void setUserBltnList(List<UserBltnListVO> userBltnList) {
   this.userBltnList = userBltnList;
  }  
 }

------------------------------------------------------------------------------------------------

 

마샬링한 데이터를 곧바로 HttpServletResponse의 getWriter()를 통해 출력하는 예제를 작성해봤습니다. JAXB로 마샬링

 

할때와 결과는 동일하지만 가독성에 있어서는 XStream이 간결해 보입니다. 다음 예제에서는 OutputStream으로 저장한

 

마샬링 데이터를 InputStream으로 변환하여 출력하는 예제를 작성해 보겠습니다.

신고

1부에서는 파일을 통한 마샬링, 언마샬링 처리, 2부에서는 HttpUrlConnection을 통해 얻어온 InputStream을 언마샬링,

 

3부에서는 마샬링된 데이터를 OutputStream에 저장하고 다시 InputStream으로 변환하여 언마샬링 하는 예제를

 

작성해봤습니다. 마지막으로 가장 간단하게 HttpServletResponse 객체의 getWriter()를 통해 마샬링된 데이터를

 

바로 출력시키는 예제를 작성해 보겠습니다. 이번 예제는 마샬링 후 바로 출력하기 때문에 언마샬링을 거치지

 

않습니다.

 

-XML 원본 데이터 예시

 <userBltnList>
     <bltnList>
         <isSecret>Y</isSecret>
         <name>TEST</name>
         <no>TESTNO</no>
         <readNum>TESTREADNUM</readNum>
         <subject>Android GCM Push with Command Pattern</subject>
         <writeDay>2013-02-15 18:00:18.0</writeDay>
     </bltnList>
 </userBltnList>

-----------------------------------------------------------------------------------------------------------------

 

※ Collection클래스를 마샬링

  import javax.xml.bind.JAXBContext;

  import javax.xml.bind.Marshaller;

 

  //list는 List Collection클래스

  UserBltnList userBltnList = new UserBltnList();
  userBltnList.setList(list);

 

  JAXBContext jaxbContext = null;
  Marshaller jaxbMarshaller = null;

  
  jaxbContext = JAXBContext.newInstance(UserBltnList.class);
  jaxbMarshaller = jaxbContext.createMarshaller();
  jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");  
  jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
  jaxbMarshaller.marshal(userBltnList, response.getWriter()); 

 

-----------------------------------------------------------------------------------------------------------------

- UserBltnList Class

 @XmlRootElement(name="userBltnList")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class UserBltnList {
 
  //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
  //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.
  @XmlElement(name="bltnList")
  private List<UserBltnListVO> list = null;

  public List<UserBltnListVO> getList() {
   if(list==null){
    list = new ArrayList<UserBltnListVO>();
   }
   return list;
  } 
  public void setList(List<UserBltnListVO> list) {
   this.list = list;
  }
 }

-----------------------------------------------------------------------------------------------------------------

- UserBltnListVO(Value Object Class)

public class UserBltnListVO {
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

 

여기까지 4부에 걸쳐 JAXB(Java Architecture for XML Binding) API 사용방법에 대해 알아보았습니다. 예전에 DOMParser를

 

통해 삽질하던걸 생각해보면 정말 간편해 졌다는 생각이 듭니다. DOMParser를 사용하다 보면 XML이 복잡해지면 이놈이

 

저놈같고 저놈이 이놈같고 그랬었죠. 머리가 단순해서인지 계층구조는 저하고 좀 안맞는 것 같습니다.;; 지금 다니는 회사에선

 

사실 이런 데이터 변환 처리를 거의 할일이 없는데 알아두면 분명 유용할 듯 싶어 예제를 작성해봤습니다. 어딘가에서 유용하게

 

쓰였으면 좋겠군요. 소스는 그대로 붙혀서 사용하시면 당연히 실행이 안되실것이고 메소드 등은 환경에 맞춰 작성해서 참고

 

하여 사용하시면 될 듯 싶습니다.

신고

1부에서는 파일을 통한 마샬링, 언마샬링 처리, 2부에서는 HttpUrlConnection을 통해 얻어온 InputStream을 언마샬링

 

하는 방법에 대해 알아봤습니다. 이번엔 마샬링한 데이터를 OutputStream에 저장하고 InputStream으로 변환하여

 

언마샬링 처리 하는 예제를 작성해봤습니다. 일반적으로 이렇게 쓰이는 사례는 거의 없을듯 합니다.

 

-XML 원본 데이터 예시(UnMarshalling시 사용)

 <userBltnList>
     <bltnList>
         <isSecret>Y</isSecret>
         <name>TEST</name>
         <no>TESTNO</no>
         <readNum>TESTREADNUM</readNum>
         <subject>Android GCM Push with Command Pattern</subject>
         <writeDay>2013-02-15 18:00:18.0</writeDay>
     </bltnList>
 </userBltnList>

-----------------------------------------------------------------------------------------------------------------

※ 마샬링한 데이터를 OutputStream으로 생성

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

 

JAXBContext jaxbContext = null;
Marshaller jaxbMarshaller = null;

 

//list는 List(Collection 클래스)

UserBltnList userBltnList = new UserBltnList();
userBltnList.setList(list);
  
ByteArrayOutputStream ous = new ByteArrayOutputStream();
ByteArrayInputStream xmlStream = null;
byte[] byteData = null;
   
jaxbContext = JAXBContext.newInstance(UserBltnList.class);
jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); 
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
 
jaxbMarshaller.marshal(userBltnList, ous);  //마샬링된 데이터를 OutputStream에 저장 
byteData = ous.toByteArray(); //OutputStream을 Byte로 처리
xmlStream = new ByteArrayInputStream(byteData); //Byte를 InputStream으로 처리  

-----------------------------------------------------------------------------------------------------------------

 

- UserBltnList Class

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

 

@XmlRootElement(name="userBltnList")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserBltnList {
 
 //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
 //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.
 @XmlElement(name="bltnList")
 private List<UserBltnListVO> list = null;

 public List<UserBltnListVO> getList() {
  if(list==null){
   list = new ArrayList<UserBltnListVO>();
  }
  return list;
 } 
 public void setList(List<UserBltnListVO> list) {
  this.list = list;
 }
}

 

-------------------------------------------------------------------------------------------------

- UserBltnListVO(Value Object Class)

public class UserBltnListVO {
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

 

-----------------------------------------------------------------------------------------------------------------

※ OuputStream에 저장된 마샬링된 데이터를 InputStream으로 변환하여 언마샬링 처리

UserBltnListUnMarshall userBltnListUnMarshall = null;

jaxbContext = JAXBContext.newInstance(UserBltnListUnMarshall.class);
userBltnListUnMarshall =

 (UserBltnListUnMarshall) jaxbContext.createUnmarshaller().unmarshal(xmlStream);

-----------------------------------------------------------------------------------------------------------------

 

-----------------------------------------------------------------------------------------------------------------

- UserBltnListUnMarshall Class

@XmlRootElement(name="userBltnList")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserBltnListUnMarshall {
 
 //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
 //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.
 @XmlElement(name="bltnList")
 private List<UserBltnListVOUnmarshall> bltnList = null;

 public List<UserBltnListVOUnmarshall> getList() {
  return bltnList;
 }
 public void setList(List<UserBltnListVOUnmarshall> bltnList) {
  this.bltnList = bltnList;
 }
}

-----------------------------------------------------------------------------------------------------------------

 

-----------------------------------------------------------------------------------------------------------------

 - UserBltnListVOUnmarshall(Value Object Class)

@XmlAccessorType(XmlAccessType.FIELD)
public class UserBltnListVOUnmarshall {
 
 //UserBltnListUnMarshall에서 루트 Element인 userBltnList를 가져오도록 하고
 //집합 Element인 bltnList를 컬렉션 형태로 가져오도록 했다. 이 bltnList의
 //Element를 XmlElement Annotation을 통해 가져오도록 한다.
 //(Marshalling때와 반대로 UnMarshalling때는 XmlElement나 XmlAttribute Annotation
 //으로 지정한 명을 원본 XML의 Element나 Attribute명을 읽어오게 된다.)
 
 @XmlElement(name="no")
 private String no = "";
 @XmlElement(name="subject")
 private String subject = "";
 @XmlElement(name="writeDay")
 private String writeDay = "";
 @XmlElement(name="readNum")
 private String readNum = "";
 @XmlElement(name="isSecret")
 private String isSecret = "";
 @XmlElement(name="name")
 private String name = "";

 ..

  getter/setter 생략

 ..

}

-----------------------------------------------------------------------------------------------------------------

 

JAXB의 Unmashaller가 OutputStream을 알아서 처리해 줬다면 참 좋았겠지만 지원하지 않으므로.. 위와같은 방법으로 사용할

 

수 있음을 예제로 만들어 봤습니다. 다음 예제에서는 최종으로 HttpServletResponse객체의 getWriter()를 사용하여 마샬링된

 

데이터를 바로 출력할 수 있는 예제를 작성해 보겠습니다.

 

신고

JAXB를 이용한 File로 마샬링, 마샬링된 XML을 언마샬링 하는 방법에 대해 살펴보았습니다. 이번엔 HttpUrlConnection

 

을 통해 얻어온 InputStream으로 언마샬링 하는 예제를 써보겠습니다. 1부의 File을 통한 Marshalling, UnMarshalling

 

예제를 보시고 나면 금방 이해 되실 듯 싶습니다. 1부에서는 List형 데이터를 마샬링, 언마샬링 하는 방법을 다뤘고

 

이번에는 약간 변경하여 XML Element의 Attribute처리를 다뤄봤습니다.

 

-XML 원본 데이터 예시(UnMarshalling시 사용)

 <packing_list>
    <packing_data barcode_read_date="XXX" packing_no="XXX" reg_userid="XXX" complete_yn="Y"     matched_result="N" /> 

    <packing_data barcode_read_date="XXX" packing_no="XXX" reg_userid="XXX" complete_yn="Y"     matched_result="N" /> 
 </packing_list>

 

-------------------------------------------------------------------------------------------------※ HttpUrlConnection을 통해 XML을 InputStream으로 가져옴

 public InputStream getXmlStreamFromUrl(Map<String, Object> paramMap){
  String packingNo = (String)paramMap.get("packing_no");
  
  URL url = null;
  HttpURLConnection httpUrlConnection = null;
  InputStream ips = null;
  
  try {
   url = new URL("
http://testurl.com/test.xml");   
   URLConnection urlConnection = url.openConnection();
   httpUrlConnection = (HttpURLConnection) urlConnection;
   
   httpUrlConnection.setDoInput(true);
   httpUrlConnection.setDoOutput(true);
   httpUrlConnection.setRequestMethod("POST");
   httpUrlConnection.setUseCaches(false);
   httpUrlConnection.setDefaultUseCaches(false);
   httpUrlConnection.setRequestProperty("Content-Type", "text/xml");
   
   ips = httpUrlConnection.getInputStream();
   ips.close();
  } catch (MalformedURLException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  return ips;
 }

------------------------------------------------------------------------------------------------

 - HttpUrlConnection을 통해 가져온 XML(InputStream) 언마샬링

 //UnMarshalling을 위해 XML을 HttpURLConnection을 통해 가져온 InputStream을
 //가져온다.  

 import javax.xml.bind.JAXBContext;

 import javax.xml.bind.Marshaller;

 

 JAXBContext jaxbContext = null;


 InputStream xmlStream = getXmlStreamFromUrl(paramMap);   
 PackingList packingList = null;

 

  try {   
   jaxbContext = JAXBContext.newInstance(PackingList.class);
   packingList = (PackingList) jaxbContext.createUnmarshaller().unmarshal(xmlStream);  
  } catch (JAXBException e) {
   e.printStackTrace();
  }

------------------------------------------------------------------------------------------------

- UnMarshalling을 위한 Java Class - PackingList

//UnMarshalling시에는 Marshalling과 반대로 XmlRootElement어노테이션에 지정한 이름에
//해당하는 데이터를 가져오게 된다.
@XmlRootElement(name="packing_list")
@XmlAccessorType(XmlAccessType.FIELD)
public class PackingList {
 //UnMarshalling시에는 Marshalling과 반대로 XmlElement어노테이션에 지정한 이름에 해당하는
 //데이터를 가져오게 된다.(Marshalling시에는 필드이름으로 지정하게 됨)
 
 //PackingListVO에서는 원본 XML과 같이 각 속성의 이름을 통해 값을 가져오도록 함.
 @XmlElement(name="packing_data")
 private List<PackingListVO> list = null;

 public void setPackingList(List<PackingListVO> packList){
  this.list = packList;
 }
 public List<PackingListVO> getPackingList(){
  return this.list;
 }
}

------------------------------------------------------------------------------------------------

- PackingListVO Class - ValueObject Class(DTO)

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;

 

//XML로드시 필드명으로 읽어 들이겠다고 선언
@XmlAccessorType(XmlAccessType.FIELD)
public class PackingListVO {
 
 //XML에 정의된 속성명을 동해 값을 가져오게 된다. 
 @XmlAttribute(name="barcode_read_date")
 private String barcodeReadDate = "";
 @XmlAttribute(name="packing_no")
 private String packingNo = "";
 @XmlAttribute(name="reg_userid")
 private String regUserID = "";
 @XmlAttribute(name="complete_yn")
 private String completeYN = "";
 @XmlAttribute(name="matched_result")
 private String matchedResult = "";

 

 ..

  getter/setter 생략

 ..

------------------------------------------------------------------------------------------------

HttpUrlConnection을 통해 언마샬링 처리는 실무에서 직접 적용 해본바로는 다른 프로그래밍 언어를 사용하는 타사와의

 

데이터 연동시에 유용하게 쓰였습니다. 사용하는 방법은 1부에서 파일로 XML마샬링 후 처리하는것과 비슷하게 크게

 

복잡한 부분은 없었습니다. 접속만 잘된다면 매우 유용하겠지요.

신고

흔히 데이터 처리 방법으로 과거부터 많이 XML을 SAX나 DOM API를 사용 하여 데이터를 가져오는 방식을 많이

 

사용 해왔습니다. 요즘은 프론트 엔드에서 AJAX를 사용한 화면전환없이 처리하는 방법을 많이 사용하면서

 

JSON(Java Script Object Notation)을 많이 사용하고 있지만 여전히 XML도 많이 사용되고 있습니다.

 

보통 스프링 프레임워크를 사용하시는 분들은 XStream을 사용하시는 것 같은데 JAXB에 비해 코드 처리가 간결해 보이긴

 

했습니다. 아직 XStream을 써보지 않은 관계로 JAXB를 통한 여러가지 XML Marshalling, UnMarshalling 처리에 대해

 

몇가지 써볼까 합니다.

 

1. JAXB(Java Architecture for XML Binding)

 

  이걸 뭐라고 읽어야 될지부터 좀 난감합니다. 전 그냥 '작스비' 라고 합니다. AJAX도 부르기 나름인것 같은데 어떤 분은

 

  에이잭스, 아약스, 아작스등..ㅎㅎ 아무튼 XML 스키마를 통해 Java 클래스 데이터를 Marshalling(직렬화), UnMarshalling

 

  (역직렬화) 작업을 좀 더 편리하게 하기 위해 만들어진 API라고 보시면 되겠습니다. Serialize와 Marshalling에는 개념의

 

  차이가 조금 있긴 합니다만 사전적 의미로 Marshalling은 '정렬하다'에 의미를 많이 두고 있는데 직렬화도 정렬된 데이터를

 

  바이트 스트림으로 전송가능하게 만든다는 의미를 두고 있으므로 차이는 있지만 비슷한 개념으로 생각하고 있습니다.

 

  어쨋든 이론은 훌륭해도 실제 써보기 전엔 의미에 불과하니 몇가지 처리방법에 대해 알아보겠습니다. 참고로 JDK 1.6버전

 

  이상에서는 별도의 라이브러리 없이 사용가능하다고 되있는데 저는 라이브러리를 다운받아서 테스트 해봤습니다.

 

1-1.  Marshalling (XML 파일 생성)

 

 처음 JAXB를 접하면서 구글링하면서 가장 많이 본 예제가 Java Object데이터를 마샬링하여 XML파일로 생성하는

 

 예제 였습니다. 실제 구현하다 보면 파일로 마샬링 하는것이 가장 심플하긴 합니다. 예를 들어보겠습니다. 자세한 소스코드는

 

생략하고 핵심 부분만 알아보겠습니다. 중간중간에 있는 주석을 보시면 이해되실 것 같습니다.

 

-XML 원본 데이터 예시(UnMarshalling시 사용)

 <userBltnList>
     <bltnList>
         <isSecret>Y</isSecret>
         <name>TEST</name>
         <no>TESTNO</no>
         <readNum>TESTREADNUM</readNum>
         <subject>Android GCM Push with Command Pattern</subject>
         <writeDay>2013-02-15 18:00:18.0</writeDay>
     </bltnList>
 </userBltnList>

 

-----------------------------------------------------------------------------------------------------------------

 

※ 마샬링한 데이터를 파일(XML)로 생성

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

 

 JAXBContext jaxbContext = null;
 Marshaller jaxbMarshaller = null;

  UserBltnList userBltnList = new UserBltnList();
  userBltnList.setList(list);
  UserBltnListUnMarshall userBltnListUnMarshall = null;
  
  File file = new File("D:\\xmlresult.xml");
  jaxbContext = JAXBContext.newInstance(UserBltnList.class);
  jaxbMarshaller = jaxbContext.createMarshaller();  
  jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");  
  jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
  jaxbMarshaller.marshal(userBltnList, file);

 

- 마샬링 대상 UserBltnList Class

 //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
 //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.

 //(XmlRootElement Annotation을 사용하여 UserBltnList클래스가 RootElement로

//  사용됨을 선언함)

 @XmlRootElement(name="userBltnList")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class UserBltnList {
 
 //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
 //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.
 @XmlElement(name="bltnList")

 

 //Generic을 통해 Collection클래스에 UserBltnListVO(Value Object)가

 //저장됨을 지정함. 
 private List<UserBltnListVO> list = null;

   public List<UserBltnListVO> getList() {
     if(list==null){
       list = new ArrayList<UserBltnListVO>();
     }
     return list;
   } 
   public void setList(List<UserBltnListVO> list) {
     this.list = list;
   }
  }

 

UserBltnListVO Class - ValueObject Class(DTO)

public class UserBltnListVO {
 private String no = "";
 private String subject = "";
 private String writeDay = "";
 private String readNum = "";
 private String isSecret = "";
 private String name = "";
 ..

  getter/setter 생략

 .. 
}

-----------------------------------------------------------------------------------------------------------------

※ 마샬링된 XML(파일)을 언마샬링

 UserBltnListUnMarshall userBltnListUnMarshall = null;

 jaxbContext = JAXBContext.newInstance(UserBltnListUnMarshall.class);
 userBltnListUnMarshall = (UserBltnListUnMarshall) jaxbContext.createUnmarshaller().unmarshal(file);

 

- 언마샬링 대상 UserBltnListUnMarshall Class

@XmlRootElement(name="userBltnList")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserBltnListUnMarshall {
 
 //Marshalling시에 Element의 이름을 정해준다. 반대로 UnMarshalling시에는
 //이 이름에 해당하는 Element속성이나 Element의 내용을 가져오게 된다.
 @XmlElement(name="bltnList")
 private List<UserBltnListVOUnmarshall> bltnList = null;

 public List<UserBltnListVOUnmarshall> getList() {
  return bltnList;
 }
 public void setList(List<UserBltnListVOUnmarshall> bltnList) {
  this.bltnList = bltnList;
 }
}

 

- 언마샬링 대상 UserBltnListUnMarshall Class의 Collection클래스 List의 VO

@XmlAccessorType(XmlAccessType.FIELD)
public class UserBltnListVOUnmarshall {
 
 //UserBltnListUnMarshall에서 루트 Element인 userBltnList를 가져오도록 하고
 //집합 Element인 bltnList를 컬렉션 형태로 가져오도록 했다. 이 bltnList의
 //Element를 XmlElement Annotation을 통해 가져오도록 한다.
 //(Marshalling때와 반대로 UnMarshalling때는 XmlElement나 XmlAttribute Annotation
 //으로 지정한 명을 원본 XML의 Element나 Attribute명을 읽어오게 된다.)
 @XmlElement(name="no")
 private String no = "";
 @XmlElement(name="subject")
 private String subject = "";
 @XmlElement(name="writeDay")
 private String writeDay = "";
 @XmlElement(name="readNum")
 private String readNum = "";
 @XmlElement(name="isSecret")
 private String isSecret = "";
 @XmlElement(name="name")
 private String name = "";

 ..

  getter/setter 생략

 ..

-------------------------------------------------------------------------------------------------

 

글로 쓰다보니 내용이 꽤 길지만 개념상으론 그렇게 복잡하진 않습니다. 다만 XML이 복잡할수록 대응되는 자바 클래스를 생성

 

해야하는것이 좀 복잡할 수 있겠습니다. 원래는 File외에 HttpURLConnection이나 InputStream, OutputStream,

 

HttpServletResponse의 getWriter()를 사용한 예도 한번에 쓰려고 했지만 복잡스러운것 같아서 4부에 걸쳐 작성하도록

 

하겠습니다.


신고

저는 4년차 개발자 입니다. 첫 직장을 3년여 있다가 떠나 제조업 전산실로 오게 된지 어느덧 반년이 훌쩍 넘었네요.

사실 전산실로 온것에는 여러가지 이유가 있었습니다만 첫번째로는 많은 개발자분들이 그렇듯 야근에 지쳤고 갑의 말도

안되는 주장과 억지에 지쳤었습니다. 물론 열의 한두개긴 했지만 좋은 갑업체도 있었습니다. 어짜피 수많은 개발자분들이

무리한 일정, 요구사항들을 많이 겪어보셨겠지만 제가 겪어본 갑 업체 담당자의 유형을 한 번 얘기해보려고 합니다.

1. 친절하고 말이 통하는 담당자

  갑업체 담당자 유형을 적겠다고 하면서 친절한 담당자가 먼저 나오다니 뭔 헛소리를 하려는 거냐 라고 생각하실 것 같습니다.

  전 직장에 있을때 SM업무를 맡고있을 당시 15~20개 정도의 업체를 담당하고 있었습니다. 이중에서 4~5개 업체는 친절하고

  괜찮은 담당자 분들이 있었습니다. 보통 SM업무를 하게되면 전화응대, 오류사항 검토 및 수정, 비교적 작은 규모의 추가개발

  을 진행하게 됩니다. 이때 보통 전화응대 차원에서 담당자들의 스타일을 접하게 되는데요. 이 친절한 담당자들이 있는 업체

  들의 공통점은 꼭 친절해서가 아니라 말이 통한다는 것이었습니다. 이분들이 개발적인 지식이 풍부해서가 아닙니다. 아무것도

  모르는 분도 분명 있었지요. 하지만 전후사정 얘기를 하고  이건 이래서 지금은 안되겠고 일단 급한건 미리 해놓겠다라고 하면

  수긍하고 일정을 조정하는 대책에 있어 말이 통했습니다.  물론 급한일의 경우가 한번에 동시에 터질경우도 있었지만

   오는말이 고우니 가는말도 곱듯 저도 반드시 해결을 해주곤 했죠. 물론 야근하거나 밤샜습니다.;; 그래도 이런업체들은

   어려운 일들을 마치고 나면 고되도 가장 보람 됐던 것 같습니다. 수고했다며 따로 식사를 대접받아본 적도 있구요. 보통 이런

   분들과 만나면 일 얘기는 한적이 없는 것 같습니다. 오히려 제가 처리가 늦어져 죄송한게 많다고 하고 온적이 많네요. 이렇게

   좋은 분들도 분명 있었습니다. 직접 업체나 기관명을 거론할 수는 없지만 제 기억속엔 항상 좋은 분들로 남아있을 것

   같습니다.

 2. 어설프게 아는 담당자(혹은 전직 개발자)

   아무것도 모르는 담당자와 함께 가장 힘든 유형이 아닐까 싶습니다. 자신만의 경험을 바탕으로 한편에서 주장하는 바를 인정

   하는법이 없습니다. 실제로 그런일이 있었는데 추가개발이 필요한 사항이 있었습니다. SM업무를 한다고 해서 개발 안하고

   유지보수만 하라는 법은 없지만 한 업체의 경우 제가 윗선에 보고 없이 몇건 임의로 개발을 해준 적이 있었습니다. 나름

   고객관리 차원에서 해준일들이었긴 했지요. 근데 그 추가개발건은 저 혼자서 하려면 밀려있는 일정과 맞물려 봤을때

   두달정도 걸리는 일이었습니다. 그래서 이래이래 얘길 해주고 지금은 안된다고 하니 갑자기 태도가 돌변해서 버럭 화를

   내더니 "이거 sql좀 몇개 넣고 jsp몇개 만들어서 하면 금방 하잖아요. 내가 해도 3일이면 하겠네." 라고 하더군요. 아마도

   모델1방식의 개발만 해보신.. 과거형 개발자의 포스가 느껴지는 말이었습니다. 여튼 그때 당시엔 그런게 이슈는 아니었고

    주 동작 모듈에도 영향을 미칠수 있는 개발이었기때문에 말했던 것이었지만 장황하게 개발론(?)에 대한 설명을 듣고 나서

    일단 전화를 끊었던것으로 기억합니다. 그 다음날에도 계속 닥달해대서 결국 저도 화가 치밀어서 "그럼 직접 만들어서 보여

    주시면 제가 앞으로 어떤 일정이나 업무지연에 있어서 아무 말 안하겠습니다." 하고 관련 쿼리와 상세설명, 소스패턴 흐름

    등을 알려줬습니다. 한 며칠 잠잠하더니 전화와서 살살 달래더군요. "에이 이거 보니까 어렵진 않겠는데 나도 해야될게

    있고.. 어쩌고 저쩌고.." 모르는척 넘어가긴 했지만 개발자의 아집 같은것이 느껴졌던 분이었습니다. 저 또한 가끔 그럴때가

    있을때가 있는데 이때의 경험을 통해 다른 개발자의 생각등을 이해해보고 항상 의식하려고 합니다. 모든 개발환경이

    동일할 순 없기때문이지요. 여튼 어설프게 아는 담당자들은 보통 자신이 아는 지식내의 생각을 꺾으려 하거나 반대입장이

    보이면 인정하지 않고 억지를 썼던 경험을 많이 겪었었습니다.

3. 여우같은 담당자

    한 업체에 여자 담당자가 있었습니다. 주제 시작에 앞서 절대 여자 개발자나 담당자들을 폄하하는것이 아니니 민감한 반응

    하지 않으셨으면 합니다. 이 담당자는 저랑 전화할때는 사근사근 얘기합니다. 그리고 알아들었다는 듯이 얘기합니다.

    전화통화를 마치고 한참있다보면 갑의 팀장이 씩씩대면서 전화가 옵니다. "당신 일을 아예 안할려고 작정을 했어?!!!"

    영문을 모르는 저는 일단 욕먹으니 화가 납니다. "아니 왜 화를 내세요? 제가 뭘 안해준다고 한적이 있습니까?"

    팀장이 말합니다. "아니 내가 누구누구한테 들어보니까 이것도 저것도 다 안된다면서요? 당신 윗사람 누굽니까 바꿔요!"

    이제 저는 여우가 지 욕안먹으려고 내가 설명한건 다 흘려버리고 "그냥 안된다고 을이 그랬져요 ㅜㅜ" 했다는 걸

    깨닫습니다. 일단 여우사냥은 둘째로 치고 팀장의 오해부터 풀어야해서 내가 이래저래 해서 안된다고 했다. 나머지

    내가 안해준게 있었느냐. 그 안된다고 한 건들도 좀더 후순위로 해서 나중에 해주겠다고 얘길했다. 오해가 있었던 것

    같다. 라고 하니 팀장이 듣고보니 제가 틱틱대면서 무조건 안된다 한게 아님을 깨닫습니다. "아 그랬었어요? 그럼

    말씀을 해주셨어야죠. 우리 같은 전산바닥에서 사는 사람들끼리 미안합니다." 저는 "네 저도 목소리 높아져서 죄송

    합니다." 하면서 훈훈히 마무리.. 그래도 팀장은 팔은 안으로 굽는다는 말대로 "누구누구 씨랑 얘기했던 내용은 지금

    통화한 선에서 정리해주셨음 좋겠네요. 저랑 얘기한걸로 푸십시다." 로 끝납니다. 저는 여우꼬리를 다 도끼로 잘라내고

    싶은 심정이지만 그냥 참습니다. 다음날.. 여우가 아무일 없었다는 듯 "이거좀 봐주시겠어요?" 어쩌고 하면서 전화가 

    옵니다. 또 왜 직급은 어디다 떼다 버렸는지 이해가 안됩니다. 대리인 저에게 언제부터 친했다는듯이 "누구씨?" 라고

    부릅니다. 대리 나부랭이지만 너랑 친구는 아니다. ㅡㅡ; 참고로 여우는 사원입니다. 회사마다 직급 정책이 다르다지만

    이 여우는 진짜 '사원' 이 었습니다. 암튼 이런 여우같은 담당자는 둘이 업무얘기할때는 조용하지만 팀장이나 그 윗선의

    후폭풍으로 영문을 모르고 박살난적이 많았던 기억이 있습니다. 이런 유형은 한번 탈이 나면 저까지 윗선의 타격을 입게

    되는 깊은 내상을 자주 남기는 유형이었습니다. 때릴수도 없고..ㅜ

 4. 귀찮아 하는 담당자 

   "무슨무슨 이름 프로그램을 우리가 쓰는데 연동좀 해주세요." 유지보수 게시판에 있던 내용입니다. 내용은 '냉무' 라고

   적혀 있습니다. 무슨 프로그램인지는 유명한 프로그램이라 알긴 하지만 뭐가 업무적으로 필요해서 뭘 연동해야되는지

   알수가 없습니다. 그래서 담당자에게 전화를 해보면 한숨 부터 쉬기 시작합니다. "하아.. 그래서 못해주신다는 거에요?"

   아니.. 뭘 원하는지 말을해요 이사람아..;; 이 사람은 아마 어릴적 공상영화를 많이 봤나봅니다. 말하지 않아도 다 알아

   서 해주는 공부기계같은 걸 원했나 봅니다. 어르고 달래서 요구사항을 도출해 냅니다. 안되면 직접 찾아도 가봅니다만

   이 사람은 일하기가 싫은건지 어쩐건지 몇시간 동안이고 잡아놓고 얘길 해댑니다. 지금 자기 일터 상황부터 시작해서

   집안 사정까지?.. 암튼 어찌어찌해서 요구사항을 듣고 옵니다. 만들다 보니 좀더 디테일한 내용이 필요해서 다시

   전화하거나 방문하면 난 몰라 개발하는 너가 알아서 해야되는거 아니냐 라는 반응입니다. 제가 요구한건 업무적인

   디테일 한 내용이지 이거 문자열 자르려면 뭐써야되요가 아닙니다. 여튼 이렇게 하다보니 점점 실랑이만 계속되고

   통화시간은 길어지고 결국 다른업체 일도 해결하다보면 야근이나 밤샘으로 때우게 됩니다. 일정이 점점 늘어지게 되고

   담당자가 자신의 윗선에서 한번 깨지고 오는날엔 큰소리가 납니다. 저는 저대로 그래서 요구사항을 분명히 하라고 하지

   않았냐 라고 말을 해보지만 소용없습니다. 다 내탓이오 하는게 오히려 속편해집니다.

5. 난 그냥 너가 싫어! (히스테리 형)

   위의 3번에 해당하는 여우담당자 처럼 이 경우에도 여자 담당자 였습니다. 몇번 일을 하다보니 이 업체.. 요구사항이

   너무 많습니다. 그래도 가능하면 이건 이래서 된다 안된다 얘기를 해줍니다. 담당자는 로봇같은 음성으로

   "그래도 해야됩니다. 아시겠지요" 하고 끊습니다. 힘없는 저는 또 밤샘과 야근으로 일을 처리 합니다. 근데 어느날

   갑자기 영업쪽 후배에게 얘길 듣습니다. "거기 갔다왔는데 담당자가 선배를 다른사람으로 바꿔달래요." "엥?

   뭔소리를 하는거냐? 내가 일을 안해주는게 아닌데?" 윗선에서도 이해를 못합니다. 유지보수 팀장이 영업과 함께

   업체를 찾아가서 담당자를 만나서 얘기해보니 비하인드 스토리가 나옵니다. 아마 제가 바쁜와중에 전화받을때

   인사를 대충하고 넘어간적이 있나봅니다. 이제까지 정황으로 봤을때 이 여자.. 내가 무슨 공주나 여왕처럼 취급해

   주길 원했나봅니다. 너무 어이가 없어서 벙찌지만 그냥 모른척 넘어가 주려고 하지만 사사건건 트집을 잡고

   안될때 마다 담당자 바꿔주세요 소리를 해댑니다. 이제 저도 한계치가 넘어서서 전화로 얘기합니다.

   "담당자 교체해드릴테니까요. 저는 이건 못하겠네요. 됏죠?" 바로 전화끊으니 나름 또 그쪽에서는 지내온 세월이

   많으니 제욕을 없는것 있는것 다 했나봅니다. 저도 여기서 지낸 시간이 있으니 당당합니다. "바꿔 줄께요. 이제

   오류 사항만 처리하겠습니다. 계약서에도 분명 그렇게 되있지요?" 하면서 전화를 끊습니다. 실제로 그 업체에선

   유지보수 통합지원 업체가 있어서 유지보수나 추가개발 관련사항을 무수하게 올리지만 전 그중에서 오류사항만

   골라서 처릴 해줍니다. 담당자는 혀를 깨물듯이 난리를 치지만 저는 거들떠 보지 않습니다. 이런 케이스는 참 뭐라고

   딱히 해결방법이 없었던 것 같습니다. 직접 본 사람도 아닌데 저정도면 직접보고 일했다면 참 뺨 한번 날라갔을지도

   모르겠다는 생각이 들었었네요.

6. 권위적인 담당자

   보통 무슨무슨 기관들에서 상하규율이 엄격해서 담당자 또한 권위적인 경우가 많았던 것 같습니다. 다른 개발자 분들도

   아마 많이 겪어보셨을 것 같습니다. 보통 이런경우 나는 갑이고 너는 을이야 이런 스멜을 풍길때가 많은데 그나마

   갑을 이면 괜찮은데.. 나는 갑이고 너는 병이야 상황에서는 정말 무슨 인도역사를 공부해서 카스트 제도를 우리나라에

   접목시키고 싶은 의지를 가지고 온사람들 처럼 인사한번에 민감해하고 내가 시키면 넌 다해야돼 ㅇㅋ? 라던지

   난 이제 퇴근할거니까 아랫것 주제에 야근해야지 라는 스타일이 있었습니다. 다행히도 많은 경우를 보진 않았지만

   이건 마지막에 퇴사 당시에 업무지원으로 나갔던 업체에서 당했던 일이었습니다. 중간과정은 길기 때문에 생략하고..

   주간회의시간에 을,병 업체들이 한데 모여있는데 갑업체 팀장 재털이가 날아다닙니다. 군대에서 가끔 본것 같은데

   다시 볼줄 몰랐습니다. 사람한테 날아가진 않지만.. 보고를 마치고 나면 이 권위적인 팀장 밑의 미니언이 졸졸 쫓아옵니다.

   "팀장님 저희 이제 좀더 상세히 보고좀 들어야 되지 않을까요? 일일회의를 하는건 어떠세요 키키키"

   "음.. 그래 너가 그러면 가서 업체들 보고 이제 다음주부터 일일회의 하자고 해. 나 먼저 들어갈께"

   미니언이 열변 토합니다. "아니 제가 팀장님 화 누그릴려고 얼마나 힘썼는데요.ㅜ 일일회의로 정리 해서 다행으로들 아세요!"

   미니언 퇴근... 결국 일일회의에 맞게 일정을 다시 조정해야 되기때문에 야근이 반복 됩니다.

   팀장은 착수보고 시에 저한테 이런말을 한적이 있었죠.. "자..이제 밤새서 개발해야지 죽어보는거야" 마치 누굴 못죽여봐서

   안달이 난 것 같이 말을 합니다. 보통 이런 스타일은 결과가 좋던 안좋던 야근을 강요하며 쓸데없이 소집을 자주 합니다.

   별로 회의할 내용도 아닌데 불러다 한두시간 쪼아대는건 취미생활이자 자신의 윗선들에게 열심히 관리하고 있군이란

   인상을 남기기 위한 것 같습니다. 이런 분들에게는 뭘 해줘도 그만큼 또 해야됩니다. 결국 벗어나기 전까진 코피를 쏟건

   밤을 새건 계속 일해야 되는 생활을 각오 해야 됩니다.

쓰다보니 엄청 길게 썼네요..;; 다 보셨을련지는 모르겠지만.. 보통 제가 겪은 갑업체 담당자의 유형이었습니다. 이외에도 더

많지만 너무 길것 같아 여기까지만 써야겠네요. 혹시 이글을 보는 분들 중 갑 업체 담당자거나 관련자시라면 제가 위에서 썼던

1번에 해당하는 담당자가 되셨으면 합니다. 개발자, 기획자, 관리자 모두 함께 협력하는 사람들입니다. 관리나 기획을 하는

갑 업체에서 개발자들에게 인간적인 대우를 한다면 십중 5~6은 분명 그만큼 열심히 해줄 겁니다. 무조건 쪼아대면 좋은 제품은

결코 나올 수 없으며 먼 훗날 자신을 되돌아 봤을때 분명 후회되는 행동이 아닐지요.

 

신고