블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 


SSO를 위한 CAS 프로토콜 소개

Authorization Control을 위한 XACML 에 대한 개념 정리

SSO를 위한 SAML


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

IDM (계정관리) 관련 몇가지 표준  (0) 2013.05.15
보안,Certification, Signing,Signature etc (작성중)  (0) 2013.03.30
XA Spec  (0) 2008.06.10
FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27

메모


개념 잡기

Certification

Signature

Signing

Key



Signed certificate <-- Signed by Certification Authority (CA : 인증 기관) / Verisign 등

Self-Signing certificate



PKI 기반 (공개키)

http://www.verisign.com.au/repository/tutorial/digital/intro1.shtml


public key

Not at all secret!
Widely available, but must be trusted
May be supplied as part of a certificate
If you send something using a public key, it can only be read by the entity to which it is addressed.
Secure communications
(But secure communications (e.g. SSL) isn’t quite as simple as that!)

How ca i trust public key?

Someone can use a public key to prove their identity to me
but only if I trust that public key
there's public keys out there that say they belong to George Bush etc.
So if someone I trusted endorsed (signed) that public key
hold that thought for a moment...

Signing with key

Keys can be used to sign things
encrypt a bit of text with your private key (can be attached 'securely' to the 'document')
people can de-crypt it with the public key and know that it was signed by you


How can i trust public key?

Put that public key on a certificate
Get someone you trust to sign the certificate
If the certificate is tampered with, the signature is broken
Organisations who sign public keys/certificates are called Certification Authorities (CA)

PKI
You create a key pair
Put one key of the pair on a certificate
Send the certificate (request) to the CA
Present yourself or identify yourself to the Registration Authority (RA)
The RA tells the CA that you are OK
The CA sends you the signed certificate

Now you have a signed certificate, people and services can trust that you are who you say you are

Present your certificate to a service
Tell them something encrypted by your private key
They like your certificate and know it is you
You keep your private key very secret
Obey the rules for this!
Your public key is on the certificate
Services must trust the CA
Your certificate will have an expiry date
after which you may have to re-visit the RA
Your certificate can be revoked at any time


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

IDM (계정관리) 관련 몇가지 표준  (0) 2013.05.15
보안,Certification, Signing,Signature etc (작성중)  (0) 2013.03.30
XA Spec  (0) 2008.06.10
FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27

XA Spec

프로그래밍/프로그래밍팁 | 2008.06.10 18:05 | Posted by 조대협

맨날 봐도 까먹는 스펙

XA recovery 관련
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

IDM (계정관리) 관련 몇가지 표준  (0) 2013.05.15
보안,Certification, Signing,Signature etc (작성중)  (0) 2013.03.30
XA Spec  (0) 2008.06.10
FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27
TAG 2pc, XA, XOPEN

FILE IO 향상 방법

프로그래밍/프로그래밍팁 | 2008.03.11 18:21 | Posted by 조대협
http://www.javaworld.com/javaworld/jw-08-2002/jw-0802-performance.html?page=4

Native IO에서 MemoryMappedBuffer와 ByteBuffer를 이용한 성능 테스트 샘플
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

보안,Certification, Signing,Signature etc (작성중)  (0) 2013.03.30
XA Spec  (0) 2008.06.10
FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27
JDK 1.5 부터 등장한 ThreadPool  (0) 2008.02.27

Work load manager in JEE

프로그래밍/프로그래밍팁 | 2008.02.29 14:45 | Posted by 조대협

JEE에서도 멀티쓰레드 프로그래밍이 가능하게 되었다.

http://dev2dev.bea.com/pub/a/2005/05/parallel_tasks.html?page=1

정말 좋은데? JEE 표준에는 안들어가나?

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

XA Spec  (0) 2008.06.10
FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27
JDK 1.5 부터 등장한 ThreadPool  (0) 2008.02.27
SQL Batch  (0) 2007.11.28

NIO

프로그래밍/프로그래밍팁 | 2008.02.27 14:43 | Posted by 조대협

JDK 1.5에는 서버 애플리케이션을 만드는데 필요한 거의 모든것이 다 들어가 있는 듯하다.
아래 포스트한 Thread Pool이외에서 JDK 1.4 부터 포함된 NIO에서는
Socket에 대한 Multiplexing이 가능한 API를 제공한다.

http://www.onjava.com/pub/a/onjava/2002/10/02/javanio.html
http://www.onjava.com/pub/a/onjava/2002/09/04/nio.html

고객사에 이슈가 있어서 검토중인데.. 간만에 재미있는 장난감 찾았다... 정리되면 나중에 다시 포스팅 해야겠다.
^^

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

FILE IO 향상 방법  (1) 2008.03.11
Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27
JDK 1.5 부터 등장한 ThreadPool  (0) 2008.02.27
SQL Batch  (0) 2007.11.28
대용량 Record select  (0) 2007.11.28
Thread Pool이라는 것이 얼핏 생각하면 구현이 간단할 수 도 있지만, 막상 구현하려면 상당히 귀찮은데, JDK 1.5에 이 내용이 포함되어 있다.
상당히 설계도 잘한것 같아서 마음에 드는데..
이정도면 쉽게 웹서버정도는 만들 수 있지 않을까?

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html#execute(java.lang.Runnable)

생성자를 잠깐 살펴보면

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)

* corePoolSize : Pool의 MIN크기
* maximumPoolSize : Pool의 MAX 크기
* keepAliveTime : Thread가 Idle이고 현재 전체 쓰레드수가 corePoolSize보다 많을때, 이 시간동안 Idle한 쓰레드는 없어진다. (Thread shirinking)
* keepAliveTime 단위
* workQueue : 쓰레드 풀에 대한 큐.
큐잉을 안하는 방법도 있고,
여러가지 정책이 있는데
Queuing
Any BlockingQueue may be used to transfer and hold submitted tasks. The use of this queue interacts with pool sizing:
  • If fewer than corePoolSize threads are running, the Executor always prefers adding a new thread rather than queuing.
  • If corePoolSize or more threads are running, the Executor always prefers queuing a request rather than adding a new thread.
  • If a request cannot be queued, a new thread is created unless this would exceed maximumPoolSize, in which case, the task will be rejected.
There are three general strategies for queuing:
  1. Direct handoffs. A good default choice for a work queue is a SynchronousQueue that hands off tasks to threads without otherwise holding them. Here, an attempt to queue a task will fail if no threads are immediately available to run it, so a new thread will be constructed. This policy avoids lockups when handling sets of requests that might have internal dependencies. Direct handoffs generally require unbounded maximumPoolSizes to avoid rejection of new submitted tasks. This in turn admits the possibility of unbounded thread growth when commands continue to arrive on average faster than they can be processed.
  2. Unbounded queues. Using an unbounded queue (for example a LinkedBlockingQueue without a predefined capacity) will cause new tasks to be queued in cases where all corePoolSize threads are busy. Thus, no more than corePoolSize threads will ever be created. (And the value of the maximumPoolSize therefore doesn't have any effect.) This may be appropriate when each task is completely independent of others, so tasks cannot affect each others execution; for example, in a web page server. While this style of queuing can be useful in smoothing out transient bursts of requests, it admits the possibility of unbounded work queue growth when commands continue to arrive on average faster than they can be processed.
  3. Bounded queues. A bounded queue (for example, an ArrayBlockingQueue) helps prevent resource exhaustion when used with finite maximumPoolSizes, but can be more difficult to tune and control. Queue sizes and maximum pool sizes may be traded off for each other: Using large queues and small pools minimizes CPU usage, OS resources, and context-switching overhead, but can lead to artificially low throughput. If tasks frequently block (for example if they are I/O bound), a system may be able to schedule time for more threads than you otherwise allow. Use of small queues generally requires larger pool sizes, which keeps CPUs busier but may encounter unacceptable scheduling overhead, which also decreases throughput.

일반적으로 LinkedBlockingQueue를 사용하면 문제는 없을듯하고, Queue의 MAX길이를 지정하고, QueueFull 시에 충분한 Exception 처리를 해주는것이 좋을듯하고
- threadFactory : 풀 크기를 느릴때 생성되는 쓰레드를 생성하는 팩토리
- handler : 풀이나 큐가 차서 처리를 못할때, Reject에 대한 처리를 하는 Handler

실제 Q에서 작업을 꺼내와서 수행하는 방법은
execute(Runnable r)을 사용하면 되고

흥미로운것은 (Hooking)
execute 전후에 훅킹 메서드를 beforeExecute,afterExecute를 넣을 수 있다는 것

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

Work load manager in JEE  (0) 2008.02.29
NIO  (0) 2008.02.27
JDK 1.5 부터 등장한 ThreadPool  (0) 2008.02.27
SQL Batch  (0) 2007.11.28
대용량 Record select  (0) 2007.11.28
Java Application의 Locking 처리문제  (0) 2007.08.21

SQL Batch

프로그래밍/프로그래밍팁 | 2007.11.28 15:27 | Posted by 조대협

대용량 SQL을  한꺼번에 수행할때

for(..){
 pstmt.setXX
 pstmt.executeUpdateXX
}
tx.commit

이 코드는 느리다.
for(..){
 pstmt.setXX
 pstmt.addBatch
}
pstmt.executeBatchXX
tx.commit

이렇게 하는게 성능에 5~10배까지 차이가 난다.

===

아래는 직접 테스트 한 코드 10배 정도 차이가 나는것을 볼 수 있다.

<%

        Context ctx = new InitialContext();
        javax.sql.DataSource ds = (javax.sql.DataSource)
                ctx.lookup("bchoDS");
        Connection conn = ds.getConnection();
        conn.setAutoCommit(false);
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("delete from bcho");
        conn.commit();
        stmt.close();

        long start = System.currentTimeMillis();
        out.println("start :"+start);

        String sql = "insert into bcho values( ?,'seoul')";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        for(int j=0;j<10;j++){
          for(int i=0;i<10000;i++){
                pstmt.setString(1,"DUMMY");
                pstmt.executeUpdate();
          }
          Statement cstmt = conn.createStatement();
          cstmt.executeUpdate("commit work write batch nowait");
          cstmt.close();

        }// for j
        pstmt.close();
        conn.close();

        long end = System.currentTimeMillis();
        out.println("<BR>end :"+end);
        out.println("<BR>elapsed :"+(end-start));

%>


==== 아래는 BATCH

<%

        Context ctx = new InitialContext();
        javax.sql.DataSource ds = (javax.sql.DataSource)
                ctx.lookup("bchoDS");
        Connection conn = ds.getConnection();
        conn.setAutoCommit(false);
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("delete from bcho");
        conn.commit();
        stmt.close();

        long start = System.currentTimeMillis();
        out.println("start :"+start);

        String sql = "insert into bcho values( ?,'seoul')";
        PreparedStatement pstmt = conn.prepareStatement(sql);

        for(int j=0;j<10;j++){
          for(int i=0;i<10000;i++){
                pstmt.setString(1,"DUMMY");
                pstmt.addBatch();
          }
          pstmt.executeBatch();
          conn.commit();

        }// for j
        pstmt.close();
        conn.close();

        long end = System.currentTimeMillis();
        out.println("<BR>end :"+end);
        out.println("<BR>elapsed :"+(end-start));

%>


BATCH elapsed :270  msec
COMMIT elapsed :24512 msec

===

애플리케이션에서 다른 업무와 함께 테스트 했을때는 2배 정도 차이가 났음.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'프로그래밍 > 프로그래밍팁' 카테고리의 다른 글

NIO  (0) 2008.02.27
JDK 1.5 부터 등장한 ThreadPool  (0) 2008.02.27
SQL Batch  (0) 2007.11.28
대용량 Record select  (0) 2007.11.28
Java Application의 Locking 처리문제  (0) 2007.08.21
업그레이드된 개발자 되기  (5) 2007.08.20

대용량 Record select

프로그래밍/프로그래밍팁 | 2007.11.28 15:26 | Posted by 조대협

게시판 리스트등 가지고 오는데 유용하겠다.

Stmt.setFetchSize
를 이용할것..

=====
참고: ResultSet에서도 FetchSize 적용가능. 양쪽에 차이점과 성능 테스트는 시간날때 정리 필요

e244. Setting the Number of Rows to Prefetch When Executing a SQL Query

When a SQL query is executed, the number of rows of data that a driver physically copies from the database to the client is called the fetch size. If you are performance-tuning a particular query, you might be able to improve performance by adjusting the fetch size to better match the use of the query.

The fetch size can be set on a statement, in which case, all result sets created from that statement will use that fetch size. The fetch size can also be set on a result set at any time. In this case, the next time data needs to be fetched from the database, the driver will copy over as many rows as is specified by the current fetch size.

    try {
        // Get the fetch size of a statement
        Statement stmt = connection.createStatement ();
        int fetchSize = stmt.getFetchSize();
    
        // Set the fetch size on the statement
        stmt.setFetchSize(100);
    
        // Create a result set
        ResultSet resultSet = stmt.executeQuery("SELECT * FROM my_table");
    
        // Change the fetch size on the result set
        resultSet.setFetchSize(100);
    } catch (SQLException e) {
    }



====
http://sangchin.byus.net/FlashHelp/Java_sql/getfetchsize.html

3. Do batch retrieval using Statement

You can get the default number of rows that is provided by the driver. You can improve performance by increasing number of rows to be fetched at a time from database using setFetchSize() method of the statement object.

Initially find the default size by using

Statement.getFetchSize();   and then set the size as per your requirement

Statement.setFetchSize(30);

http://www.precisejava.com/javaperf/j2ee/JDBC.htm

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Java AP에서 Locking처리 방법은 Synchronized 를 사용하는 방법이 대표적인데
이 경우에는 하나의 JVM Instance 내에서만 동기화 처리가 가능하다.

시스템을 설계할때, 다중 인스턴스 구조의 부하 분산 환경을 고려한다면, 인스턴스내의 Locking 처리인지 아니면 인스턴스간의 Locking처리가 필요한지를 먼저 결정해야 하고, 인스턴스간의 Locking처리인 경우에는 DB나 아니면 기타 (RMI,JMS등) 방법을 사용하는 방식이 있다.

특히 DB의 Lock 처리 메커니즘을 생각할때 고려할 부분은
보통 다음과 같은 구조로 만드는 경우가 많다.
1: select LOCK
2: if( unlocked){
3: update set LOCK
4: }else { return "Lock이 걸려있음"}
5: 임계구역

그러나 이경우, 두개의 인스턴스 A,B가 있다고 했을때
A가 1을 수행하고 Lock이 없어서 Lock을 잡으려고 시도해서 2라인에 진입했다.
이때 B가 Lock체크를 하기 위해 1에 진입하였다면?
A가 아직 Lock을 잡기 전이기 때문에, 결과적으로 A,B 두개 모두 임계구역에 진입하게 된다. Single Instance인 경우에는 당연히 Synchronized처리로 해결하면 되겠지만,
Multi Instance 인경우 다음과 같은 방안이 있다.

1) select하기 전에 해당 row에 DBLock을 거는 방법
2) select하지 않고 update의 return값으로 체크하는 방법

1) 방안은 DB마다 다르기 때문에 별도로 설명하지 않고
2)의 방안을 보면
1: ret = stmt.exeucteUpdate("UPDATE LOCK");
2: if(ret == 0){ return "Lock이 걸려있음"}
3: 임계구역

stmt.executeUpdate는 update에서 반영된 레코드수를 리턴하기 때문에 이미 lock에 대한 update가 된경우에는 0을 리턴한다.
※ 그러나 JDBC 드라이버에 따라서 executeUpdate에 대해서 update에 대한 리턴값이 무조건 0인경우가 있을 수 있기 때문에 반영전에 테스트를 필요로 한다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

월간 마이크로소프트웨어 9월에 기고한글
짧은 시간에 작성해서 완성도는 낮지만 고려해서 읽어주세요.

==

시점의 변화

 

소프트웨어 개발은 컴퓨터를 가지고 개발자가 하는 작업이다. 그러나 좀더 깊게 생각해보면 소프트웨어 개발은 결국 사람과 사람이 하는 작업이다.

 소프트웨어 개발 작업을 하는 데 있어서, 기술적인 면이 아닌 생각하고 일을 하는 면에서 조금 관점을 변화시켜야 할것들을 살펴보자.

 

1.       지금 무엇을 하고 있는가?

소프트웨어 개발 프로젝트뿐만 아니라, 지금 하고 있는 일의 의미와 목적에 대해서 생각해 본적이 있는가? 모든 일에는 그 목적을 위해서 제때 적절한 사람이 해야 할 일이 있기 마련이다.

 일을 하다 보면, 일에 대한 목적과 원래 의미는 잊혀지고 전혀 엉뚱한 이슈에 많은 시간을 낭비하는 경우가 많다. (원래 목적과는 상관없는 이슈로 삼천포로 빠져서  몇 시간씩 회의를 해본 일이 있다면 쉽게 이해할 수 있지 않을까?)

소프트웨어 프로젝트의 실패 원인중의 대부분은 무엇을 왜 만들고 있는가, 고객의 요구 사항을 제대로 파악하지 못하는데 있다.

프로젝트 중반에 오픈을 앞두고, 고객의 수정사항은 늘어가고, 기능적인 면보다는 화면 디자인의 색이나 폰트 사이즈에 더 민감한 것이 고객이다. 또한 대부분의 고객은 자신이 원하는 바가 무엇인지 제대로 알지 못하는 경우가 많지만, 고객 자신이 좋아하고 좋아하지 않는 것에 대해서는 정확하게 알고 있다.

 성공적인 프로젝트를 위해서는 가장먼저 고객의 요구 사항을 적절하게 파악하는 것이 중요하다.

UML Use Case Diagram이나 스토리보드등이 매우 효율적으로 사용될 수 있으며, 간단한 HTML또는 RIA(FLEX etc) 4GL (VB)로 만든 기능이 없는 스토리 위주의 샘플 애플리케이션은 고객의 요구 사항을 수집하는데 매우 좋은 도구가 될 수 있다. 복잡한 비즈니스 프로세스가 있는 업무의 경우에는 BPA등의 도구를 사용하여 워크플로우를 시각화 시켜놓으면 복잡한 흐름을 일목요연하게 정리할 수 있다.

이런 도구들을 이용하여 수집한 요구사항에 대해서 고객으로부터 확인을 받아놓는다면, (회의록에 대한 싸인이나, 위의 산출물에 대한 고객확인을 받아 놓는 것) 이러한 요구 사항에 따라 스케쥴된 일정에 새로운 변경 사항이 가미되었을 경우에, 합당하게 개발 비용과 시간을 요구할 수 있을 것이다.

소프트웨어 개발 프로젝트는 고객의 요구 사항만 제대로 파악하고 있어도, 80%는 성공한것이다.

 

* TAG: 요구사항 분석,Use case diagram, sample software, 복잡한 비즈니스 프로세스, 워크플로우, BPA

 

2.       닭 잡는데 소 잡는 칼 사용하기

모든 기술 역시 그 태생에 목적과 이유를 가지고 있다.

소프트웨어 개발에서 중요한 점 중에 하나가, 현재 소프트웨어 개발 규모와 요구사항에 맞게 적절한 기술을 사용하는 것이다. 일반적으로 개발자들은 기술적인 호기심에 의해서 신기술에 대한 도입에 대한 욕심이 많다. 매니져는 매니져 나름데로 신기술을 적용한 시스템이라는 업적을 원한다.

 그러나 그런 기술들은 그만큼의 습득 시간과 비용을 요구한다.

예를 들어 몇 년전 EJB 붐이 일었을 때, 많은 사이트들이 값비싼 WAS를 도입해서 개발을 한적이 있다. EJB는 분산 컴포넌트와 트렌젝션의 보장이 가장 큰 장점이다. 정작 이런 사이트들에서 그런 고차원적인 트렌젝션 처리가 필요한 경우가 얼마나 있었을까? 그 당시 많은 사이트들이 고가의 WAS를 도입했음에도 불구하고 WAS를 단순한 JSP/Servlet 컨테이너 수준정도로 밖에 사용 못하거나, EJB역시 단순한 POJO식의 Business Object 이상으로 사용하지 못한 경우를 많이 봤다.

 

요즘 같이  JSTL,WebWork,Struts,Spring,OR Mapper,AOP …etc 와 같은 각종 오픈소스 프레임웍과 새로운 개념들이 난무하는 세상에서 잘못하면 신기술에 대한 욕심으로 무리한 선택을 할 수 있다. 프레임웍과 기술은 도구일 뿐이다. 아무리 좋은 도구라도 사용법을 제대로 알지 못한다면, 이런 도구들을 오히려 소프트웨어 프로젝트에 해가 될 수 있다.

 어린아이에게 크리스마스 선물로 망치를 선물해주면, 어린아이는 그때부터 망치질할 곳만 찾아다니게되고, 친구따라 강남간다고 너도나도 이야기하는 기술들에 대해서는 한번즘 공부해보고 싶은 욕심이 들게 마련이다.

 그러나 한번더 생각해보자,  소프트웨어 개발을 위해서는 시스템 기능과 요구사항에 적합한 적절하고 사용하기 쉬운 기술이 선택되어야 하며, 기술을 도입하는데에는 그만한 도입에 대한 비용 (구입비용 뿐만 아니라 교육과 습득 시간에 대한 비용)이 고려되어야 한다.

 

*  TAG : 오픈소스, 개발자와 메니져의 욕심, 도구는 도구일뿐, 적절한 도구 사용하기

 

3.       Simple is best. Easy is best.!!

모든 기계가 그렇듯이, 복잡한 기계일수록 고장이 잘난다.

소프트웨어도 마찬가지이다. 복잡한 아키텍쳐일수록 문제가 생겼을 경우에 디버깅하기가 어렵고, 변경 사항이 생겼을 때 반영하기가 어렵다. 디자인 패턴으로 무장한 컨설턴트가 와서 시스템을 온통 디자인패턴으로 도배해놓을 수 도 있다. 그렇지만 그것을 디버깅해야 하는 것은 그 컨설턴트가 아니라 개발자 여러분이다. (디자인 패턴이 나쁘다는 것은 아니다. 불필요한 패턴 사용으로 시스템의 복잡도를 올리는 것에 대한 이야기다.)

 가능하면 시스템은 간단하게 설계하자, 고수가 설계한 시스템일 수 록 단순하고 고장이 작다.

 

CORBA라는 기술을 들어본적이 있는가? CORBA는 분산객체 기술로 이기종간의 통신이 가능하고 트렌젝션을 보장하는 등의 기능을 가진 기술로 소개될 당시에 모든 프로그램들은 CORBA로 개발될 줄 알았다. 모두들 CORBA를 공부하고, 몇몇 프로젝트는 CORBA로 구현이 되었다. 그러나 CORBA가 지금 널리 사용되고 있을까?

 좋은 기술이나 개념은 천재의 머릿속에서 나올 수 있다. 그러나, 사용하는 사람은 천재보다는 범인이 사용하게 된다. 천재들의 수준에 맞춰 개발된 기술들이 범인들이 쉽게 사용할 수 있을까?

 인기 있게 널리 오래 사용되는 기술은 대부분 개념을 이해하기 쉽고 사용하기 쉬운 기술이다.  정말 고수들이 만들어내는 각종 이론들로 무장한 시스템들이 아니라, 이해하기 쉬운 시스템이다.

 

* TAG : 간단할 수 록 튼튼하다. 쉬운 기술이 널리 퍼진다.

 

4.       깊게.. 그리고 넓게..

기술을 깊게 공부해야 하는 것은 당연한 이야기이지만,지식의 깊이와 폭에 대한 균형이 필요하다는 이야기다.

 예를 들어, Socket 프로그래밍을 할 때, JAVA의 경우 Multiplexing성능이 떨어지기 때문에, C언어로 MultiPlexer를 구현하고 JNI로 연결하면 훨씬 더 좋은 성능을 낼 수 있다.

 화면이 많고 권한 처리가 복잡한 엔터프라이즈 솔루션의 경우에는 Enterprise Portal과 같은 솔루션을 선택하면 시행착오를 줄이면서 양질의 소프트웨어를 만들어 낼 수 있다.

 SAP CRM등을 통합할 때, 모두 자신이 강점이 언어로 개발 할 수 있지만, 그보다는 EAI솔루션을 사용한다면 쉽고 성능 좋은 시스템 통합을 이끌어 낼 수 있다.

 어느정도 수준의 개발자라면, 고객의 요구사항을 구현하는 것은 어려운 일은 아니라고 본다.

그러나 이미 구현되어 있는 솔루션이나 오픈소스에 아키텍쳐에 대한 지식이 있다면 처음부터 구현하는 것 보다 그것들을 이용해서 주어진 시간과 비용 내에서 시행착오를 줄이고 양질의 소프트웨어를 만들어 낼 수 있다.

 

* TAG : 이미 있는 것들 찾아보기, 활용하기, 폭넓은 지식 가지기

 

5.       마일 스톤

마일 스톤이란 이정표라는 뜻으로 프로젝트 일정중의 중요시점으로 생각하면 된다. 예를 들어 요구 사항 분석 완료 시점, 각각 컴포넌트 완성 시점, 릴리즈 시점, 알파,베타 테스트 시기 등이 이에 속한다.

 마일스톤을 설정하는 이유는 마일스톤전의 작업에 대한 검증을 통해서 발생한 문제를 다음 단계까지 전파시키지 않기 위해서 문제를 찾아내고 확인하기 위함이며, 요즘의 개발 방법론들이 잦은 Release Feed Back등을 강조하는 것 역시 잦은 마일 스톤을 설정함으로써 문제를 가능한 한 빨리 발견하고 풀어내기 위함이다.(불확실성의 제거)

 마일 스톤이 설정된 주기는 각각이 전체 프로젝트에 대한 미니프로젝트가 되며, 각 마일스톤시 필요한 최소한의 산출물에 대한 정리와 검증(확인을 통한 문제 발결)이 뒤따라야 한다.

정확한 마일 스톤을 설정한다면, 소프트웨어 개발 프로젝트에서 발생할 수 있는 위험 요소를 줄이는 데 큰 도움이 될것이다.

 

 

나만의 도구를 갖추자

소프트웨어 개발에 있어서 IDE Debugger와 같은 툴은 생산성에 지대한 영향을 준다. 개발자라면 적어도 자기가 가지고 다니는 도구세트는 하나 있어야하지 않을까? 여기서는 이미 많이 알려진 IDE Debugging툴보다, 소프트웨어 프로젝트에 필요한 각종 자동화 도구에 대해서 간략하게 소개한다.

 

1.       소스 관리

일주일전에는 잘 돌아가던 모듈인데 일주일동안의 작업 내용이 반영된 후에는 몬가 문제가 생겼다. 어떻게 해야할까? 어느 부분을 수정했는지 알 수 있다면 좀더 빨리 문제의 원인을 밝혀낼 수 있지 않을까?

 운영중인 시스템이 새로운 코드를 반영한 후에 문제가 생겼다. 수정한 부분을 찾는 것보다 이전의 소스 코드로 원상복귀 하는 것이 운영을 정상화 하는데 더 빠르다. 그렇다면 예전에 개발한 소스는 어디에 있을까?

 고객별로 릴리즈한 버전이 많은데 A고객의 이슈를 해결한 버전은 도대체 어느 버전일까?

여러 사람이 협업 작업을 한다면, 공통으로 소스코드는 어떻게 관리해야 할것인가?

소스를 한곳에서 중앙 집중 관리하고, 협업을 가능하게 해주며, 소스에 대한 변경 내역을 관리할 수 있도록 해주는 것이 소스 관리 시스템이다.

 널리 사용되고 있는 무료 소스 관리 시스템은 CVS SubVersion이 있다.

 

TAG : 소스 관리, CVS,SubVersion

 

2.       빌드 도구

빌드는 소프트웨어 개발에서 항상해야 하는 작업이다. (물론 JSP ASP등의 스크립트 언어로만 개발한다면 모르겠지만.) 컴파일하고 기다리고 결과가 나오면 검증하고 에러가 없으면 릴리즈(또는 배포)하고 항상해야 하는 반복적인 작업이다.

 에러가 발생하지 않는 상황이라면 특별하게 할일도 없다. 우리가 빌드를 기다리는 것은 혹시나 있을지 모르는 에러에 대해서 대비하기 위해서 일뿐 빌드와 배포는 커맨드들을 반복해서 입력하는 단순작업에 해당한다.

 이런 단순작업을 내가 아닌 누군가가 해준다면, 그 시간에 코드를 최적화 하거나 좋은 소프트웨어 구조로 리펙토링을 하는등의 생산적인 작업을 할 수 있지 않을까?

 그 누군가가 바로, 빌드 자동화이다.

기본적인 도구로는 make,ant,maven과 같이 커맨드들을 조합하여 빌드를 해주는 도구가 있고,

여기에, Daily Build (Daily Build의 중요성은 여기서 언급하지 않더라도, 조엘 온 소프트웨어 와 같은 유수 개발 관련 서적에서 이미 많이 언급되어 있다.)나 스케쥴에 따른 빌드나 Release 버전 생성을 자동으로 수행해주는 빌드 자동화 소프트웨어가 있다. 이러한 소프트웨어들은 빌드 배포에 대한 스케쥴링뿐만 아니라, 자동화된 릴리즈 버전 생성등이 가능하고, 빌드중의 에러에 대해서 담당자에게 SMS 또는 EMAIL등으로 ALERT을 해주는 기능을 가지고 있기 때문에, 대규모 협업 프로젝트에서 매우 유용하게 사용될 수 있다.

 대표적인 공개 소프트웨어로는 Cruise Control, Ant Hill 등이 있다. Cruise Control Text 기반의 도구로 매우 강력한 빌드 자동화 기능을 제공하지만 Text 기반이기 때문에 다소 사용하기가 어렵다. Ant hill의 경우에는 Web UI를 제공하기 때문에 상대적으로 상용하기는 쉽지만 대신 Cruise Control과 같은 강력한 기능을 제공하기는 어렵다.

그리고, 빌드 과정중에 빌드된 컴포넌트가 제대로 작동하는지 여부를 자동으로 테스트하기 위해서 JUnit과 같은 테스트 프레임웍이 있다.

 

 빌드 자동화는 ant와 같은 빌드 도구,JUnit과 같은 테스트 도구, 그리고 Cruise Control등과 같은 빌드 자동화 도구로 구성이 되고, 빌드와 릴리즈(배포)를 수행함으로써, 시간 절약은 물론 품질에 대한 향상까지 기대할 수 있다.

 

*  TAG: ant,maven,cruise control,anthill,JUnit

 

3.       테스트 도구

 

테스트와 QA(Quality Assurance)에 대한 중요성은 언급하지 않더라도 이미 잘 인식하고 있으리라 믿는다. 테스트의 종류에는 컴포넌트별 단위 테스트, 시나리오에 따른 기능 테스트, 적절한 용량을 커버하고 성능을 낼 수 있는지를 검증하는 부하 테스트, 그리고 장애에 대한 대처 능력을 시험하는 장애 테스트등이 있다.

 그 중에서 테스트팀이나 QA팀이 아닌 개발자들이 일반적으로 수행할 수 있는 테스트로는 컴포넌트별 단위테스트와 부하테스트가 있다.

 단위테스트는 소프트웨어 개발 주기중 테스트 단계에서뿐만이 아니라 개발단계 중간에서도 컴포컴포넌 제작될 때 마다, 모듈의 기능을 검증하여 버그를 예방할 수 있다.

단위테스트는 JUnit등의 단위 테스트 자동화할 수 있으며, 위에서 설명한 바와 같이, 빌드절차에 자동화하여 포함하여 빌드때마다, 개발한 컴포넌트의 기능의 이상 여부를 검증할 수 있다.

 부하테스트는 소프트웨어의 비기능적인요소인 성능이나 용량을 측정하는데 사용되는데, 개발자 단계의 부하테스트를 통하여, 알고리즘의 최적화 여부나 과부하시에 장애 (Dead Lock, Lock 대기 현상,CPU 과점유)를 검증할 수 있다.

 부하테스트 도구로는 상용으로 머큐리의 Load Runner가 널리 사용되며, 무료 도구로는 Microsoft MS-Stress, Apache 오픈소스 그룹의 JMeter등이 있다.

 이러한 테스트에서 가장 중요한 것은 장애나 오류를 발생할 수 있는 시나리오를 추출해내고 이를 테스트에 적절하게 반영하는 것이다.

 여기서는 간단하게 기능적 비기능적 테스트에 대한 간단한 도구만을 소개했지만, 테스트 방법론이나, 테스트를 위한 조직 구조에 대한 고려등 여러가지 고려할 사항이 많다.

 

TAG: 단위 테스트, 기능 테스트,성능 테스트,JUnit,MS Stress, JMeter, Load Runner

 

4.       커뮤니케이션 도구

팀원간의 작업 배분, 이슈에 대한 기술적인 토론, 고객의 변경된 요구 사항의 반영 내용, 그리고 버그에 대한 이슈 등. 이런 이슈들을 해결해나가는 것이 개발이라고 할 수 있다.

보통 이런 이슈들은 회의나 이메일 전화등을 통해서 이루어지는데, 각각의 이슈에 대해 서로 이야기한 내용과, 협의한 내용들에 대해서 문서화하여 추후에 이슈에 대해서 어떻게 대처를 하고 소프트웨어 코드에 반영을 했는지를 추적해야할 경우가 있다.

 또는 현재 소프트웨어 개발에 몇가지 이슈가 남아 있으며, 이슈의 중요도별로 남아 있는 것들은 몇 개인지 각 이슈를 해결하는데 소요된 시간은 얼마인지를 측정하는 것은 프로젝트 관리에서 중요한 비중을 차지 한다.

 이런 이슈에 대한 추적과 커뮤니케이션을 가능하게 해주는 것이 Issue Tracking 시스템이다. 이슈를 오픈하고, 관련된 사람을 추가하며, 이슈에 대한 진행 상황과 중요도를 기입함으로써 현재 시스템에 대한 이슈가 어떤 것이 있고, 진행되고 있는 상태를 쉽게 관리할 수 있게 해준다.

해당 이슈가 반영된 버전을 기입하여, 어느 버전에 문제가 있는지 해결되었는지를 판단하게 해서, 적절한 Release 버전을 판단할 수 있도록 한다.

그리고 이슈가 해결 되었을때는 SubVersion과 같은 소스 관리 시스템에서 이슈를 해결한 Revision Number Issue Tracking 시스템에 기입하여, 이슈를 어떤 식으로 소스코드에 반영하였는지를 추적할 수 있도록 한다.

 주로 버그 관리에 많이 사용되는데, 그 외에 개발의 요구 사항을 반영하는데에도 응용할 수 있다. 대표적인 소프트웨어로는 BugZilla, JIRA와 같은 소프트웨어가 있다.

 

 TAG : Issue Tracking System, Bugzilla, JIRA

 

튼튼한 소프트웨어를 만드는 관점 갖추기

마지막으로 실제 개발을 할 때, 생각해야할것 몇가지만 짚고 넘어가도록 하자.

 

1.       개발자는 메모리로부터 자유로울 수 없다.

자바언어가 나오면서 개발자들은 malloc free (C언어에서 메모리를 할당하는 함수) 에서부터 자유로워졌다. Garbage Collector라는 강력한 기능이 자동으로 메모리를 관리해준다.

그렇다면 진정 우린 메모리에서 자유로울 수 있을까?

 32 Bit 머신을 가정했을 때, 32 Bit 머신의 프로세스당 메모리 사용량은 2^32=4G이다. 여기서 Unix의 경우 이중 2GB는 공유 메모리 영역이고 실제 자바가 사용할 수 있는 것은 2GB이다.

이중에서 Class Method가 올라가는 Perm영역역이 대략 64~256M 그리고 JVM자체가 로딩되는 메모리 영역을 다 합하면, 실제로 자바 애플리케이션의 Heap Size는 최대 1.5~1.7GB 내외이다.

그 영역 안에서도 애플리케이션의 기본적으로 꾸준히 사용되는 영역이 400~500M라면, 일반적으로 1G 안에서 프로그래밍을 해야한다는 이야기다.

 종종 장애를 일으키는 코드를 보면 SQL 에서 select한 결과를 메모리에 유지하게 하였는데, select record 수가 많아서, 메모리 부족현상을 일으키거나, 메모리 사용량이 매우 많아서 잦은 Garbage Collection으로 시스템의 성능이 떨어지는 것을 어렵지 않게 볼 수 있었다.

 물론 64Bit JVM이 출시되고 GC의 성능이 좋아지면서 메모리에 대한 부담이 덜어져가는 것은 사실이지만, 소프트웨어를 개발한다면 항상 메모리 사용에 대한 고려를 가지고 시스템을 설계해야 한다.

* TAG: 메모리 신경 쓰기

 

2.       성능에 대해 고민하기

성능에 대해서 개발자들 만큼 민감한 사람들이 또 있을까? 인터넷 문서들을 봐도 튜닝에 대한 문서들은 빠지지 않고 인기문서중 하나이다.

 그렇지만, 코드는 정말 최적의 성능을 낼 수 있도록 구현 되어 있을까?

직접 작성한 코드를 1~2User 기반에서 테스트 했을때는 잘 돌아간다. 그렇지만 실환경이 1~2User가 아니라 여러명의 동시접속자를 지원하는 서비스라면?

 SQL 문장이나 잘못된 Synchronized처리등은 실환경이나 동시 사용자가 많지 않으면 성능에 영향을 주지 않는다.

 성능에 대한 좋은 가이드와 프로그래밍 방법은 항상 고민해야 하는 문제이고, 거기에 성능에 대한 검증을 어떻게 할것인지를 고려해서 코드를 만들어보는 것은 어떨까?

컴포넌트 별로 테스트시에 Profiler APM-Application Performance Management Tool등을 이용하면 도움이 되고 간단한 부하테스트를 더한다면 성능상에 문제가 있는 코드가 아닌지 좀더 쉽게 검증 할 수 있다. 물론 어느정도 경험이 쌓인다면 이런 도구 없이도 코딩시에 성능에 문제가 되는 코드의 대부분은 걸러낼 수 있겠지만 말이다.

 

* TAG:성능 고려하기, 성능 테스트, Profiler,APM

 

3.       로깅 습관화

결함(Defect)이 없는 소프트웨어는 있을지 몰라도, 문제(Bug)가 없는 소프트웨어는 존재하지 않는다.

그러면 문제가 있을때 어떻게 빨리 발견하고 해결할 방법을 대비해야한다.

그런 방법중의 하나가 디버깅을 위한 LOGGING 처리이다.

LOGGING은 장애나 문제가 없을 때는 그다지 소용이 없는 코드이고 시간 낭비 처럼 보일 수 있지만. 잘 되어 있는 LOGGIN은 문제 해결 시간을 줄이는 데 큰 도움을 준다.

 그렇다고 LOGGING이 범람해서는 안된다. LOG 메시지도 비즈니스 로직처럼 설계가 필요하다.

(실제로 많은 LOGGING 메시지 때문에 운영 시스템에서 DISK IO를 많이 유발하여 성능 저하가 된 케이스를 종종봤다.)

 적절한 로깅에 대한 설계와 반영에 대한 습관을 들여놓도록 하자.

 

* TAG:Logging,Debugging

 

4.       장애 회피 코드 만들기

장애를 피해간다는 것은 정말 어렵다. 장애를 피할 수 있다면 버그가 발생하지 않을 것이다.

장애를 피하려면, 여러가지 상황을 예측해서 만들어 회피 코드를 만들 수 있겠지만, 예측 가능하다면 장애가 아닐 것이다.

그렇다면 어떻게 장애 회피 코드를 만들것인가? 장애에 대한 대처는 직접 장애를 겪어본 사람들의 경험에서부터 나온다. 그렇다고 장애에 강건한 코드를 만들기 위해서 몇 년동안 쫓아다닐 수 도 없는일이고. 답은 장애 경험에 대한 공유이다.

 WAS와 같은 미들웨어나 솔루션들은 이런 장애에 대해서 대처할 수 있는 방안들을 이미 제품안에 넣어놓았기 때문에 그만한 비용을 주고 구입하는 것이다.

 이러한 솔루션을 도입하는 방법이 있는 한편, 필자가 추천하는 것은 매주 진행할 수 있는 기술회의이다. 매주 기술회의를 하면서, 운영이나 개발상에서 겪었던 문제에 대해 공유를 한다면, 여러명의 경험을 한꺼번에 습득할 수 있을것이다.

 필자도, 지난회사에서 5년 가량을 매주 기술회의에 참석했다. 그때 얻었던 경험들은 덕택에 문제에 장애에 대한 시야기 달라지고 그에 대한 대처 방안도 다양해졌다.

 

* TAG: 장애 회피, 솔루션 도입, 기술 공유 회의

 

5.       기본기부터 충실하자.

무엇보다 기본기에 충실하자. 대학교 학부에서 배우는 자료구조,알고리즘,이산수학,공업수학,통계이론,운영체제 등등. 쓰지 않을 것 같지만 실제로 소프트웨어 개발과 시스템을 이해하는데 필수적이고 많이 필요하다.

 얼마전 인턴사원에게 Unix명령어중 tail(파일의 끝에서부터 지정된 라인수를 순차적으로 읽어오는 명령어) java로 구현하는 퀴즈를 낸적이 있었다.

대부분 전체 File Full Scan한후, 라인수를 Count한후, 다시 처음부터 지정된 라인수만큼 Skip  다음 읽는 알고리즘을 이야기 했다. 다른 누구는 전체를 메모리에 읽은후 다시 Count해서 출력하겠다라는 사람도 있었다.

만약 파일크기가 4G이고, 메모리가 1G라면? 전체를 한꺼번에 읽는 것은 불가능할것이다.

저장 매체가 Disk나 메모리처럼 직접 Access가 불가능한 Tape과 같은 순차Access만 가능한 매체라면, 100만 라인의 문서에서 끝에 100라인을 읽기 위해서 Tape 전체를 2번이나 Scan해야 한다.

 답은 seek 명령어를 써서 끝에서부터 순차적으로 읽어온다면 IO를 많이 줄일 수 있다. (실제로 필요한 만큼만 끝에서부터 파일포인터를 이동시킨후 다시 읽어내려오면 되니까는 전체 파일을 스캔할 필요가 없다.)

 누구나 개발자라면 기능적 요구 사항에 맞춰서 소프트웨어를 만들어낼 수 는 있다. 고수와 일반 프로그래머의 차이는 기능적 요구 사항을 구현해내는가 아닌가가 아니라, 비기능적인 요구사항(성능,장애,자원의 효율적인 배분)을 잘 구현해 내는 사람이라고 본다. (물론 커뮤니케이션이나 협업,일정 관리등에 있어서도 뛰어나야 겠지만.)

 이런 비기능적 요구사항에 대한 구현은 컴퓨터 공학의 기본이 튼튼한 사람일수록, 고품질로 구현할 수 있다.

 

 

 

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
 final static int MAX_CACHE_SIZE=20;
 static Map cache
  = new LinkedHashMap(MAX_CACHE_SIZE,0.75f,true){
     private static final long serialVersionUID = 1;
     @Override
     protected boolean removeEldestEntry (Map.Entry eldest) {
             return size() > MAX_CACHE_SIZE;
    }
   };
 private synchronized void putCache(String userId,List <ContactList> list){
  cache.put(userId, list);
 }
 private synchronized List<ContactList> getCache(String userId){
  return (List<ContactList>)cache.get(userId);
 }

생각보다 꽤나 유용하다...
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
 

티스토리 툴바