공부/JSF2014. 9. 19. 18:15

이전에 다니던 회사에서 개발한 솔루션에 사용한 UI 프레임워크인 JSF 를 처음 접하고 개발 및 유지보수를 하면서 국내에서 자료를 찾아보기 힘들었고 JSF 의 개념을 이해하는데 어려움을 느껴 혹시나 저처럼 JSF 에 대한 어려움을 느끼실 분들을 위해 제가 아는 선에서 정보들을 공유하고자 합니다.

이글을 시작으로 앞으로 공유하게될 정보들이 JSF 에 대해 많은 사람들이 한번 쯤은 경험해 보는 계기가 되었으면 좋겠습니다.


JSF (JavaServer Faces) 란?

JSF 는 JEE 의 일부로 JEE 표준이며 웹 어플리케이션을 위한 컴포넌트 기반의 UI 프레임워크 입니다.
JSF 의 초기 컨셉은 MS Visual 류의 UI 디자인에 대항하기 위한것과 마치 데스크탑 어플리케이션을 만드는것 처럼 웹 어플리케이션을 만들자는 생각에 만들어지게 되었습니다. Java Swing 으로 데스크탑용 프로그래밍을 할 때 버튼을 배치 하고 그 버튼의 이벤트 리스너를 통해 버튼의 동작을 제어 하는 방법처럼 말이죠. 하지만 몇몇 문제들로 인해 초기 컨셉을 유지하기는 조금 어려워 졌으며 초창기에 존재하던 디자인툴들은 대부분 간단한 UI 를 제외하면 사용하지 않게 된것 같습니다. 아직은 Oracle 의 jDeveloper 나 netbeans 에 디자인 툴이 포함이 되어있긴 하지만 실제 프로젝트를 진행하면서 복잡한 UI 를 구성할때 사용하기에는 큰 어려움이 있는 것은 사실입니다. 요즘은 MS 의 Visual 류도 디자인툴보다는 코드를 통해 UI 디자인 하는것으로 추세가 기울었다는 말을 어디선가 본것 같네요.
디자인과 관련된 초기 컨셉은 지금은 많이 부각되지 않고 있지만, 마치 데스크탑 어플리케이션 처럼 UI 를 만들고 핸들러를 연결하여 이벤트 처리를 하는 부분은 (Java Swing 을 생각하면 되겠네요) 여전히 JSF 의 주요 기술 중에 하나 입니다.

( JDeveloper UI 디자인 )

다만 웹이라는 특성상 데스크탑과는 다르게 각 컴포넌트들의 라이프 사이클이 복잡해지게 되고 초창기에는 AJAX 의 부재로 시대에 뒤떨어지는 프레임워크가 되었죠. 물론 Richfaces 와 Primefaces 를 개발한 분들이 그러한 문제점, 불편함을 보완하여 어느정도는 사용을 할 수 있게 된건 참 다행이긴 하지만요.
이부분은 JSF 2.0 부터 보완이 되었고 2.0 버전 이후부터는 많은 부분이 크게 개선 되어 나왔습니다. 하지만 여전히 조금씩의 문제가 있었기 때문에 많은 개선에도 불구하고 JSF 를 쓰는걸 꺼리는 사람이 많았습니다. 첫 시작을 잘못한 덕분에 JSF 는 별로 인기가 없는 프레임워크 이죠.

그나마 주변에서 쉽게 볼 수 있는것 으로는 WebLogic 의 Web 관리 콘솔과 Glassfish 의 Web 관리 콘솔입니다. 두가지 모두 JSF 를 이용하여 UI 를 구성하였습니다.

현재 JSF 는 Stable 버전이 2.2 이며 2.3 개발이 진행 중입니다.
JEE 에는 스펙(API) 만 포함되어 있으고 jdbc 드라이버 같이 서드파티 구현체가 여럿 존재하며 각각의 구현체들은 조금씩 다른 방법으로 사용이 됩니다.
JSF 의 구현체로는 가장 기본이 되는 Oracle 의 Mojarra 와 Apache 의 Myfaces, jboss 의 Richfaces, Primefaces 들이 있습니다.

<Primefaces UI>

<Richfaces UI>

<Myfaces UI>

모두 오픈소스로 공개 되어 있으며 개발이 활발하게 진행되고 있습니다.
각 구현체의 가장 큰 특징은 UI 의 모양이 각각 다르고 컴포넌트들을 컨트롤 하는 방법이 대동소이 하긴 하지만 조금씩 다른 부분이 존재합니다.
대부분 Java 의 어노테이션을 지원하며, xml 설정도 지원하고 Spring Framework 와 통합도 자연스럽습니다. JSP 와의 통합 및 tag 라이브러리를 그대로 사용할 수 있는것도 장점이라면 장점이지요.
그리고 미리 정의된 컴포넌트들을 JSF tag 를 이용하여 쉽게 작성 할 수도 있고 JSF 의 처음 디자인 컨셉인 MS Visual 류의 직관적인 UI 디자인을 할 수도 있다는것이 장점이 될 수 있습니다.

다만 JSF 의 컴포넌트 기반 특성과 미리 만들어진 컴포넌트를 사용해야 하고 컴포넌트에서 지원하지 않는 경우에는 커스텀 컴포넌트를 만들어 사용해야 하거나 기존 컴포넌트들을 확장하여 사용해야 하는데 이부분이 조금 번거롭거나 JSF 를 제대로 이해하지 못하면 사용하기 어렵고 국내에는 번역된 책이나 문서가 거의 전무하기에 국내 개발자가 접근하기는 많이 어려운 것이 현실입니다.

하지만 한번 익히게되면 나름 편하고 장점도 있는것 같습니다. 프레젠테이션과 컨트롤, 모델 부분의 경계가 확실하고 서버사이드 랜더링을 지원하기 때문에 클라이언트에 부담이 적다는것, 여러 편의기능을 제공하고 이벤트 처리가 직관적이라서 편리하다는것과 JSP 와 Spring Framework 와의 통합이 자연스러운점과 익숙해지면 빠르게 프로토타입을 만들어 볼 수 있다는것 미리 디자인된 UI 컴포넌트들 덕분에 디자인에 너무 신경쓰지 않아도 된다는게 개인적으로 좋은거 같습니다.

국내에서는 사용이 거의 전무 하지만 그래도 필요로 하는 분들이 계실꺼 같아 앞으로 계속 JSF 에 대해 제가 아는 선에서 공유를 하고자 합니다. 조금이나마 도움이 되는 분들이 계시기를...




'공부 > JSF' 카테고리의 다른 글

JavaServer Faces 버전 히스토리  (0) 2014.10.02
Facelets 소개  (0) 2014.10.02
JSF 기술의 이점  (0) 2014.10.02
JSF 어플리케이션이란 무엇일까요?  (0) 2014.10.01
JSF, JSP, Servlet 다른점  (0) 2014.09.22
Posted by #HanaLee
공부/java2014. 9. 6. 20:31

BufferedWriter 클래스에 대하여 간단한 예제를 통해 알아보려고 합니다.
BufferedWriter 클래스는 문자들을 버퍼링하여 문장, 배열, 단일 문자를 효율적으로 문자 출력 스트림(character output stream) 에 기록합니다. BufferedWriter 클래스는 문자 스트림에 기록하기 위해 추상 클래스인 Writer 를 상속하였습니다. 서브 클래스들은 반드시 write(char[] cbuf, int off, int len), flush(), close() 메소드를 구현해야 합니다. 대부분의 서브 클래스들은 더 높은 효율성, 기능의 추가, 혹은 양쪽 모두를 제공하기 위해 일부 메소드들을 오버라이드 (override) 하기도 합니다.

BufferedWriter 클래스는 JDK 1.1 부터 존재했습니다.

BufferedWriter 의 생성자 구조

기본 크기를 가지는 출력 버퍼로 버퍼링 된 문자형 출력 스트림 (character output stream) 객체를 만듭니다.

매개변수로 주어진 크기를 가지는 출력 버퍼로 버퍼링된 문자형 출력 스트림 객체를 만듭니다.

BufferedWriter 의 기본 예제

BufferedWriter 클래스가 어떻게 파일에 문자를 기록하는지 살펴 보겠습니다.

package kr.co.leehana.example.bufferedwriter;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class SimpleBufferedWriterExample1 {

	public static void main(String[] args) {
		String greetings = "Hello!!!";
		String description = "I am written into a file";

		BufferedWriter writer = null;

		try {
			writer = new BufferedWriter(new FileWriter(new File("output.txt")));
			writer.write(greetings);
			writer.newLine();
			writer.write(description);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (writer != null) {
				try {
					writer.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

BufferedWriter 는 매개변수로 Writer 클래스를 가지고 오고 예제에서는 Writer 추상 클래스를 상속한 OutputStreamWriter 의 서브클래스인 FileWriter 클래스를 사용하였습니다. 중간에 writer.newLine() 메소드를 사용하였는데 이는 플랫폼 (Mac, Linux, Windows) 의 시스템 환경변수에 등록된 line.separator 를 사용하여 호환성을 높였습니다. 여기에서 중요한 것은 마지막에 호출된 close() 메소드 입니다. 항상 기억해야 할것은 파일에 쓰기가 완료되면 close() 메소드를 반드시 호출 해줘야 한다는 것입니다.
생성된 파일을 열어보면 위에서 입력한 두줄의 텍스트가 있는것을 확인 할 수 있을 것입니다.

BufferedWriter 의 또 다른 예제

BufferedWriterflush() 메소드를 사용하는 Logger 클래스를 만들어서 log 파일을 생성하는 예제 입니다.

package kr.co.leehana.example.bufferedwriter;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;

public class Logger {
	private BufferedWriter writer;

	public Logger(String filename) throws IOException {
		this.writer = new BufferedWriter(new FileWriter(new File(filename)));
	}

	public Logger(File logFile) throws IOException {
		this.writer = new BufferedWriter(new FileWriter(logFile));
	}

	public void log(String s) throws IOException {
		String date = new Date().toString();
		this.writer.write(date + " : " + s);
		this.writer.newLine();
		this.writer.flush();
	}

	public void close() throws IOException {
		this.writer.close();
	}
}


위 Logger 클래스를 테스트 하는 예제 코드 입니다.

package kr.co.leehana.example.bufferedwriter;

import java.io.IOException;

public class SimpleBufferedWriterExample2 {

	public static void main(String[] args) {
		Logger logger = null;
		try {
			logger = new Logger("log.txt");
			logger.log("Test 1");
			logger.log("Test 2");
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (logger != null) {
				try {
					logger.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

출력된 log 파일을 열어보면 하나의 로그 파일에 두줄의 로그가 기록된것을 확인 할 수 있을 것입니다.

BufferedWriter 클래스에 대한 추가 정보

BufferedWriter 클래스를 다음과 같이 생성함으로써 출력 스트림에 쓸 수도 있습니다.
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

BufferedWriter 클래스는 직접 출력 스트림 (output stream) 에 쓰지 않습니다. 사실 BufferedWriter 클래스는 더 나은 성능을 위해 스트림에 기록되는 버퍼 입니다. 기억해야 할만한것으로는 생성자의 매개변수로 버퍼의 크기를 지정할 수 있다는것과 지정하지 않으면 기본 크기를 가지는 버퍼를 사용한다는 것입니다. close() 메소드가 호출되면 버퍼가 기록되는것이 아니고 스트림에 기록됩니다. 이를 확인 하기 위해서 close() 메소드를 주석처리해서 실행 해보면 파일에 아무것도 기록되지 않은것을 확인 할 수 있습니다.

만약 스트림을 닫지 않고 버퍼를 파일에 계속 쓰고 싶으면 flush() 메소드를 사용하면 됩니다. close() 메소드가 호출된 후 write() 메소드나 flush() 메소드를 호출 하게 되면 IOException 이 발생합니다.

마지막으로 모든 메소드는 IOException 이 발생 할 수 있으니 try catch 문을 이용해야 합니다.




소스코드

출처


'공부 > java' 카테고리의 다른 글

java.lang.System 예제  (0) 2014.09.22
Java BufferedOutputStream 예제  (0) 2014.09.22
Java List 를 배열로 변환 하는 예제  (0) 2014.09.05
Java FileWriter 예제  (0) 2014.09.05
RejectedExecutionException 해결 방법 알아보기  (0) 2014.09.03
Posted by #HanaLee
공부/java2014. 9. 5. 12:46

java 에서 많이 사용하는 java.util.List 객체를 일반 배열로 변환 하는 방법에 대한 예제 입니다.
java.util.List 에는 이를 위해 두가지의 메소드가 존재 합니다.

이 두가지 메소드들은 적절한 순서로 java.util.List 에 담겨 있는 모든 요소를 포함하는 배열을 반환합니다.
두 메소드의 시그네쳐에서 확인 할 수 있듯이 두 메소드의 차이는 첫번째는 런타임에 지정된 (T[]) 배열을 반환하고, 두번째는 Object[] 유형의 배열을 반환 한다는 것입니다.
두가지 모두의 예를 한번 살펴 보겠습니다.

먼저 두개의 예제에서 공통으로 사용할 User 클래스를 만들겠습니다.

User 클래스

package kr.co.leehana.example.listtoarray;

public class User {
	private String name;
	private int age;

	public User(String name, int age) {
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return this.name;
	}

	public int getAge() {
		return this.age;
	}
}

T[] toArray(T[] a) 예제

package kr.co.leehana.example.listtoarray;

import java.util.ArrayList;
import java.util.List;

public class ListToArrayExampleWithArgument {

	public static void main(String[] args) {
		runExample();
		runExample2();
	}

	private static void runExample() {
		List<String> strList = new ArrayList<String>();
		strList.add("One");
		strList.add("Two");
		strList.add("Three");

		String[] strArray = strList.toArray(new String[strList.size()]);

		for (int i = 0; i < strArray.length; i++) {
			System.out.println("output : " + strArray[i]);
		}
	}

	private static void runExample2() {
		List<User> userList = new ArrayList<User>();
		userList.add(new User("Hana Lee", 37));
		userList.add(new User("Gildong Hong", 41));

		User[] userArray = userList.toArray(new User[userList.size()]);

		for (int i = 0; i < userArray.length; i++) {
			System.out.println("User name : " + userArray[i].getName());
			System.out.println("User age : " + userArray[i].getAge());
		}
	}
}

위의 예제에서는 cast 를 하지 않았다는것을 확인 하세요. 반환되는 형식이 바로 매개변수로 넘긴 형식이 됩니다. 이 방법은 cast 를 줄이고 런타임에 반환되는 배열의 형태를 결정 할 때 사용될 수 있습니다.

Object[] toArray() 예제

package kr.co.leehana.example.listtoarray;

import java.util.ArrayList;
import java.util.List;

public class ListToArrayExampleWithNoneArgument {

	public static void main(String[] args) {
		runExample();
		runExample2();
	}

	private static void runExample() {
		List<String> strList = new ArrayList<String>();
		strList.add("One");
		strList.add("Two");
		strList.add("Three");

		Object[] objArray = strList.toArray();

		for (int i = 0; i < objArray.length; i++) {
			System.out.println("output : " + objArray[i].toString());
		}
	}

	private static void runExample2() {
		List<User> userList = new ArrayList<User>();
		userList.add(new User("Hana Lee", 37));
		userList.add(new User("Gildong Hong", 41));

		Object[] objArray = userList.toArray();

		for (int i = 0; i < objArray.length; i++) {
			User user = (User) objArray[i];
			System.out.println("User name : " + user.getName());
			System.out.println("User age : " + user.getAge());
		}
	}
}

위의 예제는 반환된 Object[] 배열을 String[] 으로 바로 변환 할 수 없기 때문에 Object[] 배열로 부터 요소를 꺼낸뒤 toString 메소드를 호출 해줍니다. 물론 그냥 String 이기 때문에 직접 호출 한다고 해도 큰 문제는 없습니다.

그리고 두번째 User 객체를 이용하여 출력 하는 메소드에서는 출력을 위해 User 객체로 cast 를 해야 한다는것을 확인하세요.




소스 코드

출처


'공부 > java' 카테고리의 다른 글

Java BufferedOutputStream 예제  (0) 2014.09.22
Java BufferedWriter 예제  (0) 2014.09.06
Java FileWriter 예제  (0) 2014.09.05
RejectedExecutionException 해결 방법 알아보기  (0) 2014.09.03
예외  (0) 2014.06.20
Posted by #HanaLee