IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

수학 내용을 포함하는 동적 웹 사이트 구축하기
JSP 기술과 LateX가 온라인 과학 교육과 연구를 돕는다

Michael Juntao Yuan
박사과정 , University of Texas at Austin
2002년 2월

글자의 위와 아래에 붙어있는 문자들과 특수한 기호를 가진 수학 공식을 HTML로 변환하기는 엄청나게 어려운 일이다. 대부분의 과학자와 수학자들은 미적으로 보기 좋은 공식을 만들어내기 위해 유연한 LateX 텍스트 처리기를 사용한다. 그런데 이 결과물들을 어떻게 웹에 친근한 형태로 변환할 수 있을까 ? 이 글에서 Michael Yuan은 JSP 페이지와 커스텀 태그를 이용해 LateX 포맷의 공식을 작성자가 사용하기 쉽고 클라이언트에도 특별한 소프트웨어가 필요지 않도록 웹에 올릴 수 있는 방법을 보여준다. 그가 점차 효율성이 높아지는 기법들을 반복함에 따라 여러분은 서버측 자바 기술이 서로 이기종의 third-party 도구들의 힘을 이용하여 외관상 까다롭기 그지없는 문제들을 어떻게 해결해가는지를 보게될 것이다.

인터넷과 웹은 원래 과학자들이 과학과 수학 연구 정보를 교환하기 위해 설계한 것이다. 아이러니컬하게도 인터넷이 나온 지 30여년이 지났고 웹이 개발된지는 10년이 지난 지금까지도 웹에 수학적 내용이 많은 컨텐츠를 공개하는 것은 여전히 쉬운 일이 아니다. W3C의 MathML 권장사항과 같이 웹에서의 수학 정보 교환을 위한 표준이 개발되긴 했지만, 이들을 사용하려면 저작자와 독자 모두 IBM에서 Netscape Navigator와 Internet Explorer용으로 만든 수학용 브라우저 플러그인인 techexplorer와 같은 특수 소프트웨어가 필요하다. (참고자료) . 사용자들은 기술적인 어려움, 비용 및 보안상의 위험 때문에 이런 특수한 클라이언트측 소프트웨어를 설치하는 것을 꺼려한다. 따라서 그러한 표준의 적용은 소규모 연구 단체에 국한되어 있으며, 거의 대다수의 인터넷 사용자가 이를 사용하지 못한다. 오늘날 웹에서 수학 정보를 공유하기 위한 가장 편리한 방법은 텍스트 형태가 아닌 공식들을 이미지로 포착하고 이 이미지들을 표준 HTML 페이지에 삽입하는 것이다.

대부분의 최신 GUI 기반 수학 저작 도구들은 문서를 웹 페이지로 저장하는 옵션을 가지고 있다.; 이 도구들은 공식의 이미지와 정적인 HTML 페이지를 생성한다. 이것은 단지 여러분의 논문과 같은 정적인 컨텐츠를 웹에 올려놓기 위해서는 편리한 방법이다. 그러나 사용자 참여가 대부분의 사이트에서 필수적이 되고 있기 때문에 정적인 웹 사이트의 시대는 오래 전에 지났다. 고급 수학 웹 사이트는 백앤드의 데이타베이스로부터 컨텐츠를 동적으로 웹에 공개할 수 있어야 하며, 사용자가 자신의 컨텐트를 다른 사용자와 공유할 수 있도록 해야 한다. (예를 들어, 양방향 시험 시스템과 연구 협업 시스템등이 이에 해당한다)

이 글은 이러한 문제에 대한 하나의 해결 방법을 제시할 것이다. 샘플 코드는 수학 공식이 표현된 마크업 텍스트를 그 공식을 나타내며 웹에 올릴 수 있는 그래픽 파일로 신속하고 쉽게 변환시킬 수 있는 방법을 제공한다. 이 글을 읽다 보면 여러분은 보다 일반적인 수수께끼를 푸는 접근 방식을 보게 될 것이다. 우리는 여러 개의 상호 이질적이고 연결되지 않는 도구들을 하나의 프로그램으로 결합시키기 위해 JSP 페이지와 커스텀 태그를 사용할 것이다. 다루기 힘든 동적 웹 애플리케이션을 작업할 때 잊지 말아야 할 것은 맨 땅에서 시작하지 말라는 것이다; 솔루션은 다른 형태로 여러분이 이용하기를 기다리고 있을 수도 있다.

JSP 기술 복습

동적인 서버측 애플리케이션을 구현하기 위한 앞선 기술중 하나기 JSP (JavaServer Pages) 기술이다. JSP 페이지는 백앤드의 데이터가 프런트 앤드의 웹 페이지(프리젠테이션 로직)에 어떻게 표시되는지를 제어하는데 사용될 수 있다. JSP 페이지는 자바 데이터 객체를 HTML 화면 출력 엘리먼트와 결합시키기 위해 HTML과 유사한 태그 언어를 사용한다.

JSP 기술의 가장 큰 강점은 확장가능하다는 점이다. JSP 태그 언어는 커스텀 태그로 확장될 수 있는데, 이는 태그 핸들러 클래스에서 프리젠테이션 로직을 처리하는 자바코드를 캡슐화시키도록 해주다. 웹 저작자들은 아무런 자바 코드를 작성하지 않고도 미리 정의된 태그 라이브러리를 이용해 복잡한 프리젠테이션 작업을 바로 수행할 수 있다.커스텀 태그들은 프리젠테이션 제어 코드를 재사용 할 수 있게 해주며 웹 페이지 작성자의 작업을 상당히 간편하게 해준다. JSP 커스텀 태그의 가장 보편적인 형태는 컨텐츠 번역 태그(content translation tag)인데, 태그 본문에 들어 있는 작성자 중심의 내용을 방문자 위주의 표시 엘리먼트들로 변환시켜준다.

우리의 수학 웹 사이트에서 우리는 내용 번역 태그를 사용하여 의미론적 수학 표현들을 웹 이미지로 변환할 수 있다. 다음 섹션들에서 이 기법들에 대해 상세히 설명하겠다.

무엇이 필요한가

여기에서는 컨텐츠 번역 태그가 어떻게 작동하는지를 설명하겠다. JSP 컨테이너가 커스텀 태그를 발견하면 현재 페이지의 taglib 디스크립터 파일들에서 태그 이름을 찾는다. 일치되는 것을 찾게되면 JSP 컨테이너는 태그 핸들러 클래스에게 문맥 정보를 전달한다. JSP 태그 핸들러는 먼저 커스텀 태그의 본문으로부터 수학 공식을 표시하는 텍스트 문자열을 추출한다. 그리고 의미론적인 텍스트 공식을 기반으로 이미지를 만들어내고, 그 이미지에 대한 <IMG>라는 HTML 마크업 표시를 브라우저에게 보낸다. 태그 핸들러에서 필요한 수학 이미지 생성 도구는 다음의 기능을 가지고 있어야 한다.:

  • 수학 공식은 반드시 JSP 태그의 본문에서 지원되는 유일한 형태인 평이한 텍스트로 표시되어야 한다. 이 평이한 텍스트는 또한 HTTP 프로토콜을 통하여 정보를 전달하고 데이터베이스 혹은 XML 문서에 정보를 저장하기 위한 표준 포맷이다.
  • 수학 공식을 평이한 텍스트로 표기하는 방법은 웹 저작자들이 많은 훈련없이도 사용할 수 있도록 반드시 의미론적이고 직관적이어야 한다. 이를 위해 그 의미론적인 수학 표기 시스템이 전세계 학자들에 의해 이미 사용되고 있었던 것이라면 더할 나위없다.
  • 수학 표기 도구들은 여러 플랫폼에서 사용될 수 있는 자바 애플리케이션의 이점을 살리기 위해 많은 플랫폼에서 사용가능해야 한다.

LateX 소개

위의 모든 요건을 충족하는 수학 저작 소프트웨어는 식자 도구들의 집합인 업계 표준의 TeX/LateX(후에 Latex)이다. LateX는 다음과 같은 기능을 제공한다.:

  • LateX는 표준 텍스트 입력 파일을 사용하며 그 포맷은 완전히 공개되어있다. 사실 대부분의 LateX 구현은 또한 모두 오픈 소스들이다.
  • LaTeX는 매우 직관적인 문법을 가지고 있어 배우기 쉽다. 예를 들면 다음의 입력 텍스트는
     \alpha_0^2 + \beta_0^2 = \gamma_0^2 

    LaTeX에서 처리된 후 그림 1에서와 같은 공식을 만들어 낸다.

    그림 1. LaTeX 결과 예제
    alpha_0^2+beta_0^2=gamma_0^2


  • LaTeX는 사용자 기반이 잘 확립되어 있다. 일정 기간 동안 과학계에서 표준 식자 언어로 사용되었기 때문이다. 수학계의 대부분의 저자들이 LaTeX에 이미 익숙해 있다.
  • LaTeX는 Unix, Linux, Windows 및 Mac OS의 대부분의 변종을 포함한 많은 플랫폼에서 사용가능하다. 따라서 LaTeX 문서는 이식성이 매우 높다.
  • LaTeX는 전문적인 출판 수준의 공식을 만들어낸다. 이들은 웹 그래픽에 적합한 것 이상이라 할 수 있다. 그림 2는 LaTex로 표현한 Maxwell의 방정식이다.

    그림 2. LaTex로 표현한 Maxwell의 방정식
    Maxwell's equations as rendered by LaTeX

LaTex가 생소한 독자는 본문을 계속 진행하기 전에 LaTex와 그 구문에 익숙해 두는 편이 좋을 것이다. 아래의 참고 자료 섹션에 유용한 정보로의 링크가 있다.

LaTex에서 GIF 이미지 생성하기
LaTeX는 의미론적인 수학 공식을 이미지로 처리할 수 있지만, 이 이미지들은 대부분의 웹 브라우저에서 바로 출력될 수는 없다. 모든 웹 브라우저는 GIF 이미지를 지원하기 때문에 LaTeX로 된 공식 이미지를 GIF 포멧으로 변환해야 한다. 이번 섹션에서는 Third-party 도구를 사용해 LaTex 입력 구문으로부터 GIF 이미지를 생성하는 방법에 대해 살펴볼 것이다. 우리의 궁극적인 목표는 이 절차를 가능한한 많이 자동화시키는 것이지만, 우리가 작업해야 하는 기본 원칙을 보는 것도 도움이 될 것이다. 우리는 Linux/Unix 명령행 툴을 예제로 사용하지만, 동일한 기능을 가진 도구가 WiIndows와 Mac OS용으로 나와 있다. PNG와 JPEG 같은 다른 포멧의 이미지도 비슷하게 만들 수 있다. 다음 단계들을 따르면 GIF 이미지 포멧으로 된 수학 컨텐츠가 만들어질 것이다.::

  1. 구문 입력 파일 (여기서는 샘플 파일을 sample.tex라고 부르자)에 LaTeX 구문 뒤에 수학 내용을 작성한다.
  2. 그림 3과 같이 LaTeX 프로그램을 사용해 sample.tex를 장치 독립적인 파일 (sample.dvi)로 처리한다. 명령문은 latex sample.tex이다. 처리 중에 LaTeX는 또한 로그 파일과 보조 파일을 생성한다.

    그림 3. LaTeX 실행하기
    Running LaTeX

  3. 그림 4와 같이 Dvips 유틸리티를 사용해 .dvi 파일을 포스트스크립트 파일로 변환한다. 명령문은 dvips -o sample.ps sample.dvi이다. (Dvips에 관한 상세 사항은 참고 자료 를 참조한다.)

    그림 4. Dvips 실행하기
    Running Dvips

  4. ImageMagick 툴인 convert를 사용해 포스트스크립트 파일 sample.ps를 GIF 포멧으로 변환한다. (ImageMagick에 관한 상세 사항은 Resources를 참조한다.) 명령문은 convert -antialias -crop 0x0 sample.ps sample.gif이다. 우리는 포스트스크립트 페이지에 있는 공식 주위의 여백이 GIF에 나타나지 않도록 하고 싶다. 따라서 명령행에 -crop 0x0 옵션을 써서 여백이 없어지도록 하였다. 또한 -antialias를 사용하여 매끈한 폰트가 만들어지도록 하였다.

    그림 5. ImageMagick 실행하기
    ImageMagick convert command



    여러분이 명령행에서 ImageMagick에 붙인 출력 파일명에 더해진 파일 확장자는 출력 이미지 포멧을 결정한다. 위의 예제에서 출력 이미지는 sample.gif로 지정되었는데, 이는 ImageMagick에게 GIF 이미지를 출력하라는 지시이다. 포스트스크립트를 GIF로 변환하는 데 관한 상세 사항은 보충 자료 "벡터 그래픽 대 비트맵 그래픽"을 참조한다.
벡터 그래픽 대 비트맵 그래픽

LaTeX/Dvips가 생성한 포스트스크립트 페이지 는 벡터에 기반한 이미지이며, 어떤 크기로도 자연스럽게 크기 조정이 가능하다. 그러나 GIF, PNG, JPEC과 같은 웹 이미지는 모두 비트맵 이미지에 기반하고 있다. MageMagick샘플은 추가적인 처리 과정을 거치기 전에는 기본적으로 포스트스크립트 페이지를 612 x 792 픽셀 비트맵 이미지로 샘플링한다. 비트맵 이미지의 한 가지 큰 단점은 사이즈를 조절하면 특히 사이즈를 키울 경우 보기 싫어진다는 것이다. 따라서 공식의 이미지를 ImageMagic이 샘플링한 것보다 훨씬 크게는 자연스럽게 표시할 수 없다.

ImageMagick 패키지는 오픈 소스 라이선스로 출시되어있기 때문에 소스 코드를 변경하여 포스트스크립트 페이지에 대해 보다 나은 해상도를 가진 이미지를 생성하도록 할 수 있다. magick/image.h 파일에서 기본값으로 설정되어 있는 612 x 792 해상도를 변경하고 전체 패키지를 재컴파일할 수 있다 . 더 나아가 변환 프로그램의 소스 코드를 편집하여 런타임시에 지정된 포스트스크립트 샘플링 해상도를 사용하도록 할 수 있다. 그러나 소스 코드를 수정하는 것은 대부분의 사용자에게 매우 어렵다.

고품질의 대형 이미지 작성을 쉽게 해주는 다른 이미지 변환 툴들도 나와 있다. Unix/Linux 프로그램인 Textogif (참고 자료 참조)는포스트스크립트 해석기인 GhostScript와 이미지 변환 라이브러리인 Netpbm과 결합하여 포스트스크립트 페이지에 대해 고품질의 GIF 이미지를 어떤 해상도로도 만들 수 있다. 그러나 Textogif는 Unix/Linux 프로그램에서만 작동하기 때문에 필자는 이번 예제에서는 사용하지 않겠다.

자바 애플리케이션에서 외부 프로그램 실행하기
지금까지 우리가 간략하게 살펴본 절차들은 상호 연결되지 않은 다수의 명령행 프로그램들을 포함하고 있다. 수학 이미지를 웹에 쉽게 표현하려면 이 수학 저작 툴들을 JSP 웹 애플리케이션으로 통합해야 한다. 자바 프로그램은 java.lang.Runtime API를 사용해 JVM 외부의 호스트 운영체제의 프로세스를 구동시키고 관리할 수 있다. 새로운 프로세스는 다음과 같이 구동시킨다. :


Process p = 
  Runtime.getRuntime().exec(cmd, envp, dir); 

위에서 cmd 매개변수에는 명령어가 포함된 하나의 문자열이 올 수도 있고 명령어와 옵션이 포함된 일련의 문자열이 올 수도 있다. envp에는 이름=값 포멧으로 환경 변수가 설정된다.; 그리고 dir 매개변수는 java.io.File 유형이며 프로세스의 작업 디렉토리를 나타낸다. 프로세스가 구동되면 입력 스트림을 통해 프로세스에 데이터를 전송할 수 있다.:

InputStream ins = p.getInputStream();

또한 출력 스트림으로부터 프로세스의 결과물을 얻을 수 있다. :

OutputStream ous = p.getOutputStream();

외부 프로세스가 종료될때까지 자바 애플리케이션을 중지시키고 싶다면 다음 코드를 사용한다. :

p.waitFor(); // Move on to other tasks. 

예제
지금까지 동적인 수학 컨텐츠가 담긴 웹 사이트를 구현하는데 필요한 툴과 기본 기법들을 살펴보았다. 이제 이들을 통합할 차례이다. 그 방식을 가장 잘 보여주는 방법은 이 글과 함께 제공되는 예제 애플리케이션으로 작업하는 것이다.

예제 애플리케이션 배치 방법

  1. zip archive 코드를 다운받아서 푼다.
  2. support, SlowMathTagMathTagCompile 패키지를 컴파일한다. 클래스 경로에 J2EE v1.3 j2ee.jar 파일을 포함시켜야 한다.
  3. 여러분의 JSP 서버에 새 웹 애플리케이션을 생성한다. 예를 들어, Tomcat 서버에서는 테스트 애플리케이션용으로 ebapps/JSPMath 디렉토리를 생성한다.
  4. 컴파일된 패키지인 support, SlowMathTagMathTag를 Webapps/JSPMath/WEB-INF/classes 디렉토리에 복사한다.
  5. taglib 디스크립터 파일인 tlds/*.tldWebapps/JSPMath/WEB-INF/tlds 디렉토리에 복사한다.
  6. JSP와 HTML 파일인 jsp/*Webapps/JSPMath 내의 한 디렉토리에 복사한다.
  7. 이제 여러분은 브라우저로 Test01.html이나 Test02.html을 지정하여 테스트를 시작할 수 있다.

일단 애플리케이션을 설치했으면 본 섹션의 단계들을 밟아 예제가 어떻게 작동하는지 볼 수 있다.

예제 코드 실행하기
샘플 코드는 두 개의 새로운 유형의 JSP 커스텀 태그를 포함하고 있다. <LatexRaw> 태그는 원래의 LaTeX 텍스트를 HTML 이미지 태그로 번환한다. 이 태그는 하나의 이미지에 여러 개의 공식, 표, 혹은 짧은 설명문을 표시하는데 사용될 수 있다. <LatexMath> 태그는 수학적 모드의 LaTeX 텍스트만 HTML 이미지 태그로 바꾸어 한 개의 수학 공식 이미지로 나타낸다. 이 태그는 공식을 신속하게 표시하는데 사용할 수 있다.

각 태그는 heightwidth라는 두 개의 속성을 가지고 있는데, 결과로 나오는 <IMG> 태그의 heightwidth 속성에 대응된다. 이들 속성은 필수 사항은 아니다.

아래의 화면은 실행중인 커스텀 태그를 보여 주고 있다. Test01.html은 LaTeX 텍스트 문자열을 두개의 큰 텍스트 필드에 입력한다. 페이지 위쪽에 있는 두 개의 작은 텍스트 입력 상자에는 결과로 나올 이미지에 대해 사용자가 원하는 높이와 너비를 입력한다. 커스텀 태그에서 dimenstion 속성을 어떻게 사용하는지 보여주기 위해, 여기에서 사용자가 지정한 면적으로 된 이미지와 ImageMagick이 지정한 기본 면적으로 된 이미지를 Test01.jsp에서 둘 다 표시하겠다. 작성된 HTML 양식은 브라우저에서 그림 6과 같이 나타난다.

그림 6. LaTeX 수학 입력 양식
LaTeX Math input form

Text01.html의 양식을 전송하면 JSP 페이지인 Test01.jsp로 데이터를 게시하고, 그러면 그림 7과 같이 수학 공식 이미지가 결과로 표시된다. 첫번째 이미지는 입력 HTML 양식의 MathText 필드 (한줄로 된 텍스트 필드)의 수학 모드 LaTeX 텍스트를 사용해 <LatexMath> 태그가 생성한 것이다. 첫번째 이미지에 대한 <LatexMath> 태그가 두가지 속성을 가지고 있음에 주의한다. 그러면 사용자가 지정한 heightwidth 속성에 따른 면적의 이미지가 표시된다. 두번째 이미지는 기본으로 지정되어 있는 면적으로 표시되었다는 것 외에는 첫번째 이미지와 동일한 방법으로 생성되었다. (두번째 이미지를 생성하는 태그는 dimension 속성을 가지고 있지 않다.) 세번째 이미지는 RawMathText 필드 (큰 여러행의 텍스트 필드) 에 입력된 LaTeX 텍스트로부터 <LatexRaw> 태그에 의해 생성되었으며 텍스트와 수학적 기호와 혼합된 예제이다. 지정된 높이와 너비 필드는 이 이미지에 적용되지 않았다.

그림 7. 수학 이미지 출력
Math image output

Listing 1은 이 모든 작업을 수행하는 Test01.jsp의 코드이다.

Listing 1. Test01.jsp


<%@ taglib uri="/WEB-INF/tlds/SlowMathTaglib.tld" prefix="SlowMathTag" %>

<%
   String mathText = request.getParameter( "MathText" );
   String rawMathText = request.getParameter( "RawMathText" );
   String height = request.getParameter( "height" );
   String width = request.getParameter( "width" );
%>

<html>
<head>
  <title>JSPMath test without image cache</title>
</head>
<body bgcolor=white>

<p><font color=green> Math formula in desired dimensions: </font>
<p>

<SlowMathTag:LatexMath height="<%=height%>" width="<%=width%>">
  <%=mathText%>
</SlowMathTag:LatexMath>


<p><font color=green> Math formula in default dimensions: </font>
<p>

<SlowMathTag:LatexMath>
  <%=mathText%>
</SlowMathTag:LatexMath>


<p><font color=green> Latex segment in default dimensions: </font>
<p>

<SlowMathTag:LatexRaw>
  <%=rawMathText%>
</SlowMathTag:LatexRaw>


</body>
</html>

한 번의 실행으로 JSP 컨테이너가 웹 브라우저에게 보내는 실제 HTML 코드는 Listing 2와 같다.

Listing 2. Test01.jsp가 브라우저에 보내는 HTML 코드


<html>
<head>
  <title>JSPMath test without image cache</title>
</head>

<body bgcolor=white>

<p><font color=green> Math formula in desired dimensions: </font>
<p>

<IMG 
SRC="http://localhost:8080/JSPMath/images/image1009709773390.gif" 
height=20 width=150 />


<p><font color=green> Math formula in default dimensions: </font>
<p>

<IMG 
SRC="http://localhost:8080/JSPMath/images/image1009709776535.gif" />


<p><font color=green> Latex segment in default dimensions: </font>
<p>

<IMG 
SRC="http://localhost:8080/JSPMath/images/image1009709777612.gif" />


</body>
</html>

여기의 GIF 이미지는 태그 핸들러가 생성한 것이다. 그림 7에서 보았듯이 사용자가 지정한 면적으로 확대된 이미지는 매끄럽게 표현되지 않는다. 왜 그런지와 Unix/Linux 시스템에서 이 문제에 대해 어떻게 대응할지에 대해서는 앞의 보충 자료 "벡터 그래픽 대 비트맵 그래픽"을 참조한다.

이러한 커스텀 태그 작업을 어떻게 구현하였는가? 알고 싶다면 계속 읽기 바란다.

간단한 (하지만 느린) 방식
위의 예제는 매우 간단하고 직접적인 방식으로 구현될 수 있다. 이글에서 여러분은 이미 JSP 커스텀 태그 핸들러 구현 방법을 알고 있을 것이다. 기억을 되살리고 싶다면 아래의 참고 사항 섹션을 참조한다.

<SlowMathTag:*> 태그 핸들러는 정적인 메소드인 support.MathUtil.latex2gif()을 호출하여 GIF 이미지를 생성한다. 어떻게 작동하는지를 보기 위해 이 메소드의 소스 코드를 살펴보자.

Listing 3과 같이 메소드는 우선 현재의 태그가 생성한 GIF 이미지와 중재 파일들의 이름을 결정한다. 이 파일들의 루트네임은 현재 시간의 1/1000초 값이다.

Listing 3. 파일 이름 생성하기


Date now = new Date ();
String filename = "image" + Long.toString(now.getTime());
// ...
File f = new File(path + filename + ".tex");

다음에 메소드는 Listing 4와 같이 태그 본문에서 내용을 취해 완전한 LaTeX 입력 파일을 구성한다. JSP 컨테이너는 태그 본문을 문자열 변수 latexStrlatex2gif() 메소드에 전달한다. \pagestyle{empty} 명령어는 결과 페이지의 하단에 페이지 번호가 나오지 않도록 하는데 사용된다. \batchmode 명령어는 LaTeX 프로세서가 비대화형 모드로 실행되도록 하는데 사용된다.

Listing 4. LaTeX 입력 파일 구성하기


private static String latexHead = "\\batchmode\n" +
                                  "\\documentclass[12pt]{article}\n" +
                                  "\\pagestyle{empty}\n" +
                                  "\\begin{document}\n";
private static String latexEnd  = "\\end{document}\n";

// ...

// String variable "latexStr" contains the body of the current tag.

// Process modes.
if ( mode.equals("displaymath") ) {
  latexStr = "\\Large\n\\begin{displaymath}\n" +
             latexStr.trim() +
             "\\end{displaymath}\n";
} else {
  // Unrecognized modes are raw latex strings.
}

// Write content into a latex file.
FileWriter fw = new FileWriter(f);
fw.write( latexHead, 0, latexHead.length() );
fw.write( latexStr, 0, latexStr.length() );
fw.write( latexEnd, 0, latexEnd.length() );

이제 메소드는 Listing 5와 같이 latex, dvips 및 convert 명령어를 실행하여 서버측에 미리 설정된 디렉토리 경로에 최종적인 GIF 이미지를 만든다.

Now the method executes the commands latex, dvips, and convert to produce the final GIF image in a preconfigured directory path on the server side, as shown in Listing 5.

Listing 5. GIF 파일 생성 Generating the GIF file

private static String latexCommand = "/usr/bin/latex";
private static String dvipsCommand = "/usr/bin/dvips";
private static String convertCommand = 
    "/usr/X11R6/bin/convert -antialias -crop 0x0";

// ...

public static synchronized String latex2gif (String path, String mode,
                                String latexStr) throws Exception {

  // Generate root file name and create ".tex" file
  // ...

  // Get Runtime.
  Runtime r = Runtime.getRuntime();
  Process p;
  File imagePath = new File( path );

  // ...

  // Run latex in directory "imagePath".
  p = r.exec(latexCommand + " " + filename + ".tex", null, imagePath);
  if ( p.waitFor() != 0 ) throw new Exception("Error in Latex\n");

  // Run dvips in directory "imagePath".
  p = r.exec(dvipsCommand + " -o " + filename + ".ps " +
             filename + ".dvi", null, imagePath);
  if ( p.waitFor() != 0 ) throw new Exception("Error in dvips\n");

  // Run convert in directory "imagePath".
  p = r.exec(convertCommand + " " + filename + ".ps " +
             filename + ".gif", null, imagePath);
  if ( p.waitFor() != 0 ) throw new Exception("Error in convert\n");

  // ...
}

마지막으로 메소드는 Listing 6과 같이 모든 중재 파일을 삭제한다. .

Listing 6. 중재 파일 삭제하기

f = new File(path + filename + ".tex");
f.delete();
f = new File(path + filename + ".log");
f.delete();
f = new File(path + filename + ".aux");
f.delete();
f = new File(path + filename + ".dvi");
f.delete();
f = new File(path + filename + ".ps");
f.delete();

이제 태그 핸들러는 결과로 나오는 GIF 이미지에 대한 <IMG> HTML 태그를 서버 출력 스트림에 작성 수 있다.

지금 간략히 설명한 방식은 간단하지만 매우 느리고 에러가 나기 쉽다. 다음 섹션에서는 솔루션의 성능과 강력성을 향상시키는 방법에 관해 설명하겠다.

캐싱을 이용한 성능 향상시키기
LaTeX 입력문으로부터 이미지를 생성하는 절차는 여러개의 외부 프로그램이 관여되어 있기 때문에 속도가 느리다. 위 섹션에서 살펴본 간단한 구현에서 <SlowMathTag:*> 커 스텀 태그 핸들러는 호출될 떄마다 새로운 이미지를 생성해야 한다. 이는 매우 비효율적이다. 예제 애플리케이션에서는 Test01.jsp내 두 개의 <SlowMathTag:LatexMath> 태그가 단지 다른 면적으로 이미지를 표시하기 위해 방문자가 있을 때마다 동일한 수학 공식 이미지를 두 번 생성해야 한다. 실세계 애플리케이션은 예제 애플리케이션보다 훨씬 복잡하고 불필요한 이미지 생성으로 인한 성능 과부하가 심각할 수 있다. 우리 사이트가 동적인 수학 예제를 제공해야 하고 많은 방문자가 동일한 테스트 문제를 보아야 한다고 상상해 보라. 동일한 공식을 각 방문자에 대해 되풀이해서 생성하는 것은 비용이 매우 많이 든다.

확장성 있는 솔루션을 위해 우리는 우리가 생성한 이미지를 캐쉬에 저장하여 향후 필요할 때 이를 재사용할 필요가 있다. 우리는 LaTeX 텍스트를 이미지 이름에 대한 keys로 사용할 수 있다. 태그 핸들러가 동일한 LaTeX 텍스트를 두번째 만나면 캐싱된 이미지의 파일명을 발견하여 이를 바로 보여줄 수 있다. LaTex 텍스트와 이미지 이름의 쌍을 SQL 데이터베이스에 저장하여 장기 보관하고 신속한 검색을 할 수있다. 캐쉬에 저장된 이미지에 액세스하는 것은 여러 다른 범주의 데이터베이스 액세스 JavaBeans을 사용해 더 조율될 수있다. 그러한 튜닝은 이 글의 범위를 벗어나지만, 독자에게는 매우 흥미있는 연습이 될 것이다.

여기서 우리는 캐싱된 이미지를 태그 핸들러 helper 클래스에 정적인 데이터 멤버로 저장할 것이다. 그러한 정적 데이터 멤버는 JSP 서버 컨테이너와 동일한 수명주기를 가진다. 웹 사이트를 변경하고 서버를 재구동시키면 이전 캐쉬를 포기해야 한다. 캐싱된 LaTeX 구문과 이미지 이름은 두개의 정적인 벡터에 저장된다. 태그 핸들러가 LaTeX 구문을 만나면 캐쉬된 LaTeX 구문 벡터를 반복 검색한다. 일치되는 것을 찾으면 대응되는 이미지 이름을 반환한다. 일치되는 것이 없으면 새로운 공식 이미지를 생성하고, 새로운 LaTeX 구문/이미지 쌍을 캐쉬에 저장한다. Listing 7에 이 방식이 나와 있다.

Listing 7. MathUtil.getImage()


public static synchronized String getImage (String path, String mode,
                               String latexStr) throws Exception {

  // Formatted string stored in the latexStrVec vector.
  String comp =  "MODE=" + mode + "\nLaTeX=" + latexStr.trim();

  // Iterate through the "latexStrVec" cache and check if any
  // element matches the input string and mode.
  for (int i = 0; i < latexStrVec.size(); i++) {
    String l = (String) latexStrVec.elementAt(i);
    if ( comp.equals(l) ) {
      // Return the cached image name if a match is found.
      return (String) imageNameVec.elementAt(i);
    }
  }

  // If no match is found, generate a new image
  // and store it in the cache.
  return storeImage(mode, latexStr, latex2gif(path, mode, latexStr) );
}

Test02.html과 Test02.jsp는 <MathTag:*> 태그에 대해 캐쉬로 성능향상된 태그 핸들러를 사용한다. 이를 시험해 보고 <SlowMathTag:*> 태그에 비해 성능 향상을 경험해 보라.

중재 파일 줄이기
지금까지 살펴 봤듯이, 유틸리티 프로그램들은 속도가 느린 디스크 파일을 사용해 상호 통신하며 우리는 마지막에 모든 중재 파일을 삭제해야 한다. 그러한 중재 파일들은 불필요한 과부하를 만들어낼 뿐 아니라 디스크와 파일 시스템의 에러를 내기 쉽다. Unix/Linux 시스템에서 우리는 다른 프로그램들의 입력과 출력을 연결시키고 중재 파일의 필요성을 부분적으로 없애기 위해 파이프를 사용할 수 있다. 자바 런타임은 Unix 파이프를 직접 지원하지 않기 때문에 Listing 8에서와 같이 이들을 쉘에서 불러와야 한다.

Listing 8. 파이프로 연결된 입력/출력을 사용해 명령어 호출하기


String convertCommand = "/usr/X11R6/bin/convert -antialias -crop 0x0";
String dvipsCommand = "/usr/bin/dvips";

// ...

Process p = Runtime.getRuntime().exec(
  new String[] {
    "/bin/sh",
    "-c",
    dvipsCommand + " -f < " + filename + ".dvi | " +
    convertCommand +  " - " + filename + ".gif"
  },
  null,
  imagePath
);

그러나 LaTeX 프로그램은 표준 입력/출력 파이프를 지원하지 않고 Dvips는 입력을 검색할 수 있도록 요구한다 (즉 파이프를 사용할 수 없다.). 따라서 우리는 여전히 .tex와 .dvi 중재 파일이 필요하다.

이 방식은 Unix에서만 작동하고 모든 중재 파일을 제거할 수 없기 때문에 필자는 예제 프로그램에서 이 방식을 사용하지 않는다. 다음 섹션에서는 훨씬 더 일반적이고 효과적인 방식을 설명하겠다.

외부 애플리케이션용 자바 API

위에서 수행했듯이 개별적인 자바 런타임 프로세스로 독립형 자바 프로그램을 호출하는 것이 편리하다. 그러나 이 방식은 우리가 이미 본대로 중재 파일 문제만 해결하지 못하는 것이 아니다.; 복잡한 자바 애플리케이션과도 잘 작동하지 않는다. 외부 프로그램을 계층적인 자바 클래스 아키텍처에 쉽게 통합할 수 없다.

LaTeX와 이미지 변환 유틸리티 기능을 자바 프로그램에서 직접 호출하고 자바 in-memory 버퍼를 프로세스간 데이터를 교환하는데 사용하면 보다 신속하고 지속성 있는 코드를 생성할 수 있다. 이를 위해서는 이 기능들에 액세스하는 자바 프로그래밍 API가 필요하다.

비 자바 애플리케이션에 대한 자바 API를 생성하는 한가지 표준적인 방법은 Java Native Interface (JNI)를 사용하는 것이다. JNI를 사용하려면 비 자바 애플리케이션을 새로운 자바 인식 헤더로 재컴파일해야 한다. 지금까지 언급한 모든 수학 도구들은 오픈 소스 프로젝트에서 나온 것이고 따라서 소스 코드를 받아 재컴파일할 수 있다. 우리는 도구가 파일보다는 입력/출력 버퍼를 핸들링할 수 있도록 하기 위해 소스 코드의 입력/출력 부분을 수정할 수 있다. 사실 JMagick과 같이 JNI 자바 API를 ImageMagick 라이브러리에 추가하기 위한 시도가 이미 있었다. (Resources참조) 모든 수학 툴에 대한 JNI API를 만드는 것은 이 글의 범위를 벗어난다. 그러나 여러분이 복잡한 자바 애플리케이션에 대해 이와 같은 아키텍처 구현을 고려하고 있다면 이 방향으로 움직이는 것을 검토하고 싶을 것이다. JNI에 관한 상세 정보는 아래의 참고 자료 섹션을 참조한다.

결론
본 기사에서 여러분은 JSP 커스텀 태그를 사용해 LaTeX 유형의 텍스트를 수학적 이미지로 변환할 때의 효율성을 증대시키는 몇가지 기법에 대해 배웠다. 이 방식은 XSLT와 같은 여타 고급 컨텐츠 관리 기술에 대한 자바 확장자를 생성하는데도 쉽게 확장될 수 있다. 여러분은 여러분이 수정해서 자신의 웹 사이트에 통합할 수 있는 다른 툴들에 어떤 것이 있는지를 검토해야 한다. 여기서 간략히 설명한 기법들로 우리는 이제 풍부한 수학 컨텐츠를 포함하고 있는 고급 웹 사이트를 만들 수 있는 도구를 가지게 되었다.

참고 자료

도구

  • LaTeX 프로젝트 홈페이지

  • ImageMagick 이미지 처리 도구

  • JMagick, ImageMagick Java API인 JMagick에 관한 작업

  • Textogif Tex/포스트스크립트 파일을 어떤 해상도의 GIF 이미지로도 변환

Java Native Interface.

  • MathML W3C의 표준 수학 마크업 언어

  • techexplorer IBM의 수학 문서용 브라우저

목 차:
JSP기술 복습
무엇이 필요한가
LaTeX에서 GIF 이미지 생성하기
자바 애플리케이션에서 프로그램 실행하기
예제
간단한 방식
성능 향상시키기
중재 파일 줄이기
외부 애플리케이션을 위한 자바 API
결론
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
JSP 기술 개요
JSP taglibs: 설계에 의한 유용성 증대
자바와 XSLT로 동적인 웹 페이지 생성하기
커스텀 태그로 JSP 페이지에 대한 제어력 높이기
Subscribe to the developerWorks newsletter
US 원문 읽기
Also in the Java zone:
Tutorials
Tools and products
Code and components
Articles
필자 소개
Michael Yuan은 University of Texas at Austin에서 박사 과정을 밟고 있으며, 서버측 자바 기술을 사용하여 과학 교육과 연구를 용이하게 하는데 관심을 가지고 있다.
이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의