[개발철학] Simple more Simple

단순명료(單純明瞭)함.

  나의 개발철학은 이 한마디로 정리할 수 있을 듯 하다. 다른 이들이 보아도 나의 개발철학은 단순명료함을 유지하여 적은 시간을 투자하여 빠른 이해와 높은 활용성을 얻도록 하는 것을 목적으로 하고 있다. 나와 동문수학한 다른 이들을 도와주기 위해 그들이 작성한 코드를 가만히 들여보고 있자면, 한숨이 절로 나오는 경우가 있다. 자신이 지정한 변수가 어떤 타입인지 모르고 전혀 엉뚱한 타입으로 받아서 생기는 오류(이클립스와 같은 IDE 툴을 사용하는데도 종종 볼 수 있었다)에서 시작해서 자신이 생각해낸 알고리즘이 아니라, 단순히 인터넷 검색을 통해 나와있는 코드를 그대로 복사해서 붙이면서 발생한 이해불능의 기능으로 인해서 읽기 어려움에 빠진다. 그것을 보면서 나는 저렇게 해서는 안되겠다는 생각을 다짐하고 또 다짐했다. 그와 동시에 이런 나의 생각을 내 개발습관 속에 서서히 녹아들도록 만들었다. 철저하게 코딩스타일을 유지하며 낯설은 부분에서는 이해하기 쉽도록 주석을 첨가하고, 가급적이면 한줄에 하나의 명령어만을 구현하도록 노력했다. 코드는 자기가 봤을 때도 이해하기 쉽고 다른 사람이 봤을 때도 이해하기 쉽게 만들어져야 한다.

   C언어를 배우는 초기에는 컴퓨터의 제약조건들 때문에 한줄에도 많은 명령어를 구현하려고 노력했었다. 하지만, 지금에 와서 PC의 성농은 비약적으로 증가되었으며, 객체지향언어가 발달하고 널리 사용되면서 굳이 적은 코드파일 크기를 고집할 필요성이 약해지고 있다. 이런 상황에서 나는 코드의 가독성과 이해력을 높이기 위해서라면, 한 줄로 끝날 계산도 가급적이면 나누고 나누어서 표현을 하려고 노력한다. 그것이 나의 Simple more Simple 개발철학이다. 이런 나의 개발철학은 나의 개발물들을 후에 다른 사람들이 수정할 일이 생겼을 때 수정하여 사용하기 쉽도록 하여 내 코드의 재활용성을 높여줄 것이다.

  간혹 프리랜서로 일한 사람들의 코드를 보면 쉽게 이해할 수 없는 부분들이 많은 경우가 있다. 이에 대한 문서화도 제대로 되지 않아서 급하게 수정해야할 경우 난해한 경우가 생긴다. 프리랜서로서 그렇게 해야 다시 자신들을 불러줄 거라고 생각하는지 모르겠지만, 개인적으로 그런 습관을 가지고 있는 프리랜서라면 나는 다시는 안 쓴다.  깔끔하고 이해하기 쉬운 코딩스타일을 가지고 있으면서 문서화를 잘하는 프로그래머와 계속 함께 일하고 싶어할 거니까. 나 역시 그런 프로그래머가 되려고 노력할 것이다.

구인정보를 읽다가 개발철학에 대해서 묻는 질문에 대해서 잠시 곰곰히 생각을 해보았다. 나는 단순히 일자리가 없어서 개발자가 되려는 것이 아니라, 이 분야에서 계속 일하고 싶기 때문에 5개월동안 교육을 받은 것이고, 오랫동안 개발자로서 인정받고 성장하기 위해서는 내 개발철학을 가지고 소신껏 살아갈 필요가 있는 것이다. 그래서 개발철학을 생각해본다.

이 글은 스프링노트에서 작성되었습니다.

JDK 7

The primary goal of this Project is to produce an open-source implementation of the next major revision of the Java SE Platform.

Detailed information on the approved features, as well as information on how to propose additional features, can be found on the features page. The JDK 7 development schedule is divided into a sequence of milestone cycles. Please see the builds and integrations page for detailed build and integration scheduling. A complete calendar of the entire development timeline is also available.

Status: Milestone 4 complete, work on Milestone 5 underway

No showstoppers were identified in build 66, so we declared that to be the final build for M4.

We'll start stabilizing Milestone 5 at build 72, which opens on 2009/8/28. M5 will be complete on or about 2009/9/10.

Comments and questions to: jdk7-dev@openjdk.java.net

Last update: 2009/7/30 23:09 -0700


Milestones

The JDK 7 development schedule is divided into a sequence of milestone cycles, each six to seven weeks in length. There will be no formal beta or early-access releases, as in the past. Major features and other potentially-destabilizing changes will targeted for integration early in a specific milestone. For more information, please see the current draft of the JDK 7 Development Process.

Here is the current high-level milestone schedule, with the features targeted to each cycle:

M1 2009/01/02 – 2009/02/19 (b48) 7 builds
Compressed 64-bit object pointers
Garbage-First GC (G1)
M2 2009/02/20 – 2009/04/02 (b53) 5 builds
JSR 203: More new I/O APIs for the Java platform (NIO.2)
Method to close a URLClassLoader
M3 2009/04/03 – 2009/05/14 (b59) 6 builds JavaOne Preview
Create new platform APIs for forward-ported 6u10 features
JSR 292: VM support for non-Java languages (InvokeDynamic)
SCTP (Stream Control Transmission Protocol)
SDP (Sockets Direct Protocol)
Unicode 5.1
Upgrade class-loader architecture
M4 2009/06/05 – 2009/07/23 (b66) 7 builds
Forward-port 6u10 features
JSR 308: Annotations on Java types
M5 2009/07/24 – 2009/09/10 (b73) 7 builds
Elliptic-curve cryptography (ECC)
JSR 296: Swing application framework
Update the XML stack
M6 2009/09/11 – 2009/10/29 (b80) 7 builds Stabilization begins
JSR TBD: Small language enhancements (Project Coin)
M7 2009/10/30 – 2009/12/24 (b87) 7 builds
M8 2010/01/01 – 2010/02/18 (b94) 7 builds Final milestone

The final milestone cycle, M8, will be followed by a release-candidate period of indeterminate length, but most likely four to eight weeks, after which the final release will be declared.

Some features have been approved for the release but are not yet targeted to a specific milestone. When they are targeted then they'll be added to the above table.

Last update: 2009/7/30 23:09 -0700

진행되는 과정으로 보면 M5의 단계로 들어선 것으로 봐도 되겠습니다. 내년 초면 JDK 7 최종판을 확인해볼 수도 있겠네요. ^^ 이미 http://java.sun.com 에서는 JDK 7에 대한 이야기를 슬며시 내놓고 있습니다. 올해 Java 진영은 JavaFX 1.2(http://www.javafx.com/) 와 이를 기반으로 한 WareHouse(http://java.sun.com/warehouse/), 넷빈즈 6.7(http://www.netbeans.org/) 등의 다양한 라인업을 제공하면서 자신들의 영역을 더욱 확장하려는 것처럼 보입니다. 이제 프로그래머의 길에 발을 들여놓아야만 하는 저로서는 부담되기 그지없는 상황입니다. 넷빈즈는 그저 간단한 자바코드를 작성하여 맛만 보고 있는 중이고, WareHouse(Java Software Store)는 아직 구경도 제대로 못했으며, JavaFX는 배울 엄두를 내지도 못하고 있는 그런 상황입니다. OTL... 배울 것들만 산더미처럼 늘어 가는군요.


우선... 취업 먼저 되었으면 좋겠습니다. ㅠㅅ-) 흑!!
다행인 것은 아직 우리나라에서는 JDK 5 버전으로 개발들이 진행된다는 것이죠. 가만히 보면 우리나라는 새로운 신기술을 적용하기 보다는 조금은 오래된 기술들로 안정된 기술들을 추구하는 모습을 보입니다. 한편으로 좋지만, 한편으로는 씁쓸한 모습입니다. IT 강국(물론 자칭이며 HW에 국한되었던)으로서의 개척정신은 어디로 갔는지... 쯥...
-startup
plugins/org.eclipse.equinox.launcher_1.0.200.v20090520.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-product
org.eclipse.epp.package.jee.product
-launcher.XXMaxPermSize
256m
-showsplash
org.eclipse.platform
-vmargs
-Dosgi.requiredJavaVersion=1.5
-Xms40m
-Xmx512m

이렇게 하니, 별도로 옵션 설정 안해줘도 되는구나. ㅡㅅ-);; 흐음... 몰랐어.

참고페이지 : http://lovedev.tistory.com/482

기본적인 암호화 처리를 해주는 메소드를 살짝 변경하였습니다.  암호화키를 저장해주지 못하기 때문에 별도의 페이지에서는 사용이 어려웠음.

 

필요하시면, 가져다 쓰셔도 됩니다. ^^ 암호화된 코드에다가 자기만의 암호화 처리 방법을 넣어서 해주시면 좋습니다. +_+)b

returnEncryptCode(String str)  메소드는 입력받은 문자열을 암호화 한 다음, 암호화에 사용한 암호키와 암호화된 문자열을 합쳐서 반환합니다.
public String returnDecryptCode(String str)  메소드는 returnEncryptCode(String str) 메소드에서 처리한 암호화된 코드를 받으면, 특정 부분에서 잘라서 암호키를 키로 생성하고, 암호화된 코드를 넣어서 해독하여 해독된 문자열을 반환합니다.

 

JSP에서 처리할 경우에는 returnEncryptCode(String str)에서 반환된 문자열을 저장하는 문자열 혹은 객체를 저장하는 방법만 고려하면 되겠다.

 

  1. package encrypt;

    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.security.InvalidKeyException;
    import java.security.Key;

    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.KeyGenerator;

    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;
     
    public class LocalEncrypter{
        //DESede 는 암호화시 사용되는 최대 키 사이즈를 지정하는 키워드임 : 관련페이지 내용 링크
  2.     private static String algorithm = "DESede";
        private static Key    key       = null;
        private static Cipher cipher    = null;
     
       
        // 암호화 키를 발생시키는 메소드입니다.
        // com.sun.crypto.provider.DESedeKey@ + 16진수 8자리
        public LocalEncrypter() throws Exception {
            key = KeyGenerator.getInstance( algorithm ).generateKey();
           
    //        private static String keystr = String.valueOf(key);
    //        System.out.println(key);
    //        System.out.println("암호화 키의 형태 :"+ keystr);
    //        System.out.println(keystr.length());
           
            cipher = Cipher.getInstance( algorithm );   
        }
       
       
        //1. str 을 입력 받아서 이를 암호한다.    //2. 암호화 하는데 사용한 암호키를 encKey 로 문자열화 한다.
        //3. encKey + str 값을 반환한다. 크기는 408 byte
        public  static String returnEncryptCode(String str) throws Exception {
            byte [] encryptionBytes = null;
     

            // 입력받은 문자열을 암호화 하는 부분
            encryptionBytes = encrypt( str );
            BASE64Encoder encoder = new BASE64Encoder();

            //encoder.encode(encryptionBytes) 으로 encrypt 된 값 출력
            String encodeString = encoder.encode(encryptionBytes);
           
            // 키를 문자열로 바꿔주는 곳.
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(key);
            oos.close();
            BASE64Encoder b64enc = new BASE64Encoder();
            byte[] keyArr = bos.toByteArray();
            String encKey = b64enc.encode(keyArr);   
           
    //        System.out.println("문자열이 되어 저장된 키 : " + encKey);
    //        System.out.println("저장된 키의 길이 : " + encKey.length());
    //        System.out.println("암호화된 비밀번호 : " + encodeString);


    /*                // 암호화에 사용된 키값을 뽑아낸 수
             String keycode = keystr.substring(34,42);
             System.out.println("암호화에 사용된 키 : " + keycode);
             String randomcode = returnRandomCode();
             System.out.println("암호화된 코드 : " + encodeString);*/
            
            return encKey + encodeString;
        }

       
        //1. DB에 저장되어 있는 408 byte 길이의 str을 받는다.
        //2. 그중 0~384 까지의 암호화키(encKey)부분을 keycode로 뽑아낸다.
        //3. keycode를 Key에 대입한다.
        //4. 384~408 까지의 암호화된 문자열을 code로 뽑아낸다.
        //5. code를 해독한다.
        //6. 해독된 값을 반환한다.
        public String returnDecryptCode(String str) throws Exception {
            //복호화 하기 위해서는 암호화 키가 필요하다. ㅡㅅ-);;
            // 그래서 생각해낸 것이, DB에 저장될 때, 암호화키를 한번에 집어넣고....
            //substring 으로 잘라서 쓰는 것.
            int strLength = str.length();
           
            //암호화된 비밀번호에 저장되어 있는 암호화키를 추출.
               String keycode = str.substring(0,384);
              
              
               // 추출한 암호키를 KEY 형태로 다시 복구
               BASE64Decoder b64dec = new BASE64Decoder();
               byte[] b = b64dec.decodeBuffer(keycode);
               ByteArrayInputStream bis = new ByteArrayInputStream(b);
               ObjectInputStream ois = new ObjectInputStream(bis);
               key = (Key) ois.readObject();
               ois.close();
              
            String code = str.substring(384, strLength);
           
              
    //        System.out.println("저장된 코드 길이 : " + strLength);
    //           System.out.println("암호화 사용키 : " + keycode);
    //        System.out.println("암호화된 코드: " + code);
           
            BASE64Decoder decoder = new BASE64Decoder();
            String decode = decrypt( decoder.decodeBuffer(code));
           
    //        System.out.println("Ecrypt 에서 해독한 것 : " + decode);
            return decode;
        }
       
     
       
        // encryptionBytes = encrypt( input ), input을 변조하여 encryptionBytes에 대입함.
        private static byte [] encrypt(String input) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException  {
            cipher.init( Cipher.ENCRYPT_MODE, key );
            byte [] inputBytes = input.getBytes();
            return cipher.doFinal( inputBytes );
        }
     
       
       
        //decrypt( decoder.decodeBuffer(encodeString) ) 처리부분.
        private static String decrypt(byte [] encryptionBytes) throws InvalidKeyException, BadPaddingException, IllegalBlockSizeException{
            cipher.init( Cipher.DECRYPT_MODE, key);
            byte [] recoveredBytes = cipher.doFinal( encryptionBytes );
            String recovered = new String( recoveredBytes );
            return recovered;
        }
     
    }

이 글은 스프링노트에서 작성되었습니다.

인터넷 검색을 통하여 찾아본 구현 방법들은 서블릿에서 저장된 것들을 처리하는 방법들 뿐이었음.

나름 독자적인(?!) 해석을 통하여 JSP로만 구현하는 방법을 터득했다. 이를 이용할 예정임.

현재 진행중인 프로젝트가 완료되면 특별한 기능이 있을 경우, 기재를 하여 설명드리도록 하겠음.

 

JFeeChart 구현과 관련된 JAR 파일들

1) jfreechart-1.0.0-pre2.jar

2) jcommon-1.0.0-pre2.jar

메뉴얼 API : http://www.jfree.org/jfreechart/api/javadoc/index.html

 

  1. <%@ page language="java" contentType="text/html; charset=EUC-KR"  pageEncoding="EUC-KR"%>
    <%@ page import="java.io.*" %>
    <%@ page import="org.jfree.data.general.DefaultPieDataset"%>
    <%@ page import="org.jfree.chart.JFreeChart"%>
    <%@ page import="org.jfree.chart.plot.PiePlot"%>
    <%@ page import="org.jfree.chart.ChartRenderingInfo"%>
    <%@ page import="org.jfree.chart.servlet.ServletUtilities"%>
    <%@ page import="org.jfree.chart.urls.StandardPieURLGenerator"%>
    <%@ page import="org.jfree.chart.entity.StandardEntityCollection"%>
    <%@ page import="org.jfree.chart.ChartFactory"%>
    <%@ page import="org.jfree.chart.ChartUtilities"%>
    <%@ page import="org.jfree.data.general.PieDataset"%>
    <%@ page import="org.jfree.data.category.DefaultCategoryDataset"%>
    <%@ page import="org.jfree.chart.plot.PlotOrientation"%>
    <%@ page import="org.jfree.chart.servlet.*"%>
    <%@ page import="com.oreilly.servlet.*" %>
    <%@ page import="com.oreilly.servlet.multipart.*" %>


    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>JChart 연습하기</title>
    </head>
    <body>
        <%
            DefaultPieDataset ds = new DefaultPieDataset();
            ds.setValue("홍길동", new Double(40.0));
            ds.setValue("홍길숙", new Double(25.0));
            ds.setValue("기타", new Double(15.0));
           
            JFreeChart chart = ChartFactory.createPieChart("득점분포", ds, true, true, false);
            chart.setBackgroundPaint(java.awt.Color.white);
             chart.setTitle("JChart 연습하기");
             
             ChartRenderingInfo info = new ChartRenderingInfo(new StandardEntityCollection());
           
             
            //PNG 파일명을 만들어내기
             String fileName = ServletUtilities.saveChartAsPNG(chart, 600, 300, info, session);           
           
             System.out.println("파일명 : " +fileName);
             
            //특정 임시 폴더에 이미지 파일을 만들어냄.
             String dir = application.getRealPath("/upload/"); // 파일경로 지정
             dir = "D:\\" + dir.substring(3) + "/";
             String filepath = dir + fileName;
             //System.out.println("File path = "+ filepath);
       
             FileOutputStream fos = new FileOutputStream(new File(filepath));
             File f = new File(filepath);
             ChartUtilities.writeChartAsPNG(fos, chart, 600, 300);
             
             String graphURL = request.getContextPath() + "/upload/" + fileName;
             //System.out.println(graphURL);
            %>
            <img src="<%=graphURL%>"/> <!--//파일 경로와 파일명을 받아서 차트를 보여줌-->

    </body>
    </html>

● 파일명 : jfreechart-2348981821190451270.png (파일명은 ServletUtilities.saveChartAsPNG(chart, 600, 300, info, session); 에 의해서 임의 지정됨)
● File path = D:\workspace\project\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\WomanHappy\upload/jfreechart-2348981821190451270.png  // 웹 서버에 저장된 실제 주소
● /WomanHappy/upload/jfreechart-2348981821190451270.png // 서버에 저장된 주소

JFreeChart.JPG <결과물>

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts