태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


Effective Java에 나오는 내용이긴 합니다만, 우리가 자주 저지르는 실수가 있습니다.

프로그램을 하다가 보면 자주 난수(Random number)를 발생시켜야 할 때가 있습니다.

아래와 같은 코드를 사용하여 많이 발생을 시키죠.


private static final Random rnd = new Random();

static int random(int n) {
   return Math.abs(rnd.nextInt()) % n;
}


논리적으로는 아무런 문제가 없어 보입니다.

그렇지만 실제적으로 다음과 같은 코드를 사용하여 테스트를 해보도록 합시다.

public static void main(String[] args) {
   int n = 2 * (Integer.MAX_VALUE / 3);
   int low = 0;
   for (int i = 0; i < 1000000; i++)
       if (random(n) < n/2)
           low++;
   System.out.println(low);
}

위의 코드데로라면  100만번 테스트를 해서 기준값보다 작은 수가 나오는 경우는 50% 가깝게 나와야 정상입니다.

그렇지만 실제로 돌려보면 항상 666,666에 가까운 수가 나옵니다.

난수가 제대로 발생하고 있지 않다는 이야기죠.

실제적으로 이런식의 버그는 찾아내기가 쉽지 않습니다.

로직상으로는 아무런 문제가 없기 때문이죠.


따라서 저런 프로그램으로 Load Balancing하거나 데이터를 분산하고 있다면 제대로 처리가 되고 있지 않을 것입니다.

java 1.2부터 추가된 Random.nextInt(int) 를 사용하거나,  apache commons의 RandomUtils.nextInt()를 사용해야 제대로 동작을 합니다.



Posted by Breeze.Kang

댓글을 달아 주세요


mysql에 Bulk로 대용량 데이터를 한꺼번에 import하는 경우가 있다.

여기에서 대용량이라함은 적어도 천만건 이상 정도의 데이터를 가정하고 이야기한다.



mysql은 다양한 Data import 방법을 제공하고 있다.


1. query파일로 import하기.

insert table_name values( value1...);

이런 쿼리들로 이루어진 sql문 파일을 mysql console에서 source 명령어로  import 할 수 있다.



mysql>source "file name";



이 방법은 아마도 가장 느린 방법이 아닐까 생각이 된다.

또한 query문으로 이루어진 파일은 용량이 크기 때문에  핸들링하기가 쉽지 않다.

가끔 max_allowed_packet  size를 초과한다는 에러도 나온다.

이건 my.cnf에서 이 parameter를 적당히 늘려주면 에러는 없어진다.



2. CSV 포멧으로 import하기

mysqlimport 명령 혹은 load data local infile 명령으로 CSV포멧을 import하는 방법이다.

LOAD DATA LOCAL INFILE '/importfile_path.csv'
INTO TABLE test_table
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
(field1, filed2, field3);


이 방법의 장점은 불필요한 쿼리를 제외한 데이터와 SPACER만 들어가기 떄문에 상대적으로 쿼리 파일보다 파일 사이즈가 작다.
또한 이 방법이 현재까지 해본 방법중에는 가장 빠른것 같다.

천만건 정도를 서버에 import하는데 15분정도가 걸린다.

단점은 CVS파일이름이 바로 DB Table 이름이 되 버리기 때문에 많은 Table을 핸들링 해야 하는 경우에는 각각 파일을 핸들링 해야 한다.



결론은 복잡한 데이터를 다양한 DB에 넣을경우는 쿼리 파일로 하는것이 편한것이고,

단순한 많은 양의 데이터를 import할때는 CSV포멧으로 처리하는것이 빠르고, 편할것이다.


Posted by Breeze.Kang

댓글을 달아 주세요


Java Object를 XML로 변환하고자 할때 과거에는 포맷에 맞춰서 XML을 일일이 출력해주는 방식도 사용을 했었다.

그렇지만 굉장히 노가다이고, 짜증나는 작업이 아닐수 없다. 

이런 노가다를 줄이기 위하여 Java Object를 XML로 변환해주는 많은 툴들이 나와있다.

그중에 가장 많이 사용되는 것이 JAXB(Java Architecture for XML Binding) 이다.

Using JAXB

기본적인 지식을 얻고 싶다면 아래의 주소에서 확인을 하자.
http://java.sun.com/developer/technicalArticles/WebServices/jaxb/


Maven을 사용하고 있다면 Pom.xml에 Dependency를 추가하여 필요한 라이브러리를 다운받자. 

         <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.0.5</version>
        </dependency>


Java annotation을 사용하여 편리하게 어떤 내용을 XML에 포함 시킬것인가 말것인가, 그리고 어떤 이름으로 XML에 표현할 것인가를 나타낼 수 있다.


아래 예제 소스는 Hibernate Entity class로써 DB table에 매핑되는 데이터를 나타낸다.

굵은 글쓰로 나타낸것이 JAXB에서 참조하는 annotation이다.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


@Entity
@Table(name="vct")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Vct extends AbstractEntity<Long>{
   
    /**
     *
     */
    private static final long serialVersionUID = 8595404797996134818L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
   
    @ManyToOne(targetEntity = VctInfo.class, optional = false)
    @JoinColumn(name = "vctinfo_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_vctinfo")
    private VctInfo vctinfo;
   
    @ManyToOne(targetEntity = Uct.class, optional = false)
    @JoinColumn(name = "uct_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_uct")
    private Uct uct;
   
    @Column(name = "name", length = 100, nullable = false)
    private String name;
   
    @Column(name="vct_parentid" , nullable=true)
    private Long vctParentId;
   
    @Column(name="sort_order" , nullable=false)
    private Integer sortOrder;
   
    @Column(name="visible" , nullable=false)
    private CategoryVisible visible;
   
    @Column(name="moved" , nullable=false)
    private CategoryMoved moved;
   
    @Column(name="shortcut" , nullable=false)
    private CategoryType shortcut;
   
    @Column(name="hierachy" , length=1024, nullable=false)
    private String hierachy;
   
    @Column(name="hierachyStr" , length=1024, nullable=false)
    private String hierachyStr;   

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public VctInfo getVctinfo() {
        return vctinfo;
    }

    public void setVctinfo(VctInfo vctinfo) {
        this.vctinfo = vctinfo;
    }

    public Uct getUct() {
        return uct;
    }

    public void setUct(Uct uct) {
        this.uct = uct;
    }
   
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getVctParentId() {
        return vctParentId;
    }

    public void setVctParentId(Long vctParentId) {
        this.vctParentId = vctParentId;
    }

    public Integer getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(Integer sortOrder) {
        this.sortOrder = sortOrder;
    }

    public CategoryVisible getVisible() {
        return visible;
    }

    public void setVisible(CategoryVisible visible) {
        this.visible = visible;
    }

    public CategoryMoved getMoved() {
        return moved;
    }

    public void setMoved(CategoryMoved moved) {
        this.moved = moved;
    }

    public CategoryType getShortcut() {
        return shortcut;
    }

    public void setShortcut(CategoryType shortcut) {
        this.shortcut = shortcut;
    }

    public String getHierachy() {
        return hierachy;
    }

    public void setHierachy(String hierachy) {
        this.hierachy = hierachy;
    }
   
    public String getHierachyStr() {
        return hierachyStr;
    }

    public void setHierachyStr(String hierachyStr) {
        this.hierachyStr = hierachyStr;
    }

    @Override
    public boolean equals(final Object other) {
        if (!(other instanceof Vct))
            return false;
        Vct castOther = (Vct) other;
        return new EqualsBuilder().append(id, castOther.id).isEquals();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("id", id).append("vctinfo",
                vctinfo).append("uct", uct).append("vctParentId", vctParentId)
                .append("sortOrder", sortOrder).append("visible", visible)
                .append("moved", moved).append("shortcut", shortcut).append(
                        "hierachy", hierachy).append("hierachyStr", hierachyStr).toString();
    }
}


이 Entity class를 XML로 변환하고 싶다고 한다면 다음과 같이 해주면 된다.

        JAXBContext context = JAXBContext.newInstance(Vct.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal( vct, response.getWriter());

물론 vct에는 어떤 값이 들어있어야 한다.


이 Vct라는 class의 List값을 출력하고 싶을때는 다음과 같은 List용 class를 생성한다.

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

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "vcts")
@XmlAccessorType(XmlAccessType.FIELD)
public class VctList {

    @XmlElement(name = "vct")
    protected List<Vct> vcts;

    public List<Vct> getVctList() {
        if (vcts == null) {
            vcts = new ArrayList<Vct>();
        }
        return this.vcts;
    }

    public void setVctList(List<Vct> vcts) {
        this.vcts = vcts;
    }
}

VctList라는 class는 Vct의 리스트를 가지고 있는 class이고,

annotation으로 vcts라는 이름으로 XML의 root element를 만든다고 나타냈다.

아래의 class는 Spring의 View interface를 구현하여 웹상에서 xml을 바로 볼수 있게 해줄 목적으로 만들었다.

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.springframework.web.servlet.View;


public class VctXmlView implements View {

    private Object modelKeyName;

    public VctXmlView(Object key) {
        modelKeyName = key;
    }

    @Override
    public String getContentType() {
        return "text/xml;charset=utf-8";
    }

    @SuppressWarnings("unchecked")
    @Override
    public void render(Map model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        if (model == null) {
            return;
        }
        response.setContentType(getContentType());
        List<Vct> vcts = (List<Vct>) model.get(modelKeyName);
        VctList vctList = new VctList();
        vctList.setVctList(vcts);

        if (vcts == null) {
            return;
        }

        JAXBContext context = JAXBContext.newInstance(VctList.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal(vctList, response.getWriter());

    }
}

실행한 결과는 다음과 같다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vcts>
<vct>
<id>1</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
  </country>
<createUser>
<email></email>
<name></name>
<password></password>
<readLevel></readLevel>
<writeLevel></writeLevel>
  </createUser>
<createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description></description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
            <name></name>
</vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
                <readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-14T14:28:10+09:00</createdAt>
<description></description>
<hierachy>6 7 8 9 11</hierachy>
            <hierachyStr></hierachyStr>
<name>itemshop</name>
<parentId>9</parentId>
</uct>
<name>아이템몰</name>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1</hierachy>
<hierachyStr>아이템몰</hierachyStr>
</vct>
    <vct>
<id>2</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
</country>
            <createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
            <createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description>Shop에서 사용할 VCT</description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
<name>Itene Shop</name>
        </vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
                <writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-19T16:23:26+09:00</createdAt>
<description>hair chage item</description>
<hierachy>6 7 8 9 11 20</hierachy>
<hierachyStr></hierachyStr>
            <name>Hair change</name>
<parentId>11</parentId>
</uct>
<name></name>
<vctParentId>1</vctParentId>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1 2</hierachy>
<hierachyStr></hierachyStr>
</vct>
</vcts>


Posted by Breeze.Kang

댓글을 달아 주세요

  1. 으아니.. 프로그래밍 포스팅도하시네요? ㅎㅎㅎ 잘지내시죠? 저도 요기능 필요해서 검색하다가 눈에 익어서 들어왔네요.

    2009.06.03 17:01 [ ADDR : EDIT/ DEL : REPLY ]
    • Breeze

      ㅋㅋ 라이덴 오랜만!
      아, 이젠 프로그래밍 관련 포스팅도 하려고~

      2009.06.03 17:34 [ ADDR : EDIT/ DEL ]
  2. 오 좋네요. 좋은정보좀 많이 포스팅해주세요. 전 요새 트위터로 뭐할거 없을까 뒤져보는 중이에요. 트위터아이디 raidenz 입니다 :) 아 결혼도 곧 합니다. 연락드립죠. ㅎㅎ

    2009.06.03 18:07 [ ADDR : EDIT/ DEL : REPLY ]

Effective Java 3nd Edition을 회사사람들과 함께 스터디하는 중에 보게된 명언들이다.

More computing sins are committed in the name of efficiency (without necessarily achieving it) than for any other single reason—including blind stupidity.
—William A. Wulf [Wulf72]

( 맹목적인 어리석음을 포함한 다양한 이유중에 죄악같은 프로그램을 행하게 되는 으뜸의 이유는 바로 efficiency라는 이름으로 행하여 지게 된다,  )


We should forget about small efficiencies, say about 97% of the time: premature
optimization is the root of all evil.
—Donald E. Knuth [Knuth74]( 작은 효율성따위는 잊어버려야 한다, 어설픈 Optimization은 모든 악의 근원이다)


We follow two rules in the matter of optimization:
Rule 1. Don’t do it.
Rule 2 (for experts only). Don’t do it yet—that is, not until you have a
perfectly clear and unoptimized solution.
—M. A. Jackson [Jackson75 ]
( Optimization문제에 대하여 두가지 원칙을 따라야 한다. 첫번째는 하지 말라.두번째도 하지 말라이다. 단, 전문가의 경우, 당신의 솔루션이 명백하게 unoptimized되어있다는것이 명백해 지기 전까지는 절대 하지 말아라.)


약간의 의역과 오역이 있을수 있다;;
즉 결론은 잘 모르면서 성능 튜닝이나 Optimization을 하지 말라는 이야기다.

절대적으로 맞는 말이다.

내가 하는일이 어떤 결과를 나을지 어느정도 예측이 불가능하다면 하지 않는 편이 더 나은 경우를 많이 보아왔다.

또한 성능상의 이유로 좋은 아키텍처를 포기하지 말라는 말도 빼먹지 않고 있다.

Don’t sacrifice sound architectural principles for performance. Strive to write good programs rather than fast ones


이건 내가 기억해야 할 부분인 것 같다.



Posted by Breeze.Kang

댓글을 달아 주세요


요새 보고 있는 소프트웨어 개발의 모든것(All of Software Project) 이란 책에서 나오는 내용입니다.




소프트웨어 프로젝트팀을 평가하는 항목표인데, 각자 자신의 회사를 평가해보시는 지표로 사용하시면 좋을 것 같습니다.

소스코드 관리 시스템
1. 전사적으로 소스코드 관리 시스템을 딱 하나만 사용하고 있다.
2. 모든 소스 코드 관리 및 개발 문서는 소스코드 관리 시스템에 저장되고 있다.
3. 각 마일스톤마다 베이스라인을 설정하고 있다.
4. 소스코드 관리시스템에 체크인 시 메시지를 작성하는 규칙을 가지고 있고, 모든 개발자가 이를 지키고 있다.
5. 모든 소스코드를 리뷰하고 있다.

버그 관리 시스템
6. 자동적으로 일일빌드를 하고 있다.
7. 전사적으로 버그 관리 시스템을 딱 하나만 사용하고 있다.
8. 모든 버그를 버그관리 시스템에 등록하고 있으며 다른곳에서 별도로 관리하지 않는다.
9. 모든 직원이 버그 관리 시스템에 스스로 이슈를 등록한다.

스펙(요구사항)
10. 프로젝트의 스펙문서를 가지고 있다.
11. 스펙문서를 모든 관련자가 충분히 리뷰한다.
12. 스펙이 바뀜에 따라 스펙문서가 업데이트 되고 있다.
13. 스펙변경이 통제 관리되고 있다.

일정
14. 1,2일 단위의 상세한 일정을 가지고 있다.
15. 일정은 개발자가 산정한다.
16. 일정은 지속적으로 업데이트 되고 있다.

테스트
17. 별도의 테스트팀이나 테스터가 있다.
18. 테스트 케이스를 가지고 있다.

리스크관리
19. 프로젝트 리스크 관리를 하고 있다.
20. 리스크에 대한 백업 플랜이 있으며 리스크 관리계획이 주기적으로 갱신된다.


채점 방법은 간단합니다. 해당되면 1점 아니면 0점입니다.

20점이면 아주 최상의 상태,
15점 이상이면 양호한 편
10점 이상이면 중간정도
10점 미만이면 프로젝트가 성공했다면 기적이나 운이라고 생각할 정도의 수준 -_-;;


스펙이나 일정 부분은 사실 개발팀만의 문제가 아닙니다.

또한 테스트팀을 유지할 정도의 규모를 가진 회사는 사실 우리나라에 그렇게 많지 않은것이 현실입니다.

CVS 나 SVN같은 소스버전관리툴 정도는 많이 사용하지만 버그관리 시스템 (Bugzilla, Mantis등)를 사용하는 회사도 많지 않은것이 현실이죠.

스펙관리 부분은 더 난관입니다.

개발팀만의 문제가 아니기 때문이죠.

참 여러가지를 생각하게 하는 책인것 같습니다.


관심이 있으신 분은  저작권 문제도 있고, 책 을 사서 읽어보시기 바랍니다. ^^


 


Posted by Breeze.Kang

댓글을 달아 주세요

  1. 안녕하세요. "소프트웨어 개발의 모든것"을 쓴 전규현입니다.
    독자를 블로그를 통해서 뵙게 되니 반갑습니다. 책에서 다 다루지 못한 얘기를 나누려고 블로그를 운영하고 있습니다. 관심있으면 한번 들려주세요. http://allofsoftware.net
    소프트웨어 개발에 대한 얘기를 많이 나누고 싶습니다.

    2009.04.07 17:13 [ ADDR : EDIT/ DEL : REPLY ]
    • Breeze

      네 찾아주셔서 감사합니다. 블로그에도 북마크 해두고 자주 들르도록 하겠습니다.

      2009.04.07 22:29 [ ADDR : EDIT/ DEL ]

fdajax 0.9버전을 기준으로 설치법을 설명하겠다.

lighttpd 모듈로써 설치가 되는데  파일에 첨부된 파일을 보면 다음과 같은 설치 문서가 들어있다.


FdAjax module version 0.9, Thu, Jul 22, 2007

FdAjax short compilation and installation doc (http://www.refwell.com/blog).

1. Download and unpack Lighttpd 1.4.15 sources (http://www.lighttpd.net/download/).

2. Copy FdAjax source files to Lighttpd src directory.

3. Run ./configure  --prefix=/usr/local/lighttpd
3a. You can enable other configure options, e.g. --with-openssl

4. Run make

5. Run ./configure --enable-maintainer-mode --prefix=/usr/local/lighttpd
 
6. Add the following lines to src/Makefile.am file (http://trac.lighttpd.net/trac/wiki/HowToWriteALighttpdPlugin).

lib_LTLIBRARIES += mod_fdajax.la
mod_fdajax_la_SOURCES = mod_fdajax.c mod_fdajax_parser.c mod_fdajax_peercall.c mod_fdajax_info.c mod_fdajax_users.c mod_fdajax_alerts.c mod_fdajax_chat.c mod_fdajax_messages.c mod_fdajax_windows.c mod_fdajax_groups.c mod_fdajax_events.c
mod_fdajax_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
mod_fdajax_la_LIBADD = $(common_libadd)

7. Run make

7a. Make sure that new Makefile files were generated.  In case of problems with compilation download and install latest automake and autoconf packages.


이 방식으로 설치가 안되서 애를 먹었는데 autoconf 버전문제였다.

6번과 7번사이에 다음을 실행해주면 된다.
autoreconf -fi

설치가 완료되면 lighttpd 의 /lib 디렉토리에

mod_fdajax.la
mod_fdajax.so

두개의 파일이 생성이 된다.

이렇게 되면 테스트를 할 준비가 완료가 된것이다.

PHP를 인스톨하면 example로 들어있는 웹채팅이 실행 가능하다.

lighttpd는 FastCGI방식으로 php를 실행할수 있는데 자세한 설명은 다음 주소에 나와있다.

http://trac.lighttpd.net/trac/wiki/TutorialLighttpdAndPHP


내가 설치해본 데모는 다음 주소에서 볼수 있다.
http://211.218.209.242/

active-x 나 별다른 클라이언트없이 인터렉티브한 웹어플리케이션을 구현할수있다.

실행화면 스샷이다.

사용자 삽입 이미지



Posted by Breeze.Kang

댓글을 달아 주세요

  1. 우올.. 좋은 팁 감사합니다. 궁금했었는데... 좋은 reference 가 생겼네요. ^^
    잘 지내시죠? 새로 오픈하신 서비스 대박 나시길 기원할께요.. 늦었지만 새해 복 많이 받으시고요.. (__)

    2008.01.18 00:08 [ ADDR : EDIT/ DEL : REPLY ]
    • 네 반갑습니다. 잘지내시죠? 역삼역근처 오시면 연락 함 주세요~ 식사나 같이 하시죠

      2008.01.18 09:52 [ ADDR : EDIT/ DEL ]

wekipedia의 정의를 빌려보자.

http://en.wikipedia.org/wiki/Comet_(programming)

Comet is a World Wide Web application architecture in which a web server sends data to a client program (normally a web browser) asynchronously without any need for the client to explicitly request it. It allows creation of event-driven web applications, enabling real-time interaction otherwise impossible in a browser. Though the term Comet was coined in 2006,[a] the idea is several years older, and has been called various names, including server push, HTTP push, HTTP streaming, Pushlets, Reverse Ajax, and others.

Comet applications use long-lived HTTP connections between the client and server, which the server can respond to lazily, pushing new data to the client as it becomes available. This differs from the original model of the web, in which a browser receives a complete web page in response to each request, and also from the Ajax model, in which browsers request chunks of data, used to update the current page. The effect is similar to applications using traditional Ajax with polling to detect new information on the server, but throughput is improved and latency and server load are decreased.

Comet does not refer to any specific technique for achieving this user-interaction model, but encompasses all of them?though it implies the use of browser-native technologies such as JavaScript as opposed to proprietary plugins. Several such techniques exist, with various trade-offs in terms of browser support and side effects, latency, and throughput.

요약하자면, comet이란 서버에서 데이터를 클라이언트로 asynchronous하게 보내주는 아키텍처이다.

기존의 웹어플리케이들이 주로 client에서(주로 웹브라우저) request를 던지면 response를 주는 방식이었다면 코멧기술은 request없이(혹은 매우 긴 주기로)서버에서 데이터를 밀어넣어주는 기술을 말한다.

간단하게 생각한다면 주식거래를 하는 홈 트레이딩 시스템을 생각해보면 서버에서 주식거래량과 주식가격을 항상 밀어넣어주고 있는것과 같다. 단지 그 기술이 웹브라우저 같은 클라이언트에서 구현이 된다고 생각하면 된다.

실제 구현은 두가지 방식으로 가능한데..

1. Streaming
이 방식은 커넥션을 항상 유지하는 방식이고 서버에서 내려주는 데이터를 브라우저에서 받아서 필요한 부분만 처해주면 된다.

2. Long Polling
이 방식은 각 이벤트 마다 커넥션을 client에서 요청하고 서버에서는 response를 보내기전까지 계속 커넥션을 유지하다가 response를 보낸후에 커넥션을 끊는다. 그 후에 브라우저에서는 바로 다시 커넥션을 맺어서 response가 오기전까지 유지한다.  일반적인 웹어플리케이션과 유사하나 request의 주기가 길어짐으로서 성능 향상을 꽤할수 있고 , 1번 방식을 흉내낸 방식이라고 생각하면 될꺼 같다.


1번과의 차이점은 커넥션의 consistency에 있지만 너무 자주 이벤트가 일어난다면 1번이 더 효율적인 방식이다.

실제 구현을 하고 있는 어플리케이션은

lighttpd를 이용한  FDAjax(Full-Duplex Ajax) 모듈이 있다.

http://www.fdajax.com/wiki/index.php?title=Main_Page




 

Posted by Breeze.Kang

댓글을 달아 주세요

Firefox에서 제공하는 Web Developer Toolbar ( https://addons.mozilla.org/ko/firefox/addon/60 ) 를 설치하게 되면 Tools > View Speed report 라는 메뉴가 있다.

이 메뉴는 WebSite Optimization (http://www.websiteoptimization.com/ )으로 링크가 걸려있고 현재 보고 있는 페이지의 Performance를 측정해준다.

다음 페이지는 내가 테스트한 FreeEgg의 웹퍼포먼스 측정 결과이다.

사용자 삽입 이미지

한페이지를 보여줄때 Http Request를 몇번했는지, 총 다운받는 양은 얼마가 되는지를 별도의 로그램 설치 없이 간단하게 보여준다.

그리고 HTML갯수, 이미지 갯수, CSS, JavaScript파일 갯수등이 표시가 되어서 전반적인 사이트의 최적화 정도를 측정해볼수 있어서 매우 편리하다.


Posted by Breeze.Kang

댓글을 달아 주세요

현재 회사에서 사용하고 있는 OS가  CentOS 4.4 64bit 버전 입니다.

제온 쿼드코어 혹은 듀얼코어구요.

uname -a의 결과입니다.
Linux  2.6.9-42.ELsmp #1 SMP Tue Aug 15 10:35:26 BST 2006 x86_64 x86_64 x86_64 GNU/Linux

이 서버에 php, apache, mysql설치시에 여러가지 문제점들이 발생하고 있습니다.

php의 경우는 --with-mysql옵션을 선택하는 경우  make중에 다음과 같은 에러를 만나게 됩니다.

/usr/bin/ld: /usr/local/mysql/lib/libmysqlclient.a(libmysql.o): relocation R_X86_64_32S can not be used when making a shared object; recompile with -fPIC
/usr/local/mysql/lib/libmysqlclient.a: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [libphp5.la] 오류 1

php에서 사용하 mysql cllient library에 문제가 있어서 생기는 것이구요.

관련 mysql buglist

http://bugs.mysql.com/bug.php?id=4670

해결방법은 mysql을 binary로 설치하시면 안되고 꼭 컴파일을 하셔서 설치를 해야합니다.










Posted by Breeze.Kang
TAG 64bit, MySQL, php

댓글을 달아 주세요

목수가 책상 하나를 만들기 위하여 여러가지 연장을 사용하듯이

개발자들도 여러가지 개발툴을 사용하게 된다.

eclipse나 Visual Studio같은 툴에서부터 시작해서 FTP프로그램, CVS등 개발과 직접적인 도구들은 사용하는 Language에 따라서 그 수나 종류가 너무 많기 때문에 일 생략하고,  직접적인 개발도구외에 기획이나 타 부서와 코웍하고 communication을 도와서  개발 생산성을 향상 시킬수 있는 도구들을 살펴 보기로 한다.

1. bugzilla
버그를 트래킹해주는 툴로써 많이 사용하고 있을것으로 생각되므로 자세한 설명은 생략...
사용자 삽입 이미지

벅질라











2. twiki
여러명이 share하여 문서화를 할때 도움을 주는 툴로써 역시 많이 사용하고 있을것으로 생각되므로 자세한 설명은 생략...
사용자 삽입 이미지

twiki







3. dotproject
MS프로젝트의 웹버전이라고 생각하면된다. 웹에서 프로젝트 관리를 해줄수 있는 툴이다.
http://www.dotproject.net/
사용자 삽입 이미지












4. XPlanner
http://www.xplanner.org/index.html
XP 를 하는 프로젝트를 관리할때 사용하기 좋은 툴.  스크린샷을 참고하면 감이 잡힐것이다.


사용자 삽입 이미지























































기타 다른 좋은 툴들이 있으면 추천해주시기 바랍니다. ^^

Posted by Breeze.Kang

댓글을 달아 주세요

  1. 태터툴즈나 제로보드XE 개발에는 TRAC이 사용되는 것 같더군요.

    2007.11.20 18:59 [ ADDR : EDIT/ DEL : REPLY ]
    • Trac도 사용해보진 않았지만 참 편리할꺼 같군요. 저도 한번 이용을 해봐야겠네요. 좋은 정보 감사합니다.

      2007.11.20 19:02 [ ADDR : EDIT/ DEL ]
  2. Tomais

    버그질라보다는 맨티스가 더 가볍고 편한 듯 합니다.
    그런 이유에서 맨티스를 조금 커스터마이징해서 회사 표준으로 쓰고 있답니다.

    2007.11.20 19:10 [ ADDR : EDIT/ DEL : REPLY ]
    • 맨티스라는 툴이 있었군요. 그것도 한번 사용을 해봐야겠네요. 감사합니다.

      2007.11.20 19:48 [ ADDR : EDIT/ DEL ]