오늘은 지난시간에 이어 Json.net으로 Serialize와 Deserialize에 대해 알아보자.

Serialize는 흔히 직렬화라 이야기하기도 한다. 네트워크상에서 Class를 전송하는 등의 입출력을 위한 데이터의 배열 형태로 변환하는 과정을 직렬화라 하며,
반대의 경우 데이터의 배열 형태를 Class로 변환화는 과정을 Deserialize(역직렬화)라 한다.

이때의 데이터 형태는 Byte 또는 string 등의 형식으로 변환 될 수 있다.

암튼 각설하여 지난 시간에 이어서 JSON.NET 모듈을 구해서 Import 하던가 기타 등등의 Json Parser를 구하자.
(코딩 노가다 안하려면 Serialize / Deserialize 지원이 잘되는 모듈로 구하자. 안그럼 개고생은 예약해 놓은 거다)

Import가 완료 되었다면 지난시간에 사용한 Entity Class를 다음과 같이 고쳐주자. (본 예제는 JSON.NET을 사용한다. Windows어플에서 가장 많이 쓰이는 모듈이라서...)
using System.Collections.Generic;
using System.Collections;
using Newtonsoft.Json;

public class TestEntityRoot
{
//JsonProperty로 설정하였다.
 [JsonProperty("SubEntity")]
//Static이므로 Get; Set; 선언으로 입출력이 가능하도록 하였다.
 public static List<SubEntity> SubEntity { get; set; }
}

public class SubEntity
{
 public string x { get; set; }
 public string y { get; set; }
 public List<Sub2Entity> sub { get; set; }
}

public class Sub2Entity
{
 public int z;
}


이제 Json Code가 포함된 Scene 0 에 사용할 코드를 작성하자.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Scene0Behavior : MonoBehaviour {
 // Use this for initialization
 void Start () {
//JSON 데이터를 정의한다. x는 a, y는 b로 선언했다.
 string _json = @"{
           ""SubEntity"": [
            {
                       ""x"": ""a"",
                       ""y"": ""b"",
                       ""sub"" : [
                       {""z"" : 0 },
                       {""z"" : 1 }
                       ]
                      }
            ]
            }";
 //할당할때는 아무런 클래스를 선언하고 할당한다.
 var _e = JsonConvert.DeserializeObject<TestEntityRoot>(_json);
 
//접근할때는 엔티티 클래스를 직접 호출한다.
 Debug.Log("Scene 0 입력값시작##############");
 foreach (SubEntity _s in TestEntityRoot.SubEntity)
 {
            Debug.Log(_s.x);
 }
 Debug.Log("Scene 0 입력값끝##############");
//저장된 Json 데이터를 출력하고 다음 레벨을 로딩한다.
 Application.LoadLevel(1);
 }

}


Scene1에 사용될 소스를 다음과 같이 입력한다. Scene0과 다른점은 Json데이터 외에 변하는 것은 없다.
(단지 씬이 변경되더라도 데이터가 살아 있고 새로운 데이터를 넣었을때 어떻게 되는지 보여준는데 그 역할이 있다.)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Scene1Behavior : MonoBehaviour {

 // Use this for initialization
 void Start () {

 string _json = @"{
            ""SubEntity"": [
            {
                       ""x"": ""c"",
                       ""y"": ""d"",
                       ""sub"" : [
                       {""z"" : 2 },
                       {""z"" : 3 }
                       ]
                       }
            ]
            }";
 //할당할때는 아무런 클래스를 선언하고 할당한다.
 var _e = JsonConvert.DeserializeObject<TestEntityRoot>(_json);
 //접근할때는 엔티티 클래스를 직접 호출한다.
 Debug.Log("Scene 1 입력값시작##############");
 foreach (SubEntity _s in TestEntityRoot.SubEntity)
 {
 Debug.Log(_s.x);
 }
 Debug.Log("Scene 1 입력값끝##############");

 Application.LoadLevel(2);

 }

}


마지막으로 Scene2에서 사용될 소스는 데이터를 클리어 하고 입력된 값을 출력하는 코드이다.
using UnityEngine;
using System.Collections;

public class Scene2Behavior : MonoBehaviour {

 // Use this for initialization
 void Start () {
//시작과 동시에 데이터를 날려버린다.
 TestEntityRoot.SubEntity.Clear();
 Debug.Log("Scene 2 입력값시작##############");
 foreach (SubEntity _s in TestEntityRoot.SubEntity)
 {
 Debug.Log(_s.x);
 }
 Debug.Log("Scene 2 입력값끝##############");

 }

}


결과는 다음과 같다.
사용자 삽입 이미지
정상적으로 씬이 변경되더라도 데이터가 살아 있고, 새로운 Serialize 된 데이터가 들어오면 추가된다.

2015/08/11 01:47 2015/08/11 01:47
유니티 3D로 개발하다보면, 파편화된 데이터때문에 유지보수나 관리에 어려움을 겪게 되는데,
그러다 보니 Entity Class를 만들고 Dontdestroy 옵션으로 삭제되지 않는 불멸의 데이터 클래스를 생성해서 사용하는 개발자 분들이 많이 보인다.
그런데, 이렇게 하다보면 결국 소스가 꼬여서 오작동 하거나 관리상 문제로 인해 불편함을 가지고 가는 경우도 많은데 그럴 필요 없이 Static 으로 설정하여 Scene을 넘어가더라도 Data가 살아 있는 Class를 만들고 관리하는 것을 목표로 한다.
(물론 Json을 Serialize 하거나 Deserialize 하는건 다음 편에서 보자)

EntityMaster.cs파일을 하나 만들어서 다음과 같이 추가해두자.
(폴더위치는 관계없다.)

using System.Collections.Generic;
using System.Collections;

//테이블과 같은 클래스이다.
public class TestEntity
{
 public static List<SubEntity> _sub = new List<SubEntity>();
}

//1개 Row라고 생각하면 비교가 쉽다.
public class SubEntity
{
 public string _x;
 public string _y;
//Row안에 또 하나의 테이블을 가질 수 있다.
 public List<Sub2Entity> _sub = new List<Sub2Entity>();
}
//SubEntity에 포함된 클래스이다.
public class Sub2Entity
{
 public int _z;
}


이제 Scene0를 만들어서 MainCamera에 다음과 같은 Script를 만들어 Attach하자.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Scene0Behavior : MonoBehaviour {
 // Use this for initialization
 void Start () {
//새로운 Sub2Entity 객체를 만든다.
 List<Sub2Entity> _sub2 = new List<Sub2Entity>();
//Sub2Entity 타입의 객체에 데이터를 넣는다.
_sub2.Add ( new Sub2Entity { _z = 1 });
//테스트엔티티 테이블에 Row를 추가하고 다음 씬을 호출한다.
 TestEntity._sub.Add(new SubEntity { _x = "a", _y = "b", _sub = _sub2 });
 Application.LoadLevel(1);
 }

}


이제 2번째 씬을 만들고 다음과 같이 코딩한후 MainCamera에 Attach하자.
* 위에서 데이터를 추가한 것이라 별도 설명은 생략한다.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Scene1Behavior : MonoBehaviour {

 // Use this for initialization
 void Start () {
 Debug.Log(TestEntity._sub[0]._x);
 List<Sub2Entity> _sub2 = new List<Sub2Entity>();
 _sub2.Add(new Sub2Entity { _z = 2 });
 TestEntity._sub.Add(new SubEntity { _x = "c", _y = "d", _sub = _sub2 });
 Application.LoadLevel(2);
 }
 
}


마지막으로 3번째 씬을 만들어서 다음과 같이 코딩후 Attach하자.
using UnityEngine;
using System.Collections;

public class Scene2Behavior : MonoBehaviour {

 // Use this for initialization
 void Start () {
//시작하면 데이터를 찍는 역할이 전부다.
 Debug.Log(TestEntity._sub[1]._x);
 Debug.Log(TestEntity._sub[1]._sub[0]._z);
 }
 
}


최종 결과는 다음과 같다.

* 씬을 다음과 같이 3개로 구성했고, MainCamera에는 각각의 Script가 Attach되어 있다.
사용자 삽입 이미지
* 최종 결과는 Debug.Log로 다음과 같이 출력된다.
사용자 삽입 이미지
2015/08/07 02:14 2015/08/07 02:14

비난의 화살

Memory 2015/07/18 15:07
최근 몇달간 중견 모 게임의 컨설팅을 수행하면서 특이한 경험을 하게되었다.
(물론 1월 부터 시작된 활동은 6월부로 종지부를 찍고 현재는 떨어진 체력과 멘탈 회복 중입니다.)

"인간은 타인의 실패와 자신의 성공으로 부터 배운다"라고 하던데, 금번 프로젝에서 내가 성공한건 없으므로, 기록으로 남길 만한게 없다.
그렇다고 타인의 실패를 기록으로 정리하는건 옳지 못하다고 생각한다.
하지만, 매우 특이하게도 정말 일부의 사람들이 불평불만을 엄청 많이 하는 프로젝트였는데...
결여된 몇가지 윤리적 문제를 차지하고 (기본적인 월급쟁이의 윤리 문제나 공감되지 않는 문제를 포인트처럼 찍어서 공격하는 어른 답지 못함 등)

비난의 화살의 방향과 비난의 마음을 다스리는 몇가지 인사이트를 얻었다.

1. 비난의 마음 다스리기
일이 마무리되고 나서 모 교수님과 한잔 기울이며 심리적인 문제나 요인에 대해 이야기하던 중, 
최근에 읽으신 문서중 이런 내용이 있었다고 한다.
- 어느 여자 정신과 의사는 어릴때 가정폭력의 희생자로 부친으로부터 많이 맞고 자랐다고 함.
- 성인이 되고나서도 폭력의 트라우마를 가지고 살았다고 함.
- 그러던 어느날 병원 엠블란스의 경광등을 보고 있었는데...
사용자 삽입 이미지

- 의미없는 정보에 집중하면서 트라우마를 떠올리자, 트라우마가 사라져 가는걸 느꼈다고 한다.
집에와서 테스트해본 결과 악몽이 사라졌다. 
(악따구쓰며 꿈속에서까지 괴롭히던 X을 떠올렸을때 더이상 긴장되지 않는다. 이제는 좀 편해졌다.)

이 원리를 찾던중 하나의 의미있는 단서를 찾게되는데 바로 파블로프의 조건화이론이다.
a. 조건화 이전
   - 개는 먹이를 보면 (무조건자극) 침을 흘린다 (무조건반응)
   - 종을 울려도 (중성자극) 침을 츨리지 않는다 (무반응)
b. 조건화
   - 먹이를 줄때마다 종을 울린다. (중성자극을 무조건자극과 일치시키는 과정)
c. 조건화 이후
   - 종을 울리면 (무조건자극) 침을 흘린다 (무조건반응)

이러한 원리를 적용하면 다음과 같은 심리기재가 작동하지 않을까 싶다.
a. 조건화 이전
   - 그 이미지를 떠올리면 (무조건자극) 그때의 반응이 한다 (무조건반응)
   - 사이렌 경광등을 보면 (중성자극) 그때의 반응을 하지 않는다 (무반응)
b. 조건화
   - 사이렌 경광등을 보면서 (중성자극) 그때의 이미지를 떠올리면(무조건자극), 그때의 반응을 마음이 되세긴다 (무조건반응)
   - 하지만, 아무일도 일어나지 않는다. (무반응)
c. 조건화 이후
   - 그때의 이미지를 떠올려도 사이렌을 볼때와 같이 아무런 느낌이 없다.

2. 비난의 화살의 방향
암튼, 중요한건 우리 인간은 왜 비난하는가에 대해서는 많은 이유가 있겠지만, 인간이 비난할때의 방향은 딱 2가지인것 같다.

a. 내가 병신이야라고 자책하거나 
b. 내가 아닌 모두가 병신이라고 비난하거나

켈리라는 분이 만든 이론중 귀인이론 다시말해, 어디에 책임있느냐에 대한 이론을 살펴보면 흥미롭다.
개인의 행동을 살펴서 "특이성", "합의성", "일관성" 3가지 요인을 살핀후 내적 책임론 혹은 외적 책임론을 펼친다.
(물론 가중치가 어디에 있으냐에 따라 해석이 맞니 틀리니 하는 요소가 나옴)

- 특이성은 상황에 따라 자신이 얼마나 다르게 반응하는지에 대한 해석이다.(High : 외부책임, Low : 내부책임)
- 합의성은 유사한 상황에 빠진 다른사람과 얼마나 일치되는지에 대한 해석이다. (High : 외부책임, Low : 내부책임)
- 일관성은 특정행동이 특정조건에 얼마나 반복되는지에 대한 해석이다. (High : 내부책임, Low : 외부책임)

여기서 책임을 외부로 돌리고 싶을 때 사람은 이렇게 타인에게 설명하는 것 같다.
- 내가 얼마나 보편 타당한 사람인지... (나는 합의성이 무지 높아요)
- 현재 프로젝트 상황(환경과 주변인 등) 이 얼마나 특이한지... (특이성이 주미 높아요)
- 주변인이 얼마나 일관성 높게 나쁜 짓을 하는지... (그 쉐는 딱 그상황에서 다른 사람 깔아뭉게면서... 어쩌구)

3. 그래서 어쩌라구...?
그냥 솔찍해지자. 그저 싫은거잖아?
싫은데 여러가지 이유가 있는거고,
단지 그 이유가 못생겨일수도 있고, 호감이 안가서일수도 있으며, 목소리가 기분 나빠서일 수도 있다.
(나도 내말 안듣는 사람이랑 일하는게 싫다.) 

그런데, ego 놀음이란 표현이 있더라. 이게 뭔 소리냐면...누군가를 비난할 땐, 

- 도덕심
- 전문지식
- 배려 
3가지가 동시에 발현되어야 한다고 생각한다.

- X도 모르면서 전문지식을 지적하거나,
- 배려심도 없으면서 지적질만 하거나, 
- 지는 맨날 지각하면서 지각하는 동료를 지적하는건

"스스로 못배운거 티내는 거다."

그럼 어떻게 비난하는게 좋을까? 물론 나도 자신없는 영역이기도 하다. 사람을 바꾸는게 제일 힘든거니까...
하지만, 우리는 일한 결과물로 얼마든지 Feedback할 수 있으며 해야만 한다.

- 일을 분해하자. (진짜 무능력한 인간들이 제일 못하는게 바로 이거다.)
- 일을 분배하자. (언제까지 어느 퀄리티로 일할지 합의하는 과정이다.)
- 일을 복기하자. (정해진 일정에 일을 모아서 담당자들과 함께 복기하자.)
- 일을 개선하자. (마지막으로 개선 Feedback해서 처음으로 돌아간다)

우리는 얼마든지 신사적이고 예의바르게 위의 루틴으로 비난할 수 있다.
관리자가 앞에서 비난하지 않고 Feedback하지 않는 것도 문제다. (일을 안하고 있다는 뜻이다.)
2015/07/18 15:07 2015/07/18 15:07
TAG ,
어느날 문득, 누군가에게 도움을 줘야겠다는 생각이 들어 책한권을 손에 쥐고는 전달하며, 최근 회사의 이야기를 했다.
여러개의 우리 조직의 목표가 있었는데 몇몇 부분이 불만인지라 이래저래 힘들다고 푸념을 널어놓자 그분이 추천해주신 책이 "만약고교야구여자매니저가 피터드러커를 읽는다면"이다.

물론, 책은 소설이다.
이렇게 아주 쉽게 생각한대로 이론대로 될턱이 없다.
(1. 그렇다면 유능한 경영자가 너무 많아져서 경영의 가치가 떨어져야 함에도 우리는 유능한 경영자에 목말라한다.
2. 성인들은 그렇게 속마음을 쉽게 열지 않을 뿐더러, 대부분의 경우 자기가 무엇을 원하는지 모른다!)

그럼에도, 이책에 가지는 가치는 어떤 명제를 익숙한 상황으로 끌고온다는 것이다.

망가져 가는 조직을 어떻게 재건하는가가 이책의 주요내용인데,
1. 내외부 고객의 욕구를 모아 조직의 정의를 분명히 하기
2. 전문가와 구성원을 연결하고 각자의 장점을 최대한 살리기
3. 구성원의 목표와 책임을 분명히하기
4. 데이터를 바탕으로 공정한 보상하기
5. 이노베이션을 통해 조직밖으로 영향력을 확대하기
는 경영서의 일반적인 내용이라 감이 먼 느낌이 있지만 이 경영의 진리를 우리가 조금만 노력하면 다가갈 수 있는 이야기로 풀어냈다는데 의의가 있다는 이야기다.

Gittd라는 회사의 가치는 결과보다 과정을, 경쟁보다 협력을, 계획보다 실행에 더 많은 가치를 부여하고 있다. 이 모든 가치의 구체적인 사례가 바로 이책에 구체적인 사례로 제시되고 있다.

한가지 놓치고 있었던 사례가 있었는데 바로 "인사"이다.
상벌과 포상이 모두 인사영역이었다는 점을 놓치고 있었는데, 이 책은 그 길을 제시해준다.

끝부분에서는 나도 모르는 감동의 눈물을 흘렸다.

소설이지만, 그 성과를 위해 달리는 한 소녀가 어찌보면 공감 되었을 지도 모른다.

앞으로는 회사운영을 조금 바꿔야 겠다.

1. 아이디어를 내면 1점을 위키에 기록한다.
2. 문제를 해결하면 2점을 위키에 기록한다.
3. 1,2는 2주일에 한번씩 정산하여 보상한다.
4. 2주일에 1일은 아무일도 안하고 회의만 계속하는 날로 정해야 겠다. 즉, 이터레이션의 끝과 시작을 하루에 몰아서 해야 겠다.


2012/01/23 21:32 2012/01/23 21:32

Vista 사용자로 다른 제품군은 모르겠지만 XML Core Services 4.0 Service Pack 2를 계속 계속 재설치하려 한다.
한 몇일 참았지만 참지못해 뒤져보니...

시작 > 실행 > CMD 입력후에
시커먼 DOS창이 뜨면
"ren %windir%\System32\msxml4.dll msxml4.old" 입력

다시말해 msxml4.dll 을 삭제하거나 다른 이름으로 변경하면 된다나?
아무튼 지금은 재설치하라고 뜨지 않아 다행이다.

2009/01/07 17:03 2009/01/07 17:03