반응형
 
출처 Don't Worry~ Be Happy!! | 바간나
원문 http://blog.naver.com/swucs/40003944891

MVC 이해하기

Duncan Mills 지음

Oracle9i JDeveloper가 Model-View-Controller 디자인 패턴 기반 J2EE 애플리케이션의 구축을 돕는 방법

필자는 여러분들이 내년 이후에는 MVC (Model-View-Controller) 패턴이라 불리는 디자인 패턴에 대하여 훨씬 더 많이 접하게 될 것이라고 확신합니다. 이번 기고는 그런 의미에서 MVC의 정확한 정의와 언제, 어디서 그리고 어떻게 Oracle9i JDeveloper를 사용하여 MVC 애플리케이션을 구축할 수 있는 지에 대하여 설명할 수 있는 좋은 기회라고 생각합니다.


이번 기고에서는 우선 디자인 패턴부터 소개를 하고, 그 후에 MVC에 대하여 자세하게 살펴보도록 하겠습니다.

필수 용어

J2EE 애플리케이션 디자인을 다룰 때 극복해야 할 첫번째 과제는 새로운 용어들과 특정 소프트웨어 형식 관련 전문 용어들입니다. 그래서 이번 기고에서는 자주 다루게 될 J2EE 관련 중요 개념들을 먼저 살펴본 후 본 내용을 다루도록 하겠습니다

디자인 패턴

"디자인 패턴"이라는 용어가 요즘 매우 많이 사용되고 있지만 여기에서 다루고자 하는 것은 프로그래밍 문제 해결을 위한 증명된 시도 방법에 대해서 입니다. 불행하게도 그 용어는 그 동안 남용되어 오면서, 그 자신이 목적이 되곤 했습니다. 소프트웨어는 디자인 패턴에 기반을 둘 수 있고, 그러한 경우에는 소프트웨어의 개발이 더 용이해질 수도 있지만, 소프트웨어를 구입하거나 디자인하는 경우에 기능보다 디자인 패턴을 더 중요하게 여긴다면 역효과를 낼 수도 있습니다.

"이것이 과연 디자인 패턴을 통해 나를 도울 수 있습니까?"라고 질문하면서 개발 환경을 지켜보는 것은 그리 생산적인 행동은 아닙니다. 디자인 패턴이라는 것은 목적에 대한 수단이 되어야지 결코 그 자체가 목적이 되어서는 안되기 때문입니다. 개발 툴을 평가할 때 할 수 있는 의미 있는 질문은 아마도 "애플리케이션 구축을 위해 이 환경이 얼마나 많은 것을 제공할 수 있습니까?" 정도가 될 것입니다.

다음은 고려해야 할 중요한 사항들입니다:

  • 디자인 패턴은 비즈니스 문제들을 해결하기 보다는 특정 프로그래밍 과제들을 해결합니다.
  • 디자인 패턴은 실제 구현보다도 가이드라인을 제공합니다.
  • 디자인 패턴은 재사용이 가능합니다
  • 디자인 패턴은 입증된 트랙 기록을 갖고 있습니다.
현재 웹 상에는 디자인 패턴과 관련된 다양한 정보들이 존재하고 있는데 그 중에서도 Sun Java Blueprints site 사이트는 반드시 확인해 보시기 바랍니다.

MVC

MVC는 디자인 패턴 중의 하나로 프로그래밍 세계에서는 전혀 새로울 것이 없습니다. Smalltalk 등과 같은 객체형 프로그래밍의 초기 시대 부터 Java Swing 컴포넌트 집합의 기초를 제공하는 최근까지 디자인 패턴으로서의 MVC 사용과 관련된 많은 레퍼런스들이 존재하고 있습니다. 그런데 MVC가 다시 주목을 받게 된 이유는 그것의 패턴이 웹 기반 애플리케이션 구축 시 발생하는 기본 문제들 중의 대다수를 해결하는데 적합하다는 것을 깨달았기 때문입니다.


일반적인 데이타베이스-중심 애플리케이션들과 특정한 웹 기반의 씬-클라이언트 애플리케이션들을 살펴보면 애플리케이션이 여러 가지 구분되는 작업들을 수행해야 한다는 것을 발견할 수 있습니다:

  • 데이타 액세스
  • 비즈니스 로직 구현
  • 사용자 인터페이스 표시 (데이타 프리젠테이션)
  • 사용자 상호 작용
  • 애플리케이션 (페이지) 플로우
MVC 아키텍처 또는 패턴은 사용자가 사용자 인터페이스를 재작성하지 않고 다른 데이타 소스에서 애플리케이션으로 용이하게 플러그할 수 있도록 데이타 프리젠테이션 등과 같은 작업들을 데이타 액세스로부터 분리시켜야만 한다는 전제 조건을 갖고 이러한 작업들의 구분 방식을 제공하고 있습니다.

지금은 MVC를 여기까지만 살펴보고 나중에 다시 자세하게 살펴보도록 하겠습니다.

JSP Model 1과 Model 2

진행을 하기에 앞서 JSP Model 1와 Model 2 아키텍처에 대해 잠시 살펴보도록 하겠습니다. 현재 많은 씬-클라이언트 웹 애플리케이션들은 사용자 인터페이스의 디스플레이 처리 방법으로 JSP (JavaServer Page) 를 사용하고 있습니다. 특히 복잡한 애플리케이션에서 여러 페이지를 함께 연결할 때 사용자는 하나 이상의 "루트"를 갖는 페이지들 사이에서 플로우를 어떻게 제어해야 할지 결정을 해야 합니다. 이러한 문제의 경우 JSP는 두 개의 시도 방법을 갖고 있습니다: Model 1 아키텍처와 Model 2 아키텍처

Model 1 아키텍처 ( 그림 1) 는 페이지들 사이의 라우팅을 JSP 자체에게 맡깁니다. 그래서 JSP는 하드코딩된 링크를 갖고 있거나 또는 페이지 내에 내장된 이동 (navigation) 로직을 갖고 있어야 합니다. 그러나 이 전략은 하나의 문제를 해결함과 동시에 또 다른 문제를 야기시키는데, 그것은 프리젠테이션과 이동 로직이 섞여있어서 페이지를 쉽게 재사용할 수 없기 때문입니다. 심지어 JSP Model 1를 사용하는 간단한 페이지 플로우들도 쉽게 복잡해질 수 있기 때문에 각각의 페이지는 그것이 링크된 다른 페이지들을 모두 알고 있어야만 합니다.

Model 1 architecture

JSP Model 2 (그림 2) 는 이 문제에 대한 해결 방법입니다. Model 2 아키텍처의 경우에 페이지 플로우는 JSP에 의해 처리되지 않습니다. 오히려 아키텍처는 페이지와 함께 제출된 정보를 기반으로 하여 분리된 서블릿이 라우팅을 결정하도록 해주어서 페이지들은 논리적으로 링크된 다른 페이지들을 인식할 필요가 없습니다. 이 서블릿은 Controller라고 호칭되는데, 이것은 이번 기고의 원래 주제인 MVC 패턴과 밀접한 관계를 맺고 있습니다.

JSP Model 2

MVC의 상세 내용

MVC는 애플리케이션을 Model, View 그리고 Controller라고 호칭 되는 세 가지 레이어 또는 기능 영역으로 논리적 방법을 통해 분리한 것입니다.


MVC와 같은 디자인 패턴은 각기 다른 레벨로 적용될 수 있는데, MVC는 애플리케이션 구축 방법으로서 뿐만 아니라 컴포넌트 레벨에서도 유용한 전략으로 활용될 수 있습니다. 잠시 JSP와 웹으로부터 벗어나서 Java Swing 리스트 박스 (이것은 단순한 컴포넌트이지만 훨씬 더 지역화된 범위에서 세 가지의 MVC 요소들을 모두 보유하고 있습니다) 와 같은 것을 고려해 보는 것도 좋습니다.


그럼 이제부터 세 가지 레벨을 한번 살펴보도록 하겠습니다:

The Model

Model은 애플리케이션 데이타 및 비즈니스 로직의 저장소 (repository) 입니다. 그러나 Model이 데이타베이스를 표시한 것이라고 말하는 것은 너무나 극단적인 표현입니다. 일반적으로 Model 기능의 일부는 데이타베이스 기반 애플리케이션을 통해 데이타를 데이타베이스로부터 읽어 들이거나 또는 데이타를 데이타베이스에 지속시키는 것입니다. View의 데이타 액세스는 데이타를 드러내거나 또는 View를 통해 입력된 데이타를 입증 및 소모하기 위해 비즈니스 로직 레이어를 구현하는 작업도 필요로 하고 있습니다.


애플리케이션 레벨에서 Model은 표시하는 사용자 인터페이스와 표시되는 비즈니스 데이타 사이의 입증 및 추상화 레이어 처럼 동작을 합니다. 데이타베이스 서버 자체는 단순히 Model을 위한 퍼시스턴스 (persistence) 레이어 입니다.

The View

View는 Model 데이타를 렌더링하는 것과 관련이 있습니다. 이제부터는 View를 렌더링하는데 사용되는 다른 기술들에 대하여 살펴볼 예정인데, 보통은 JSP 페이지를 사용하고 있습니다. 여기에서 주목해야 할 것은 View 코드는 사용자 역할에 따라 조건부 데이타 표시와 같은 작업들의 수행 로직을 포함할 수는 있지만 View 코드 자체가 애플리케이션이나 이동 로직을 하드코딩하지는 않는다는 것입니다. 최종 사용자가 View로부터 렌더링 되는 HTML 페이지 내의 동작을 수행할 때에는 이벤트가 Controller에게 제출이 되고 그 다음에 무엇을 할 것인지는 전적으로 Controller에게 달려 있습니다.

The Controller

Controller는 이름이 나타내는 것과 같이 전체 패턴의 연결 고리 입니다. View에서 수행된 모든 사용자 동작은 브라우저의 요청 컨텐트에 기반을 두고 프로그래밍 또는 메타데이타에 결합되어 다음에 무엇을 할지를 결정하는 Controller를 통해 제출됩니다.


Controller들은 여러 가지 다른 방식으로 운영될 수 있습니다. 어떤 것들은 요청들을 정확한 코드로 라우팅하기 위해 URL 인수들을 사용할 것이고 다른 것들은 요청이 제출되어 지는 페이지를 참작할 것입니다. 또한 그 외의 것들은 페이지 제출 시에 무엇을 할지를 알아내기 위해 숨겨진 필드들을 사용할 수도 있습니다. 그런데 MVC 디자인 패턴 자체는 Controller가 어떻게 동작하는지 그리고 단순히 그것의 기능이 무엇인지에 대해 규정을 하고 있지는 않습니다.


Controller는 여러 가지 구분되는 프로세스들 또는 서블릿들로 만들어져서 전체 Controller 기능의 다른 측면들을 처리할 수 있습니다. 예를 들면, 사용자는 하나의 서블릿이 제어하는 페이지 플로우 컨트롤과 또 다른 서블릿이 제어하는 사용자 인터페이스 이벤트 컨트롤 등과 함께 정확한 하위 Controller에게 디스패치하는 마스터 Controller를 가질 수 있습니다. 이 개념 자체는 다른 디자인 패턴의 주제이기도 합니다: Front-Controller 패턴

웹 애플리케이션에서의 작동 방식

MVC 패턴은 요약이 가능하여 그림3 에서와 같이 다이어그램을 사용하는 전통적인 씬-클라이언트 웹 애플리케이션에 적용 시킬 수 있습니다.

MVC pattern

이와 같은 웹 애플리케이션에 있어서 명심해야 할 것은 모든 것들은 페이지를 제출하는 사용자에 대한 응답을 통해 발생한다는 것입니다. "다음 10 개의 레코드를 표시하십시오" 등과 같은 간단한 UI 작업은 Controller에 대한 클라이언트 브라우저의 요청에 의해 구현되어 더 많은 데이타가 필요하다는 것을 Model에게 가르쳐 준 후 원래 페이지를 다시 표시할 것입니다. 그런 후에 View가 Model로부터 데이타를 요청할 때에는 다음 10 개의 행들이 표시 가능하게 될 것입니다.

지금까지는 모든 것이 매우 간단하게 보였고, 언급된 세 개의 부분 모두 명확하게 설명되었습니다:

  1. View를 이루는 개별 페이지들은 다른 페이지들에 대한 관계를 알지 못합니다. 그것들은 단지 "이벤트"를 발생시키고 Controller는 정확한 일이 발생하였다는 것을 보증해 줍니다.
  2. View와 Controller는 기본이 되는 데이타 구조 또는 비즈니스 규칙에 대해서 알지도 못 하고 구현도 하지 않습니다. 그것들은 단순히 Model의 공용 API들을 사용 (consume) 할 뿐입니다

  3. Model은 View나 Controller Model에 대해서 아무 것도 알지 못 합니다.
MVC 패턴의 본질은 장소에 구애 받음이 없이 애플리케이션의 View와 Model 부분의 재사용을 간편하게 만드는 것이고, 애플리케이션 자체는 본래 데이타 소스와 UI를 의미있는 방식으로 결합하는 Controller 부분에 의해 표현이 됩니다.

마찬가지로, 이러한 논리적 분리는 사용자가 나머지 애플리케이션을 다시 작성하지 않고 선택하는 기술을 특정 레이어를 위해 변경할 수 있게 해줍니다. 예를 들면, View의 구현을 위해 JSP를 사용하여 애플리케이션을 프로토타입할 수 있지만, XML 메타데이타-방식 서블릿을 통해 이후에 View를 바꾸어 놓는 것도 가능합니다. 이 작업은 Model을 변경함이 없이 Controller을 최소한만 변경하여 이행할 수 있습니다. (Controller에 있어서 이러한 경향은 나중에 다시 한번 자세히 살펴보겠지만 Jakarta Struts와 같은 메타데이타-방식 Controller 프레임워크를 사용하기 위함입니다. 그러므로 View를 교환할 때는 Controller 로직 자체가 아니라 그 메타데이타만 변경하면 됩니다.)

한번 MVC-기반 애플리케이션의 구현을 시작하게 되면 모든 것들이 보다 복잡해 지고, 프로그래머들은 레이어들 사이에서 논리적인 분리를 계속 유지하기 위해서는 교육을 받아야 합니다. 예를 들어 링크를 하드코딩해서 네비게이션 로직을 JSP로 코딩하는 것이 좋게 보일 수는 있지만, 만약 이것이 구현되면 페이지는 더 이상 사용할 수 없게 될 것입니다.

레이어들 사이의 라인들이 뚜렷하지 않다는 것도 반드시 인식하고 있어야 합니다. 예를 들면 데이타가 페이지로부터 제출될 때 Struts와 같은 Controller 프레임워크는 JavaBean을 데이타로 채우고 계속 진행하기 위해 빈을 Controller로 전달할 수도 있습니다. 그러면 지금의 그 빈은 View의 일부입니까 아니면 Controller의 일부입니까? 솔직히 말씀드리면 어느 버킷 (bucket) 을 선택해서 그것을 위치시키는가 하는 문제는 그리 중요한 것이 아닙니다. 중요 컴포넌트들 사이에서는 항상 인터페이스 레이어들이 존재할 것입니다. 여기에서 중요하게 여겨야 할 것은 올바른 장소에 정확한 종류의 로직을 유지해야 하는 것입니다.

실제 상황에서의 MVC

앞에서는 MVC의 이론을 살펴보았고, 지금부터는 J2EE가 포함하고 있는 기술들과 MVC 기반 애플리케이션 구축 과정을 도울 수 있는 Oracle9i JDeveloper에 대하여 살펴보도록 하겠습니다.
MVC의 각 부분에 대하여 역할 완수를 위해 사용자가 채택할 수 있는 선택 가능한 구현 방법들이 있는데, 당연히 앞으로 언급할 옵션들은 소모적인 것이 아니라 가능성의 일부를 설명해 주는 것들입니다. 뿐만 아니라 일부 솔루션들은 하나 이상의 MVC 부분도 포함할 것입니다.

실제 상황에서의 Model

Model의 역할은 애플리케이션 기능과 관련된 애플리케이션 데이타와 비즈니스 로직을 처리하는 것이라고 알려져 있는데, Model은 단지 여러 레이어로 이루어져서 다음과 같은 작업을 처리하는 것이라고 생각하면 됩니다:

  • 비즈니스 객체 지속
  • 데이타 액세스
  • 비즈니스 서비스 제공
Enterprise JavaBeans (EJB), JDBC, Web Services, 그리고 Oracle9iAS TopLink 등과 같은 기술들은 모두 Oracle9i JDeveloper Business Components for Java (BC4J)와 같은 완벽한 Model 프레임워크를 통해 가장 생산적인 솔루션을 제공하면서 이러한 작업들의 전부 또는 일부를 이행할 수 있는데, 이 프레임워크는 Model 레이어들의 생산을 위해 선언적인 메타데이타-방식의 시도 방법을 제공하면서 프로그래머들이 로우-레벨 보다는 그들의 코드를 통해 비즈니스 요구 사항들의 해결에 집중할 수 있도록 해줍니다. 그리고 BC4J는 지속성을 위해 EJB를 사용하는 것과 같이 다양한 Model 레이어 작업들을 위해 각각 다른 구현 방법을 사용할 수 있는 유연성을 프로그래머에게 제공하고 있습니다. BC4J와 같은 프레임워크를 사용하게 되면 Model의 사용자들은 (View 개발자들) 데이타 액세스 및 비즈니스 로직 구현에 대한 세부 사항들을 정확하게 알 수가 없고 그들은 단지 추상적 레이어만을 제공 받게 됩니다.

이번 기고에서는 Model 레이어 구현의 다양한 시도 방법에 대한 상대적 장점에 대해서 많은 부분을 할애하지는 않을 것입니다. 그런데 여기에서 알아야 할 것은 JDeveloper는 Model 내에서 사용자들이 비즈니스 프로세스 프로그래밍 로직에 집중할 수 있게 해주면서 이러한 Model 레이어들을 사용하는 기본 작업을 보다 쉽게 만들 수 있는 툴들을 제공한다는 것입니다.

예를 들어 사용자는 JDeveloper를 통해 데이타베이스를 찾고 Model의 기본으로 사용할 데이타베이스 테이블들을 선택한 다음 그 테이블들을 직접 UML 클래스 다이어그램으로 끌어놓을 수 있습니다.

JDeveloper는 사용자가 기본 위저드와 등록 정보 편집기 등을 통해 Model 레이어를 생성할 수 있게 해줍니다. 그리고 동일한 방식으로 기본적인 EJB와 BC4J 클래스들, 메타데이타 그리고 전개 기술자 (deployment descriptor) 등의 정의 작업을 수행할 수도 있습니다. BC4J의 경우에는 사용자가 등록 정보 편집기를 통해 검증과 재사용 가능한 비즈니스 규칙들을 그들 자신의 모델로 적용할 수 있는 능력을 얻게 됩니다.

실제 상황에서의 View

일반적으로 사용자 인터페이스를 생성할 때 어떠한 기술을 선택해야할 지 무척 당황해 할 수 있습니다. 다음은 선택 가능한 세 가지 시도 방법입니다:

  • HTML 페이지 생성 Java 코드를 작성하는 Java 서블릿
  • 기본적으로는 HTML 페이지를 생성하지만 Model로부터 데이타를 가져오는 것과 같은 기능들을 수행할 때에는 특별한 태그 또는 스크립틀릿 (scriptlet) 들을 내장하는 JSP
  • 메타데이타-방식 또는 템플릿-방식 프레임워크
Java 서블릿 방식은 Java 프로그래머들이 많이 선호하는 방식으로서 View-구축에 필요한 요구 사항들을 해결합니다. 모든 것은 프로그램 문자열 내에 내장된 HTML 요소들을 통해 코드 내에서 즉시 처리되어야만 하는데, 이와 같은 방식은 복잡하고 오류가 많이 발생합니다.

현재 View 생성에 있어서 가장 유명한 기술은 JSP 방식인데, 이것은 페이지를 위한 기본적인 사용자 인터페이스 디자인 툴인 Macromedia Dreamweaver 등과 같은 표준 HTML 편집 툴들의 사용 능력과 그 페이지의 작업 방식과 데이타 바인딩을 처리하기 위한 Java 코드의 내장 능력을 함께 결합한 것입니다. JSP가 최초로 실행이 될 때에는 서블릿으로 컴파일이 되는데, HTML 내에 Java 스니핏 (snippet) 들을 내장하는 방식은 Java 내에 HTML을 내장하는 반대 프로세스보다 훨씬 더 생산적이라고 판명되었습니다

JSP들은 그것들 내부로 직접 내장되는 Java 코드의 세그먼트들을 갖거나 또는 커스텀JSP 태그들을 사용할 수 있습니다. 태그들은 컴파일 시에 즉시 배치되는 Java 코드를 위한 위치 표시자 (placeholder) 인데 그것들의 재사용이 가능하도록 해주는 API와 함께 디자인되어 사용되고 있습니다. 그래서 프로그래머는 기본적 구현에 대한 지식을 보유하지 않고도 애플리케이션 내에서 태그 라이브러리를 재사용이 가능한 컴포넌트들의 라이브러리처럼 사용할 수 있습니다.

JSP와 JSP 태그 라이브러리들을 결합하는 것은 View 개발자들에게 막대한 능력을 제공함과 동시에 많은 문제점을 발생시킬 수도 있습니다. 그러한 태그 라이브러리들은 BC4J-기반 모델에 대한 간편한 액세스 기능을 제공하는 Oracle BC4J 태그 등과 같은 특별 라이브러리들부터 Struts 태그 라이브러리와 Java Standard Tag Library (JSTL) 등과 같은 보다 일반적인 "개방형 소스" 라이브러리들 까지 존재합니다.

프로젝트를 위해 정확한 태그 라이브러리를 선택하는 것은 어려운 일이지만 사용을 위해 선택한 다른 기술들이 그 선택 과정을 이끄는 경우도 가끔 발생할 것입니다. 예를 들어, Model 프레임워크로 BC4J를 사용하고 Controller로 Struts를 사용하기로 결정한 경우 JDeveloper는 사용자에게 이러한 조합을 위해 맞추어진 표준 태그 라이브러리들의 집합을 제공할 것입니다

View 개발의 마지막 방식은 템플릿-방식 또는 메타데이타-방식 프레임워크를 사용하는 것입니다. 이것의 관련 예는 XML을 선언적으로 사용하여 페이지 정의 방식을 제공하는 JDeveloper 내의 UIX 프레임워크입니다.

Jakarta Velocity 프로젝트는 또 다른 템플릿-기반 방식을 제공하는데 Velocity는 XML-방식 보다는 Velocity가 대신하는 템플릿 HTML 페이지 내의 특별 마크업을 사용하여 오히려 JSP 페이지처럼 동작합니다.

이와 같은 메타데이타-방식의 시도 방법은 서블릿 또는 JSP를 사용하는 것보다 많은 이점을 제공할 수 있습니다. 우선, 프레임워크는 UI가 무슨 일을 하고 그것이 어떻게 보이는지를 정의하지만 그것이 어떻게 구현되는지는 정의하지 않기 때문에 다른 장비로부터 출력을 얻어낼 때 동일한 메타데이타 정의를 사용할 수 있습니다 (예를 들면 브라우저 클라이언트로부터 HTML 출력을 얻어내거나 또는 전화로부터 WML 출력을 얻어낼 때). 두 번째는 메타데이타의 선언적 성격이 그것 자신에게 정의 뿐만 아니라 시각 편집기의 사용도 추가해 주고 있습니다. 사용자 인터페이스의 포인트-앤드-클릭 편집은 J2EE 개발자의 생산성을 증가시키기 위한 필수 사항 중 하나입니다.

실제 상황에서의 Controller

웹 기반 애플리케이션에 적용되었을 때 Controller 기술이 모든 MVC 컴포넌트들 사이에서 가장 완성된 것은 아닙니다. 이것은 Controller와 View가 혼합된 JSP Model 1 방식이 지금까지 광범위하게 사용되어 왔기 때문입니다. Controller들이 계속 사용되어 온 경우 Controller들은 자체 내에서 성장하면서 Jakarta Struts Controller 프레임워크에 기반을 두는 경향도 갖고 있습니다.

Struts Controller는 매우 유명한 JSP 애플리케이션 구축용 Controller 프레임워크로서 핵심 Controller 기능을 포함하면서 View 레이어를 위해 많은 태그들을 제공하고 있습니다. Struts는 개별 페이지들을 위해 위치 추상화 (abstraction) 를 정의하는 XML 메타데이타와 페이지들 사이의 실제 흐름을 제어하기 위한 프로그래밍 코드의 혼합된 형태를 사용하고 있습니다. 보다 자세한 정보는 Apache 웹 사이트에서 확인해 보시기 바랍니다.

JDeveloper는 Struts 구성 파일 편집기 그리고 단순 Struts 또는 Struts, BC4J, JSP UIX 등의 조합을 사용하는 애플리케이션들의 구축을 보다 간편하게 만들어 주는 위저드와 JSP 태그들의 집합을 제공하여 Controller로서의 Struts 사용을 완벽하게 지원하고 있습니다.

MVC의 미래

이번 기고의 시작 부분에서 잠시 언급했던 것처럼, MVC는 점차 발전하면서 J2EE 애플리케이션들을 위해 선택 가능한 개발 방법론이 되어가고 있습니다. 우리는 현재 매우 흥미로운 개발들이 (특히 View 및 Controller 분야에서) 진행 중인 것을 보고 있습니다.


Controller 측면에서 Struts 버전 1.1은 베타 상태에 있는데, 이 새로운 버전은 Struts 1.0 보다 훨씬 더 유연하고 또한 많은 일을 처리할 수 있습니다. 또한 페이지 플로우 정의 작업을 더욱 선언적으로 만들면서 단순 페이지 플로우 이상으로 Controller의 범위를 확대하는 Controller를 통해 보다 많은 일이 수행되고 있습니다.


페이지 플로우의 시각 모델링이 첫번째 단계인데, 많은 벤더들은 현재 이 기술의 작업을 계속 진행하고 있습니다. 그러나 개발자들이 웹 배치를 위해 보다 복잡한 시스템을 구축하기 시작하면서 단순 페이지 플로우 보다는 전체 프로세스들을 모델링하는 능력에 대한 요구가 점차 증가하고 있습니다. 이와 같은 프로세스들 중에서 페이지를 최종 사용자에게 보여주는 것은 플로우를 위해 가능한 여러 작업들 중의 하나일 뿐입니다. Oracle은 매우 가까운 미래에 이와 같은 종류의 Controller 기술을 통해 흥미로운 개발들을 제공할 예정입니다!

View 측면에서 커다란 변화는 JavaServer Faces (JSF) 입니다. 이것의 목적은 HTML을 위해 J2EE를 사용하여 그래픽 인터페이스의 새로운 표준을 개발하는 것이고, 개념은 표준 UI 요소들과 이벤트 핸들링을 통해 Swing GUI Toolkit과 같은 것을 HTML을 위해 제공하는 것입니다.

Oracle은 Java Community Process (JSR 127) 의 일부로 정의되고 있는 이 과제의 정의 프로세스에 참여하고 있고, 표준 작업이 종료되자 마자 JSF를 구현할 예정입니다. JSF에 대한 보다 자세한 사항은 http://www.jcp.org/en/jsr/detail?id=127을 확인해 보시기 바랍니다.

JavaServer Faces는 MVC의 Model에 영향을 미치고 있습니다. 표준화된 GUI 툴킷이라는 것은 View와 Model 사이의 상호 작용이 Model 데이타를 특정 필드 또는 컨트롤로 바인딩을 해서 표준화가 될 수 있다는 것을 의미합니다. 그래서 필자는 J2EE 개발을 위한 패턴으로서 MVC를 사용하는 흥미로운 단계에 접어들었다고 믿고 있습니다. 이 기술은 이제 막 성숙한 단계에 접어들었고 또한 표준화 작업도 함께 이루어지고 있습니다.


비즈니스 프로그래머들의 작업을 간편하게 해줄 수 있는 시각적 모델러와 UI 편집기를 통해 코드-중심의 애플리케이션 구축으로부터 선언적 컴포넌트 어셈블리로 현재 이동하고 있고, 보다 많은 프레임워크들은 J2EE-관련 표준 및 디자인 패턴의 구현을 위해 통합되어서, 프로그래머들은 코드 작성보다는 비즈니스 문제 해결에 좀 더 집중할 수 있게 되었습니다.

Duncan Mills는 Oracle Application Development Tools 그룹의 제품 관리자로서 Oracle9i JDeveloper와 Oracle9i Forms의 전문가인데 1988년 이후로 DBA 또는 개발자로서 Oracle 제품을 담당해 왔습니다. 

반응형
쉘 프로그래밍 강좌

  • 참고서적: 초보자용 리눅스 프로그래밍 (대림출판사, 한동훈,이만용역, NEIL MATTHEW, RICHARD STONES 저)
  • 넷츠고 리눅스 동호회 7월 제 5회 정기 공개강좌 자료
  • 글쓴이: 위경섭 <powerhack@netsgo.com>
  • 위키문서 변환: 윤현호 <hhyoon@kldp.org> 2005년 2월 23일. 원본: http://wiki.kldp.org/KoreanDoc/Shell_Programming-KLDP


1 변수

  • 쉘변수는 처음 사용될 때 만들어진다. 즉 미리 선언할 필요가 없다.
  • 쉘변수는 유닉스 명령과 마찬가지로 대소문자에 구별이 있다.
  • 쉘변수는 기본적으로 데이터를 문자열로 저장한다. 수치를 대입해도 실제 수치가 아닌 문자열이 저장된다. 계산이 필요할 경우는 자동으로 수치로 변환하여 계산후 다시 문자열로 저장된다.
  • 쉘변수의 값을 사용할 때는 변수명앞에 "$" 를 붙여서 사용한다.
  • 쉘변수에 값을 대입할때는 "$"를 사용하지 않는다.
  • 쉘변수는 타입이 없다. 즉 아무 값이나 다 넣을 수 있다.

1.1 환경변수

쉘을 기동하고나면 기본적으로 셋팅되어있는 변수들이다. 유닉스/리눅스에는 많은 환경변수들이 있고 필요한경우 이 변수들을 마치 일반변수처럼 값을 얻어오거나 셋팅할 수 있다. 여기서는 쉘과 직접적인 관련이 있는것만 설명한다.
  • $0 - 실행된 쉘 스크립트 이름
  • $# - 스크립트에 넘겨진 인자의 갯수
  • $$ - 쉘 스크립트의 프로세스 ID

1.2 인자 변수

쉘스크립트에 인자를 넘겨줄때 그 인자들에 대한 정보를 가지고 있는 변수들.
  • $1~ $nnn - 넘겨진 인자들
  • $* - 스크립트에 전달된 인자들을 모아놓은 문자열. 하나의 변수에 저장되며 IFS 환경변수의 첫번째 문자로 구분된다.
  • $@ - $*과 같다. 다만 구분자가 IFS변수의 영향을 받지 않는다.

2 일반변수

일반변수에 특별한 제약은 없다. 단 대소문자 구분만 정확하게 해주면 된다.

예제
#!/bin/sh
echo "This Script Executable File : $0"
echo "Argument Count : $#"
echo "Process ID : $$"
echo "Argument List \$* : $*"
echo "Argument List \$@ : $@"
echo "Argument 1 : $1"
echo "Argument 2 : $2"
echo "Argument 3 : $3"
echo "Argument 4 : $4"  
실행
$chmod 755 test1
$./test1 a1 a2 a3 a4
This Script Executable File : ./test1
Argument Count : 4
Process ID : 905
Argument List $* : a1 a2 a3 a4
Argument List $@ : a1 a2 a3 a4
Argument 1 : a1
Argument 2 : a2
Argument 3 : a3
Argument 4 : a4

2.1 연산

sh
변수의 산술 연산은 생각하는 것처럼 쉽지 않다. 위에서 언급했듯이 변수에는 모든 것이 문자열로 저장되기 때문에 연산이 불가능하다. 연산을 위해서는 좀 복잡한 절차를 거쳐야 한다.
변수 = $((산술식))
이것이 가장 단순한 연산 규칙이다. 산술식내에는 변수($1, $a 와 같은) 도 들어갈 수 있다. 산술식 내에 숫자가 아닌 문자열, 또는 문자열이 담겨있는 변수가 들어가면 그것들은 계산에서 제외된다. (정확히 말하면 0 으로 간주되어 연산이 이루어 지지 않는다.)

2.2 매개변수 확장

매개변수 확장이란 변수의 값을 문자열 등으로 대체하는 것을 말한다. 단순한 대체뿐 아니라 변수내의 문자열을 조작하여 원하는 문자열만을 추출할 수도 있다.

형식:
  • ${parm:-default} - parm이 존재하지 않으면 default로 대체된다.
  • ${#parm} - parm의 길이를 참조한다.(가져온다)
  • ${parm%word} - 끝에서부터 word와 일치하는 parm의 최소부분(첫번째 일치)을 제거하고 나머지를 반환한다.
  • ${parm%%word} - 끝에서부터 word와 일치하는 parm의 최대부분(마지막 일치)을 제거하고 나머지를 반환한다.
  • ${parm#word} - 처음부터 word와 맞는 parm의 최소부분(첫번째 일치)을 제거하고 나머지 부분을 반환한다.
  • ${parm##word} - 처음부터 word와 맞는 parm의 최대부분(마지막 일치)을 제거하고 나머지를 반환한다.
word에는 와일드 카드를 사용할 수 있다.예를 보자.
1 #!/bin/sh
2
3 p="/usr/X11R6/bin/startx"
4
5 unset p
6 a=${p:-"Variable p Not found"}
7 echo $a
8
9 p="/usr/X11R6/bin/startx"
10 a=${p:-"Variable parm Not found"}
11 echo $a
12
13 a=${#p}
14 echo $a
15
16 a=${p%/*}
17 echo $a
18
19 a=${p%%/*}
20 echo $a
21
22 a=${p#*/}
23 echo $a
24
25 a=${p##*/}
26 echo $a
27                    
위 스크립트의 결과는 다음과 같다.
Variable p Not found
/usr/X11R6/bin/startx
21
/usr/X11R6/bin

usr/X11R6/bin/startx
startx
  • 6행 : 변수 p 가 제거 되었으므로 "Variable p Not found" 가 a에 들어간다.
  • 10행 : 변수 p 가 있으므로 그대로 a에 들어간다.
  • 13행 : a에는 변수 p의 길이가 들어간다.
  • 16행 : p 에서 가장 오른쪽의 "/"부터 끝까지 지우고 나머지를 a에 넣는다.
  • 19행 : p 에서 가장 왼쪽의 "/" 부터 끝까지 지우고 나머지를 a에 넣는다. (아무것도 없다)
  • 22행 : p 의 처음부터 가장왼쪽의 "/" 까지 지우고 나머지를 a에 넣는다.
  • 25행 : p 의 처음부터 가장 오른쪽의 "/"까지 지우고 나머지를 a에 넣는다.

3 조건 판단

쉘 스크립트에서 조건판단은 if 와 test 명령을 혼합하여 사용한다. 일반적인 예는 다음과 같다.
if test -f test1
then
...
fi

-f 는 주어진 인자가 일반 파일일 때 참이 된다.

test 명령은 [] 로 대체될 수 있다.
if [ -f test1 ]
then
...
fi

if [ -f test1 ]; then
...
fi

3.1 test 명령

sh
test 명령의 조건은 다음과 같이 세 부류로 나누어진다.

3.1.1 문자열 비교

  • [ string ] - string이 빈 문자열이 아니라면 참
  • [ string1 = string2 ] - 두 문자열이 같다면 참
  • [ string1 != string2 ] - 두 문자열이 다르면 참
  • [ -n string ] - 문자열이 null(빈 문자열) 이 아니라면 참
  • [ -z string ] - 문자열이 null(빈 문자열) 이라면 참

3.1.2 산술 비교

  • [ expr1 -eq expr2 ] - 두 표현식 값이 같다면 참 ('EQual')
  • [ expr1 -ne expr2 ] - 두 표현식 값이 같지 않다면 참 ('Not Equal')
  • [ expr1 -gt expr2 ] - expr1 > expr2 이면 참 ('Greater Than')
  • [ expr1 -ge expr2 ] - expr1 >= expr2 이면 참 ('Greater Equal')
  • [ expr1 -lt expr2 ] - expr1 < expr2 이면 참 ('Less Than')
  • [ expr1 -le expr2 ] - expr1 <= expr2 이면 참 ('Less Equal')
  • [ ! expr ] - expr 이 참이면 거짓, 거짓이면 참
  • [ expr1 -a expr2 ] - expr1 AND expr2 의 결과 (둘다 참이면 참, 'And')
  • [ expr1 -o expr2 ] - expr1 OR expr2 의 결과 (둘중 하나만 참이면 참, 'Or')

3.1.3 파일 조건

  • [ -b FILE ] - FILE 이 블럭 디바이스 이면 참
  • [ -c FILE ] - FILE 이 문자 디바이스 이면 참.
  • [ -d FILE ] - FILE 이 디렉토리이면 참
  • [ -e FILE ] - FILE 이 존재하면 참
  • [ -f FILE ] - FILE 이 존재하고 정규파일이면 참
  • [ -g FILE ] - FILE 이 set-group-id 파일이면 참
  • [ -h FILE ] - FILE 이 심볼릭 링크이면 참
  • [ -L FILE ] - FILE 이 심볼릭 링크이면 참
  • [ -k FILE ] - FILE 이 Sticky bit 가 셋팅되어 있으면 참
  • [ -p FILE ] - True if file is a named pipe.
  • [ -r FILE ] - 현재 사용자가 읽을 수 있는 파일이면 참
  • [ -s FILE ] - 파일이 비어있지 않으면 참
  • [ -S FILE ] - 소켓 디바이스이면 참
  • [ -t FD ] - FD 가 열려진 터미널이면 참
  • [ -u FILE ] - FILE 이 set-user-id 파일이면 참
  • [ -w FILE ] - 현재 사용자가 쓸 수 있는 파일(writable file) 이면 참
  • [ -x FILE ] - 현재사용자가 실행할 수 있는 파일(Executable file) 이면 참
  • [ -O FILE ] - FILE 의 소유자가 현재 사용자이면 참
  • [ -G FILE ] - FILE 의 그룹이 현재 사용자의 그룹과 같으면 참
  • [ FILE1 -nt FILE2 ] - : FILE1이 FILE2 보다 새로운 파일이면 ( 최근파일이면 ) 참
  • [ FILE1 -ot FILE2 ] - : FILE1이 FILE2 보다 오래된 파일이면 참
  • [ FILE1 -ef FILE2 ] - : FILE1 이 FILE2의 하드링크 파일이면 참

3.2 if 구문

if 문은 조건을 판단하여 주어진 문장을 수행한다.

3.2.1 형식 1 (단일 if 문)

형식:
if [ 조건 ]
then
    문장1
    문장2
fi

3.2.2 형식 2 (if-else 문)

형식:
if [ 조건 ]
then
    문장3
    문장4
fi

3.2.3 형식 3 (if-elif 문)

형식:
if [ 조건 ]
then
    문장1
    문장2
elif
    문장3
    문장4
else
    문장5
    문장6
fi

3.3 case 구문

'패턴'에는 * 문자, 즉 와일드카드를 사용할 수 있다.

형식:
case 변수 in
패턴 [ | 패턴 ] ... ) 문장 ;;
패턴 [ | 패턴 ] ... ) 문장 ;;
....
* ) 문장 ;;
esac

3.4 목록

여려 명령을 실행할때 앞의 명령의 결과에 의해서 다음행동이 결정되어야 할 경우가 있다. 이런경우에 AND나 OR조건을 사용해서 한번에 처리할 수 있다. 이것은 쉘 스크립트 뿐 아니라 명령행에서도 사용 가능하다. 물론 if 문을 이용해서 반환값을 검사하여 처리할 수 있지만 문장이 길어지고 복잡해진다.

3.4.1 AND 목록

statment1 && statment2 && statmentN && .....

위의 명령들은 각 명령이 거짓이 될 때 까지 명령을 수행해 나간다. 수행 도중 결과가 거짓이 되면 그이후의 명령은 수행되지 않는다.

3.4.2 OR 목록

statment1 || statment2 || statmentN || .....

위의 명령들은 각 명령이 거짓이 나오는 동안 계속된다. 즉 참이 나오면 실행을 멈춘다.

3.4.3 AND와 OR목록은 혼용이 가능하다.

[ 조건 ] && 문장1 || 문장2

위의 예는 조건이 참이면 문장1을 수행하고 거짓이면 문장2를 수행한다.

또한 위의 문장1이나 문장2에서 여러개의 문장을 수행하고 싶을 때는 {}를 사용하면 된다.
[조건] && {
    문장1
    문장2
    문장3
} || {
    문장4
    문장5
    문장6
}

4 제어문

4.1 for

for 문은 지정된 범위안에서 루프를 수행한다. 범위는 어떤 집합도 가능하다.

형식:
for 변수 in 값1, 값2, ...
do
    문장
done

매 루프를 돌때마다 변수의 값은 in 이후의 값으로 대체된다.

예제:
for str in "test1", "test2", "test3", "test4"
do
    echo @str
done

출력:
test1
test2
test3
test4

값에는 와일드 카드 확장을 사용할 수 있다.
for file in $(ls -a | grep "^\.")
do
    echo "$file is Hidden File"
done

위 예의 출력 결과는 현재 디렉토리에서 처음이 "." 으로시작하는 파일(히든파일)만을 출력한다.

for file in $(ls chap[345].txt); do
    echo "--- $file ---" >> Books.txt
    cat $file >> Books.txt
done

위의 예는 chap3.txt, chap4.txt, chap5.txt 파일을 Books.txt 라는 파일에 붙여 넣는다.

다음의 예를 보고 결과를 예측해보자.
echo "\$* output"

for fvar in $*
do
    echo $fvar
done

echo "\$@ output"
for fvar in $@
do
    echo $fvar
done

4.2 while

for 명령의 경우는 횟수를 지정해서 루프를 수행하는 데는 문제가 있다. while 문은 실행 횟수가 지정되지 않았을 때 편리하다.

형식:
while 조건문
do
    문장
done

예제를 보자. 패스워드를 입력받고 맞는지 확인하는 프로그램이다.
echo "Enter Password : "
read password1

echo "Retype Password : "
read password2

while [ "$password1" != "$password2" ]
do
    echo "Password mismatch Try again "

    echo "Retype Password : "
    read password2
done

echo "OK Password Match complete"

어떻게 동작하는가 ?

4.3 until

until은 while문과 동일한 효과를 내지만 조건이 반대이다. 즉, while문은 조건이 참일동안 루프를 수행하지만 until은 조건이 거짓일 동안 루프를 수행한다.

형식:
until 조건문
do
    문장
done

다음 예를 보자. 이 예는 지정한 유저가 로그인하면 알려준다.
#!/bin/sh

until who | grep "$1" > /dev/null
do
    sleep 10
done

echo "User $1 just logged in ^_^"

4.4 select

select문은 원하는 리스트를 출력하고 그 중 선택된 것을 돌려주는 구문이다. 주의할 점은 select의 루프 내에서는 자동적으로 루프를 벗어날 수 없다. 반드시 break문을 사용해서 루프를 벗어나야 한다.

예: 간단한 퀴즈
#!/bin/sh

echo "다음중 스크립트언어 프로그래밍에 속하는 것은 ?"
select var in "쉘 프로그래밍" "C 프로그래밍" "자바 프로그래밍" "Exit"
do
    if [ "$var" = "쉘 프로그래밍" ]
    then
        echo "정답입니다."
        exit 0
    elif [ "$var" = "Exit" ]
    then
        echo "종료합니다."
        exit 1
    else
        echo "$var 을 선택하셨습니다. 오답입니다."
        echo "다음중 스크립트언어 프로그래밍에 속하는 것은 ?"
    fi
done

5 함수

쉘 스크립트 내부에 또는 다른 스크립트파일에 함수를 정의해 놓고 사용할 수 있다. 함수를 사용하면 코드를 최적화 할 수 있고, 코딩이 간결해지며,재사용이 가능하다. 그러나 다른 스크립트 파일을 호출해서 함수를 실행할 경우, 가능은 하지만 스크립트의 실행시간이 길어지고, 함수의 결과를 전달하는 것이 까다롭기 때문에 가급적이면 외부파일의 함수는 안쓰는 것이 좋다.

형식:
함수명 ()
{
	문장
	return 값
}

사용
함수명 인자1, 인자2, ...

함수는 독립적으로 $#, $*, $0 등의 인자 변수를 사용한다. 즉 함수내의 $#과 본체의 $#은 다를 수 있다는 것이다.

다음의 예를 보자
#!/bin/sh
		
func()
{
    echo ------ this is func --------
    echo "This Script Executable File : $0"
    echo "Argument Count : $#"
    echo "Process ID : $$"
    echo "Argument List \$* : $*"
    echo "Argument List \$@ : $@"
    echo "Argument 1 : $1"
    echo "Argument 2 : $2"
    echo "Argument 3 : $3"
}

echo ------ this is main --------
echo "This Script Executable File : $0"
echo "Argument Count : $#"
echo "Process ID : $$"
echo "Argument List \$* : $*"
echo "Argument List \$@ : $@"
echo "Argument 1 : $1"
echo "Argument 2 : $2"
echo "Argument 3 : $3"
echo "Argument 4 : $4"
func aa bb cc 

본체와 함수에서 동일한 변수를 보여주지만 값은 틀린다는 것을 알 수 있다.

함수에서 값을 반환하기 - 함수에서 반환값은 반드시 정수값만을 반환할 수 있다. 이 값을 if 등으로 조건을 판단해서 사용할 수 있다. 반환값 중 0은 참으로 나머지 숫자는 거짓으로 판별된다.

6 명령어

쉘에서 쓸 수 있는 명령어는 두가지로 나누어진다. 명령 프롬프트 상에서 실행 시킬 수 있는 외부 명령어와 쉘 내부 명령이다. 내부 명령은 보통 쉘 내부나 쉘 구문상에서 쓰인다. 외부명령은 쉘에 관계없이 사용이 가능하다.

6.1 break

제어문이나 조건문의 루프를 빠져나갈때 사용한다.

예제
while [ $a -eq 10 ]
do
    if [ $a -eq 5 ]; then
        break
    fi
done

6.2 continue

제어문이나 조건문의 처음으로 돌아가서 다시수행한다.

예제
while [ $a -eq 10 ]
do
    if [ $a -eq 5 ]; then
        continue
    fi
done

6.3 : 명령

의미없는 명령. 논리값 true를 대신해 쓰기도 한다.

6.4 . 명령

. 명령을 사용하면 현재 쉘에서 명령을 실행시킨다 그러므로 실행된 명령의 결과를 본 프로그램에서 사용할 수 있다.

예를 들면 A 라는 스크립트에서 B라는 스크립트를 그냥 실행할 경우 B에서의 변화(환경변수 등)는 A에게 아무런 영향도 미치지 않는다. 그러나 . 명령을 사용해서 실행하면 B에서의 변화가 A에도 영향을 미친다.

6.5 echo

문장을 출력한다. 자동으로 개행문자가 삽입된다. (다음 줄로 넘어간다)

6.6 eval

인자의 실제 값을 구하는데 사용한다.
foo=10
x=foo
y='$'$x
echo $y

이 예를 실행해 보면 $foo가 출력된다
foo=10
x=foo
eval y='$'$x
echo $y

이 예에서는 $foo의 값 즉 10 이 출력된다. eval명령은 원하는 문자열들을 조합해서 변수를 액세스 할 수 있다.

6.7 exec

현재 쉘을 다른 프로그램으로 대체한다.

예제
exec csh

6.8 exit n

현재 쉘을 종료한다. 종료시 n 값을 리턴한다.

6.9 export

해당 쉘에서 파생된 자식 프로세스에서 export한 환경변수는 본래 쉘에서 관리한다.

6.10 expr

표현식의 값을 구한다.
x=`expr 1 + 2`
요즘은 expr보다는 $((계산식)) 구문을 많이 사용한다.

6.11 printf

C 언어의 printf명령과 흡사하다.

형식:
printf "Format String" arg1 arg2 arg3 ...

6.12 return

쉘 함수에서 값을 반환 할 때 쓰인다. 0은 성공을 1~125까지는 쉘 에러코드를 나타낸다.

6.13 set

쉘 내부에서 매개 인자를 설정한다. set의 인자로 쓰인 문자열은 공백에 의해 $1 부터 차례대로 대입된다.

예제
#!/bin/sh
echo $#
set $(ls)
echo $# 

결과는
0
22

이다. (22는 필자의 ls 결과의 갯수이다.) 첫번째 0는 이 스크립트에 인수가 없으므로 0이고 set $(ls) 에 의해서 인수의 갯수가 22개로 늘었다.

6.14 shift

쉘의 인자를 한자리씩 아래로(n -> 1 로) 이동시킨다.

예제
#!/bin/sh

echo $1
shift
echo $1
shift 5
echo $1

실행
#./myscript 1 2 3 4 5 6 7 8 9 0
1
2
7

6.15 trap

쉘의 실행도중 시그널을 처리하는 시그널 처리기를 만드는 역할을 한다.

형식:
trap command signal

쉘 스크립트는 위에서 아래로 실행되므로 보호하려는 부분 이전에 trap 명령을 사용해야 한다. trap 조건을 기본으로 사용하려면 명령에 - 를 넣으면 된다. 신호를 무시하려면 '' 빈 문자열을 준다.

6.16 unset

변수나 함수를 제거한다.

7 명령 실행

외부 명령의 실행 결과를 변수에 집어넣어 변수의 값으로 사용할 수 있다.

형식:
x = $(명령)

이렇게 변수에 결과를 넣은 후에는 이 변수를 일반문자열로 생각하고 원하는 가공을 해서 결과를 얻어낼 수 있다. 위에서 보았던 매개변수 확장이나 set명령을 이용해서 원하는 부분을 추출해 내면 그만이다.

8 쉘 스크립트 내부에서 명령에 입력 전달하기 (Here Documents)

이 기능은 쉘 내부에서 명령어에 입력을 전달하는 방법이다. 전달된 입력은 마치 키보드에서 눌려진 것처럼 반응한다.

형식:
명령 << 종료문자열
입력값.....
종료문자열

예제: 자동으로 메일을 보내는 스크립트
#!/bin/sh

mail $1 << myscript
This is Header
This is Body
.

myscript

9 디버깅 하기

쉘 프로그래밍 시 간단하게 디버깅하는 방법을 소개합니다.

9.1 쉘 옵션

  • sh -n 스크립트 : 문법 에러만을 검사, 명령을 실행하지 않음
  • sh -v 스크립트 : 명령을 실행하기 전에 에코
  • sh -x 스크립트 : 명령줄에서 처리한 다음 에코

9.2 set 옵션

위의 쉘 옵션은 아래와 같이 set 옵션으로도 설정할 수 있다.
  • set -o noexec 또는 set -n : 문법 에러만을 검사, 명령을 실행하지 않음
  • set -o verbose 또는 set -v : 명령을 실행하기 전에 에코
  • set -o xtrace 또는 set -x : 명령줄에서 처리한 다음 에코
  • set -o nounset 또는 set -u : 정의되지 않은 변수가 사용되면 에러 메시지를 제공한다.

아래와 같이 set -x를 이용하여 손쉽게 실행과정을 추적할 수 있다. (참고로 set 옵션을 취소하려면 set +x를 입력하면 된다. 다른 옵션도 마찬가지)
set -x
for str in "test1" "test2" "test3" "test4"
do
    echo $str
done

결과
+ for str in '"test1"' '"test2"' '"test3"' '"test4"'
+ echo @str
@str
+ for str in '"test1"' '"test2"' '"test3"' '"test4"'
+ echo @str
@str
+ for str in '"test1"' '"test2"' '"test3"' '"test4"'
+ echo @str
@str
+ for str in '"test1"' '"test2"' '"test3"' '"test4"'
+ echo @str
@str
반응형
◆ 비즈니스를 위한 디지털 마인드맵의 활용

기획서나 제안서 등의 문서는 논리적으로 기술되어야 한다. 이 문서를 왜 작성하고 있으며 어떤 목적을 달성할 것인지를 점검하고 그에 맞는 내용들이 논리적으로 서술되어야 한다. 그러므로 문서 작성 전에 기술하고자 하는 내용들에 대해서 모두 끄집어내고 이들을 논리적으로 정렬할 필요가 있다. 즉 문서에 담고자 하는 내용들을 대표하는 주요 키워드를 끄집어내어 논리적으로 배치함으로써 기획서의 초안을 먼저 구성해야 한다. 초안을 바탕으로 구체적인 제안서를 만들어가는 것이 좋다.


그렇다면 머리 속에 떠오르는 막연한 아이디어와 생각들을 정리해서 어떻게 초안을 만들어야 할까? 이때 사용할 수 있는 것이 마인드맵이다. 마인드맵은 머리 속에 떠오르는 생각을 핵심단어, 기호, 이미지 등을 사용해 구조적이고 체계적으로 정리하는 기법을 말한다. 이러한 정리 기법은 막연하고 추상적인 아이디어를 체계화하는데 큰 도움을 준다. 기획서를 작성하기에 앞서 이러한 방법을 활용해 체계적으로 초안을 정리하면 실제 문서 작성에 큰 도움이 된다. 노트에 무작정 생각을 필기하는 것보다는 마인드맵을 활용하는 것이 좋다.

 

▪ 마인드맵 프로그램을 이용해 디지털 마인드맵 작성법
마인드맵은 1970년대 유럽의 Tony Buzan에 의해 시작된 필기법이다. 생각과 아이디어를 핵심 아이디어를 기준으로 바깥으로 뻗어 나가는 가지를 사용함으로써 구조화하는 것이다. 이렇게 비주얼한 기록을 통해 기억, 회상, 연상을 보다 쉽게 하고 이것이 창조적인 생각을 가능하게 할 뿐 아니라 생각을 구조적으로 정리할 수 있도록 해준다. 마인드맵을 활용하면 창의성 계발과 사고력을 증진시킬 수 있다.

일반적으로 우리는 생각이나 아이디어를 정리하고 메모할 때 직선식의 필기법을 활용한다. 떠오르는 생각들을 노트에 그어진 줄에 맞춰서 순차적으로 정리한다. 이러한 방법은 단조롭고 지루하기 때문에 창의적인 사고를 방해한다. 또한 집중력이 떨어지고 필기한 내용을 한 눈에 알아보기 어렵다. 반면 마인드맵으로 작성된 문서는 필요한 단어만을 사용해 시각적으로 배치하기 때문에 창의적인 생각을 가능하게 해준다.

마인드맵을 PC에서 손쉽게 구현할 수 있도록 도와주는 프로그램이 있다. 심테크시스템의 씽크와이즈라는 프로그램을 이용하면 마인드맵을 쉽게 PC에서 사용할 수 있다. 이 소프트웨어는 ‘http://www.thinkwise.co.kr’에서 30일 동안 무료로 사용할 수 있는 프로그램을 다운로드받을 수 있다. 이 프로그램을 이용하면 머릿속에 떠오르는 여러 아이디어를 비주얼한 이미지와 기호, 색상 등을 이용해 쉽게 정리할 수 있다.

마인드맵은 방사사고의 표현으로 중심을 기준으로 주요 키워드를 사방으로 뻗어나가며 기술한다. 이때 단어를 단색으로 정리하는 것이 아니라 다양한 색상 그리고 이미지와 부호를 사용한다. 그러므로써 좌우 뇌의 기능을 유기적으로 연결하여 사고력 증대를 가져다준다. 즉 마음 속의 지도를 글자는 물론 기호, 그림을 이용해 표현함으로써 창의성과 기억력을 증진시켜준다. 기존의 노트 필기법과는 달리 이미지와 언어의 연상작용을 통해 시각적인 노트 작성법이라 할 수 있다. 마인드맵은 백지와 색펜을 이용해서도 작업이 가능하다. 하지만 씽크와이즈와 같은 PC용 프로그램을 이용하면 쉽고 빠르게 마인드맵을 할 수 있을 뿐 아니라 저장이 용이하다. 씽크와이즈를 실행하면 중앙에 핵심 주제를 입력할 수 있는 메뉴가 나타난다. 이것을 중심어라 한다. 이곳에 다루고자 하는 핵심적인 단어를 기입한다. 입력이 끝나면 엔터를 누른다.

스페이스바를 누르면 중심어의 옆에 주가지가 나타난다. 이곳에 주제를 기입하고 엔터를 누른다. 이렇게 중앙의 핵심 이미지 주위로 가지를 쳐내려가며 주제어를 기입해나가며 생각의 나래를 지도로 정리하는 것이 마인드맵의 핵심이다.

주제어 입력을 끝내면 주제어를 마우스로 클릭하거나 키보드의 방향키를 이용해 주제어를 선택한다. 그리고 스페이스바를 누른다. 주제어 옆에 부가지가 나타난다. 주제어에 대해 세부적인 내용을 담은 핵심어로 부주제를 기입한다. 기입이 끝나면 엔터를 누르고 다시 스페이스바를 누르면 부가지가 나타난다. 이러한 방법으로 부주제를 계속 기록해나간다.

부주제는 주제에 대한 세부적인 내용을 담고 있어야 한다. 그리고 가급적 핵심적인 단어만을 이용해 구성하는 것이 좋다. 또한 주제, 부주제 등에는 심볼 등을 적절히 배치함으로써 시각적으로 강렬한 인상을 주도록 하는 것이 좋다. 심볼은 우측의 기호창에서 선택할 수 있다. 기호를 넣을 주제 또는 부주제를 클릭하고 기호창에서 넣고자 하는 심볼을 클릭하면 기호가 삽입된다. 기호창은 ‘보기 > 도구모음 > 기호’를 클릭해서 화면에 표시할 수 있다.

이러한 방법으로 중앙어를 중심으로 주제와 부주제를 주가지와 부가지를 이용해서 정리해가도록 한다. 부주제는 좀 더 세부적이고 자세한 내용을 기록해 넣도록 한다. 너무 추상적인 단어만으로 구성하면 창의적 아이디어나 다양한 정보를 생각해낼 수 없다. 전체적으로 중앙에 위치한 중앙어 중심으로 가지를 통해서 다양한 정보들이 연계됨으로써 생각을 체계적으로 정리할 수 있다.


[Tip : ] 마인드맵은 PC없이도 할 수 있다.


마인드맵을 꼭 PC에서만 할 수 있는 것은 아니다. 흰 백지와 색펜을 이용해 작업할 수 있다. 오히려 PC에서 작업하는 것보다 더 편하고 자유로울 수 있다. 백지는 가급적 줄이 없는 종이가 좋다. 줄이 쳐진 종이는 생각을 하는데 제한할 수 있기 때문이다. 색펜의 경우 주가지의 수만큼 준비하는 것이 좋다. 대개 5색 정도를 준비하고 중앙에 중심어를 넣으면서 색펜을 이용해 각각의 주가지를 다른 색상을 색칠하면서 이미지와 단어를 이용해서 생각을 정리해나가면 된다.

 


▪ 마인드맵으로 제안서의 초안을 구성하기


마인드맵을 이용해 제안서의 초안을 작성하면 정리하면서 새롭고 창조적인 아이디어를 떠올릴 수 있다. 마케팅 기획안이나 각종 제안서를 작성하는데 처음부터 문서를 만들려 하면 막막하기만 하다. 이때 마인드맵으로 생각을 정리하다보면 쉽게 생각하기 어렵던 기발한 발상도 가능하다. 또한 다양한 경우를 점검해볼 수 있어 빈틈없는 기획안을 작성하는데 밑거름이 되기도 한다. 마인드맵 프로그램은 사용이 그리 어렵지 않으며 생각을 빠르게 정리하는데 큰 도움이 된다.

마케팅은 고정관념에서 벗어나 독특한 발상의 전환이 필요하다. 자유로운 사고를 통해서 기발한 아이디어로 마케팅이 전개되어야 하는데 마인드맵이 이러한 아이디어를 생각하게 하는데 큰 도움이 된다. 우선 중앙에 마케팅의 제목을 기입하고 그 주변으로 생각나는 모든 주제어를 기입한다. 마케팅의 목표, 방안, 컨셉, 일정, 예산 등의 생각나는 중요한 항목들을 모두 주가지로 구성한다.

기입한 주제어 중에서 부주제로 정리해야 할 것들을 정리한다. 예를 들어 컨셉, 지표, 포지셔닝 등을 ‘목표’의 부가지로 위치를 변경하려면 ‘컨셉’을 클릭한채 드래그해서 ‘목표’에 놓는다. ‘지표’와 ‘포지셔닝’을 Shift를 이용해 연속으로 선택해서 한꺼번에 옮길 수도 있다. 이러한 방법으로 부주제와 주제를 정리한다.

가지의 색상을 변경하려면 변경할 가지의 주제를 마우스 오른쪽 버튼으로 클릭한 후에 ‘서식’을 선택한다. ‘가지’에서 가지의 색상과 굵기를 변경할 수 있다. 각각의 가지별로 다른 색상을 지정해서 사용하면 다양한 색상으로 인해 마인드맵의 목적을 달성하는데 큰 도움이 된다.

‘외곽선’을 선택한 후에 적절한 도형을 클릭하면 선택한 주제에 테두리가 표시된다. 중요한 주제어를 강조해서 표현하고자 할 때 유용하다.

가지의 색상과 외곽선이 적용된 모습을 볼 수 있다. 이러한 방법으로 각각의 가지 색생과 주제, 부주제 등을 꾸밀 수 있다.

마케팅 마인드맵에는 가급적 다양한 기호와 이미지를 사용하는 것이 좋다. 이러한 이미지들이 보다 창의적이고 유연한 생각을 떠오르게 하는데 도움을 준다.

마케팅 전략에는 기본적으로 목표와 지표, 컨셉 등이 표시되어야 하며 그 외에 구체적인 마케팅 방안, 예산, 일정 등이 표기되어야 한다. 주제어를 이러한 항목으로 구성한 후에는 부주제에 부가지를 쳐서 세부적인 내용을 기입해 넣는다. 각 항목에 최대한 자세한 내용을 기록해 넣음으로써 한 장의 마인드맵만으로 마케팅 전반적인 계획에 대한 내용을 쉽게 파악할 수 있도록 구성하는 것이 좋다.

철저하고 빈틈없이 작성해야 하는 사업계획서도 마인드맵으로 정리하면 큰 도움이 된다. 최종 문서는 워드프로세서나 프리젠테이션 파일의 형태로 저장하는 것이 좋지만 처음 생각을 정리할 때는 마인드맵을 활용하는 것이 좋다. 특히 원고의 목차나 강의 커리큘럼 등을 정리할 때도 유용하게 사용할 수 있다. 실제 많은 테크라이터와 강사들이 마인드맵을 이용해 책이나 강의를 준비하곤 한다. 물론 사업계획서를 마인드맵으로 처음부터 끝까지 작성할 수는 없다. 마인드맵은 사업계획서의 목차를 잡고 초안을 구성하는데 도움이 된다. 우선 사업계획서에서 다루고자 하는 중심 주제들을 주가지로 정리한다. 각각의 항목별로 색상을 다르게 지정함으로써 다소 지루할 수 있는 계획서의 내용에 신선함을 부여하도록 한다.

주제를 기입해 넣은 후에는 각각의 항목별로 세부적인 사항을 채워 넣는다. 기본적으로 사업계획서의 1차 주제어로는 회사개요, 사업개요, 시장분석, 인력구성, 재무계획, 마케팅 계획, 생산 계획 등이다. 이러한 각 항목 아래에 부가지를 치면서 세부적인 내용을 기록해 넣는다. 사업계획서마다 조금씩 내용 구성이나 형태는 달라질 수 있다. 전체적인 내용을 보면서 각 세부 항목에 어떠한 것을 포함시켜야 할지 비교하면서 중복되지 않도록 채워 넣는다.

이제 가장 중요한 부분이다. 부주제 아래에 보다 상세한 내용을 기입해 넣는다. 앞서 작성한 내용들은 목차 정도의 수준이다. 하지만 3단계의 부주제에 기록해 넣을 사항은 해당 항목에서 실제 다룰 내용들을 기록한다. 내용은 길제 작성하지 않도록 한다. 핵심어를 이용해서 본 사업계획서의 중요한 특징이자 반드시 다루어야 할 사항들을 핵심 단어를 이용해 채워 넣는다.

이렇게 상세한 내용을 채워 넣다보면 사업 계획서의 전체적인 그림이 구성된다. 이렇게 작성된 사업계획서는 초안일 뿐 완성된 문서는 아니다. 이렇게 그려진 마인드맵을 통해서 전체적인 사업계획서의 밑그림을 확인할 수 있다. 이제 전체적인 내용을 살펴보면서 미흡한 부분과 강조할 사항, 특징 등을 기입하며 보다 세부적으로 완성시켜 나간다. 이 작업은 하루, 이틀에 할 수 있는 것이 아니다. 수일, 수십일에 걸쳐 다양한 사람들의 의견을 들으며 정리해나간다. 이후에 이 마인드맵을 기본으로 세부적인 사업계획서를 작성하면 된다.


[Tip : ] 마인드맵 파일 PPT로 변환하기
대개 사업계획서는 MS워드나 파워포인트로 정리한다. 마인드맵으로 구성한 사업계획서는 초안이기 때문에 실제 계획서를 작성하려면 MS워드나 파워포인트를 이용해야 한다. 이때 씽크와이즈에서 제공하는 변환 기능을 활용하면 MS오피스에서 쉽게 계획서를 작성할 수 있는 기본 문서 파일을 생성할 수 있다.
사업계획서의 초안을 만든 마인드맵에서 ‘파일 > 보내기 > Microsoft PowerPoint'를 선택하여 PPT 파일로 변환한다. 이렇게 되면 앞서 마인드맵에서 정리한 내용들이 파워포인트에 그대로 표시되어 나타난다. 이제 마인드맵에서 구성한 목차대로 파워포인트에서 세부적인 내용을 채워나가면 된다.


글/김지현(oojoo@oojoo.co.kr)




원문링크:

http://hdbbs.hanafos.com/Board.aspx?act=View&tbl=QBIC_WEBZINE&pg=1&bid=1&seq=245&thread=49

+ Recent posts