얼마 전에 진행하고 있던 프로젝트가 종료되었습니다.
일정에 맞춰 종료되었지만 개인적으로 만족스러운 프로젝트는 아니었습니다.
회사에서 진행하는 프로젝트의 대부분이 그렇듯이 품질보다는 완성에 초점이 맞춰진 프로젝트였거든요.

저희 팀은 유지보수가 주업무다 보니 프로젝트 시 직접 코딩에 참여하지는 않습니다.
그러다보니 SI 팀에서 진행한 프로젝트를 건내 받아 코드를 열어 보고 나면 한숨이 나올 때가 많습니다.
물론 그 중에 굉장히 잘 만들어진 코드가 있기도 하고, 
과연 우리가 만든다면 더 나은 코드가 나올 것이냐. 에 대해서도 장담할 수 없지만,
이걸 가지고 운영해나갈 생각을 하면 저절로 한숨이 나오는 걸 어찌하나요~ ^^;

물론, 프로젝트 진행 중에 함께 참여해서 코드 리뷰하고 하고 중간 중간 점검도 해야하겠지만,
이번을 포함하여 회사에서 진행되었던 대부분의 프로젝트 일정이 어처구니 없을 정도로 촉박했던 터라
여건 상 그렇게 하지 못하는 경우가 대부분이었습니다.
중간에 제대로 점검 및 서포트 하지 못했던 우리의 잘못도 크지요.
결국은, 모두의 잘못인 거겠죠...

아래는 이번 프로젝트에서 잘 지켜지지 못해서 아쉬웠던, 
Java 프로젝트에 있어 지켜져야 한다고 생각하는 것들을 정리한 내용입니다.


개발표준안을 정하고 지속적으로 표준을 지키고 있는지 확인해야할 점들



보시다시피 별 대단한 내용이 아닙니다.
개발자라면 모두 아는 내용이고, 기본적인 거지요.
뛰어난 로직을 바라는 게 아니라, 표준이 잘 지켜진 알아볼 수 있는 코드를 부탁하는 거예요.

문제는 이런 내용을 모두 알고 있으면서도 지키지 않는다는 거예요. (혹시 잘 모른다면 공부하셔야 합니다.)
단지 시간도 없고 귀찮다는 이유로, 대충 마음에 드는 대로 작성하고 Copy & Paste 하고 말아버리는 거죠...
'어차피 내가 할 거 아닌데...' 라는 생각을 가지기도 하고,
심지어는 '쟤네들 이거 받아서는 고생 좀 하겠군.' 이라고 생각하기도 하지요.

다소 도발적일 수도 있지만, 
누군가가 내가 작성한 코드를 보고 
'이거 누가 이렇게 개떡같이 짜놨어??' 라고 하는 걸 상상해보세요.

SI 팀에서는 '우리가 완성한 프로젝트를 누군가가 받아 운영하게 될 것' 이라는 걸 항상 염두해주시면 좋겠습니다.
SI 프로젝트 개발자에게 바라는 건 '코드에 대한 책임감' 입니다.

저작자 표시 비영리 변경 금지
Posted by ohgyun
후배들에게 Ajax 를 설명해주고 자동 완성 기능 구현을 실습 과제로 주려다가 문득,
각 포텰별 검색어 추천 기능의 차이점이 궁금해졌습니다.

아래는 주요 포털의 기능을 비교하여 정리한 내용입니다.


구글의 검색어 제안 기능

구글의 검색어 제안 기능



먼저 글에서 공통적으로 사용할 용어는 아래와 같습니다.

용어 정의
    검색인풋: 검색어를 입력하는 input box
    서제스트레이어: 검색어 추천 기능을 제공하는 레이어
    RMB: Right Mouse Button
    LMB: Left Mouse Button
    G : Google
    N : Naver
    D : Daum


기본 공통 특성
    모두 타이머 방식으로 구현
    한 글자 이상 존재할 경우 보여짐


서제스트레이어의 전반적인 모습
    G: 검색어 이외의 단어를 bold 처리해 줌.
        서제스트레이어 내에 검색 버튼이 존재함.
        검색 버튼이 검색인풋 하단에 있어 서제스트 레이어에 가려지지만,
        이를 통해 버튼이 노출될 수 있게 함.
        완성된 글자가 아닐 경우, (예를 들어 'ㅇ', '강ㄴ')
        모든 제시 검색어가 bold 처리됨.
    N: 구글과는 다르게 검색어를 오렌지 bold 로 처리해 줌.
         검색어가 제시어와 완벽히 일치될 경우에만 bold 처리
         끝 글자 검색, 끄기 버튼 제공됨
    D: 검색어를 오렌지 처리해 줌.
        역시 검색어와 제시어가 완벽히 일치될 경우에만 오렌지 처림
        끝 글자 검색, 끄기 버튼 제공


서제스트레이어의 전반적인 모습에서 찾아볼 수 있는 구글과 네이버/다음의 차이는,
사용자의 관심이 검색어인지, 아니면 검색어 이외의 것인지에 대한 인식의 차이라고 생각합니다.
또한 구글은 검색에만 포커스를 두는 한편,
네이버/다음은 사용자에게 다양한 선택을 제공하고 있다는 것도 찾아볼 수 있습니다.


네이버의 검색어 제안 기능

네이버의 검색어 제안 기능



검색 input 에 포커스가 들어갈 경우 (LMB 클릭)
    G: 서제스트 레이어가 보여지지 않음
    N,D: 서제스트 레이어를 다시 보여줌


검색 input 에 포커스가 들어갈 경우 (외부에서 tab 키로 들어감)
    GND: 키보드 포커스에 의해서는 서제스트 레이어가 보이지 않음


서제스트 레이어가 보여지는 시점
    GND: 검색 input 에 포커스가 있고, 한 글자 이상 존재하며 텍스트가 변경될 경우.
    N, D: 한 글자 이상 존재하고 마우스 포커스가 들어갈 경우


외부 영역에 LMB 또는 RMB 클릭
    GND: 서제스트 레이어가 숨겨짐


다음의 검색어 제안 기능

다음의 검색어 제안 기능



입력 중 Tab 키를 누를 경우
    G: 서제스트 레이어가 닫기고 Search 버튼으로 포커스 이동
    N: 서제스트 내 다음 단어로 이동
    D: 서제스트 레이어는 그대로 있고 로그인 스팟의 아이디 input 으로 포커스 이동
        영문 검색어일 경우, id 입력 칸으로 검색어가 잘라져 들어감
 
네이버는 Tab 키를 누를 경우, 검색 버튼이 아니라 다음 단어로 이동하도록 되어있습니다.
유용하기도 하지만, 한편으론 일반적인 Tab 키의 기능(element 간 포커스 이동)을 가지도록 하는 것도 좋을 것 같습니다.
예를 들어, 아래의 케이스에선 네이버의 Tab 키의 작동은 기대하지 않은 것일 수도 있습니다.
    1. 검색 input 에 검색어 입력
    2. 외부 클릭으로 포커스를 잃음
    3. 다시 tab 키로 검색 input 으로 포커스
    3-1. (tab 키를 눌러서 '검색' 버튼으로 포커스가 이동되기를 기대함)
    4. tab 키를 누르면 자동 검색의 다음 단어로 이동함

다음의 경우엔, 검색 창의 영문어를 입력하고 Tab 키를 누를 경우,
자동으로 로그인아이디인풋으로 검색어가 카피되어 들어가고 비밀번호인풋으로 포커스가 이동합니다.
Tab 키를 누르면 '검색' 버튼으로 포커스가 이동하기를 기대했기 때문에,
처음 이런 증상을 확인했을 때에는 버그인가 싶었지만 디테일하게 사용자의 행동을 고려한 것이라는 걸 알게 됐습니다.
전 개인적으로는 거의 포털에서 로그인을 하지 않지만,
로그인이 잦은 사용자라면 포털에 접속하자마자 능숙하게 아이디를 적고 바로 로그인을 할 것입니다.
메인 화면이 로딩됨과 동시에 (또는 로딩되는 중간에) 매우 빠른 속도로 "아이디 - 탭 - 패스워드 - 엔터" 를 입력하겠죠.
검색사이트이기 때문에 기본적으로는 검색인풋에 포커스를 두는 걸 있어야 하겠고,
단골 사용자의 패턴을 고려하여 상세하게 구현한 부분이 인상적입니다.


검색 input 포커스 안에서 RMB 클릭 시
    G: 정상적으로 컨텍스트 메뉴가 나옴. 이상 없음.
    N: 정상적으로 컨텍스트 메뉴가 나옴. 이상 없음.
        클릭 위치의 단어 단위로 선택됨(W3C 브라우저에 한함)
    D: 컨텍스트 메뉴가 나오나, 서제스트 레이어가 토글됨.
        click 마우스 이벤트 핸들러에 대해, 왼쪽 버튼만 작동하도록 변경이 필요할 듯.


빠른 입력으로 지웠다 삭제할 경우 (예: a 를 썼다 지웠다 썼다 지웠다 할 경우)
    G: 빠르게 반복하다가 삭제할 경우 정상적으로 적용됨. 반응 속도가 약간 느림.
         빠르게 반복하다가 한 글자를 남길 경우, 서제스트레이어가 보이지 않는 경우가 있음.
    N: 빠른 반복에도 모두 정상적으로 작동됨.
    D: 내용이 없을 경우에도 서제스트 레이어가 남아 있는 경우가 있음.

구글의 경우 반응 속도가 다른 포털에 비해 약간 늦습니다. 최고보다는 최적을 선택한 것일까요.
네이버의 경우엔 타 포털에 비해 기술적으로 더 꼼꼼하게 구현되어 있는 것 같네요.
기술적 구현의 디테일도 중요한 한편, 최적의 선택도 나쁘지 않다고 생각됩니다.


자음 단위 검색 (예를 들어, '강남' 검색을 위해 '강ㄴ' 까지 입력했을 경우)
    GNB: 정상적으로 검색됨


한글 2벌식으로 영문을 입력했을 경우
    (입력 예: 영단어가 존재하지 않는 경우: 피카 --> vlzk, 강남 ---> rkdska, 완성 ---> dhkstjd
                 영단어가 존재하는 경우: 맘스 --> akas)
    G: 구글코리아만 해당. 영어 세글자부터 검색되며, 2벌식 결과와 영문 결과를 동시에 보여줌.
    N: 영어 네글자부터 검색됨. 정확히 파악되진 않으나,
        2벌식의 경우 단순 자소 단위가 아니라 완성된 글자이되 2글자 이상으로 검색되는 듯.
        예) rkdsk (강나 부터 검색), dhkstj (완서 부터 검색)
             자음 + 모음의 형태로 두 글자가 만들어 질 때부터로 파악됨
    D: 영어 네글자부터 검색됨. 한 글자가 만들어 질 때부터 검색도미.
        예) dhks(완 부터 검색)



여기까지가 각 포털별 검색어 제안 기능에 대해 비교해본 내용입니다.

전반적으로 느낀 개인적인 느낌은 이렇습니다.
    G: 기본과 목적에 충실, 최적을 고려
    N: 다양한 선택을 제공하며 실질적인 사용자를 고려. 기술적 디테일이 좋음.
    D: 다양한 선택을 제공하며 실질적인 사용자를 고려. 기술적 디테일이 약간 부족. 

기술적 디테일에서는 다음이 약간 부족한 듯 느껴졌었으나,
검색어가 Tab 키에 의해 아이디로 변환되어 들어가는 부분은 굉장히 인상적이었습니다.

Tab 키에 구현에 있어서는 구글이 해당 키의 '기본적인 기능' 을 추구했다면,
국내 포털은 나름대로의 '실질적인 기능'을 추구했다는 데에서 좋은 느낌을 받았습니다.

중요한 것은 어느 포털이 더 잘 구현했냐. 보다는
모든 포털이 사용자의 누적된 행동 패턴(User Experience)을 파악해서 
조금이라도 더 편리하게 구현하려고 노력한다는 게 아닐까요~

이러한 디테일한 노력을 사용자가 알아주고 잘 사용해준다면,
만든 이도 굉장히 뿌듯할 거라 생각됩니다.^^


저작자 표시 비영리 변경 금지
Posted by ohgyun
2009 Google IO 의 한 세션이었던 The Myth of the Genius Programmer 동영상을 보고
좋은 느낌을 받아 요약해보려 합니다.


The Myth of the Genius Programmer (동영상: 약 1시간, 영문 자막있음)


소프트웨어 개발에 있어서 모든 사람들이 똑똑해 보이기를 원하는데,
이런 자존심을 버리고 자기 발전을 이룰 수 있는 방법에 대한 세미나예요~

1시간 짜리 동영상이라 보기 좀 힘들지만, 굉장히 유익하다고 생각됩니다.
시간 내서 한 번쯤 보시기를 추천합니다.

영어 세미나이지만 다행히 영어 자막이 있어서 그나마 좀 알아들을 수 있었네요^^;;
동영상을 보면서, 자유롭게 기술적으로 토론할 수 있는 환경이 있다는 게 참 부럽더군요.
발표자들도 굉장히 재미있고 편하게 발표하고 말이예요. :)

특히, 세미나의 두 발표자를 보고,
아이디어를 나누고 발전시킬 수 있는 파트너의 중요성에 대해서도 더욱 알게 됐습니다.
(전 그럴 파트너가 몇 명 있는 것 같아 참 좋습니다.^^)

여튼, 아래는 제가 이해한 것들을 요약한 목록입니다.
(잘못 알아들어서 동영상과 다른 정보일 수도 있습니다.^^;;; 잘못된 내용이면 교정 부탁드립니다.)

====================================================================================

천재 프로그래머는 없다
  - 비판은 나쁘지 않다. 적극적으로 비판하라
  - 실패를 받아들이고, 빨리 실패하라
  - 연습하라
  - Small Fish 가 되라 (큰 연못의 작은 물고기가 되어 많이 배우라)
  - Be influenced, Be Vulnerable
  - 실수를 인정하라

코드를 공개할 타이밍
  - 거의 완성된 상태에서 오픈소스로 공개하는 것은 의미가 없다
  - 너무 일찍 공개할 경우, 배가 산으로 갈 수 있다
  - 웹사이트를 만들어 목표가 무엇인지 정확히 명시한다
  - 컨셉을 표현할 수 있을 정도의 코드는 있어야 한다.
  - 히스토리를 모두 남겨라
  - 프로젝트를 시작할 때는 2~3명이 좋을 듯

서머리
  - 지니어스가 되려고 하지 말라
  - 일찍, 그리고 자주 협력하라
  - 툴과 타이밍에 집중하라 (협업에 도움이 되는)


Q&A 타임
  짝프로그래밍에 대해 어떻게 생각하나
     - write-code-review process 를 더 선호한다
     - 서로를 잘 알아야 한다고 생각한다. 사소한 것에 대해 논쟁을 벌일 수 있다
  
  비평적인 코드 리뷰에 대해 질문자 왈,
    - 비평적인 코드 리뷰를 적용할 때는 실질적인 환경을 조심스럽게 고려해야 한다.
      다른 사람들은 그것들에 상처받을 수도 있기 때문

====================================================================================

*  XPER 의 개발자에게 필요한 자질이 따로 있을까요? 스레드에서 동영상 링크를 얻었습니다.
저작자 표시 비영리 변경 금지
Posted by ohgyun
발생일: 2010.05.06

문제:
현업이 종종 특정 데이터를 엑셀로 뽑아달라는 요청을 합니다.
요청이 간헐적이고 같은 데이터를 시도 때도 없이 새로 뽑아달라는 요청을 해서,
좀 효율적으로 처리하고자 동적 쿼리를 수행하는 메뉴를 하나 만들었습니다.

해당 쿼리가 자주 변하고 보안 문제도 있었기 때문에,
관리를 편하게 하기 위해 DB 대신 파일 기반으로 설계했습니다.
서버에 올라가 있는 sql 파일을 읽어 목록을 구성하고,
해당 쿼리를 담은 sql 파일을 읽어 엑셀로 다운로드 받을 수 있는 기능입니다.
(우리는 요청 쿼리를 담은 sql 파일을 서버에 올리기만 하면 되도록 말이죠.)

iBATIS 를 사용하고 있어 파일에서 읽은 쿼리를 아래와 같이 $sql$ 형태로 전달하도록 했는데,

    <select id="dynamicQuery" resultClass="hashmap">
        $sql$
    </select>

첫 번째는 정상적으로 실행되고, 그 이후 다른 쿼리를 다운로드 받으려 시도했을 때
아래와 같은 에러가 발생합니다.


Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:   
--- The error occurred while applying a result map.  
--- Check the 쿼리ID - AutoResultMap.
--- Check the result mapping for the 컬럼명 property.  
--- Cause: java.sql.SQLException: 부적합한 열 이름


문제가 뭘까요...


해결책:
iBATIS 는 기본적으로 해당 쿼리에 대한 메타데이터(필드, 타입 등)를 캐시한다고 합니다.
따라서 위 dynamicQuery 구문이 실행된 이후 그 결과의 컬럼 정보가 캐시되었고,
이후 다른 컬럼 정보를 포함한 쿼리가 dynamicQuery 로 실행되었을 때
캐시된 컬럼 정보로 값을 찾으려하다 오류가 난 거였던 거죠.

이 경우엔, 아래와 같이 해당 select 구문의 메타데이터를 캐시하지 않도록 설정하면 된다고 합니다.

    <select id="dynamicQuery" resultClass="hashmap" remapResults="true">
        $sql$
    </select>


아래 포스트에서 참고했습니다.

저작자 표시 비영리 변경 금지
Posted by ohgyun
문서를 정리하다가 예전에 헤드퍼스트 디자인 패턴 책을 읽고 정리해 놓은 파일이 있어 옮겨봅니다.

==============================================================

디자인 원칙
    - 애플리케이션에서 달라지는 부분을 찾아내고, 달라지지 않는 부분으로부터 분리한다.
    - 구현이 아닌 인터페이스에 맞춰서 프로그래밍한다.
    - 상속보다는 구성을 활용한다.
    - 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결한하는 디자인을 사용해야 한다.
    - 클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다.
       (OCP : Open-Closed Principle)
    - 추상화된 것에 의존하도록 만들어라. 구상클래스에 의존하도록 만들지 않도록 한다.
    - 최소 지식 원칙 - 정말 친한 친구하고만 얘기하라.
       (다음 네 종류의 객체의 메서드만 호출한다.
         1. 객체 자체 / 2. 메서드에 매개변수로 전달된 객체 / 3. 그 메서드에서 생성하거나 인스턴스를 만든 객체 / 4. 그 객체에 속하는 구성 요소)
    - 헐리우드 원칙 - 먼저 연락하지 마세요. 저희가 연락 드리겠습니다.
    - 클래스를 바꾸는 이유는 한 가지 뿐이어야 한다.
    + ... 나중에 어떻게 바뀔 것인가?


스트래티지 패턴(Strategy Pattern)
    - 알고리즘군을 정의하고 각각을 캐슐화하여 교환해서 사용할 수 있도록 만든다.
    - 알고리즘을 사용하는 클라이언트와는 독립적으로 알고리즘을 변경할 수 있다.
    - 구성을 사용한다.
    - 일반적으로 서브클래스를 만드는 방법을 대신하여 유연성을 극대화하기 위한 용도로 쓰인다.
    - 예: QuarkBehavior & FlyBehavior
    

옵저버 패턴(Observer Pattern)
    - 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체들한테 연락이 가고
       자동으로 내용이 갱신되는 방식으로 일대다(one-to-many) 의존성을 정의한다.
    - 주제(Subject) & 옵저버(Observer)
    - Observable & Observer:
         Observable 에 register, remove, notify 가 있고, 
         Observer 에 update 가 있다. (notify 에서 update 를 호출)
    - 예: 신문 구독 서비스, 기상관측 시스템
    

데코레이터 패턴(Decorator Pattern)
    - 객체에 추가적인 요건을 동적으로 첨가한다.
    - 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다.    
    - 예: 스타버즈 커피
    
    
팩토리 패턴(Factory Pattern)    
    - 팩토리 메서드 패턴 :
       객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브클래스에서 결정하게 만든다.
       클래스의 인스턴스를 만드는 일을 서브클래스에 맡긴다.
    - 제품을 생산하는 부분과 사용하는 부분을 분리시킬 수 있다.
    - 추상 팩토리 패턴 :
       인터페이스를 이용하여 서로 연관된, 또는 의존하는 객체를 구상 클래스를 지정하지 않고 생성한다.
       구상 클래스는 서브 클래스에 의해 만들어진다.


싱글턴 패턴(Singleton Pattern)
    - 해당 클래스의 인스턴스가 하나만 만들어지고,
       어디서든지 그 인스턴스에 접근할 수 있도록(전역 접근) 하기 위한 패턴
       
       
커맨드 패턴(Command Pattern)
    - 요구 사항을 객체로 캡슐화 할 수 잇으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수 있다.
       또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 잇으며, 작업취소 기능도 지원 가능하다.
    - 예: 리모콘
    - 서블릿의 doGet(), doPost() 또는 스트럿츠의 Action() 메서드도 커맨드 패턴이지 않을까?
    

어댑터 패턴(Adapter Pattern)
    - 한 클래스의 인터페이스를 클라이언트에서 사용하고자 하는 다른 인터페이스로 변환한다.
       어댑터를 이용하면 인터페이스 호환성 문제 때문에 같이 쓸 수 없는 클래스들을 연결해서 쓸 수 있다.  
       

퍼사드 패턴(Facade Pattern)
    - 어떤 서브시스템의 일련의 인터페이스에 대한 통합된 인터페이스를 제공한다.
       퍼사드에서 고수준 인터페이스를 정의하기 때문에 서브시스템을 더 쉽게 사용할 수 있다.
    - 서브시스템의 호출을 퍼사드에서 처리해준다. (기본 명령 호출 정도랄까...)
    - 일련의 클래스들에 대한 인터페이스를 단순화 시킨다.
    
    - 각 패턴별 차이점:
       데코레이터 패턴 : 인터페이스는 바꾸지 않고 책임(기능)만 추가
       어댑터 패턴 : 한 인터페이스를 다른 인터페이스로 변환
       퍼사드 패턴 : 인터페이스를 간단하게 바꿈


템플릿 메서드 패턴(Template Method Pattern)
    - 메서드에서 알고리즘의 골격을 정의한다.
       알고리즘의 여러 단계 중 일부는 서브클래스에서 구현할 수 있다.
       템플릿 메서드를 이용하면 알고리즘의 구조는 그대로 유지하면서 서브클래스에서 특정 단계를 재정의할 수 있다.
    - 스트래티지 패턴과 다른 점:
       템플릿 메서드 패턴은 알고리즘의 개요를 정의한다. 실제 작업 중 일부는 서브클래스에서 처리.
       스트래티지 패턴은 객체 구성을 통해서 알고리즘을 캡슐화 및 구현
    - 예) Arrays.sort(배열); --- compareTo() 를 구현하도록 되어 있다.
            Applet , init(), start(), stop(), destory()
            그렇다면 서블릿에도 템플릿 메서드가 쓰이는 거구나. init() - service() - destory()

            
이터레이터 패턴(Iterator Pattern)
    - 컬렉션 구현 방법을 노출시키지 않으면서도
       그 잡합체 안에 들어있는 모든 항목에 접근할 수 있게 해주는 방법을 제공한다.
    - 컬렉션의 구현을 드러내지 않으면서 컬렉셔네 있는 모든 객체들에 대해 반복작업할 수 있다.
    

컴포지트 패턴(Composite Pattern)
    - 객체들을 트리 구조로 구성하여 부분과 전체를 나타내는 계층구조로 만들 수 있다.
       이 패턴을 이용하면 클라이언트에서 개별 객체와 다른 객체들로 구성된
       복합 객체(composite)를 똑같은 방법으로 다룰 수 있다.
    - 클라이언트에서 객체 컬렉션과 개별 객체를 똑같은 식으로 처리할 수 있다.
    - 예) 트리 구조의 패턴, 디렉토리 구조
    - 예) XMLObject 객체가 컴포지트 패턴을 구현한 게 아닐까
    

스테이트 패턴(State Pattern)
    - 객체의 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있다.
       마치 객체의 클래스가 바뀌는 것과 같은 결과를 얻을 수 있다.
    - 상태 전환의 흐름을 결정하는 코드를 어느 쪽에 집어넣는지 잘 고려해야 한다.
       (상태 객체인지, Context 객체인지)
    - 각 상태를 클래스로 캡슐화함으로써 나중에 변경시켜야 하는 내용을 국지화시킬 수 있다.
    - 스트래티지 패턴:
          어떤 클래스의 인스턴스를 만들고 그 인스턴스에게 어떤 행동을 구현하는 전략 객체를 건내준다.
       스테이트 패턴:
          컨텍스트 객체를 생성할 때 초기 상태를 지정해주는 경우 이후로는 컨텍스트 객체가 알아서 상태를 변경.
          
          
프록시 패턴(Proxy Pattern)
    - 어떤 객체에 대한 접근을 제어하기 위한 용도로 대리인이나 대변인에 해당하는 객체를 제공하는 패턴
    - 다른 객체를 대변한느 객체를 만들어서 주 객체에 대한 접근을 제어할 수 있다.
    - 원격프록시(remote proxy): 원격 객체에 대한 접근 제어
                                                클라이언트와 원격 객체 사이에서 데이터 전달을 관리
       가상프록시(virtual proxy): 생성하기 힘든(인스턴스를 만드는 데 많은 비용이 드는) 자원에 대한 접근 제어
       보호프록시(protection proxy): 접근 권한이 필요한 자원에 대한 접근 제어
                                                     호출하는 쪽의 권한에 따라서 객체에 있는 메소드에 대한 접근 제어
       방화벽 프록시: 일련의 네트워크 자원에 대한 접근 제어
       스마트 레퍼런스 프록시: 주 객체가 참조될 때마나 추가 행동을 제공. 객체에 대한 레퍼런스 개수를 세는 등
       캐싱 프록시: 비용이 많이 드는 작업의 결과를 임시로 저장
                          웹 서버 프록시 또는 컨텐츠 관리 및 퍼블리싱 시스템 등에서 사용
       동기화 프록시: 여러 스레드에서 주 객체에 접근하는 경우 안전하게 작업을 처리할 목적(분산 환경 등에서 사용)
       복잡도 숨김 프록시: 복잡한 클래스들의 집합에 대한 접근을 제어하고 복잡도를 숨겨줌
                                     퍼사드 프록시라고도 함.
                                     프록시에서는 접근을 제어하지만 퍼사드 패턴에서는 대체 인터페이스만 제공
       지연 복사 프록시: 클라이언트에서 필요로 할 때까지 객체가 복사되는 것을 지연시킴으로써 객체의 복사 제어
       
    - 아래 객체들은 모두 클라이언트와 객체 사이에 끼여들어서 요청을 전달한다.
         데코레이터 패턴: 클래스에 새로운 행동을 추가하기 위한 용도
         어댑터 패턴: 다른 객체의 인터페이스를 바꿔주기 위한 용도
         프록시 패턴: 어떤 클래스에 대한 접근을 제어하기 위한 용도
    - java.reflect.Proxy 에 기능이 내장되어 있다.
    
    
디자인 패턴 정의
    - 패턴이란 특정 컨텍스트 내에서 주어진 문제에 대한 해결책이다.
    - 어떤 컨텍스트 내에서 일련의 제약조건에 의해 영향을 받을 수 있는 문제에 봉착했다면,
       그 제약조건 내에서 목적을 달성하기 위한 해결책을 찾아낼 수 있는 디자인을 적용하면 된다.    
      

주의점 및 추가 사항      
    - 디자인 패턴의 과다한 사용은 불필요하게 복잡한 코드를 초래할 수 있다.
       항상 가장 간단한 해결책으로 목적을 달성할 수 있도록 하고, 반드시 필요할 때만 디자인 패턴을 적용하자.      
    - 코딩할 때 어떤 패턴을 사용하고 있는지 주석으로 적어주자.
       클래스와 메서드 이름을 만들 때도 사용 중인 패턴이 분명하게 드러날 수 있도록 해보자.
       다른 개발자들이 그 코드를 볼 때 무엇을 어떻게 구현했는지 훨씬 빠르게 이해할 수 있다.


그 외 잘 정리된 참고 사이트 : http://vincehuston.org/dp/
저작자 표시 비영리 변경 금지
Posted by ohgyun