TRIZ 를 배운 이후로 문제에 대한 해결책을 찾아내는 방식에도 패턴이 있다는 것을 느끼곤 한다.

GoF 의 Design Patterns 같은 패턴도 있지만, 단순한 문제에 대한 해법의 패턴보다는, 해법을

찾아내는 방식에 대한 패턴, 다시 말하자면 Higher-order Problem solving 으로서의 패턴을

모아보았다.


TRIZ에 등장하는 발명 원리들은 원자단위의 세계에서 다루는 문제 해결방법이기 때문에 물질장(Field)

모델을 기준으로 모순과 해결방식을 제안하고 있다. 하지만 소프트웨어는 비트단위의 세계이기 때문에

근본적인 장(Field)의 정의가 다르고 제약조건들도 다른 부분이 많아 그대로 가져오기엔 곤란한 부분과

그대로 적용할 수 있을만한 부분이 공존하고 있다.


아래에 모아본 리스트는 시간이 지남에 따라 계속 보강/정리될 것이고 관련 사례들도 추가될 것이다.


사례는 주로 게임 프로그램 디자인이라는 관점에서 정리한 것이며, 기술 파라메터(모순)에 해당하는 것들과 발명원리에 해당하는 것들을 우선 모아보았다.


기술 파라메터

* 반응속도 (Response)
실행 시간시 입력에 대한 출력의 도출 속도. 반응속도를 일정수준 이상으로 높여야 하는 요구사항이 존재한다.
예) 게임의 FPS (Frame per second)

* 계산시간
런타임 이외의 부분을 포함한 계산시간
예) 3d CG 소프트웨어에서의 Radiosity 계산 속도

* 메모리 사용량
런타임시 사용할 RAM 의 요구량

* 로직의 복잡도
알고리즘이나 자료구조의 복잡성

* 코드의 양
소스코드의 양. 유지 보수와 관련이 있다

* 데이타의 양
배포해야 하는 데이타의 양.
예) CDN 에 올라갈 패치 파일의 용량

* 메인터넌스 비용
요구사항 변동과 추가에 따른 작업노력의 양

* 작업 비용
데이타 작성을 위해 필요한 수작업의 양
예) 모델에 라이트맵 제작을 위해 직접 세컨드채널 uv 맵을 손으로 만드는 경우
예) 3d 월드에 길찾기를 위한 네비게이션 메쉬를 직접 만드는 경우

* 융통성
하나의 소프트웨어로 얼마다 다양한 상황에 대응할 수 있는가

* 로딩시간
데이타를 메모리로 읽어와 사용가능한 상태로 만드는데 필요한 시간

* 정밀도 (Precision)
이상적인 경우의 결과값과 계산된 결과값이 얼마나 가까운가



발명원리
* 단계추가 (Indirection)
모든 프로그래밍의 발전은 Indirection 을 증가시키는 것과 관계가 있다는 말이 있다. 더 많은 상황에 대응할 수 있도록, 단계를 추가함으로써 차후에 커스터마이즈를 원활하게 한다. 거의 모든 디자인 패턴들은 단계추가와 관련되어있다고 할 수 있다
예) C언어의 포인터
예) 엑셀로 가계부를 만들때 상품의 단가를 직접 입력하는 대신, 다른 셀들에 단가들을 입력해놓고 셀의 이름을 참조하게 하여, 후에 단가 변경시 재계산을 용이하게 한다

* 국부적 품질 (Local Quality, Adaptiveness)
중요한 부분과 덜 중요한 부분을 분리하여 처리함으로써, 계산시간이나 메모리사용량, 배포용량을 절약한다
예) MP3 인코딩시 모든 구간에 대해 같은 비트레이트를 사용하는 대신, 음파의 복잡도에 따라 다른 비트레이트를 사용하는 VBR 방식

* 포개기 (Nesting)
하나의 메모리나 기능 단위가 여러가지 기능을 포함하도록 한다
예) c 언어의 union

* 명세 분리 (Separating Interface)
예) 플러그인

* 표현단계 (Level of detail)
거리 등의 정해진 요소에 따라 다른 품질의 계산결과를 사용한다. 국부적 품질의 특정한 부분집합으로 볼 수 있다
예) 오브젝트나 지형을 거리에 따라 간단한 버전으로 바꾸어 표현한다
예) 거대한 월드에서의 많은 NPC 들의 행동을 모두 계산하기 힘들때, 플레이어와 멀리 있는 오브젝트는 간략화된 AI 를 사용한다.

* 근사치사용 (Approximation)
정확한 알고리즘을 사용해서 정확한 결과를 내는 것이 어렵거나 불가능한 경우에, 그것을 대체할만한 비슷한 다른 값싼 방식을 사용한다
예)

* 선계산 (Precalculation)
예) 뷰 정보와 관계없이 사용할 수 있는 라이트맵을 미리 계산해놓는다
예) PVS (Potentially Visible Set) 를 미리 계산해서 실내의 프러스텀 컬링을 효과적으로 한다

* 실행시간시 조합 (Runtime composition)
예) 실시간으로 캐릭터를 조합한다
예) 앰비언트 오클루전(Ambient Occlusion) 레이어와 라이트에 의해 만들어진 그림자 레이어를 분리하여, 용량을 줄이면서 비주얼 퀄리티를 유지한다

* 동적 코드 생성 (dynamic code)
코드를 실행시간에 동적으로 만들어냄으로써 적은 코드로 다양한 경우에 대처하게 한다
예) 리스프의 매크로

* 코드 생성 (Code generation)
예) Trolltech 의 Qt Library 는 코드 제너레이션을 이용해 C++ 언어에서 직접 지원하지 않는 signal/slot 개념을 구현한다.
예) toLua 같은 외부 언어 바인딩 방법
예) yacc 같은 처리기는 입력 데이타에 추가 코드를 덧붙여 실행 가능한 lexer 소스 코드를 생성해낸다

* 분산처리/병렬화 (Parallelization/Distribution)
대칭적인 처리단위를 병렬화하여 처리 대역폭을 늘릴 수 있다.
예) 존단위로 MMORPG 게임서버를 분산한다
예) 비디오카드를 2개를 장착 (SLI/CorssFire) 하여 스캔라인단위로 병렬화하여 성능을 높인다

* 통합처리/직렬화 (Serialization/Consolidation)
동기화 부하가 병목이 되는 경우에는 직렬화를 통해 고속화할 수 있다.
예) 관리 편의를 위해 클러스터링된 DB 가 전체 서비스를 관리하도록 한다. 분산트랜잭션의 부하를 낮추는 데에도 관련이 있다
예) ATA 인터페이스는 병렬식이었던 PATA 에서 직렬화된 SATA 로 바뀌면서 오히려 더 속도를 높일 수 있었다

* 캐싱 (Caching)
자주 쓰이는 데이타와 그렇지 않은 데이타를 서로 다른 성능의 기억장치를 사용하게 하여, 한정된 고속 장치를 더 잘 활용할 수 있게 한다

* 버퍼링 (Buffering)
데이타를 항상 직접처리하지 않고, 묶어서 처리함으로써 반응시간을 희생하여 쓰루풋을 높인다
예) TCP/IP 의 네이글 (Nagle) 알고리즘
예) stdio 의 버퍼

* 선험적 통계 자료 활용 (Heuristic)
하나의 법칙으로 정리할 수 없는 통계 자료를 활용하여 알고리즘을 보강한다
예) 해싱할 때의 공식에 들어가는 특정 상수값
예) 알파벳으로 이루어진 사용자 id 들을 복수개의 db 에 나누어서 분산 처리한다고 할 때, 앞 글자 (a 부터 z 까지) 별로 디비를 나누는 방법이 있다. 그런데 사용자의 선호도상 a-z 까지의 글자별로 골고루 분포되어있기보다는 특정 패턴을 따르는 경우가 많다. 이럴 때에는 휴리스틱으로 만든 자료가 도움이 된다.

* 백그라운드 작업
앞으로 사용될 혹은 사용될 가능성이 높은 데이타를 미리 처리한다
예) 심리스한 지형의 표현을 위해, 플레이어와 가까워진 부분의 지형을 백그라운드로 읽어놓고, 플레이어와 멀어진 부분의 지형은 메모리에서 버린다

* 처리 지연 (Lazy Evaluation)
사용되지 않을 가느성이 있는 데이타의 처리를 최대한 뒤로 미룬다
예) Copy on write - string 을 구현하는 방법중 하나로, string 을 다른 string 에 복사, 대입할 때 새로운 메모리에 할당하고 복사하는 작업을, 원본이나 복사본이 변경될 시점으로 미룬다.

* 부가 정보
원 데이타에 부가적인 정보를 덧붙여서 데이타의 품질을 높인다
예) 벡터 폰트를 래스터라이제이션할 때, Hinting 정보를 사용하여 품질을 높인다.

imcgames 의 김학규입니다