퇴근5분전

 요새 개발자 커뮤니티에 가면 okky나 devpia가면 비전공자들의 질문들이 가끔 올라온다.

눈팅만 하는 정도지만... 비관적인 답글들을 많이 본다. 여러사람의 생각들을 답글을 통해 볼 수 있어서 좋긴한데,

마음이 아프다.. 동병상련이랄까?

 나도 전자과 출신이니 비전공인가.. 애매한 포지션에 나이도 28인가에 시작해서 지금 마흔이다...

게다가 학원출신... 한국정보기술연구원 (KITRI) 국비지원 임베디드교육을 받았다. 1년간 전자전공 지식과 임베디드 배운 것으로

새로운 일을 해보고자 방황하다. 끝내는 10년간 해온 전공을 버렸다. 가는 곳마다 공장으로 보내서...

아예 전산쪽에 들어왔고 지금 11년이 넘었다. 그때 목표는 "전공자들을 따라잡자" 였는데...  갭이 얼마나 좁혀졌는지... 음! 알게 뭐야...

 SI를 쭉 다니면서 비슷한 수준의 작업들을 초, 중, 고급이 나눠서 하기 때문에 더 알 수가 없다.

마흔이 되었으니 늦은 감이 있지만, 업무에 대해 익혀야 할 때가 온것 같아서...

미리 추측하고 어깨너머로 보고 구글링을 해가며 만든 툴이 [화면정리 프로그램], [테이블 정의서 뽑는 프로그램],

항상 가지고 다니는 [디자이너], [ssms addin]과 [vs addin]. 그외 다양한 툴... 

나름 비전공으로 이 정도 프로그램 툴을 직접 만들어서 쓸 정도가 되었으면 된거지 뭐... 라는 생각도 든다.

 필요한 프로그램이 생기면 설계하고 만든다.

 

 지금까지 11년동안 축적된 지식들을 정리하여 비전공자분들에게 도움이 될만한 유튜브 컨텐츠를 만들어볼까 한다.

스토리를 작성해야지.. 이번 설이 지나면... 어설프게나마 시작해봐야지...

 비전공 개발자분들 기다려욧! 그리고 힘내요!

'--- 취미 > 생각하기' 카테고리의 다른 글

투표를 앞두고... II  (0) 2017.05.07
개발이 지지부진? ...  (0) 2017.04.25
SI 와 SM...  (0) 2016.11.27
비가 많이 오네....  (0) 2016.07.01
이생각 저생각...  (0) 2016.05.30

 

 음... 디자이너를 하나 더 만들다가 하루만에 소스를 버렸다.

출퇴근하며 수첩에 디자이너 관련 된 것을 그려보다가 해볼까 해서 그리다가 그냥 접었다.

새로 만든 디자이너가 충분히 좋은데 굳이... 또 만들 필요도 없고, 하다보니... 내가 왜 이러고 있나 ...

지금의 업무들은 대부분 기존 프로그램으로 소스를 만들어낼 수 있으니 뭐 어렵지 않고

오늘도 간만에 신규화면 하나 만들었는데 3시 23분에 시작해서 4시 20분에 dll 배포 했다.

이번 화면은 sp도 만드는거였는데 툴로 CRUD모두 생성하고 R 내용은 받은 쿼리로 덮어쓰고

나머지는 모두 툴로 생성했다.

 간만에 툴을 쓴거라... 소스를 만들어내고 나서 수정하는 방법을 까먹어서 ... ㅡ.,ㅡ;;;

컨텐츠를 어떤걸 늘려서 만들것인가가 문제네...

# 추가

 -  Image 컨트롤

 - 파라미터로 도구상자에 툴박스아이템 생성하기

 - 데이타그리드의 Item목록 입력받는 창 만들기 

 - 미리보기 - 주석을 달 수 있음.

 - Xaml ... 로 저장 가능. ... [ Export xaml ] : 현재 SI프로젝트의 회사에서 사용하는 WPF 스타일대로 만들어냄.

< 그리드에 컬럼 생성할때 입력받는 창 >

 

<도구상자에 화면에 필요한 컨트롤 생성 할때 사용하는 창 >

< 생성하면 도구상자 뒤쪽 판넬에 위처럼 생성이 된다. - 드래그&드롭 하면 됨. >

< 디자인 중일때의 화면 >

< 미리보기 할때의 화면 >

< 미리보기 - 우측 속성창엔 주석을 적을 수 있다. >

 

 

 

새로 만들어진 프로그램!!

미리보기 한 상태이고, 디자인상태가 되면 숨겨진 컨트롤들이 되살아 난다.

- 버그. dockPanel 구현로직이 잘못되어 있어.... 이런 저런 옵션들을 주면 컨트롤이 엉뚱한곳에 표시되거나 뒤로 숨어버리거나...

- TableLayout 을 이용하여 구현한 컨트롤에 Jsfw_Mover 를 붙였을때 ... Mv관련 컨트롤들이 추가되면서 Row, Column이 증가하면서 제대로 안되어 우선 패스.

- delete 할때 Grid가... 엉뚱한게 지워진다..  ( 버그 잡음 12-27 )

 

대략 기능들은 만들어져있고... 위에 버그는 다시 만들어야지...

디자인이 이쁘게 안나오네 ... 나중에 색상조합을 해봐야겠다.

--- 추가~~~

 버그는 다 잡았다.

다행이 JSFW_Mover를 쉽게 수정해서 마쳤다.

기존 > 선택된 컨트롤의 부모창에 M, L, R, T, B 각 이동기능을 가진 컨트롤들을 추가하고 해당 컨트롤위에 챡! 붙였었는데...

TableLayout에 들어가 있는 컨트롤을 선택했을때... 추가되는 컨트롤때문에 골때린 현상이 생겨서 이번에 수정했다.

추가없이... 가능하도록 만들었다.

 

 

만들다 보니 기존 컨트롤들을 거의다 구현이 끝났네.

# 가장 까다로운 레이아웃 그리드는 TableLayoutPanel로 다시 만들었다.

예전에 내가 만든 레이아웃그리드엔 꾀 많은 코드가 들어갔는데... TableLayoutPanel을 손봐서 만든건

코드 복잡도가 많이 줄었다. 잘 만들어져 있는 TableLayoutPanel의 기능들을 이용하는 것 뿐이니까!

동적으로 Cell Resize 처리를 하는게... 쉽지 않았다.

기존에 판넬 사이즈 변경이나 이동처리 하는 로직으로 안된다. 계속 비교는 해봤지만...

우연히 찾은 소스에서 설마!! 하고 적용했더니 되더라.. ㅡ.ㅡ; 그게 될줄이야...

 

# 데이타 그리드는 편집기능 판넬만 떼어다가 가져다 붙였다.

새로 구현하려니 너무 귀찮아서...

# 오늘 드디어 미친듯이 새로운걸 만들때마다 괴롭히던게 잡혔다.

에러 문구

---------------------------
Microsoft Visual Studio
---------------------------
'CellContent' 속성의 코드를 생성하지 못했습니다. 오류: ''JSFW.MockupIII, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' 어셈블리의 'JSFW.Controls.MockupIII.mkLabel' 형식이 serializable로 표시되어 있지 않습니다.'
---------------------------
확인  
---------------------------
에러 문구가 왜 뜨냐면...

mkLabel에 새 프로퍼티로 CellContent라는 걸 만드는데 class를 새로 정의한 것이었다.

이걸 mkLabel에 추가하고 Form 디자이너에 mkLabel을 드랍해두고 아무 프로퍼티나 수정을 하게 되면

프로퍼티내용을 직렬화 하는 과정에서 새로 만든 클래스 타입을 인식을 못하는것 같다.

실제 [Serializable] 걸어도 의미없다.

그렇게 삽질을 하다가 찾은게

[System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)]

요거다. 직렬화 하지 말라는거... 프로퍼티위에서 걸어주면 form에서 직렬화 하지 않아서 에러 메세지가 나타나지 않는다.

하나의 어셈블리 파일로 만들꺼면 set을 internal로 걸면 또 직렬화 하지 않는다.

 저 클래스의 용도가 .designer.cs에 소스코드로 보여질 내용이 아니므로 직렬화해서 관리하지 않아도 된다.

난 경우가 다르므로 꼭 직렬화를 피해야 한다. 다른 프로그램만들때 저런 에러가 나서 프로퍼티말고 Set, Get Method로 처리했던것 같은데...

어째든... 성공이다. 나중에 내부 데이타들을 모두 다른 dll로 뽑아내고 플러그인에 들어갈 객체로 써야 하므로 internal이면 안되기 때문에...

 [System.ComponentModel.DesignOnly(true)] 요것도 있다. 

.resx에 프로퍼티 직렬화되어 값을 보존하는 듯 하다. .designer.cs 소스로 생성되어 뿌려지지 않는다.

위 에러가 나타나서 해당 프로퍼티에 걸었더니  .resx에 형식이 (없음/null) 로 보이게 된다.

여기까지 만들어진 화면이다.  ( 아래 레이어 mkLabel2는 테스트 도중 위치값이 바뀐경우라... 에러 아님.)

 

 

 

 

 

 현재 툴로도 나름 만족하지만... 자꾸 눈에 밟히는게 웹을 지원하려면.. 디자이너의 컨텐츠가 부족하다...

컨텐츠 부족  요새 머리속을 흔들고 있다.

 

MockupII는 뭔가 어정쩡한 느낌이라 소스를 버리고,,,

MockupIII를 만들었다. ( 잘만들어졌다... ㅠㅠ )

문제는 컨텐츠인데... 머리속에서 뱅글뱅글 돌아....

이번에 만들어진 컨트롤들... 왼쪽은 테스트로 올려둔거.. 두번째는 선택한 컨트롤의 속성탭, 세번째는 첫번째 판넬을 xml로 변환한것. 네번째(오른쪽 마지막)는 xml을 다시 컨트롤로 변환시킨것...

 전처럼 어렵게 코딩안해도 변환이 쉽고, 필요한 속성을 쉽게 추가 할 수 있다.

나중에 플러그인으로 내부데이타(속성)들을 받아서 변환처리도 쉽게 할수 있게 구조를 다 바꾸어 두었다.

--- 여기서 문제는.... 컨텐츠.부족!!

윈폼이라든가 wpf는 그럭저럭 비슷하게 디자인을 할 수 있게 만든다.

그러나 웹!은 어떻게 할까?  요새 구글링으로 와이어 프레임 프로그램들을 살펴보고는 있지만 대부분 모바일용이 많고 웹도 있긴한데...

디자인은 이쁘게 나오던데... 그렇게 많은 컨텐츠가 필요할까 싶기도 하고... html로 변환한다고 했을때... 어떤 프로그램은 그냥 그대로 뜨는것 같던데..

어떻게 한걸까?

 일단 디자이너를 만들기전에 컨텐츠 정리를 해봐야 하는데... 머리속에서 뱅글뱅글 돌기만 한단 말이지...

포털사이트를 디자이너로 만든다고 했을때... 필요한 컨트롤들이... 과연? css는??

출퇴근시간 수첩들고 이리저리 그려보고 있는데... 쉽지 않네..

 밤에 썼더니.. 오타가 많넹...

 

 

 화면 정보를 등록하는 화면에서 [테스트 시나리오] 탭을 추가 했다.

 

 우선 필수 파라미터 체크하는 것인데. 경우의 수를 모두 담기엔... 무리가 있다.

 

파라미터가 10개 만되어도 2^ 10 만큼의 테스트를 해야 하므로 ... 미친짓이다?

 

그래서 10개일경우 1개씩 값을 넣으면서 그때 필요한 필수값<<에 대한 체크를 하고 YES/ NO를 선택하게 된다.

NO인경우 우측에 기록!!...

 

차수도 있어서 1차 부터 n차까지 계속 미친짓을 할수 있다.

 

또 펼치기를 누르면...

 

입력값을 적을수 있는 텍스트박스 와 예상결과값을 넣을수 있는 텍스트 박스가 나타나고

별도의 테스트 조건을 넣을수 있게된다.

 

[생성]버튼을 누르면 위 두가지를 합한 테스트 조건들이 차수에 기록되고 만들어진다.

 

보통 테스트중에는 스샷 찍어서 오류 내용을 적어두는게 보기 쉬운데... 텍스트 박스로 해놨다 ㅡㅡ# ( 귀찮아서 ... ) 

 

 

낼부터는 진짜 업무에 사용해서 화면정리를 해봐야지... 소감은 다음에... 이어서...

 

화면과 관련된 내용을 어떻게 채워 넣을지 계속 고민하다가.... 우선!

 

# 기능중에 작업버튼 색상구분( 녹색 : Execute , 오렌지 : 창 Link )

# 디자이너 연결 ( 새로 만들려다가... 기존 디자이너 연결함. )

# 썸네일 이미지 등록 기능.

 

# 예외메세지 관리기능 

 - 화면마다 발생하는 주요 예외 메세지에 대해 어떤 처리를 해야 예외가 사라지는지. 원인이 무엇인지... 적어두어 관리한다.

 

 

# 화면에 사용하는 SP를 등록해두고, 관련된 객체목록을 살펴볼수 있게 만들었다. sp_depends 를 이용하여 정보를 조회하면서, 조회된 정보를 다시 클릭하면 선택된

객체와 관련된 객체목록을 다시 검색해서 보여준다. 다이어그램 같은걸로 뿌리려다가... 귀차니즘에...

- 이 화면은 필요할까? ... :0

 

# 우선 ... 데이타베이스 정보에 대해 필요할까??? 고민 하다가 넣긴 했는데...

 테스트 시나리오를 넣으려는데... 머리속에 쉽게 안그려지네.

 

 화면에 대한 테스트 시나리오를 작성한다....  전에 이상한 회사에서 작성한 이상한 시나리오가 자꾸 떠올라서 그림이 자꾸 이상하게 그려지는데...

좀더 고민해봐야지..

 

다음주부터는 실제로 이 프로그램으로 화면들을 정리해봐야지...

 

 

 

 

 

 

프로세스 다이어그램 보다는 화면정리 프로그램이 나을것 같다.

 

프로세스를 그린 후 시간에 대한 정보도 담으려고 했었는데... 곰곰히 생각해보니

프로세스와는 크게 관련이 없어보인다. 단지 화면들을 관계들을 업무별로 정리하는 프로그램정도로 마무리 해야겠다.

부가적인 정보로 화면들을 시간순서대로 나열하면서 주석과 기호등을 통해 우선순위정도만 표시해도 괜찮을듯 싶다.

 

화면정의 프로그램을 붙이려고 하는데 옛날 디자이너를 그대로 붙여버릴까 하는 생각이 자꾸 든다... ( 다시 만드는 과정이 ... 생각만 해도 지친다. )

 

새로 만든 프로세스 다이어그램이다.

 

이제 다이어그램 그리는 정도 만든거지만... 추가할 기능에 대한 생각이 많아진다.

 

전 버젼에서의 화면 기능에 추가작업버튼의 경우를 별도 오브젝트로 빼다 보니 다이어그램이 보기도 어렵고 해서 계급장 처럼 바꿔서 표시했다.

 

창으로 여는 일을 하는 빨간색 계급장, 그냥 실행만 하고 끝나는건 녹색계급장.

 

프로세스를 그릴때 다른 업무에서의 화면과 연계될때는 위에보이듯이 타이틀에 해당 업무에 지정된 색상으로 표시해준다.

ex)프로젝트상세, 프로젝트목록 은 [공유] 업무에 있는 화면으로 현재 [테스트] 업무에 포함된 프로세스에 그려지므로 색으로 다름을 표시한다.

 

상세보기를 들어가는 경우 화면 구성에 대한 정보를 기록하게 되는데 이를 화면 설계나 디자이너를 붙여 작업에 이용하려고 한다.

 

여기에 첨부파일, 코멘트등을 추가한다.

 

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

 

 이 프로그램 기획의도는 ... 나중에 PL역할을 혹시? 하게 되면 업무에 대한 설계나 화면 설계를 빠르게 하기 위함이기도 하고

 

기존 화면에 대한 화면분석을 빠르게 할수 있지 않을까? 그런 욕심에 만들게 되었다.

 

SI를 하다보면 설계할때와 개발할때의 문서들이 유지보수하는 인력에게 전달될때!!! 좋은 방법이 없을까 싶어서 생각을 해보고 있다.

 

 위 다이어그램과 함께 누적된 기록들을 클라우드 같은 곳에 올려두고, SM 인력들에게 비쥬얼 스튜디오에서 위 다이어그램등이 쉽게 접근 수정가능해지면?

 

좋지 않을까? 특정화면에서 어떤 문제를 만났을때... 과연 어떤 해결과정을 거칠까?

 

  지금까지 본 바로는 보통 개인의 머리 속 기억에 의존하게 된다. 그러다 그 사람이 나가면? 인수인계가 제대로 이뤄질까? 인수인계된 내용에 대해 검증이 될까?

 

유지보수하면서도 비쥬얼 스튜디오의 .cs 또는 .proj 파일에서 해당 화면에 대한 전체 프로세스를 쉽게 볼수 있다면?

 

 유지보수 하면서 만약 수정이 되는 프로세스나 알아둬야 할 값들이 있다면? 프로그램에서 수정해두면 ...

 

한가지 걸리는게 있다. 문서화 하지 않는 사람... 이건 뭘 가져다 줘도 안되니까.

 

 

 음... SI와 SM에 대해 곰곰히 생각해본다.

 

다양한 SI를 하긴 했지만... SM은 잠깐 해봤었다.

 

그리고 SI에서 개발할때의 문서들과 정보들은 SM으로 전달되지 않는다.

 

인수인계로써 업무에 대해 잠깐 설명하고 끝난다. 내가 있던 곳들이 그런건지... 다 그런지는 잘 모르겠다.

 

SM인력들은 보통 업무를 대부분 알고 있으니 새로 개발된 내용들에 대해 잠깐씩 설명들으면 그걸로 아는걸까?

 

SM인력들이 옆에서 일하는것도 보고 있지만... 쉽지 않아보였다.

 

 이를 개선하기 위해 어떤 방법이 있을까?

 

 

 SI를 작업하면서 도와줄 프로그램(A)과 개발이 끝났을때 SM인력들이 프로그램(A)에서 기록된 정보들을

 

볼수있게 해주면 좀더 좋지 않을까? 공통적인 문제해결등을 SM인력끼리도 공유할수있도록 해주면

 

좀더 일이 편해지지 않을까?

 

 Visual Studio와 SSMS의 툴의 ADDINS 프로그램으로 SI와 SM을 연결해주는 매개체로 사용하면 좋을것 같은데...

 

 

'--- 취미 > 생각하기' 카테고리의 다른 글

개발이 지지부진? ...  (0) 2017.04.25
비전공 나이많은 개발자에 대한 생각...  (0) 2017.01.04
비가 많이 오네....  (0) 2016.07.01
이생각 저생각...  (0) 2016.05.30
1박2일에 나온 내가 살던 섬 '율도'  (0) 2016.05.29

 

친구의 프로그램에 사용한 내용이다.

 

0시~9시까지 <시간외근무>, 9시~18시까지 < 시간내근무(점심 12시~13시제외) >, 18시~24시 <시간외근무>

 

18시 이후에 저녁식사시간을 체크해야함. 18시가 될수도 있고 19시가 될수도... 또 30분동안먹을수도 있고 1시간을 먹을수도 있고.

 

그시간을 계산해서 각각 포인트 및 메모를 한다.

 

근무시간을 이리 저리 바꿔가며 테스트함. 저녁시간도 이리 저리 바꾸며 테스트

 

- 09:00 ~ 18:00

- 07:00 ~ 10:00

- 11:00 ~ 14:00

- 15:00 ~ 19:00 ( 저녁 먹은날, 안먹은날 )

- 08:00 ~ 20:00 ( 저녁 먹은날, 안먹은날 )

- 16:00 ~ 19:30 ( 저녁 먹은날 18:30분 부터 1시간 or 30분, 저녁안먹은날 )

 

# 테스트를 위한 시간설정 {

- 09:00 ~ 12:30 ( 점심시간 12시부터이므로 30분을 빼버림 ㅡ.ㅡ;; 밥은 꼭 12시에 먹어야 한다! )

- 11:30 ~ 13:00

- 12:00 ~ 12:30

- 12:30 ~ 13:00

# 테스트를 위한 시간설정 }

 

기타 시간을 바꿔가면서 테스트 했음.

 

점심시간에 대해 무조건 12시 ~ 13시 한시간으로 처리하다보니...

12시부터 13시는 무조건 제외하도록 만들었다.

 

 

* Method내에 있는 memo는 여기서 사용하지 않음. 다른곳 Method를 복사해와서 그냥 두었다.

    private decimal Calc(string gubun)
        {
            // todo: 9to6 에 맞춰 8hour 이후 시간은 OT로 잡는다.
            decimal sumWT_Value = 0m;
            decimal sumOT_Value = 0m;

            Dictionary<string, decimal> TimeTables = new Dictionary<string, decimal>() {
                {"", 0.0m},
                {"00:00",  0.0m}, {"00:30",  0.5m},
                {"01:00",  1.0m}, {"01:30",  1.5m},
                {"02:00",  2.0m}, {"02:30",  2.5m},
                {"03:00",  3.0m}, {"03:30",  3.5m},
                {"04:00",  4.0m}, {"04:30",  4.5m},
                {"05:00",  5.0m}, {"05:30",  5.5m},
                {"06:00",  6.0m}, {"06:30",  6.5m},
                {"07:00",  7.0m}, {"07:30",  7.5m},
                {"08:00",  8.0m}, {"08:30",  8.5m},
                {"09:00",  9.0m}, {"09:30",  9.5m},
                {"10:00", 10.0m}, {"10:30", 10.5m},
                {"11:00", 11.0m}, {"11:30", 11.5m},
                {"12:00", 12.0m}, {"12:30", 12.5m},
                {"13:00", 13.0m}, {"13:30", 13.5m},
                {"14:00", 14.0m}, {"14:30", 14.5m},
                {"15:00", 15.0m}, {"15:30", 15.5m},
                {"16:00", 16.0m}, {"16:30", 16.5m},
                {"17:00", 17.0m}, {"17:30", 17.5m},
                {"18:00", 18.0m}, {"18:30", 18.5m},
                {"19:00", 19.0m}, {"19:30", 19.5m},
                {"20:00", 20.0m}, {"20:30", 20.5m},
                {"21:00", 21.0m}, {"21:30", 21.5m},
                {"22:00", 22.0m}, {"22:30", 22.5m},
                {"23:00", 23.0m}, {"23:30", 23.5m},
                {"24:00", 24.0m}
            };

            string fromTime = From;  // 근무시작시간
            string toTime = To;         // 근무종료시간
            
            string fromdinner = ("" + FromDinner).Trim(), todinner = ""; //  밥먹기 시작시간, 종료시간.( toDinner는 소스에서 구한다 )

            string hourMinute = ( "" + DinnerHourMinute).Trim();          // 밥먹는 시간 H: 1시간, M: 30분
            
            var getAfterTime = new Func<string, string, string>((fdTime, HM) =>
            {

                // todo : 밥먹는 시간 구함,  todinner 구할때 쓴다.

                string afterTime = "";
                DateTime tmpTime;
                if (DateTime.TryParseExact(DateTime.Today.ToShortDateString() + " " + fdTime, "yyyy-MM-dd HH:mm", null, System.Globalization.DateTimeStyles.AssumeLocal, out tmpTime))
                {
                    if (HM == "H")
                    {
                        afterTime = tmpTime.AddHours(1).ToString("HH:mm");
                    }
                    else
                    {
                        afterTime = tmpTime.AddMinutes(30).ToString("HH:mm");
                    }
                }
                return afterTime;
            });

            decimal val1 = TimeTables[fromTime];
            decimal val2 = TimeTables[toTime];
            decimal val = val2 - val1;

            string memo = "";

            string _from = fromTime;
            string _to = toTime;

            if ("09:00".CompareTo(toTime) <= 0 && fromTime.CompareTo("09:00") < 0)
            {
                // 아침 OT 계산!
                val1 = TimeTables[fromTime];
                val2 = TimeTables["09:00"];
                val = val2 - val1;
                _from = fromTime;
                _to = "09:00";
                sumOT_Value += val;
                memo += string.Format("{0}~{1} > {2}", _from, _to, val);
                memo += Environment.NewLine;
            }

            if ("09:00".CompareTo(toTime) <= 0)
            {
                if ("09:00".CompareTo(fromTime) < 0)
                {
                    val1 = TimeTables[fromTime];
                    _from = fromTime;
                }
                else
                {

                    val1 = TimeTables["09:00"];
                    _from = "09:00";
                }

                if ("18:00".CompareTo(toTime) <= 0)
                {
                    val2 = TimeTables["18:00"];
                    _to = "18:00";
                }
                else
                {
                    val2 = TimeTables[toTime];
                    _to = toTime;
                }


                val = val2 - val1;

                decimal offset1 = 0m;
                decimal offset2 = 0m;

                if (_from.CompareTo("12:00") <= 0 && "12:30".CompareTo(_to) <= 0)
                {
                    offset1 = TimeTables["12:00"];
                }
                else if (_from.CompareTo("12:30") <= 0 && "12:30".CompareTo(_to) <= 0)
                {
                    offset1 = TimeTables["12:30"];
                }
                if ("13:00".CompareTo(_to) <= 0 && _from.CompareTo("12:30") <= 0)
                {
                    offset2 = TimeTables["13:00"];
                }
                else if ("12:30".CompareTo(_to) <= 0 && _from.CompareTo("12:30") <= 0)
                {
                    offset2 = TimeTables["12:30"];
                }
                val = val - (offset2 - offset1);

                sumWT_Value += val;
                memo += string.Format("{0}~{1} > {2}", _from, _to, val);
                memo += Environment.NewLine;
            }

            // 오후 OT
            if ("18:00".CompareTo(toTime) <= 0)
            {
                if (string.IsNullOrEmpty(fromdinner.Trim()) == false)
                {
                    if ("18:00".CompareTo(fromdinner) >= 0)
                    {
                        // 식사시간이 18시면
                        todinner = getAfterTime(fromdinner, hourMinute);
                        if (todinner.CompareTo(_to) < 0)
                        {
                            val1 = TimeTables[fromdinner];
                            val2 = TimeTables[todinner];

                            _from = fromdinner;
                            _to = todinner;
                            val = val2 - val1;
                            if (val > 0)
                            {
                                memo += string.Format("{0}~{1} <밥> {2}", _from, _to, val);
                                memo += Environment.NewLine;
                            }
                        }
                    }
                    else
                    {
                        if (fromdinner.CompareTo(_to) < 0)
                        {
                            // 식사시간이 18시가 지나서 18시 30분이라면...
                            //# 밥먹기 전까지 일한 시간
                            val1 = TimeTables["18:00"];
                            val2 = TimeTables[fromdinner];
                            _from = "18:00";
                            _to = fromdinner;
                            val = val2 - val1;
                            memo += string.Format("{0}~{1} > {2}", _from, _to, val);
                            memo += Environment.NewLine;
                            // 밥먹은시간..
                            todinner = getAfterTime(fromdinner, hourMinute);
                            if (todinner.CompareTo(_to) < 0)
                            {
                                val1 = TimeTables[fromdinner];
                                val2 = TimeTables[todinner];

                                _from = fromdinner;
                                _to = todinner;
                                val = val2 - val1;
                                if (val > 0)
                                {
                                    memo += string.Format("{0}~{1} <밥> {2}", _from, _to, val);
                                    memo += Environment.NewLine;
                                }
                            }
                        }
                    }

                    if (todinner.CompareTo(toTime) < 0)
                    {
                        if (fromdinner.CompareTo(toTime) < 0)
                        {
                            todinner = getAfterTime(fromdinner, hourMinute);

                            val1 = TimeTables[todinner];
                            val2 = TimeTables[toTime];
                            _from = todinner;
                            _to = toTime;
                            val = val2 - val1;
                            if (val > 0)
                            {
                                sumOT_Value += val;
                                memo += string.Format("{0}~{1} > {2}", _from, _to, val);
                                memo += Environment.NewLine;
                            }
                        }
                    }
                }
                else
                {
                    if (todinner.CompareTo(_to) < 0)
                    {
                        // 저녁식사 X
                        val1 = TimeTables["18:00"];
                        val2 = TimeTables[toTime];
                        _from = "18:00";
                        _to = toTime;
                        val = val2 - val1;
                        if (val > 0)
                        {
                            sumOT_Value += val;
                            memo += string.Format("{0}~{1} > {2}", _from, _to, val);
                            memo += Environment.NewLine;
                        }
                    }
                }
            }

            if (gubun == "Total")
            {
                return sumOT_Value + sumWT_Value;
            }
            else
            {
                return sumOT_Value;
            }
        }