2015. 2. 20. 14:04


0. 컴퓨터 시스템

1. API (Application Programming Interface)

2. 라이브러리 (Library)

3. API vs. Library

4. 프레임워크 (Frameworks)

5. 통합개발환경(IDE : Integred Development Environment)

6. 지속적인 통합 (continuous integration)

7. 소셜 코드 공유

.... and more

Posted by 곽중선
2015. 2. 20. 14:01



  • 소프트웨어 기술 요소
  • 학사 커리큘럼에서 익힐 수 있는 것들
  • 전공 필수와 선택, 우선 순위는?
  • 소프트웨어 개발자 직무의 다양성과 변화
  • 소프트웨어 개발자 직무별 필수 기술 요소
  • 직무 유형별 필수 기술 정리
  • 학생으로서 공부해야 할 것들


Posted by 곽중선
2015. 2. 11. 00:11

각설하고, 완성된 사칙연산 계산기 프로그램입니다.



FourArithExprParser.java


FourArithExprProcessor.java



import java.util.Scanner;

/**
 * 사칙 연산 계산기.
 * 
 * - 사칙 연산 수식을 입력 받고,
 * - 해석한 후,
 * - 계산 결과를 출력한다.
 * 
 * @author sunnyk
 */
public class FourArithExprProcessor {

	public static void main(String args[]) {
		// 스캐너 열기
		Scanner scanner = new Scanner(System.in);

		// 사칙연산 수식 입력
		System.out.print("Input expression : ");
		String mathExpression = scanner.nextLine();

		// 빈 문장을 입력한 경우, 오류 메시지 출력
		if (mathExpression.trim().isEmpty()) {
			System.out
					.println("You entered empty expression, so do nothing and quit!");
		} 
		// "test"를 입력하면, 사칙연산 테스트 실시...
		else if ("test".equals(mathExpression)) {
			runParser("A + B becomes A B +", "10 + 2");
			runParser("A / B becomes A B /", "15 / 2");
			runParser("A * B + C becomes A B * C +", "76 * 32 + 2");
			runParser("A + B * C becomes A B C * +", "64 + 39 * 4");
			runParser("A * (B + C) becomes A B C + *", "31 * (61 + 2)");
			runParser("A * (B + C * D) + E becomes A B C D * + * E +",
					"1 * (2 + 3 * 4) + 2");
		}
		// 수식이 입력된 경우 해석...
		else {
			System.out.format(
					"Entered four arithmetic operation (expression) is '%s'\n",
					mathExpression);
			runParser("", mathExpression);
		}

		// 스캐너 닫기
		scanner.close();
	}

	/*
	 * 사칙연산 수식을 계산하고, 결과를 출력한다.
	 * 
	 * @param msg 안내 메시지
	 * @param expr 입력 수식
	 */
	private static void runParser(String msg, String expr) {
		
		if(msg == null || !msg.isEmpty()) {
			System.out.println("Run : " + msg);
		}
		
		FourArithExprParser parser = new FourArithExprParser(expr);

		// parse four arithmetic expression as infix.
		System.out.print("Infix expression : ");
		parser.parseSymbols(); 
		parser.print();

		// convert infix expression to postfix.
		System.out.print("Postfix expression : ");
		parser.toPostfix(); 
		parser.print();
		
		// calculate expression
		int result = parser.calcalate();
		System.out.println("Caculcation result = " + result);
		System.out.println();
	}

}
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 사칙 연산 수식 해석 (parse four arithmetic expression)
 * 
 * @author sunnyk
 *
 */
public class FourArithExprParser {

	// 사칙연산자 목록
	private static char[] OPERATORS = { '+', '-', '*', '/' };
	// 좌/우 괄호
	private static char[] PARENTHESISES = { '(', ')' };
	private String numberBuffer;
	private String inputExpr;
	private List<String> symbols = new ArrayList<String>();
	private Stack<String> aStack = new Stack<String>();
	
	/**
     * 생성자에 중위식 사칙연산 수식을 입력.
	 */
	public FourArithExprParser(String expression) {
		this.inputExpr = expression;
	}

	/**
	 * 중위식 사칙연산 수식에서 항목(symbol)들을 추출한다.
	 */
	public void parseSymbols() {

		// 문자(character) 단위로 분석..
		for (int idx = 0; idx < inputExpr.length(); idx++) {
			char charInExpr = inputExpr.charAt(idx);

			// 공백(whitespace) 문자 - linefeed, space, tab 등-이면, 이전 버퍼의 내용을 비움.
			if (Character.isWhitespace(charInExpr)) {
				handleTempBuff();
			}

			// 사칙연산 연산자 혹은 괄호인 경우, 항목 추가.
			else if (isMathOperatorOrParenthesis(charInExpr)) {
				handleTempBuff();
				symbols.add(String.valueOf(charInExpr));
			}

			// 숫자 문자인 경우, 숫자 버퍼에 추가..
			else if (Character.isDigit(charInExpr)) {
				if (numberBuffer == null) {
					numberBuffer = String.valueOf(charInExpr);
				} else {
					numberBuffer += charInExpr;
				}
			}
		}
		
		handleTempBuff();
	}

	/**
	 * 중위식을 후위식으로 변환.
	 */
	public void toPostfix() {
		List postfixExpr = new ArrayList();
		
		// 중위식 표현식의 각 항목에 대해서...
		for(String symbol : symbols) {
			
			char firstCharOfColumn = symbol.charAt(0);
			
			// 피연산자이면, 피연산자를 후위식에 추가
			if(!isMathOperatorOrParenthesis(firstCharOfColumn)) {
				postfixExpr.add(symbol);
			}
			// 좌괄호이면 스택에 추가
			else if('(' == firstCharOfColumn) {
				aStack.push(symbol);
			}
			// 우괄호이면, 좌괄호 '('가 나올 때까지 스택에서 꺼냄.
			else if(')' == firstCharOfColumn) {
				
				// 스택의 최상위 값이 좌괄호 '('가 아니면..
				while (!"(".equals(aStack.peek())) {
					postfixExpr.add(aStack.pop());
				} // while의 끝
				
				// 좌괄호'(' 제거
				aStack.pop();
			}
			// 연산자이면, 스택에 있는 더 높은 우선순위 연산자 처리
			else {
				// 만약, 스택이 비어 있거나, 스택의 최상위에 좌괄호가 들어 있으면, 연산자를 스택에 추가
				if(aStack.isEmpty() || "(".equals(aStack.peek())) {
					aStack.push(symbol);
				}
				// 연산자의 우선순위가 스택의 최상위에 있는 연산자보다 높으면 스택에 추가
				else if(priority(symbol) > priority(aStack.peek())) {
					aStack.push(symbol);
				}
				// 연산자의 우선순위가 스택의 최상위에 있는 연산자와 같으면, 연관에 따라 처리..
				// (좌측에서 우측으로 연산하는 경우, 스택의 최상위 연산자를 꺼내고, 연산자를 스택에 추가)
				else if(priority(symbol) == priority(aStack.peek())) {
					postfixExpr.add(aStack.pop());
					aStack.push(symbol);
				}
				// 새로운 연산자의 우선순위가 스택의 최상위에 있는 연산자보다 낮으면,
				// 스택의 최상위 연산자를 꺼내고, 새로운 연산자를 스택에 추가
				else {
					while(!aStack.isEmpty() && priority(symbol) <= priority(aStack.peek())) {
						postfixExpr.add(aStack.pop());
					}
					aStack.push(symbol);
				}
			}
		}

		// 후위식에 스택에 남은 연산자들을 추가
		while(!aStack.isEmpty()) {
			postfixExpr.add(aStack.pop());
		} // while의 끝
		
		// 중위식을 후위식으로 덮어쓰기...
		symbols = postfixExpr;
	}

	/**
	 * 후위식 계산을 수행하고 결과 값을 반환한다.
	 */
	public int calcalate() {
		
		// 후위식 기호(symbol)들을 순차적으로 처리한다.
		for(String symbol : symbols) {
			char firstChOfSymbol = symbol.charAt(0);
			
			// 사칙연산 연산자인 경우...
			if(isOperator(firstChOfSymbol)) {

				// 피연산자(operand)를 스택에서 꺼낸다.
				// (순서가 반대로 저장되어 있음을 주의할 것)
				int secondOperand = Integer.valueOf(aStack.pop());
				int firstOperand = Integer.valueOf(aStack.pop());

				// 연산자의 유형에 따라 계산을 수행한다.
				int result = 0;
				switch(firstChOfSymbol) {
					case '+':
						result = firstOperand + secondOperand;
						break;
					case '-':
						result = firstOperand - secondOperand;
						break;
					case '*':
						result = firstOperand * secondOperand;
						break;
					case '/':
						result = firstOperand / secondOperand;
						break;
				}
				// 연산 결과를 다시 스택에 담는다.
				aStack.push(String.valueOf(result));
			} 
			// 피연산자인 경우에는 스택에 무조건 담는다.
			else {
				aStack.push(symbol);
			}
		}
		
		// 모든 처리가 끝나면, 결과 값이 스택에 남아 있다.
		return Integer.valueOf(aStack.pop());
	}

	/**
     * 수식 분석 결과를 화면에 출력.
	 */
	public void print() {
		for (String symbol : symbols) {
			System.out.print(symbol + " ");
		}
		System.out.println();
	}

	/* 
	 * 새로운 항목(symbol)을 찾은 경우, 임시 버퍼의 내용을 항목 목록에 추가
	 */
	private void handleTempBuff() {
		if (numberBuffer != null) {
			symbols.add(numberBuffer);
			numberBuffer = null;
		}
	}

	/*
     * 연산자 혹은 괄호인지 검사.
	 */
	private boolean isMathOperatorOrParenthesis(char inputChar) {
		for (char op : OPERATORS) {
			if (inputChar == op) {
				return true;
			}
		}
		for(char brace : PARENTHESISES) {
			if (inputChar == brace) {
				return true;
			}
		}
		return false;
	}
	
	/*
	 * 연산자 인지 검사. 
	 */
	private boolean isOperator(char inputChar) {
		for (char op : OPERATORS) {
			if (inputChar == op) {
				return true;
			}
		}
		return false;
	}


	/*
	 * 연산자의 우선순위(priority)를 반환한다.
	 */
	private int priority(String symbol) {
		int priority = 0;
		switch(symbol){
		case "*":
		case "/":
			priority = 2;
			break;
		case "+":
		case "-":
			priority = 1;
		}
		
		return priority;
	}

}


Posted by 곽중선
2015. 2. 1. 13:37

수식 입력 처리는 간단한 문제 같지만, 기초적인 원리와 기법을 이해하는데 있어서 중요한 과정입니다. 사칙연산 수식을 콘솔(console)에서 입력 받아 연산자와 피연산자로 분리하는 문제를 아래와 같이 자바로 코딩한 사례를 보여드리고 무엇이 문제인지 설명해보겠습니다.
import java.util.Scanner;

public class Operation {

	public static void main(String args[]) {
		// 스캐너 열기
		Scanner sc = new Scanner(System.in);
		String imsi = new String();
		int countOp = 0;
		char imsiOp = 0;

		do {
			System.out.print("Enter expression : ");
			imsi = sc.nextLine();
		} while (imsi.charAt(0) == '0');

		int size = imsi.length() + 1;
		char expr[] = new char[size];
		int num[] = new int[size];
		char op[] = new char[size];

		for (int i = 0; i < imsi.length(); i++) {
			expr[i] = imsi.charAt(i);
		}

		for (int i = 0; i < imsi.length(); i++) {
			for (int j = 0; j < imsi.length(); j++) {
				if (expr[j] >= 48 && expr[j] <= 57) {
					num[i] = (int) expr[j] - 48;
					if (expr[j + 1] > 48 && expr[j + 1] <= 57)
						num[i] = num[i] * 10 + ((int) expr[j] - 48);
				} else if (expr[j] == '*' && expr[j] == '/' && expr[j] == '+'
						&& expr[j] == '-') {
					op[i] = expr[j];
					countOp++;
				} else if (expr[j] == 0)
					break;
			}
		}

		for (int i = 0; i <= countOp; i++) {
			if (op[i] == '*' || op[i] == '/')
				System.out.printf("%d %c %d", num[i], op[i], num[i + 1]);
			else if (op[i] == '+' || op[i] == '-')
				if (op[i + 1] == '*' || op[i + 1] == '/')
					imsiOp = op[i];
			op[i] = op[i + 1];
			op[i + 1] = imsiOp;
		}

		// 스캐너 닫기
		sc.close();
	}

}


자바의 Scanner 클래스는 입력 스트림(input stream)에서 텍스트를 읽어들이는 기능들을 제공합니다. sc.nextLine() 메소드를 호출하면, 사용자가 콘솔에서 텍스트를 입력하고 엔터(enter key)를 누를 때까지 기다린 다음... 줄바꿈 문자(line feed)를 제외한 문자열을 반환합니다. 아래 코드에서는 안내 문구를 출력한 후에 사용자의 입력을 받아들이고, 입력 받은 문자열의 첫번째 문자가 '0' 가 아니면 계속 반복 입력 받게 됩니다. 안내 문구인 'Enter expressiion : ' 을 봐서는 첫번째 문자를 '0'으로 입력해야 한다는 것을 알 수 없으므로, 부정확한 - 혹은 잘못된 UX (User eXperience, 사용자 경험)입니다.


		do {
			System.out.print("Enter expression : ");
			imsi = sc.nextLine();
		} while (imsi.charAt(0) == '0');


더욱 더 잘못된 것은 입력을 받은 후의 수식 해석입니다.  ASCII 코드 테이블에서 48 부터 57 코드 값은 '숫자'에 해당하는 문자입니다만, 자바의 문자(character) 타입은 2 byte 크기이며, UNICODE-16 코드 체계를 사용합니다. 즉, ASCII 코드 값으로 비교하면 안되는 것입니다.

		if (expr[j] >= 48 && expr[j] <= 57) {
			num[i] = (int) expr[j] - 48;
			if (expr[j + 1] > 48 && expr[j + 1] <= 57)
				num[i] = num[i] * 10 + ((int) expr[j] - 48);
		}


2진수 기반의 컴퓨터 동작원리를 익혀야 하는 이유가 바로 이 점입니다. 하나의 문자를 표현하는 방법도 컴퓨터 내에서는 다양한 방법이 사용됩니다.


제가 작성한 수식 해석 프로그램 예시는 아래와 같습니다.


import java.util.Scanner;

/**
 * 
 * 사칙 연산 계산기.
 * 
 * - 사칙 연산 수식을 입력 받고,
 * - 해석한 후,
 * - 계산 결과를 출력한다.
 * 
* * @author sunnyk */ public class FourArithExprProcessor { public static void main(String args[]) { // 스캐너 열기 Scanner scanner = new Scanner(System.in); // 사칙연산 수식 입력 System.out.print("Input expression : "); String mathExpression = scanner.nextLine(); // 빈 문장을 입력한 경우, 오류 메시지 출력 if (mathExpression.trim().isEmpty()) { System.out .println("You entered empty expression, so do nothing and quit!"); } // 수식이 입력된 경우 해석... else { System.out.format( "Entered four arithmetic operation (expression) is '%s'\n", mathExpression); // 입력된 수식을 해석하는 파서(parser) 생성 FourArithExprParser parser = new FourArithExprParser(mathExpression); // 입력된 사칙연산 수식 해석 parser.parse(); // 수식 해석 결과 출력 parser.print(); } // 스캐너 닫기 scanner.close(); } }
import java.util.ArrayList;
import java.util.List;

/**
 * 사칙 연산 수식 해석 (parse four arithmetic expression)
 * 
 * @author sunnyk
 *
 */
public class FourArithExprParser {

	// 연산자 종류
	private static char[] OPERATORS = { '+', '-', '*', '/' };

	// 입력 수식
	private String inputExpr;

	// 수치 입력을 위한 임시 버퍼 (temporary buffer for input number)
	private String numberBuffer;

	// 입력된 연산자와 비연산자 목록 (분석 결과 리스트)
	private List <string> columns = new ArrayList<string>();

	/**
	 * 생성자, 사칙연산 문자열을 입력 받는다.
	 * 
	 * @param expression
	 *            사칙연산 문자열
	 */
	public FourArithExprParser(String expression) {
		this.inputExpr = expression;
	}

	/**
	 * 사칙 연산 문자열을 해석해, 연산자(operator)와 피연산자(operand)를 구분한다.
	 */
	public void parse() {

		// 입력 수식 문자열의 처음부터 마지막 문자까지 scan 한다.
		for (int idx = 0; idx < inputExpr.length(); idx++) {
			char charInExpr = inputExpr.charAt(idx);

			// 공백 문자이면, 무시(skip)
			// 공백 문자(white space char)는 space, tab, enter character 등 다양함.
			if (Character.isWhitespace(charInExpr)) {
				
				// 공백 이전에 입력된 수치 문자열을 분석 결과 리스트에 추가..
				handleTempBuff();
			}
			// 사칙 연산자이면, 연산자 항목에 추가
			else if (isMathOperator(charInExpr)) {
				columns.add(String.valueOf(charInExpr));
			}
			// 숫자이면, 임시 버퍼에 추가.
			else if (Character.isDigit(charInExpr)) {
				if(numberBuffer == null) {
					numberBuffer = String.valueOf(charInExpr);
				} else {
					numberBuffer += charInExpr;
				}
			}
		}

		// 마지막으로 버퍼에 남은 수치 값이 있으면, 분석 결과 리스트에 추가
		handleTempBuff();
	}

	/**
	 * 입력 문자가 사칙 연산자인지 검사
	 * 
	 * @param inputChar
	 *            입력 문자
	 * @return 사칙연산자 중에 하나이면 true, 아니면 false 반환
	 */
	private boolean isMathOperator(char inputChar) {
		for (char op : OPERATORS) {
			if (inputChar == op) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 수식 해석 중, 연산자 혹은 공백이 발견된 경우, 
	 * 이전에 임시 버퍼에 남겨둔 숫자 값을 입력 항목 목록에 추가.
	 */
	private void handleTempBuff() {
		if (numberBuffer != null) {
			columns.add(numberBuffer);
			numberBuffer = null;
		}
	}

	/**
	 * 수식 해석 결과를 출력한다.
	 */
	public void print() {
		// 입력된 수식의 전체 항(column)의 갯수를 출력한다.
		System.out.println("Number of columns in expression : " + columns.size());
		
		for(int idx=0; idx < columns.size(); idx++) {
			System.out.format( (idx+1) + "'th columns is '" + columns.get(idx) + "'\n");
		}
	}

}


Posted by 곽중선
2014. 11. 25. 14:16

NoORM의 디자인과 컨셉은 오라클의 의존하지 않지만, 스토어드 프로시져(stored procedue)  사용하는데 있어서는 데이터베이스 세계의 공통 표준이 부족하기 때문에 오라클에 종속될 수 밖에 없습니다. NoORM 은 오라클 데이터베이스 10gR2 혹은 상위 비전을 지원하며, 오라클 익스프레스 에디션을 포함한 모든 에디션을 지원합니다.


Though design and concept of NoORM do not depend on Oracle, the usage of stored procedures, which still lack a common standard in the database world, currently requires the usage of Oracle. NoORM supports Oracle database 10gR2 or higher. All editions are supported, including Oracle Express Edition.


NoORM은 Java 6 혹은 상위 버전을 필요로 합니다.


NoORM requires Java 6 or higher.


NoORM은 두개의 파트로 구성되어 있습니다. 코드 생성기(code generator)와 런타임 라이브러리(runtime library)입니다.  코드 생성기는 어플리케이션 개발 단계에서 필요하며, 런타임 라이브러리는 개발 및 어플리케이션 실행 과정에서 모두 필요합니다. NoORM 코드 생성기 없이 어플리케이션을 개발할 수 있지만 권장하지는 않습니다. 개발 생산성 향상은 코드 생성기 활용으로 인해 야기됩니다.


NoORM comes with two parts: the code generators and the runtime library. The code generators are required for application development, the runtime library is required for both, development and your applications runtime. Though you can develop applications without the NoORM code generators, this approach is not recommended. The improvement of development productivity is primarily caused by the usage of the code generators.


코드 생성기는 아파치 벨로시티(Apache Velocity)를 사용합니다. 코드 생성기는 다양한 옵션을 제공합니다. 고유한 환경 설정 메커니즘으로 인해 코드 생성기의 강점을 가려지지 않게끔, 코드 생성기는 환경설정을 위한 커스텀 XML 스키마를 포함한 메이븐(Maven) 플러그인 형태로 만들어져 있습니다. Maven 3 사용을 권장하지만, Maven 2 역시 지원합니다.


The code generators use Apache Velocity. Various configuration options are available for the code generators. To exploit the power of the code generators without the need for a new proprietary configuration mechanism, the code generators are wrapped into a Maven plugin using a custom XML schema for the configuration. We recommend the usage of Maven 3, though Maven 2 is also supported.


NoORM을 사용하기 위해서는 이어지는 자바 라이브러리들이 필요합니다. (코드 생성기 포함) Oracle JDBC 는 법적인 이유로 공개 메이븐 저장소에서 제공하지 않기 때문에 제공되지 않지만 나머지 의존성은 메이븐에 의해 자동으로 검색(resolve)됩니다.


The following Java libraries are required to use NoORM (including the code generators). Except for the Oracle JDBC driver, which is not provided by a public Maven repository for legal reasons, all other dependencies can be resolved automatically using Maven:


Oracle JDBC Driver (NoORM has been tested with all available Versions of the Oracle 10.2g, 11g and 12c series, note that for Oracle 12c you may have to add Oracle XML libraries to your classpath)

Velocity 1.7

SLF4J API 1.7.5

Logback Classic 1.0.13 (or any other logging library with support for SLF4J like log4j)


NoORM은 두개의 내장 PL/SQL 패키지를 포함합니다. NOORM_METADATA 패키지는 자바 코드 생성기를 위해 필요하며, 자동 클래스 검증(Automatic Class Validation) 기능을 런타임 시에 사용하고자 한다면 런타임 환경에서도 필요합니다. DYNAMIC_SQL 패키지는 런타임 시에 동적인 SQL 생성을 지원하기 위해 제공됩니다. 패키지들과 패키지에 필요한 부가적인 데이터베이스 요소들이 운영 중인 오라클 데이터베이스 스키마에 설치되어야 합니다. Maven SQL 플러그인을 사용하면 NoORM 데이터베이스 요소들과 어플리케이션 고유의 데이터베이스 객체에 대한 생성과 운영을 메이븐 빌드에 통합할 수 있기에 추천합니다. SQL 빌드 통합 섹션을 참조하면 좀 더 자세한 정보를 얻을 수 있습니다.


NoORM comes with two internal PL/SQL packages: package NOORM_METADATA is required by the Java code generator and, if you make use of the Automatic Class Validation feature, it is required at runtime, too. Package DYNAMIC_SQL provides support for Dynamic SQL generation at runtime. The packages and additional database objects required by these packages must be installed into your working Oracle database schema. It is recommended to use the Maven SQL Plugin to integrate the creation and maintenance of NoORM database objects and your own database objects with your Maven build. Refer to section SQL Build Integration for more information.

 

NoORM PL/SQL 패키지와 관련된 데이터베이스 요소들을 생성하는 필요한 SQL 스크립트들은 NoORM 런타임 라이브러리에 포함되어 있습니다. (JAR 파일 내의 /plsql 폴더)

 

The SQL scripts required to install the NoORM PL/SQL packages and associated database objects are bundled with the NoORM runtime library (under /plsql in the JAR-file)


샘플 스키마 

Sample Schema


이어지는 퀵스타트(quick start) 튜터리얼은 잘 알려진 오라클 샘플 스키마인 HR (인사 정보 : Human Resources)에 기초한 것입니다. 일부 오라클 에디션들은 사전 설치된 데이터베이스에 이 스키마를 포함하고 있습니다. (예를 들면, 오라클 익스프레스 에디션)  만일, 데이터베이스 설치에 HR 스키마가 포함되어 있지 않다면, 오라클 샘플 스키마 온라인 문서를 참조하기 바랍니다. 해당 도큐먼트에는 스키마 다이어그램과 샘플 스키마들에 대한 설명이 포함되어 있습니다.


The following quick-start tutorial is based on the well-known Oracle sample schema HR ("human resources"). Some Oracle editions contain this schema in the pre-installed database (e.g. Oracle Express Edition). If schema HR is not available with your database installation, refer to the Oracle Sample Schemas Online Documentation for more information about the sample schemas. The referred document also contains schema diagrams and explanations about the meaning of the sample schemas (Note that you may have to unlock the account prior to accessing it).


설정되어 있는 코드 생성기


Configuring the Code Generator


제대로 설정된 코드 생성기가 준비되어 있다면, 작업할 준비가 거의 된 것입니다. 그러나, 코드 생성기 설정을 시작하기에 앞서, 데이터베이스 객체들과 그에 상응하는 코드 생성에 관련된 자바 클래스들에 대해 빠르게 살펴 볼 필요가 있습니다.


With properly configured code generators, you are already close to code ready for operation. But before we start with the configuration of the code generators, we should have a quick look at the database objects and their corresponding Java class types, which are subject to code generation:


자바 빈(java bean)은 데이터베이스 테이블 혹은 뷰(view)를 표현합니다 : 데이터베이스 데이터를 자바 어플리케이션에서 사용하기 위해서는 데이터베이스 테이블 및 뷰에 포함된 데이터를 표현하는 클래스 명세가 필요합니다. NoORM은 테이블이나 뷰를 표현하는 자바 빈들을 생성합니다.


Java Beans representing database tables or views: To utilize database data in your Java application, we need a class specification to represent the data contained in database tables or views. NoORM generates Java Beans for tables or views of your choice for this purpose.


자바 열거형(Enums) 은 컨텐츠를 포함하는 데이터베이스 테이블들을 표현합니다 : 일부 테이블들은 어플리케이션 라이플 사이클의 단일 사이클에서 변하지 않는 데이터를 가지고 있습니다. 예를 들자면, 사전 부류의 컨텐츠(성별, 주문 유형, 상품 유형 등)를 포함한 테이블을 가지고 제3의 양식을 채우는 업무를 구현하는 것일 수도 있습니다.  이런 데이터 유형은 일반적으로 어플리케이션의 기능에 가깝고, 어플리케이션 기능이 수정될 때 값이 변경됩니다. 따라서, 테이블 컨텐츠를 자바 Enum 타입을 이용해 자바 어플리케이션 코드에 고정(hard-wiring)하는 것이 가능합니다. 보다 자세한 정보는 자바 Enums 생성 섹션을 참고하기 바랍니다.


Java Enums representing database tables including content: Some tables may contain data which does not change within one cycle of your application life-cycle (e.g. release). For instance, you may have a table with some dictionary-like content to fulfil requirements to the third normal form in your database model like gender, order types, product types, etc. Data of this kind is typically closely tied to the functionality of your application and does only change when your application is modified. Thus it is possible to hard-wire the tables content into your application using a Java Enum. Refer to section Generating Java Enums for more information.


PL/SQL 코드를 감싼 자바 서비스 혹은 DAO(Data Access Object) : NoORM는 PL/SQL 프로시져에 내장된 SQL 쿼리들을 지원합니다. 오라클 REF CURSOR 타입을 이용해 저장 프로시져에서 JDBC ResultSet을 반환하는 것도 가능합니다. 자바 코드 생성기는 PL/SQL 패키지들을 분석하고 상응하는 API 자바 클래스를 생성합니다. 또한 SQL 쿼리에서 참조하는 테이블들에 상응하는 자바 빈들도 생성합니다.


Java Services or Data Access Objects wrapping PL/SQL code: NoORM supports SQL queries embedded into a PL/SQL procedure, resp. PL/SQL package. By utilizing the Oracle type REF CURSOR it is possible to return a JDBC ResultSet from a stored procedure. The Java code generator analyzes your PL/SQL packages and creates a corresponding Java class providing the API of the package under consideration of the Java Beans generated for the entities addressed in the SQL queries. Whether you denote the generated Java classes as service or as DAO (Data Access Object) depends on the semantically richness of the PL/SQL and is up to your development team. Refer to section PL/SQL is easy for more information.


단순하고 전형적인 쿼리 : 대다수의 SQL 문들은 단순한 형태를 띄게 마련입니다. FROM 절에 하나의 테이블을 사용하고, WHERE 조건에 AND로 연결된 조건들을 선언하는 것입니다. 이러한 SQL 문을 위해 PL/SQL 패키지를 선언하는 것은 부담이 될 수 있습니다. NoORM 은 단순한 쿼리를 설정할 수 있는 옵션을 제공함으로써 간편한 개발 절차를 제공합니다.


Declared Queries for canonical trivial SQL statements: Most SQL statements are rather trivial, using a single entity in the FROM-clause and using WHERE-conditions combined by an AND. For these statements even the implementation of PL/SQL packages can be a burden. NoORM provides configuration options to declare simple queries, which simplifies the development process significantly.



The very first step for the Maven configuration is the plugin configuration. The NoORM generator plugin requires the database connection parameters as mandatory parameters. All application specific parameters are specified in a separate XML file (One can specify a location for the NoORM configuration file, the default location is src/noorm/configuration.xml).

 

We start with a code generator configuration for Java Beans only in the first step. Only a few configuration parameters are mandatory, so the NoORM Maven plugin configuration is pretty straight-forward:

 

Minimal but complete Maven pom.xml with a NoORM code generator configuration:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"

         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

                             http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>


    <groupId>noorm-tutorial</groupId>

    <artifactId>noorm-tutorial</artifactId>

    <version>1.0</version>


    <properties>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    </properties>


    <build>

        <plugins>

            <plugin>

                <groupId>org.noorm</groupId>

                <artifactId>noorm-generator</artifactId>

                <version>1.0.0</version>

                <dependencies>

                    <dependency>

                        <groupId>com.oracle</groupId>

                        <artifactId>ojdbc6</artifactId>

                        <version>11.2.0.4.0</version>

                    </dependency>

                    <dependency>

                        <groupId>ch.qos.logback</groupId>

                        <artifactId>logback-classic</artifactId>

                        <version>1.0.13</version>

                    </dependency>

                </dependencies>

                <executions>

                    <execution>

                        <goals>

                            <goal>generate-noorm</goal>

                        </goals>

                    </execution>

                </executions>

                <configuration>

                    <url>jdbc:oracle:thin:@localhost:1521:XE</url>

                    <username>hr</username>

                    <password>hr</password>

                </configuration>

            </plugin>

        </plugins>

    </build>


    <dependencies>

        <dependency>

            <groupId>ch.qos.logback</groupId>

            <artifactId>logback-classic</artifactId>

            <version>1.0.13</version>

        </dependency>

        <dependency>

            <groupId>org.noorm</groupId>

            <artifactId>noorm-runtime</artifactId>

            <version>1.0.0</version>

        </dependency>

    </dependencies>


</project>


Let's go step by step through this configuration.


The first part of a Maven plugin configuration is always about the plugin itself. The groupId and the artifactId specify the NoORM Java code generator. The dependency for the Oracle JDBC driver requires that the drivers library is available for your local Maven installation (for more information see section Local Maven Repository).

 

The NoORM Java code generator has only the execution goal generate-noorm, so this part will stay the same for any configuration.

 

The values for url, username and password in the configuration section are self-explanatory and already provide a working setting, when you have installed Oracle Express Edition.

We will start with a minimal generator configuration containing not more than the package names for the generated beans and services:

 

Minimal NoORM code generator configuration file (configuration.xml)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<generatorConfiguration xmlns="http://www.noorm.org/generator-configuration/1.0.0"

                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                        xsi:schemaLocation="http://www.noorm.org/generator-configuration/1.0.0

                                            http://www.noorm.org/xsd/generator-configuration-1.0.0.xsd">


    <beanJavaPackage name="org.noorm.tutorial.hr.beans"/>

    <serviceJavaPackage name="org.noorm.tutorial.hr.services"/>


</generatorConfiguration>


 

For a first minimal project this is indeed enough! You may use your favourite IDE or you may setup a Maven project manually to build this project. The NoORM code generator creates a Java Bean for each table or view in the addressed database schema. For the Oracle sample schema HR, this results in the following classes (assuming you have used the package names as described in the listed configuration.xml):

 

Java Bean Class generated by the NoORM Java code generator

org.noorm.tutorial.hr.beans.Countries

org.noorm.tutorial.hr.beans.Departments

org.noorm.tutorial.hr.beans.EmpDetailsView

org.noorm.tutorial.hr.beans.Employees

org.noorm.tutorial.hr.beans.GenericBeanValidator

org.noorm.tutorial.hr.beans.JobHistory

org.noorm.tutorial.hr.beans.Jobs

org.noorm.tutorial.hr.beans.Locations

org.noorm.tutorial.hr.beans.Regions

 

You will find the generated classes in your Maven project in target/classes/org/noorm/tutorial/hr/beans.

The directory for the generated services in target/classes/org/noorm/tutorial/hr/services contains a single class file called BeanDML. This class contains a complete API for all DML operations applicable for the generated beans (insert, update and delete for single objects and lists of objects).

 

Naming Conventions and Custom Name Mappings


Java developers and database engineers typically use different naming conventions. For the generated Java code, NoORM follows best practices used by the Majority of Java developers (Code Conventions for the Java Programming Language).

Usually, this results in class, method and attribute names, which slightly differ from database object names. Database names are typically in upper-case with underscores to separate different parts of a single name. NoORM removes underscores and changes names according to the Camel-Case mechanism, i.e., a Java Bean generated for table JOB_HISTORY gets the name JobHistory.

 

However, you may have special requirements concerning the names of you Java classes, methods and attributes. In this case, the generator configuration parameters tableNameMappings and columnNameMappings provide the required functionality to adjust the generated names (see Code Generator Reference).

Posted by 곽중선
2014. 11. 24. 16:14

개발 방식을 바꾸는 15가지 기술 - Q&A version


개발 방식을 15가지 기술이라는 인터넷 기사를 Q&A 버전으로 재구성했습니다. 

다음은 PPT 슬라이드로 제작할 예정입니다.


기사 출처 : http://www.itworld.co.kr/slideshow/90480


Q. 프로그래머가 되고 싶습니다. 무엇부터 공부해야 하죠?

A. 컴퓨터 구조부터 공부해야 합니다. 컴퓨터의 구성 요소를 간단히 요약하면 하드웨어와 운영체제 그리고 어플리케이션으로 표현할 수 있습니다.일반적으로 대다수의 프로그래머는 이중에서 어플리케이션을 개발하는 일을 수행합니다.


Q. 그렇다면 하드웨어를 어떻게 직접 제어(구동)할 수 있나요?

A. 그건 운영체제가 다 알아서 해줍니다. 신경쓰지 맙시다. 어플리케이션은 하드웨어를 직접 제어 못합니다.

Q. 하드웨어를 조작할 수 없다면, 어플리케이션은 어떻게 키보드, 마우스, 모니터에 입출력하고 통신도 하죠?

A. 운영체제가 Application Programming Interface (API)라고 하는 기능(함수, function)들을 제공합니다. 어플리케이션 개발자는 하드웨어와 운영체제가 제공하는 기능을 이해하고 제어하기 위해 운영체제가 제공하는 API 부터 공부해야 합니다.

  

Q. 그럼 API는 운영체제가 어플리케이션 개발자를 위해 제공하는 기능들을 말하는 건가요?

A. 최초의 API는 운영체제가 어플리케이션을 위해 제공하는 기능들을 말했지만, 점차 의미가 확대되고 무언가 하부 시스템 (운영체제, 가상 머신, 컨테이너 등)에서 상위 어플리케이션이나 앱, 위젯에 제공하는 각종 소프트웨어 기능(함수)들의 집합(set)을 API라고 부릅니다.

   

   API 정의 - http://ko.wikipedia.org/wiki/API

   예시 - MS Windows SDK (System Developement Kit), MS Direct X, 구글 API, 네이버 API


Q. API 와 라이브러리(library)의 차이는 무엇인가요?

A. API는 독자적으로 구동되는 프로그램(운영체제, 제품)나 서비스(운영)되고 있는 특정 플랫폼(구글/네이버 등의 서비스)에서 해당 소프트웨어를 제어하거나, 제공하는 기능을 호출할 수 있는 함수들의 집합입니다. 반면에, 라이브러리는 특정 알고리즘이나 작업을 처리할 수 있는 기능들을 수행할 수 있는 함수의 집합입니다.

API는 제품(운영체제 같은 경우)을 구매하거나, 사용(구글 같은 경우)해야 쓸 수 있는 것이고 개발자가 제작하는 어플리케이션에 포함되지 않습니다. 즉, 부품이 아니라 어플리케이션 외부의 기능을 호출하는 것입니다

반면에 라이브러리는 프로그래머가 제작하는 어플리케이션의 부품 형태로 사용할 수 있게 만들어져 배포되는 기능 모듈입니다.(라이브러리는 언어에 따라 배포되는 파일 형식이 다릅니다. 자바에서는 jar, C 혹은 C++에서는 lib, so, 윈도우에서는 dll 확장자 등)

  

라이브러리로 제작되고 있는 것들의 예시를 들자면, 암호화, 압축 및 해제(zip), 이미지 변환, 문자열 처리 등등이 있습니다.

  

그런데... 라이브러리와 API는 정확하게 구분하기 어려운 경우가 많습니다.

JDK(Java Development Kit) 같은 경우에도 API의 특징과 라이브러리 특징을 모두 포함하고 있습니다.

  

예시 - Apache commons 라이브러리 (문자열 처리, 날자 계산 등),  zlib 라이브러리 (압축 해제)

  Joda Time (날짜/기간 계산, 양/음력 변환)

  Netty (비동기 통신 라이브러리), jQuery, Dojo (자바스크립트 라이브러리)

  

Q. 그렇다면 라이브러리와 유사하게 들리는 (혹은 사촌이라는데..) 프레임워크(framework)는 무엇인가요?

A. 프레임워크는 특정 목적의 서비스 혹은 어플리리션을 제작하기 쉽게끔 일련의 작업 흐름을 미리 만들어 둔 소프트웨어 부품입니다. 라이브러리는 개별 부품들의 단순 집합 - 레고 블럭들을 넣어둔 상자라고 연상해 봅시다 - 이라고 설명할 수 있습니다. 동작하는 무언가를 만들고자 하면 직접 하나의 부품을 조립(혹은 코딩)을 해야 합니다.


반면에 프레임워크는 일련의 과정을 수행하는 부품들이 조립되어 있어 간단한 설정만으로 어플리케이션을 제작할 수 있습니다.

사례를 들어 보자면, 데이터베이스의 데이터를 읽고 있는 기능을 라이브러리만으로 구현하려 한다면, 데이터베이스에 연결하는 기능, 쿼리 전송하는 기능, 쿼리 수행 결과를 가져오는 기능, 연결을 종료하는 기능 등등을 직접 조립하고, 구현하고 테스트해야 합니다. 프레임워크를 사용하면 이러한 일련의 기능들이 쉽게 쓸수 있도록 구현되어 있는데다 테스트까지 완료되어 있고, 연쇄적으로 실행하고 결과를 반환하거나 오류 처리하는 기능을 한번의 호출로 처리할 수 있습니다. (실제 구현할 때는 개인의 적용 방식에 따라서 절차가 조금 다를 수 있습니다.)

요약하자면, 라이브러리는 그냥 '부품 상자'이고 프레임워크는 부품들을 연결하고 조립해둔 '모듈 형태의 반제품'입니다.


추가로, '엔진'이라고 불리는 것들은 특정 분야의 제품을 만들기 위해 사용되는 라이브러리/프레임워크의 진화된 형태를 말합니다. '게임 엔진'을 예로 들면, 개발자가 어떤 라이브러리들을 사용할지 고민하거나 필요한 기능들을 사전 제작하는 과정없이,바로 게임 개발에 착수할 수 있도록 게임 제작에 필요한 모든 기능을 제공합니다. 프레임워크는 일반적으로 범용적(general purpose)인 용도로 만들어지기 때문에 바로 원하는 소프트웨어를 제작할 수 없고,개발자 혹은 시스템 엔지니어가 각종 환경 설정 및 시스템 구성, 그리고 목표 소프트웨어에 맞도록 커스터마이징(customizing) 혹은 조립, 설계를 거쳐야 합니다.


Q. 통합개발환경(IDE : Integred Development Environment)는 무엇인가요?

A. 프로그래머는 자신이 구상한 프로그램을 '프로그래밍 언어'로 작성하고, 컴파일러를 이용해 실행 파일 형태로 만듭니다. 오동작 할 경우에는 원인을 찾기 위해 디버거(debugger)를 이용해 버그를 찾아냅니다. 이러한 일련의 작업을 수행하기 위해서는 프로그램 소스 편집기(program source editor), 컴파일러(compiler), 디버거(debugger) 등의 개발 도구(development tool)들이 필요한데, 이것들을 하나의 종합선물셋트로 모은 것이 통합개발환경(통칭 IDE)입니다.

가장 널리 쓰이는 통합개발환경으로는 MS Visual Studio, Eclipse, IntelliJ 등이 있습니다. 개발 현장에서는 델파이(Delphi), 파워빌더(Power Builder) 등도 더불어 사용합니다.

Q. 지속적인 통합이라는 것은 무엇인가요?

A. 앞서 언급한 통합개발환경이 도입된 이후로 단 하나의 개발도구만 가지고, 소프트웨어 개발에 필요한 모든 과정을 편하게 수행할 수 있습니다. 하지만, 소프트웨어의 규모가 커지면서 더 이상 소프트웨어를 단 한 명의 개발자가 만들어 낼 수가 없게 되었습니다.

대다수의 상용 소프트웨어는 수 명에서 수백명의 개발자가 하나의 제품을 만들기 위해 협력합니다. 동시에 여러 사람이 개발을 진행하다 보면, 각자가 작업한 소스 코드를 합치고(merge)하고, 컴파일한 후, 정상적으로 동작하는지 여부를 테스트하는 과정을 도저히 사람이 수행할 수 없게 됩니다. 따라서, 주기적으로 변경된 소스를 찾아서 자동으로 컴파일하고 기능을 테스트하며, 그 결과를 기록해주는 제품이 만들어진 것입니다.

Q. 깃허브(GitHub), 소스포지(SourceForge) 등의 소셜 코드 공유는 무엇인가요?

A. 90년대에는 소수의 개발자들이 작은 사무실에 모여서 개발하는 형태를 '소프트웨어 하우스'라고 부르는 유행이 있었습니다. 닷컴 열풍이 불기 전, 인터넷이 광범위하게 퍼지기 전에는 소프트웨어 개발은 자동차 창고 같은 허름한 공간에 열정적인 개발자들이 모여서 함께 작업하는 것이 당연했습니다.

하지만, 인터넷이 발전하고, 세상의 모든 개발자들 연결되면서 전세계의 모든 개발자들이 가상의 인터넷 공간에서 함께 작업할 수 있게 되었습니다. 서로 다른 시간과 공간에서 작업을 하면서도 서로의 작업을 확인하고, 의견을 나누고 소스를 취합할 수 있는 공간이 소셜 소스 공유 사이트입니다.

Q. 애플리케이션 컨테이너(Application Container)란 무엇인가요?

A. 개인 PC 환경에서만 작업해 본 사람에 '어플케이션'을 담는 컨테이너라는 용어가 생소하게 들릴 수 있다. 당연히 PC에서는 어플리케이션을  실행하는데 운영체제 이외의 요소는 필요 없습니다. - 윈도우나 OS X, 리눅스에서 바탕화면의 아이콘만 클릭하면 프로그램이 동작하는 건 너무나 당연합니다 -

하지만, 서버라는 환경에서는 이야기가 달라집니다. 서버에서 구동되는 소프트웨어들은 한 명의 사용자를 염두에 두고 개발되는 것이 아닙니다. 수십명에서 수천 명의 사용자가 네트워크틀 통해 접속하기 마련입니다. 게다가 서버 소프트웨어는 장비 자체의 자원(디스크, 메모리)만 사용하는게 아니라 이메일을 주고 받거나, 데이터를 송수신하거나, 원격지에 존재하는 장비들과 통신해야 하기 때문에 굉장히 높은 부하에서 다양한 작업을 수행합니다. 동시에 벌어지는 복잡한 작업에 필요한 자원을 할당하고, 관리하고, 반환하는 일련의 과정은 어플리케이션 서버가 담당하고, 서버 어플리케이션은 어플리케이션 서버가 제공해주는 각종 자원(스레드, DB 연결, 소켓, 메모리 자원 등)들을 이용해 동시에 수많은 작업을 처리합니다. 서버의 어플리케이션은 대게 운영체제 위에서 직접 실행되지 않고, 어플리케이션 컨테이너 위에서 실행됩니다. (물론 서버에도 운영체제가 있지만, 서버 운영체제의 역할은 여전히 하드웨어 제어가 최우선입니다.)

Q. '가상 머신(virtual machine)'은 무엇인가요?

A. 가상 머신(Virtual Machine, VM)은 컴퓨팅 환경을 소프트웨어로 구현한 것, 즉 컴퓨터를 에뮬레이션(emulation)하는 소프트웨어입니다. 초기에 나온 가상 머신은 특정 하드웨어 장비에서 다른 유형의 하드웨어에서 동작하는 소프트웨어를 구동하는자 하는 욕구에서 시도되었다고 볼 수 있습니다. (예전에는 매킨토시에서 윈도우용 게임을 실행할 수 없었습니다. 그 반대의 요구도 있을 수 있습니다.)

지금은 가상 머신 기술이 발전해서, 서버 차원에서 주로 활용되고 있습니다. 아마존 웹 서비스가 주요 사례입니다.


Q. '브라우저'가 개발 기술 중에 언급되는 이유는 뭔가요?

A. 초창기 웹 브라우저들은 정적인 HTML 컨텐츠를 마치 모니터에 출력해주고 책처럼 읽게끔 해주는 것이 주된 역할이었습니다. 그런데, 넷스케이프에서 웹 브라우저에 보다 동적인 요소를 가미하고자 자바스크립트 언어를 추가했고, 점차 웹 브라우저에서 다양한 기능을 구현할 수 있게 되었습니다. 이제 홈페이지 화면들은 액자 속의 그림처럼 멈추어 있지 않습니다. 마우스와 키보드를 이용해 다양한 상호작용(interaction)을 이끌어 낼 수 있고,브라우저 내에서 동작하는 다양한 어플리케이션들이 나타나고 있습니다. 이러한 혁신은 지속되고 있는 상황입니다.

Q. Node.js와 JavaScript의 의미는 무엇인가요?

A. 프로그램 개발 도구들이 점점 진화하듯, 개발 언어도 개발자가 좀 더 쉽게 코딩할 수 있게끔 문법적으로 단순화되어 가고 있습니다. 물론, 비즈니스 개발을 위한 언어들은 실수를 방지하기 위해 여전히 엄격한 문법을 고수하고 있기는 합니다. 

javascript는 쉽게 배워서 빠르게 원하는 목표를 달성할 수 있는 입문자용 언어입니다. 점차 비즈니스 업무을 개발하는데 필요한 기능들이 확장되고 있기 때문에, 과거에 '연습용 언어', '장난감이나 만들 수 있는 언어'라는 식의 평가도 사라지고 있습니다.


Q. '서비스로 제공되는 인프라/플랫폼'란 무엇인가요?

A. 다수의 사용자를 위해서 인터넷 서비스를 만들고자 한다면, 어딘가 인터넷 망에 연결된 고성능의 서버를 마련해야 해야 합니다. 또한, 서비스를 개발하고 테스트 할 수 있는 환경 (서버 하드웨어, 소프트웨어, 개발도구, 모니터링 도구 등)도 있어야 하고, 24시간 운영해 줄 운영요원도 구해야 합니다. 이러한 서버 구축/개발지원/운영 서비스를 가입하고 요금만 내면 즉시 제공해 되는 서비스들이 '서비스로 제공되는 인프라/플랫폼'입니다.

Q. '데브옵스(DevOps) 도구'란 무엇인가요?

A. 글로벌 시대에는 서버 장비의 규모도 달라지고 있습니다. 단 몇 대의 서버 장비를 운영하는 것이 아니라, 수십 혹은 수백대의 장비에 각종 소프트웨어를 설치하고 기능이 변경될 때마다 업데이트해야 합니다. 과거의 개발자는 소프트웨어를 서버에 일일이 설치했습니다. 하지만 지금은 쉐프(Chef), 퍼핏(Puppet) 같은 서버 관리 도구를 통해 자동으로 수백배의 서버의 설정을 변경하고, 재배치하는 것이 가능합니다. 이러한 기술들을 '데브옵스(devops)'라고 합니다.


Q. '성능 모니터링'이란 무엇인가요?

A. 서버는 당연히 수많은 사용자가 접속하기 마련입니다. 몇 명의 사용자가 언제 얼마나 접속할지 예측할 방법은 없습니다. 그렇다면 서버를 안정적으로 운영하기 위해서는 지속적으로 어느 정도의 부하(load)가 발생하는 모니터링해야 합니다. CPU 사용량의 변화, 메모리가 부족하지는 않는지, 사용자에게 응답하는 시간이 오래 걸리지 않는지 변화를 기록하고 통계를 만들어 냅니다. 그리고, 통계 결과를 통해 향후에 얼마나 많은 서버를 증설해야 하는지 계획을 수립하는 것입니다. 예측할 수는 없지만, 과거와 현재의 결과를 통해 미래를 준비하는 기술이 성능 모니터링 입니다.


Q. '소셜 미디어 포탈'을 염두에 두어야 하는 이유는 무엇인가요?

A. 초창기 인터넷은 고립된 섬들의 집합과 같았습니다. 좋은 휴양지나 보물섬과 같은 사이트는 최초 발견자가 자신의 지인들에게 알음알음 소개해서 알려졌습니다. 그러다가 제리 양이 'Yahoo.com'를 만들었습니다. 인터넷에 전화번호부가 생기고, 구글 검색이 생기고 사람들은 포털과 검색을 통해 흥미로운 사이트를 찾아다녔습니다.

하지만, 이제는 굳이 검색이 아니라 뉴스와 이웃들의 관심사를 통해 최신 정보를 얻고 있습니다. 아무리 좋은 사이트 혹은 어플리케이션을 만들어도 외딴 섬처럼 방치해서는 곧바로 망하고 마는 것입니다. 소셜 미디어 포털에 홍보하거나, 소셜을 활용하는 서비스 혹은 어플리케이션 제작을 염두에 두어야 합니다.

Q. 그리고 마지막으로 '소프트웨어를 판매하는 스토어'에 대해 알고 싶습니다.

A. 소프트웨어는 초기에 우편 배달 방식으로 팔렸습니다. 그리고, 이후에는 상자에 CD와 매뉴얼을 담아 팔던 시절이 있었습니다. 소포 포장이나 박스에 담은 형태를 패키지(package)라고 부르던 것에 빗대어 '패키지 소프트웨어'라는 표현이 여전히 쓰이고 있습니다.

이제는 인터넷을 모든 것이 팔리고 있습니다. 모바일 앱스토어, 브라우저 플러그인 스토어, 그리고 연쇄 할인마 라는 별명으로 유명한 스팀까지 다양한 형태의 소프트웨어 마켓이 존재합니다. 소프트웨어를 제작하고 설계하는 시점부터 온라인 스토어에 판매하는 것을 염두에 둘 필요가 있습니다.


Posted by 곽중선
2014. 11. 21. 18:11

http://www.noorm.org/


Efficient persistence for Java applications

자바 어플리케이션을 위한 효율적인 퍼시스턴스(persistence)


NoORM 은 코드 생성기(code generator) 및 자바 오픈소스 프로젝트 (아파치 라이센스)

NoORM는 코드 생성기를 제공하며 손쉽게 오라클 데이터베이스의 관계형 데이터에 대한 액세스를 자동화하는 런타임 라이브러리를 제공하는 자바 오픈 소스 프로젝트 (아파치 라이센스, 소스 코드와 이슈는 Java.Net 에서 확인) 입니다. NoORM은 현재까지는 오라클에 제한되어 있지만, 버전 2.0에서는 MySQL에 대해서도 지원을 제공할 것입니다. 많은 다른 툴과 라이브러리가 유사한 기능을 제공하고 있지만, NoORM는 데이터베이스 중심의 접근 방식을 따른다. 적절한 관계형 데이터 모델을 기반으로 NoORM는 자바 애플리케이션을 위해 오라클의 강점을 이끌어내는 자바 빈즈, 자바 열거형 및 Java 서비스에 필요한 자바 코드를 생성 할 수 있습니다. 특히, NoORM를 사용하여 당신에게 다음과 같은 혜택을 가져올 수 있습니다 :


NoORM is a Java open source project (Apache Licensing, source code and issue tracking at Java.Net) providing code generators and a runtime library to simplify and automate access to relational data residing in an Oracle database. Even though NoORM is still presently limited to Oracle, version 2.0 will offer support also for MySQL. In distinction to many other tools and libraries providing functionality in this area, NoORM follows a consequent database-centric approach. Having a proper relational data model, NoORM can generate the required Java code for Java Beans, Java Enums and Java Services to exploit the power of Oracle for Java applications. In particular, using NoORM can bring you the following benefits:

 

가파른 학습 곡선 : 런타임 환경설정 없음, 복잡한 API 없음. (실질적으로 의존적인 API가 거의 없음!)

놀라운 성능 : 성능 벤치 마크 자체에 복잡한 문제이지만, 우리는 자신있게 NoORM이 경쟁자들 보다 거의 항상 빠를 것이라도  주장할 수 있습니다.

관심사의 완전히 분리 : SQL은 클라이언트의 문제가 아니다! 데이터베이스 개체는 클라이언트 응용 프로그램에서 직접 해결해야 할 문제가 아닙니다! NoORM 응용 프로그램을 개발하는 것은 개발자도 데이터베이스 개체를 직접 조작하거나 데이터베이스 외부에서 SQL을 사용하지 않는다는 의미입니다!

향상된 코드 품질 : 코드 생성은 두 가지 장점이 있습니다 : 이기종 시스템을 위한 소프트웨어를 개발한다는 것은 항상 플랫폼 간의 중복이 어느 정도 발생하게 되어 있습니다. NoORM 데이터베이스 오브젝트에 액세스하기 위해 자바 코드를 생성하는  코드 생성기를 활용하면, 시스템 접속에 대한 코드를 생성하는 단 하나의 시스템만을 분석 할 수 있게 됩다. 코드 생성기의 두 번째 장점은 빌드 프로세스에서 런타임 시스템의 복잡한 작업을 '미리보기(preview)' 할 수 있다는 점 입니다. NoORM의 가장 복잡한 중요한 파트는 코드 생성기에 의해 구현되며, 이를 활용해 런타임 시점에 발생할 수 있는 잠재적인 문제점들을 빌드 시점에 점검할 수 있게 됩니다.


Steep learning curve: No runtime configuration, no complex API (actually almost no proprietary API at all!)

Extraordinary performance: Though performance benchmarking is a complex issue on its own, we can confidently assert that NoORM is almost always significantly faster than its competitors.

Clean Separation of Concerns: SQL is not a matter of the client! Database objects are not to be addressed directly from a client application! Developing applications with NoORM means that the developer neither addresses database objects directly nor uses SQL outside of the database!

Improved Code Quality: Code generation has two benefits: developing software for heterogeneous systems always includes some degree of redundancy across the different systems and platforms in use. Code generators can analyze one system to generate code for a connecting system, like NoORM generates Java code to access database objects.

A second benefit of code generators evolves from the pre-drawing of complex operations from the runtime system already in the build process. A significant part of the complexity of NoORM is implemented with the code generators, which will cause potential problems to occur at build time rather than at runtime!


왜 새로운 ORM 도구 또는 프레임워크가 필요합니까?


이 글을 쓰는 시점에서 이미 다양한객체 관계형 매핑 (ORM) 라이브러리와 프레임워가 나와 있습니다. 그럼, 왜 우리에게 새로운 툴이 더 필요할까요?

오라클 데이터베이스의 기능 활용 범위(혹은 수준)는 오라클을 사용하는 다수의 기업 자바 프로젝트 사이에 크게 다릅니다. 대부분의 엔터프라이즈 자바 프로젝트는 주로 자바 세계의 근원적인 설계 사상에 의해 구축됩니다. 많은 (기업) 자바 아키텍트들은 자바로 생각(Thinking in Java) 합니다.


Do we need another ORM Tool or Framework for Java?


There are plenty of ORM-tools (ORM : Object-Relational-Mapping) , libraries and frameworks available for Java at the time of this writing. So, why do we need one more?

The utilization of the features of an Oracle database varies significantly between numerous enterprise Java projects using Oracle. Many enterprise Java projects are mainly driven by architectural guidelines having their origin in the Java world. Many (enterprise) Java architects perceive themselves as "thinking in Java" (this is not to be understood as a hidden cross reference to the great Java book "Thinking in Java" from Bruce Eckel).


그 자체가 나쁜 것은 아닙니다. 그러나, 복잡한 엔터프라이즈 자바 프로젝트를 고려하면, 거의 항상 관계형 데이터베이스 관리 시스템을 사용하여 데이터를 유지하게 마련인데, 앞서의 접근방안은 관계형 데이터베이스 시스템의 역할 및 성능을 제대로 이끌어내지 못할 수 있다.

데이터베이스의 성능을 제대로 활용하면 응용 프로그램의 아키텍처와 디자인을 주목할만큼 개선할 수 있습니다.


This is not a bad thing per se. However, considering complex enterprise Java projects, which almost always use a relational database management system to persist data, this approach could easily result in an underestimation of the role and power of the relational database system. 

Leveraging the power of the database could significantly improve architecture and design of an application.


NoORM 은 오라클 데이터베이스 엑세스를 구성하는데 도움이 되는 또 다른 도구이지만, 소프트웨어 기능 요구사항을 기술하기 위한 새로운 스펙을 제시하지는 않습니다. NoORM 을 사용하기 위해 새로운 고유 API를 배울 필요가 없습니다. SQL 코드의 관리 및 유지는 생성기 설정의 간단한 쿼리 선언으로 이루어지며, 기존의 지식과 코드를 활용해 SQL을 구성할 수 있습니다.


Though NoORM is yet another tool to help you organize Oracle database access from a Java application, it does not introduce new specifications to specify your requirements. You do not even have to learn a new proprietary API to use NoORM. Managing and maintaining your SQL code is done through simple query declarations in the generator configuration or by using PL/SQL, so even for SQL you can build upon existing knowledge and/or code.


"NoORM"이름은 무엇을 의미 하는가?


NoORM이 실질적인 의미는 "no ORM"이나, 실제로 그런 것은 아닙니다. 자바와 같은 객체지향 프로그래밍 환경에서 관계형 데이터베이스를 사용하기 위해서는 언제나 "ORM(Object Relational Mapping)"이 필요합니다. 즉, 데이터베이스 데이터와 어플리케이션 데이터 간의 매핑(mapping) - 데이터베이스의 데이터가 어플리케이션에서 이용되는 방법 - 을 정의해야 하는 것입니다. NoORM 은 종종 '황금률'이라고 불리는 단순히 자바 클래스에 대에티베이스 테이블 또는 뷰를 매핑하는 아주 기본적인 ORM 패러다음을 사용합니다.


What does the name "NoORM" mean?


NoORM actually means "no ORM", which, of course, is not really true, since using a relational database system with an object-oriented programming environment like Java always requires some "ORM", i.e., you are required to define some mapping between database data and your application data, resp. the way the database data is utilized in your application. NoORM uses the very basic ORM paradigm often referred to as "golden rule", which simply maps a database table or view to a Java class (i.e., rows of a table or view are represented as object instances of the Java class representing the table or view).


사실상, 데이터를 매핑하는 것에 대해 더 할 말은 없습니다. NoORM은 최소한 매핑을 통해 중복을 최소화하는 기술을 제공하는 ORM 도구로 고려할 만 합니다.  좀 더 깊이 얘기하자면, NoORM 은 관계형 데이터 모델 (혹은 ER-모델)의 상세한 특성들을 다루지 않는데, 관계 조언, 제약 조건 등은 데이터베이스에 실행 책임을 맡기는 것이 최선입니다.


Effectively, there is not much more to say about mapping data, i.e., NoORM can be considered as an ORM-tool reducing the required redundancy implied by the mapping to the bare minimum. In particular, this means that NoORM does not care about the detailed characteristics of your relational data model or ER - model, but leaves this part to the database, which is effectively the best place to deal with relationships, joins, constraints, etc.


대상 그룹


NoORM 은 분명히 오라클을 사용하는 모든 엔터프라이즈 자바 프로젝트에 대해 관심을 두고 있습니다.  특히 PL / SQL을 사용할 수 있게 하는 것입니다. (그것뿐 아니라!).


Target Group


NoORM is obviously of interest for all enterprise Java projects using Oracle, in particular those which make use of PL/SQL (but not only!).


엔터프라이즈 자바 개발자들에게 있어 다른 ORM 도구들이 익숙하지만, PL/SQL 사용에 있어서는 의문이 있습니다. PL/SQL을 사용하지 않는 프로젝트 또한 그렇습니다. 하지만, NoORM 은 비즈니스 로직을 stored procedure에 저장된 PL/SQL로 이전할 것을 요구하지는 않습니다. PL/SQL 적용 범위는 매우 가변적이며 프로젝트의 요구사항에 따라 달랍니다. 기본적으로 PL / SQL의 사용에 관한 두 가지 시나리오를 고려할 수 있습니다. (물론, 상상할 수 있는 모든 시나리오 또한 가능합니다.)


It is quite natural that enterprise Java developers familiar with other ORM - tools question the usage of PL/SQL, in particular for projects which are not using PL/SQL yet. However, NoORM does not require moving your business logic into PL/SQL stored procedures. The degree of PL/SQL usage is quite variable and depends on your projects needs. Basically two scenarios concerning the usage of PL/SQL are possible (though any thinkable scenario in the range in between is possible, too):


PL/SQL 패키지로서의 SQL 컨테이너 : 어떤 ORM 도구를 사용하던 SQL을 사용할 수 밖에 없고, SQL을 어디에 저장할 지 고민해야 합니다. 엔터프라이즈 자바 어플리케이션 내부는 SQL을 관리하기 위한 적절한 저장소가 아닙니다. SQL을 XML 파일 같은 리소스 파일들에 저장하거나, 정적 클래스 변수 혹은 어노테이션에 저장하던 간에 둘 다 자바 어플리케이션 환경에서는 아무런 의미 없는 형식으로 저장됩니다. 데이터베이스로 SQL 명령이 전송될 때까지 SQL은 아무런 가치(의미)가 없습니다.그러므로, 궁극적으로 SQL 명령의 존재 의의가 있는 데이터베이스에 저장하는 것이 너무나 자연스러운 것입니다.


PL/SQL packages as SQL - container: Whatever ORM - tool you use, in any case you have to deal with SQL, in particular deciding where to store your SQL. We think that an enterprise Java application does not seem to be the appropriate place for maintaining SQL. Whether SQL is stored in (proprietary) resource files like XML - files, in static class variables or in (proprietary) annotations, in either case SQL is kept in a format which is actually meaningless to its environment (here: the Java application). The SQL does not become meaningful until it is submitted to the database. So it sounds quite natural to store SQL in a place which ultimately gives the SQL statements their meaning - in the database.


SQL 컨테이너로서의 PL / SQL 패키지는 SQL 코드의 검증 기능을 포함하는 선택 가능한 옵션입니다. 결국, PL/SQL을 sql 컨테이너로 사용하기 위한 방법을 학습하는 것은 엔터프라이즈 자바 어플리케이션에서 SQL을 관리하는 방법을 익히는 것보다 많은 것을 노력을 요구하지 않습니다.


SQL로 PL / SQL을 사용하는 방법을 학습 - (절대 PL / SQL 초보자 용) 용기 당신의 엔터프라이즈 자바 응용 프로그램과 함께 저장 SQL에 사용할 수있는 독점적 인 방법 중 하나를 배우는 것보다 더 요구하지 않습니다.

비즈니스 로직을 포함하는 PL / SQL : PL / SQL이 이미 프로젝트에 대한 비즈니스 로직의 중요한 부분을 포함하는 경우, 어쨌든 NoORM 을위해 잘 준비가 되어 있는 것입니다.


Using PL/SQL packages as SQL - container is a viable option here, including the validation of the SQL code. In the end, learning how to use PL/SQL as a SQL - container (for an absolute PL/SQL beginner) is not more demanding than learning one of the proprietary methods available to store SQL with your enterprise Java application.

PL/SQL to contain business logic: When PL/SQL is already used in your projects for significant parts of your business logic, you are well prepared for NoORM anyway.

 

그러나, SQL 문 대다수를 사용하는데 있어서 PL/SQL을 사용할 필요는 없다. SQL 문장의 대부분은 SELECT * <하나의 엔티티> WHERE A = X와 B = Y FROM ...' 와 같은 사소한 형식을 따른다.  이러한 단순한 형식의 쿼리들은 쿼리 생성을 위한 각종 설정과 쿼리(코드) 생성기에 손쉽게 통합될 수 있다. 데이터베이스 뷰를 이용해 복잡한 쿼리 조차 쿼리를 선언하는 출발점으로 활용할 수 있고, 거의 모든 쿼리 또한 간결한 형식으로 제공할 수 있다.


However, for the majority of SQL statements it is not even necessary to use PL/SQL. The vast majority of SQL statements follow a rather trivial format: SELECT * FROM <one single entity> WHERE A = x AND B = y ...

Queries with this trivial format can easily be integrated (and generated) using the code generator for an appropriate query declaration as part of the generator configuration. By using database views it is even possible to provide even complex SQL as starting point for the declared query, turning almost all queries into this trivial format.

 

"데이터베이스 중심"코드 생성의 기본 원리는 직접 데이터베이스 객체에 접근하지 않는다는 것이다. 테이블, 뷰 등의 데이터베이스 객체의 이름은 생성기 설정에서만 사용되면, 손으로 만든(hand-made) 자바 코드에서 사용되지 않는다.

 

The basic principle of "database-centric" code-generation is that the developer using NoORM will never address a database object directly (the names of database objects, i.e., tables, views, etc. are used in the generator configuration only, but never in the ("hand-made") Java code.


왕복 엔지니어링


엔터프라이즈 소프트웨어 환경의 시스템이나 구성 요소 간의 매핑 데이터는 항상 코드 및 사양에 약간의 고유 중복을 포함한다. NoORM로 구현된 최소한의 객체 관계형 매핑 접근 방식은 완전 자동화 된 왕복 엔지니어링 솔루션을 실현한다. 이것은 데이터베이스 데이터에 대한 표현과, 필요한 기능이 완전히 NoORM 코드 생성기에 의해 생성된다는 것을 의미한다.


Roundtrip Engineering


Mapping data between systems or components of enterprise software environments always includes some intrinsic redundancy in code and specifications. The minimal object-relational-mapping approach implemented with NoORM is realized as fully automated roundtrip engineering solution. This means that the code required to represent database data and functionality is completely generated by the NoORM code generator.

Posted by 곽중선
2014. 4. 27. 16:08

여우는 입을 다물고 어린 왕자를 오랫동안 쳐다보더니

"부탁이야...... 나를 길들여 줘!" 하고 말했다.


어느새 나이를 많이 먹어 나도 보아뱀을 삼킨 코끼리를 모자라 착각하는 아저씨가 되어 간다.

어릴 적에는 생 떽쥐베리의 어린 왕자가 아름답게만 여겨지더니, 나이를 먹고 보니 이런 처참한 절규로 가득한 이야기 달리 없다.


세상에나.. 생 떽쥐베리... 그는 얼마나 외로운 사람이었을까?

어찌하여 생의 마지막 순간조차 차가운 밤 바다에서 사라져야만 했을까?

아.... 이제 그를 이해하는 나이가 되어간다.


부탁이야... 부탁이야.. 

그래 나도 부탁하고 싶다.

목구멍에서 터져나오는 듯 그러나, 아무 소리조차 나지 않는다.


아무에게도 들리지 않는다. 다들 무심히 내 곁을 지나칠 뿐이다.


’부탁이야...... 나를 길들여줘!’

Posted by 곽중선
2014. 4. 24. 17:18

AWS 에서 가상 서버(virtual servers) 들을 실행하고 관리하기 위해서는 Amazon Elastic Compute Cloud (Amazon EC2)를 사용할 수 있다. 가상 서버는 AMI 라고 불리는 머신 이미지(machine image)로부터 초기화 되고, EC2 인스턴스로 기동(launch)된다.


무료 사용 계층(free usage tier)에서는 t1.micro EC2 인스턴스를 기동할 수 있다. 마이크로 인스턴스는 기본적으로 작은 용량의 CPU 자원을 제공하며, 추가적인 싸이클 지원을 위한 CPU 사용을 허용한다. t1.micro 인스턴스는 작은 작업량(low-throughput)의 어플리케이션과 간혹 많은 요청을 처리하는 웹 사이트에 적합니다.


[가상 서버 실행]


Amazon EC2 콘솔을 연다. https://console.aws.amazon.com/ec2/


EC2 콘솔에서 Launch Instance 버튼을 클릭한다.


'Choose an Amazon Image (AMI)' 페이지에서는 사용 가능한 AMI 목록이 출력된다. 테스트를 하고자 한다면, 무료 계층(free tier)에서 사용할 수 있는 것으로 체크된 AMI를 선택한다. (무료 계층에서 사용할 수 없는 AMI를 선택하려면, 아마존에서 서버 사용 청구서가 날아올 것이다.   적절한 AMI 아이템을 선택하고, Select 버튼을 클릭한다.



'Choose an Instance Type' 페이지에서는 인스턴스의 유형(type)을 선택한다. 적은 리소스를 사용하는 Micro instance 부터, 메모리, 일반형, 메모리 사용량이 높은 타입, 저장소가 많은 타입, 처리 능력이 높은 타입 등을 살펴보고 적절한 타입을 선택한다.




'Review and Launch' 을 클릭하면 기본 설정으로 서버가 실행되며, 위저드에 의해 서버 기동 작업이 수행된다. 'Review Instance Launch' 에서 상세한 인스턴스 설정을 확인할 수 있다. 설정이 적절한지 여부를 검토한 후, 최종적으로 Launch 버튼을 클릭한다.




Select an existing key pair or create a new key pair 다이얼로그 박스에서 첫번째 선택 박스에서 'Create new key pair'를 선택한 후, key-pair 명칭을 입력한다. key-pair 파일을 다운로드할 수 있는 유일한 기회이기 때문에 확실히 다운로드 받아야 하고, 개인 서버 키 파일은 안전한 곳에 보관해야 한다. 이후에 인스턴스를 시작할 때마다 key-pair 명칭을 입력해야 하며, 인스턴스에 연결할 때마다 개인 키(private key)가 필요하다.




준비가 되면 동의(acknowledgement) 체크 박스를 선택하고, Launch instances 버튼을 클릭한다.


AWS가 서버를 프로비저닝(provisioning)하는데 몇분이 소요되며, 프로비저닝이 완료되면 기동된(launched) EC2 인스턴스는 EC2 콘솔의 인스턴스 페이지에 표시된다.

Posted by 곽중선
2014. 4. 24. 14:50

AWS에 파일을 저장하기 위해서 Amazon Simple Storage Service (이하 S3)를 사용할 수 있다. S3에 저장된 파일들을 오브젝트(object)라 부르고, 오브젝트들이 저장되는 위치(혹은 공간)을 버킷(bucket)이라고 부른다. 버킷을 생성하고 파일을 업로드(upload)하는 절차는 다음과 같다.


[버킷(Bucket) 생성 절차]

  1. Amazon S3 콘솔(console)을 연다. https://console.aws.amazon.com/s3/
  2. S3 콘솔에서 Create Bucket 을 클릭한다.



  3. 'Create Bucket - Select a Bucket Name and Region' 다이얼로그 박스의 'Bucket Name' 입력 상자에 버킷 명칭을 입력한다. 생성하는 버킷 명칭은 Amazon S3 내에서 유일해야 한다. (unique across all existing bucket names) 그리고, 버킷 명칭은 생성한 후에 변경할 수 없다.


    만일 이미 존재하는 버킷 명칭을 입력하면 다음과 같은 오류 다이얼로그가 출력된다.



  4. Region 을 선택한다. 지리적으로 가까운 region을 선택하면 된다.
  5. 입력한 설정이 검토한 후, 제대로 입력했다면 Create 를 클릭한다.
    Amazon S3 가 성공적으로 버킷을 생성하면, 콘솔의 All Buckets 영역(pane)에 신규 생성한 버킷 명칭이 표시된다. 신규 생성된 버킷에 파일을 업로그 할 수 있다.


[파일 업로드 절차]


  1. Amazon S3 콘솔에서 파일을 업로드할 버킷을 선택한다.



  2. Actions 버튼을 클릭한 후, Upload 항목을 선택한다.
  3. 'Upload - Select Files' 다이얼로그 박스에서 'Add Files' 버튼을 클릭한다.



  4. 'File Upload' 다이얼로그 박스에서 업로드할 파일을 선택한다.
  5. Open 버튼을 클릭한다.
  6. 'Upload - Select Files' 다이얼로그 박스에서 Start Upload 버튼을 클릭한다.

  7. 파일 업로드가 완료되면, 다음과 같이 표시된다.


참조 사이트 : http://docs.aws.amazon.com/gettingstarted/latest/awsgsg-intro/gsg-aws-store-files-aws.html

Posted by 곽중선