Program/JAVA

java :코드성데이터의 클래스생성

나이트로 2008. 5. 19. 10:31



















프로젝트 실무 컨설팅
제목 :코드성데이터의 클래스생성..
간단한 프로젝트를 수행중인데..
일단 DB에는 코드성 테이블 생성을 하지 못하게되었습니다.
(DB관리자가 그런것은 낭비라고 생각하는 경향이 있어서..)

암무튼 저와 다른 개발자가 클래스를 가지고 하기로 했는데...
저같은 경우는 어떤 코드를 상수형태로 가지고 쓰자고 하고 있으며
다른 개발자는 해쉬테이블 형태로 가지고 가자고 하고 있습니다.

해쉬테이블로 가자는 이유는...DB의 구조를 그대로 
클래스로 옮기자라는 건데 그래야만 해쉬테이블내에

코드 코드에 대한 한글명 <--이런 데이터들이 다 관리된다는 이유입니다.
즉..
A01(해쉬키값) A01 신규생성 <--이런식의 데이터를 해쉬테이블로 유지하겠다는 뜻..
A02(해쉬키값) A02 확정 

반면 저같은 경우는 
아래와 같은 형태의 클래스를 가지고 가자고 하고 있습니다.

class Code{
 public static final String A01="A01";
 public static final String A02="A02";

 //이 케소드는 원래는 생각에 없었으나
 //다른 개발자와 언쟁 중에 한글설명(?)에 대한 관리에 대한 얘기가 나와서
 //이런 방식을 추가하자고 제안했습니다.
 public String getXX(String field){
  if(field.equals(A01)){
    return "신규생성";
  }
 }
}

그리고 만일 해쉬테이블로 굳이 가겠다면 일단 위의 클래스를 바탕으로
따로 확장해서 해쉬테이블로 구현하라고 하려합니다.

현제 제가 지적하고 싶은 해쉬테이블로 구현되었을 때의 문제는..
그 안의 데이터 하나를 얻어오려면 일단 키로서 A01 A02등이 주어져야 하는데
문제는 그것이 get메소드내에 하드코딩이 되어야 한다는거겠죠..

그걸방지하려면 역시 제가 제안한 코드클래스를 가지고 써야할 듯 보이구요..


제목 :힘드시겠네요.
제 생각은 다음과 같습니다.

-> DB에는 코드성 테이블 생성을 하지 못하게 되었습니다.
-> (DB관리자가 그런것은 낭비라고 생각하는 경향이 있어서..)

실환경 서비스 후에 입력된 데이터들을 점검하다 보면
생기지 말아야 할 데이터들이 입력되어 있는걸 보게 됩니다.

예를 들면 DEL_YN 이라는 필드가 있고
'Y' 일때는 삭제 'N' 일때는 삭제아님 이라는 의미를 부여했는데
엉뚱하게 null 이나 '*','&' 코드가 들어가는 경우가 발견이 됩니다.

여기서 뭐가 문제일까요? 
프로그램의 오류 문제? 
개발자간 커뮤니케이션 문제?

위의 것들이 근본적으로 해결이 될 문제는 아니라고 생각합니다.
오류는 항상 있는 것이고, 완벽한 커뮤니케이션은 불가능 한 것이기 때문이죠.

따라서 근본적인 문제점을 해결해야 하는데 
요점은 DB 상에서 해결해야 한다는 것입니다.

DEL_YN 은 not null 이라는 속성을 주고

아래 테이블을 만든 후에 

   create table T_DEL_YN AS 
   SELECT 'Y' CODE,'삭제' CODE_NAME from dual
   union all
   SELECT 'N' CODE,'삭제아님' CODE_NAME from dual

   ALTER TABLE T_DEL_YN ADD CONSTRAINT PK_CODE PRIMARY KEY (CODE);

DEL_YN 과 T_DEL_YN.CODE 의 관계를 설정하면
DEL_YN 에는 항상 'Y', 'N' 이 들어간다는 것이 
이론적으로 물리적으로 들어갈 데이터는 확정이 된다고 할 수 있습니다.

위와 같은 방법을 통해 
프로그램 오류나 커뮤니케이션 오류에 따른 
이상한 데이터가 입력되는 것을 방지할 수 있다고 생각합니다.

따라서 DB 관리자분에게 코드성 테이블이 단순히 데이터를 보관하는 관점을
버리라는 말을 하고 싶습니다.

2. 코드값을 위해 
   Code 클래스나 HashMap을 사용하는 것은 효율적이지이 않다고 생각됩니다.
   이유는

   신규 코드 추가시 컴파일을 해야지 사용할 수 있다.
     컴파일을 해야지만 그 코드를 사용할 수 있습니다.
     극단적으로 실환경에서 작업을 할 경우
     서비스를 중단해야 하는 불편이 따르게 됩니다. 

   코드에 대한 공유가 안된다.
     A와 B 의 개발자가 작업을 할 경우 
     A가 만든 코드와 B가 만든 코드가 충돌할 경우가 많습니다.
     바꾸어 말하면 서로 다른 의미의 "0001"의 코드를 만들어 사용할 수 있고
     A가 만든 코드 클래스를 B가 바꾸어 사용할 수 있다는 의미입니다.
     
   따라서 DB 관리자분을 설득할 수 없다면
   xml와 같이 공유가 가능하고 컴파일 없이 추가나 삭제가 가능한
   저장소를 사용하라고 권하고 싶습니다.


   
제목 : 아.. 그런식으로 관리가 되는군요~
아마 DB에 반영되긴 힘들겠지만...
잘 몰랐던 것을 알게 되네요..(나만몰랐나.. DB쪽은 깊이 모르니..)

지금건은 아니더라도 앞으로 하게 될 건에 대해서 염두에 두어야 할 것 같습니다.

그리고 코드공유관련해서는 두 사람이 공유할 클래스..를 가지고 하니..
충돌이 나지는 않을 듯합니다..

제목 : 코드 테이블 관리
XML을 코드 저장소로 사용하는 것은 좋은 생각입니다만, 어차피 그 내용을 불러 쓰기 위해서는
자바 객체로 담고 있어야 하겠죠? 물론 DOM 객체를 그대로 메모리에 담고 핸들링할 수도
있겠지만 어차피 키-값 구조로 담아야하는 거라면 HashMap이 낫다고 생각됩니다.

get 메소드에서 키값이 하드코딩되는 건 별 문제가 아니라고 봅니다. 어차피 DB에 코드테이블을
유지할 경우에도 코드값이 sql 문에 하드코딩되지 않겠습니까? sql에서 하드코딩을 피할 수
있다면 map에서도 피할 수 있고 map에서 피할 수 없다면 sql에서도 피할 수 없는 문제일 겁니다.

코드 클래스를 쓰는 것이 나쁜 생각은 아닙니다만, 님의 지적처럼 동적으로 변경하기가
아주 힘들겠죠. 게다가,
    public static final String A01="A01";
이런 식으로 쓰는 것은 좋지 않습니다. 차라리 쓰려면
    public static final String 신규생성="A01";
이렇게 쓰는 게 맞겠죠. 중요한 것은 사용하는 코드의 의미가 소스에도 기술되어야한다는 것입니다.
A01이라고 쓰면 코드 명세서를 찾아보지 않으면 이게 뭘 뜻하는 건지 알 수가 없죠.
실제 소스에는 신규생성이란 말이 들어가고 오히려 A01이 가려져야합니다.
제목 : Re: 저두 한글변수를 즐겨쓰는편입니다만..
저같은 경우엔 내부적으로 쓰는 코드에서만 한글변수를 즐겨사용합니다..
외부로 이용되는 코드의 경우 한글변수를 쓰면.. 왠만해서는 문제가 없지만
가령 poi나 jexcel등을 쓰지않고 그냥 jsp상으로 엑셀다운로드기능을 했을 경우
(헤더만변경해서)..
오류가 발생하게됩니다.. 원인은 역시..한글변수...(영문은 사용못하니 논외~)
(jrun상에서만 그런지도..저희회사는 jrun을 씁니다..)

그리고 그 코드성 테이블의 상태라는것을 가지고 프로그램내부적으로 제어할일이
발생합니다..
즉 현재A01상태를 A02란 상태로 바꾸는 경우가 생기는데 단순히 현재 row데이터만 A02로 
바꾸는 것이아니라 다른 테이블의 데이터역시 이 상태를 가지고 변경되어야합니다.
프로그램내부적으로 현재 변경하려는 상태가 A02인지 아니면..A01인지를 판단하려면
내부적으로 그 상태를 비교해야합니다.
또한 A01이란데이터만 A02로 바뀔 수가 있는 경우라면
만일 A03을 A02로 바꾸려했을 때는 오류가 발생해야 합니다..
그렬려면 역시 내부적으로 현재 row가 A03인지를 판단해야하는데..
해쉬테이블에 들어있는 값은 단순히 데이터들의 집합의 의미이지 특별한 의미가
있을거라고 보이진 않습니다.(우리가 생각하기엔 의미가 있겠지만..컴퓨터로서는
이것이 어떤의미를 가지는지 모른다는뜻이랄까..)

그래서 프로그램상으로..해쉬테이블상에 들어가면...
아래와같이되지만..(해당기능과 유사한모든프로그램에서)
if(field.equals("A03")){
 throw Exception~ 
}

코드성테이블을 유지하게 되면..
->
if(field.equals(Code.A03)){
 throw Exception~ 
}
위와같이 적어도 데이터가 한군데에서 유지되는 장점이 존재합니다.
(코드클래스의 값과 비교를 하게 되면 되므로 ..물론 field에서 넘어온 값은
 해쉬테이블 혹은 디비상에서 얻어온 값이 될 수 있습니다)

그리고 또한가지로서는..

저희 회사솔류션이 외국솔류션입니다..
거기의 데이터베이스내부에서 상태를 나타내는 코드 등이 삽입되어 있는데
이 코드 등은 또 별도로 자바클래스내에도 들어가 있습니다.
물론 확장을 위한 코드를 체계를 별도로 제공해서 몇가지 상태는 확장가능하지만
역시 그에 대한 코드도 자바클래스내에 내장되어서 그것과 
데이터베이스상의 상태를 바탕으로 프로그램이 움직이게 됩니다.


흠.. 정리가 잘 안되네염..^^) ... 



제목 : 왜 hashmap보다 dom이 나은가에 대해서..
글을 보다가 긁적입니다. hashmap이 dom보다 낫다.. 
a=b란 1대1식의 단순한 맵핑이상도 이하도 아닐 경우에는 hashmap이 나을 수도 있습니다만,
우리가 보아야 할 것은 그것이 모델을 표현하는데 적정한가 여부입니다.

님이 말씀하신 바와 같이 '어차피..'로 시작해서 구현한
프로젝트 중에 흔히 구현하는 code, value성 동적 리파지토리서버만 보더라도..
결국은 확장되어 a=b와 c=d에서 a=(a1,b1) b1=(c1,d1,e1)이런 것을 
포함할 수 있어야 하고 그것들 간의 관계나 데이터를 모델로써 수용할 수 있어야 합니다.
그렇다고 클래스를 동적으로 리로딩하는 것은 그리 좋은 방법은 아니라 생각됩니다..
직관적이지 않고, 모델자체가 한번 더 덧씌워져있기 때문에..

따라서 모델을 정의가능한 메타데이터인 dom은 매우 좋은 선택입니다.
'어차피'로 시작한 hashmap때문에 나중에 확장된 모델과 관계를 
결국은 하드코딩해서 쓰는 경우가 많고 자주 봐와서 긁적여봅니다..
제목 : 고민많이됩니다..^^
다 맞는 말씀같습니다.. 고민이 더 늘어버린듯..
제가 있는회사에서 그런 고민을 할 일이 별로 없었다는것이 참 지금생각하니
안타깝네요.. 이런건 실제 겪어봐야 느끼겠지요~ ^^

제목 : 박성덕
code, value의 1차원 구조라면 

다차원의 dom보다는 hash로 쓰는게 더 간단하리라 봅니다.


그런데 문제의 핵심은 code값을 hard코딩 하지 않고 

soft 코딩하고자 하시는 것 같군요

그렇다면 제 생각에는 아래의 방법을 추천합니다.

핵심은 Bean클래스와 Factory 그리고 value는 파일에 존재합니다.


아래와 같은 간단한 Bean 클래스를 만듭니다.

class CodeBean
{
  public String A01;
  public String A02;
  // 
  public getXX();
  이하 생략
}

그런 다음 사용하고자 하는 클래스에서

가령 

class XXXUsage
{
  public void xxx()
  {
     CodeBean myCode= CodeBeanFactory.getCodeBean();
     
     String mag= myCode.getA01();
     System.out.println(msg);
     // 결과는 "제고없음"

  }
}

이렇게 하면 하드코딩을 하지 않을 수 있습니다.

그리고 향후 value의 값을 변경 시킬 수 있습니다.

그럼 문제는 CodeBeanFactory를 어떻게 만드냐

두가지 방법이 있습니다. 

Factory 내 getCodeBean()메소드를 하드 코딩하는 방법....
가장 쉽죠.... 

두번째 방법.... 
java.lang.reflect 패키지를 사용해서 CodeBean클래스의 field를 

동적으로 접근하여 값을 할당하는 방법....









제목 : 어쨌든..
1차원이 다차원으로 확장되는 것은 자명한 사실이라는 점을 염두하시기 바랍니다..

code간의 관계를 1차원으로 명시하게 되면 XXXUsage, CodeBean은 수정, 확장,

관계들을 관리하는 새로운 클래스를 정의해야 될겁니다..

이런 점을 염두하시고 구현하시길.. 

추가로, reflect는 느리고 클래스 자체 접근방법 자체를 추천드리고 싶진 않습니다.
제목 : reflect ... proxy... code성 data
reflect의 경우 runtime에 동작해야 하는는 관계로 

내부적으로 복잡한 처리를 거치기 때문에

속도가 느린 것은 사실입니다. 

compiletime의 경우보다 수천배 느렸던 것 같습니다.

(replytime을 체크한 적이 있는데 수백~수천배였던 기억이)



그러나 다행인 것은 문제의 특성이 code성 데이터란 것입니다.

code성 데이터는 특성상 update 주기가 무척 깁니다.

따라서 이 주기에 비례하여 

매 요청시마다 value값을 다시 파일(혹은 db)로 부터 불러오지 않고

application이 초기 loding시 메모리에 올리는 것이 좋다고 봅니다.

loding시 약간의 시간이 걸릴 수 있으나 처음뿐이니 

실 이용시간인 그 이후의 시간에서는 문제가 되지 않으면 

동작 중에 update시킬 경우에 한해서만 값을 재적재 하도록

refresh(), invalidate() 등의 메소드를 관리자 프로그램에서 실행시키면 되리라 생각됩니다.

아 그리고 proxy를 사용하면 메소드 매 호출시마다 시간이 걸리더군요...

실제로 성격은 좀 다르겠지만 대부분의 framework가 제공하는 

configuration이 이와 비슷한 예라 생각됩니다 

carbon이란 framework은 정확히 proxy를 사용해서 이런 문제를 해결합니다만 

매요청시 속도가 느렸고 apache avalon의 경우는 dom처럼 메모리상에 tree를 

형성하지만 코딩시 key값을 hard코딩해야만 합니다.

편의상 vm이 하나라면 간단히 singleton을 사용하면 쉽게 해결되리라 봅니다.



제목 : Re: 하드코딩을 줄이고자 하는군요.
하드 코딩을 줄이고자 한다면 상수의 개념이 필요하겠지요.
효율성과 단순성에 대한 두가지 고민을 함께 해야 할것 같습니다.

아래의 요구조건이라면,

키들이 상수로 정의되어야 하고, 그것을 기준으로 각 한글이름을 반환하는 메소드
가 필요하다고 보여지는 경우

저는, properties를 이용하겠습니다.

public static final String A01="A01"; 
...

public String getName(String key)
{
   String name = "null";
   try{
     name = (String)getProperties().get(key);
   }catch(Exception e){}
   return name;
}

어차피 키의 추가는 상수의 추가를 의미하므로, 추가가 있다는 가정을 
하지 않는다면, 효율적인 방법이 아닐까 생각합니다.

menu.cfg 파일의 일부 내용이 아래처럼 될것으로 보입니다.
----------------------
A01 = 신규생성
A03 = 확정
...

제목 : 프로젝트 진행시 무지 고민하셨던 부분일 것입니다~~
1년 반전에 모 통신사의 업무시스템의 담당자로 참여한 적이 있었습니다
기존 A 업무의 모바일버젼으로 A업무를 조금 더 보완하며 대부분 
모바일 파트를 개발하는 프로젝트였습니다

A 업무가 기업의 기본 업무여서 연동되는 테이블들이 무지 많더군요
기초코드는 모두 DB에 구성되어 있었는데 기존의 시스템에서 
정보 추출시 필요한 모든 테이블들을 조인해서 가져오도록 되어있어
어떤 로직은 로직테이블 1 개에 기초코드 테이블을 10개를 
조인해서 가져오는 경우도 있었습니다 -.-;

문제는 모든 로직처리가 DB에 있다보니 무지 복잡해 진다는 것입니다
쿼리를 A4용지에 복사해 넣으면 쿼리만 12 라인이 입니다
물론 복잡한 로직인경우 이렇게 되는경우가 있긴하지만 굳이 이렇게 할 필요가 없다고 
생각했습니다
그래서 여러가지 테스트 후 고민끝에 새로 구성하는 부분은 
기존과 다르게 가기로 했습니다

사용하는 코드테이블만 15개 였는데 이를 더미빈이나 hashmap 으로 만들고
시스템 시작시 로딩하도록 하였으며 코드정보는 거의 수정되지 않기는 하지만
관련 데이블 수정시 RMI 로 저희 시스템의 코드처리 함수를 호출하도록 구성했습니다
DB가 oracle 이였기때문에 트리거로 RMI 함수를 호출하도록 했습니다
mssql 도 외부 프로그램을 호출할수 있으니 위처럼 하실수 있습니다

이렇게 구성하니 로직과 프리젠테이션의 구성이 무지 가벼워졌습니다

이 프로젝트하면서 느낀점은 
모든 로직을 DB 딴에서 처리하도록 구성하면 상상외로 복잡해진다는 것입니다
DB 에서의 처리와 구현부의 처리를 적절히 혼합해 사용하면 
쉽게 개발할 수 있다는 것이었습니다 
이 프로젝트 이후로 코드관련된 부분은 모두 이렇게 구성해 사용하고 있습니다

'Program > JAVA' 카테고리의 다른 글

tomcat web.xml  (0) 2008.05.19
tomcat 6.0 host 추가  (0) 2008.05.19
tomcat server.xml  (0) 2008.05.19
Tomcat 5 JNDI DataSource를 통한 DB 커넥션 풀 사용  (0) 2008.05.19
java로 연관배열  (0) 2008.05.14