'etc' 카테고리의 다른 글

svn connector  (1) 2014.09.23
자바 코드 영타 연습  (0) 2014.06.26
RESTful 웹 서비스에 대해 알아보자  (0) 2013.09.09
[번역] 와이프에게 REST 설명하기  (0) 2013.09.09
Posted by 꼬렙
:

svn connector

etc 2014. 9. 23. 09:04 |

http://community.polarion.com/projects/subversive/download/eclipse/4.0/update-site/

Posted by 꼬렙
:

자바 코드 영타 연습

etc 2014. 6. 26. 17:36 |
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;




class Search extends JFrame implements TreeWillExpandListener, ActionListener {
    private Container con;

    private JSplitPane sp = new JSplitPane();

    private JSplitPane sp1 = new JSplitPane(JSplitPane.VERTICAL_SPLIT);

    private DefaultMutableTreeNode root = new DefaultMutableTreeNode("My 탐색기");

    private JTree tree_jt = new JTree(root);

    private JScrollPane tree_jsp = new JScrollPane(tree_jt);

    private Vector view_vc = new Vector();

    private JList view_li = new JList(view_vc);

    private JScrollPane view_jsp = new JScrollPane(view_li);

    private JButton view_bt = new JButton("VIEW");

    private JButton edit_bt = new JButton("EDIT");

    private JButton del_bt = new JButton("DELETE");

    private JButton end_bt = new JButton("EXIT");

    private JTextArea data_ta = new JTextArea();

    private JScrollPane data_jsp = new JScrollPane(data_ta);

    private Dimension screen;

    public Search() {
        super("My 탐색기");
        screen = Toolkit.getDefaultToolkit().getScreenSize();
        this.init();
        this.start();
        this.setSize((int) screen.getWidth(), (int) screen.getHeight());
        this.setLocation(0, 0);
        this.setVisible(true);
    }

    public void init() {
        con = this.getContentPane();
        con.setLayout(new BorderLayout());
        con.add("Center", sp);
        tree_jsp.setPreferredSize(new Dimension(200, (int) screen.getHeight()));
        sp.setLeftComponent(tree_jsp);
        JPanel jp = new JPanel(new BorderLayout());
        view_jsp.setPreferredSize(new Dimension((int) screen.getWidth() - 220, 300));
        jp.add("Center", view_jsp);
        JPanel jp1 = new JPanel(new GridLayout(1, 4, 5, 5));
        jp1.add(view_bt);
        jp1.add(edit_bt);
        jp1.add(del_bt);
        jp1.add(end_bt);
        jp.add("South", jp1);
        sp1.setTopComponent(jp);
        sp1.setBottomComponent(data_jsp);
        sp.setRightComponent(sp1);

        File[] file = File.listRoots();
        for (int i = 0; i < file.length; i++) {
            DefaultMutableTreeNode dmt = new DefaultMutableTreeNode(file[i]);
            dmt.add(new DefaultMutableTreeNode("EMPTY"));
            root.add(dmt);
        }

    }

    public void start() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        tree_jt.addTreeWillExpandListener(this);
        view_bt.addActionListener(this);
        edit_bt.addActionListener(this);
        del_bt.addActionListener(this);
        end_bt.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == view_bt) {
            TreePath tp = tree_jt.getSelectionPath();
            // System.out.println("tp = " + tp);
            StringTokenizer stk = new StringTokenizer(tp.toString(), "[,]");
            stk.nextToken();
            if (stk.hasMoreTokens()) {
                String filepath = stk.nextToken().trim();
                while (stk.hasMoreTokens()) {
                    filepath += stk.nextToken().trim() + "/";
                }
                String filename = (String) view_li.getSelectedValue();
                filename = filename.substring(0, filename.indexOf("(")).trim();
                File f = new File(filepath, filename);
                try {
                    BufferedReader in = new BufferedReader(new FileReader(f));
                    data_ta.setText("");
                    while (true) {
                        String str = in.readLine();
                        if (str == null)
                            break;
                        data_ta.append(str + "\n");
                    }
                    in.close();
                } catch (IOException ee) {
                }
            }
        } else if (e.getSource() == edit_bt) {
            TreePath tp = tree_jt.getSelectionPath();
            // System.out.println("tp = " + tp);
            StringTokenizer stk = new StringTokenizer(tp.toString(), "[,]");
            stk.nextToken();
            if (stk.hasMoreTokens()) {
                String filepath = stk.nextToken().trim();
                while (stk.hasMoreTokens()) {
                    filepath += stk.nextToken().trim() + "/";
                }
                String filename = (String) view_li.getSelectedValue();
                filename = filename.substring(0, filename.indexOf("(")).trim();
                File f = new File(filepath, filename);
                int xx = JOptionPane.showConfirmDialog(this, "정말 수정하시겠습니까?", "수정", JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
                if (xx == 0) {
                    try {
                        DataOutputStream dos = new DataOutputStream(
                            new BufferedOutputStream(
                                new FileOutputStream(f)));
                        byte[] data = data_ta.getText().trim().getBytes();
                        dos.write(data);
                        dos.close();
                    } catch (IOException ee) {
                    }
                }
            }
        } else if (e.getSource() == del_bt) {
            TreePath tp = tree_jt.getSelectionPath();
            // System.out.println("tp = " + tp);
            StringTokenizer stk = new StringTokenizer(tp.toString(), "[,]");
            stk.nextToken();
            if (stk.hasMoreTokens()) {
                String filepath = stk.nextToken().trim();
                while (stk.hasMoreTokens()) {
                    filepath += stk.nextToken().trim() + "/";
                }
                String filename = (String) view_li.getSelectedValue();
                filename = filename.substring(0, filename.indexOf("(")).trim();
                File f = new File(filepath, filename);
                int xx = JOptionPane.showConfirmDialog(this, "정말 삭제하시겠습니까?",
                    "삭제", JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE);
                if (xx == 0) {
                    f.delete();
                    view_vc.clear();
                    view_li.setListData(view_vc);
                    data_ta.setText("");
                }
            }
        } else if (e.getSource() == end_bt) {
            System.exit(0);
        }
    }

    public void treeWillExpand(TreeExpansionEvent e) {
        if (e.getSource() == tree_jt) {
            tree_jt.setSelectionPath(e.getPath());
            TreePath tp = tree_jt.getSelectionPath();
            // System.out.println("tp = " + tp);
            StringTokenizer stk = new StringTokenizer(tp.toString(), "[,]");
            System.out.println(stk);
            stk.nextToken();
            if (stk.hasMoreTokens()) {
                String filepath = stk.nextToken().trim();
                while (stk.hasMoreTokens()) {
                    filepath += stk.nextToken().trim() + "/";
                }
                // System.out.println("file = " + filepath);
                File dir = new File(filepath);
                File[] data = dir.listFiles();
                if (data == null) {
                    return;
                }
                DefaultMutableTreeNode imsi = (DefaultMutableTreeNode) e.getPath().getLastPathComponent();
                imsi.removeAllChildren();
                view_vc.clear();
                if (data.length == 0) {
                    imsi.add(new DefaultMutableTreeNode("EMPTY"));
                } else {
                    int count = -1;
                    for (int i = 0; i < data.length; i++) {
                        if (data[i].isDirectory()) {
                            DefaultMutableTreeNode dtm = new DefaultMutableTreeNode(data[i].getName());
                            dtm.add(new DefaultMutableTreeNode("EMPTY"));
                            imsi.add(dtm);
                            count++;
                        } else {
                            view_vc.add(data[i].getName() + " (" + data[i].length() + "byte, " + new Date(data[i].lastModified()) + ")");
                        }
                    }
                    if (count == -1) {
                        imsi.add(new DefaultMutableTreeNode("EMPTY"));
                    }
                }
                view_li.setListData(view_vc);
            }
        }
    }

    public void treeWillCollapse(TreeExpansionEvent e) {}
}

public class SaerchFileUpdate {
    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception ee) {
        }
        Search ws = new Search();
    }
}

'etc' 카테고리의 다른 글

2014 코스닥 상장기업 취업박람회 포스터  (5) 2014.10.21
svn connector  (1) 2014.09.23
RESTful 웹 서비스에 대해 알아보자  (0) 2013.09.09
[번역] 와이프에게 REST 설명하기  (0) 2013.09.09
Posted by 꼬렙
:

RESTful 웹서비스
작성자 : 김문규
최초 작성일 : 2008. 4. 2
 
 인터넷 업계는 OpenAPI의 열풍이 불고 있다. 너도나도 OpenAPI를 공개하고 있고 사용자들에게 다양한 방식의 사용을 기대하고 있다. 최근 이 OpenAPI와 함께 거론되는 기술을 당연 REST이다. 구글, 아마존, 네이버 모두가 OpenAPI를 REST 방식으로 지원한다. (물론 기존의 SOAP 방식도 지원한다.) 
 그렇다면 REST란 과연 어떤것일까? W3C 표준이 아님에도 불구하고 업계의 사랑을 받는 이유는 무엇일까? 이 궁금증을 풀기위해 본 포스트를 작성하고자 한다.

1) 정의
REST는 ROA를 따르는 웹 서비스 디자인 표준이다.
 - ROA : Resource Oriented Architecture

2) 주요 특징
+ REST 방식의 웹서비스는 잘 정의된 Cool URI로 리소스를 표현한다.
무분별한 파라미터의 남발이 아니라, 마치 오브젝트의 멤버변수를 따라가듯이~
예를 들면 아래와 같다.
http://www.iamcorean.net/user/mk/age/32
기존의 서블릿을 이용한 URI는 대부분 이랬다.
http://www.iamcorean.net/finduser.jsp?user=mk&age=32
차이가 보이는가?

+ REST 방식의 웹서비스는 세션을 쓰지 않는다는 거다.
기존의 서블릿 개발에서는 세션을 이용해서 인증 정보들을 가지고 다닌다. 개발자의 개념(?)에 따라서는 파라미터까지 마구마구 집어넣어서 사용하기도 한다. 이 때문에 요청 처리가 너무너무 무거워진다. 
또한 요청간의 전후 관련성이 생기기 때문에 한 세션의 일련의 요청은 무조건 하나의 서버가 처리해야 한다. 그래서 로드발란싱을 위해 고가의 로드발란싱 서버가 필요하게 된다.
하지만 REST는 세션을 사용하지 않기 때문에 각각의 요청을 완벽하게 독립적이다. 따라서 각각의 요청은 이전 요청과는 무관하게 어떠한 서버라도 처리할 수 있게 된다. 즉! 로드발란싱이 간단해 질 것이라는 것이 느낌이 오는가? (물론 인증 관련해서는 복잡한 문제가 생긴다.)

3) ROA의 정의
+ ROA는
 - 웹의 모든 리소스를 URI로 표현하고 
 - 모든 리소스를 구조적이고 유기적으로 연결하여
 - 비 상태 지향적인 방법으로
 - 정해진 method만을 사용하여 리소스를 사용하는
 아키텍쳐 이다.

+ 이는 4가지의 고유한 속성과 연관되어 진다.
 - Addressablilty
 - Connectedness
 - Statelessness
 - 
Homogeneous Interface

+ 여기서 잠깐! 정리하자면 
REST란 위에 언급한 4가지 속성을 지향하는 웹서비스 디자인 표준이다.

4) RESTful 웹 서비스 속성 (ROA 속성)
+ Addressablilty (주소로 표현 가능함)
 - 제공하는 모든 정보를 URI로 표시할 수 있어야 한다.
 - 직접 URI로 접근할 수 없고 HyperLink를 따라서만 해당 리소스에 접근할 수 있다면 이는 RESTful하지 않은 웹서비스이다.
 - 예를 들면, GMail은 모든 메일 리소스는 하나의 URI와 연결되어 있다. (http://mail.google.com/mail/?hl=ko#sent/1036854d04d6de9e) 하지만 코리아닷컴의 경우에는 http://mbox07.korea.com/mail/mailView.crd 라는 주소에 접근한 후에 페이지에 표시된 메일의 링크를 통해서만 접근이 가능하다. (특정 회사를 지칭해서 유감입니다. 관계자 분들은 이해 부탁드립니다.) 둘 간의 차이가 이해가 되십니까?

+ Connectedness (연결됨)
 - 일반 웹 페이지처럼 하나의 리소스들은 서로 주변의 연관 리소스들과 연결되어 표현(Presentation)되어야 한다.
 - 예를 들면,
<user>
  <name>MK</name>
</user> 는 연결되지 않은 독립적인 리소스이다.
<user>
  <name>MK</name>
  <home>MK/home/</home>
  <office>MK/office</office>
</user> 는 관련 리소스(home, office)가 잘 연결된 리소스의 표현이다.

+ Statelessness (상태 없음)
 - 현재 클라이언트의 상태를 절대로 서버에서 관리하지 않아야 한다.
 - 모든 요청은 일회성의 성격을 가지며 이전의 요청에 영향을 받지 말아야 한다.
 - 다시 또 코리아닷컴의 예를 들면 메일을 확인하기 위해 꼭 '..코리아닷컴../mailView.crd'에 접근하여 해당 세션을 유지한 상태에서 메일 리소스에 접근해야 한다. 이것이 바로 Statelessness가 없는 예이다.
 - 세션을 유지 하지 않기 때문에 서버 로드 발란싱이 매우 유리하다.
 - URI에 현재 state를 표현할 수 있어야 한다. (권장사항)

+ Homogeneous Interface (동일한 인터페이스)
 - HTTP에서 제공하는 기본적인 4가지의 method와 추가적인 2가지의 method를 이용해서 리소스의 모든 동작을 정의한다.
 - 리소스 조회 : GET
 - 새로운 리소스 생성 : PUT, POST (새로운 리소스의 URI를 생성하는 주체가 서버이면 POST를 사용)
 - 존재하는 리소스 변경 : PUT
 - 존재하는 리소스 삭제 : DELETE
 - 존재하는 리소스 메타데이터 보기 : HEAD
 - 존재하는 리소스의 지원 method 체크 : OPTION
 - 대부분의 리소스 조작은 위의 method를 이용하여 대부분 처리 가능하다. 만일 이것들로만 절대로 불가능한 액션이 필요할 경우에는 POST를 이용하여 추가 액션을 정의할 수 있다. (되도록 지양하자)


5) 정리
REST는 . 웹의 모든 리소스를 URI로 표현하고 . 이를 구조적이고 유기적으로 연결하여 . 비 상태 지향적인 방법으로 . 일관된 method를 사용하여 리소스를 사용하는 웹 서비스 디자인 표준이다.

6) SOAP과 비교

사용자 삽입 이미지
사용자 삽입 이미지



SOAP은 SOAP메세지를 이용하여 특정한 서비스를 요청한다. SOAP 메세지를 사용해야 하기 때문에 무겁다고 말하고 서비스를 요청하기 때문에 SOA와 가깝다.
REST는 URI를 이용해서 리소스를 요청한다. URI를 사용하기 때문에 가볍다고 말하고 리소스를 요청하기 때문에 ROA와 가깝다.
SOA와 ROA에 대한 관점은 시각에 따라 다를 수 있지만 극명하게 대조하기 위해서는 위와 같이 차이점을 이해하는 것이 가장 좋다고 생각된다.

7) 맺음말
 최대한 쉽게 작성하고자 했지만 여전히 MK 본인에게도 설명하기 어려운 것은 사실이다. 하지만 중요한 것은 REST는 아키텍쳐가 아니라는 사실이다. ROA라는 아키텍쳐를 반영한 디자인 철학이다. 
ROA의 4가지 중요한 속성을 잘 이해한 후 이를 가슴에 깊이 새기고 이를 어기지 않고 웹 서비스를 디자인하면 이것이 바로 RESTful 한 웹 서비스가 될 것이라는 것이다.
 다음 포스트에서는 REST 구현체들에 대해 생각해 볼 예정이다. .net, java, ruby on rails에서 각각의 접근 방식에 대해서 좀 더 구체적으로 알아보도록 하자.

8) 참고자료 
1) Fielding 논문 원문

1. Dissertation_Roy_Fielding.pdf


2) Restlet.org의 FAQ를 한국어로 번역한 자료

2. Restlet.org_General_FAQ_한국어번역.pdf


3) KUT의 한연희님의 자료

3. Restlet_by_KUT_YounHee_Han.ppt


4) overstock.com에서 만든 자료

4. Restlet_Overview_by_overstock.com.pdf


5) RESTful Web Service , O'Reilly (author : Leonard Richardson & Sam Ruby)


출처 : http://www.iamcorean.net/22

'etc' 카테고리의 다른 글

2014 코스닥 상장기업 취업박람회 포스터  (5) 2014.10.21
svn connector  (1) 2014.09.23
자바 코드 영타 연습  (0) 2014.06.26
[번역] 와이프에게 REST 설명하기  (0) 2013.09.09
Posted by 꼬렙
:

Wife: Roy Fielding 이 누구야?

Ryan: 똑똑한 사람이지.

Wife: 그래? 뭐 하는 사람인데?

Ryan: 최초의 웹서버를 만드는데 일조했고 웹이 어떻게 동작하는지에 대한 연구도 많이 한 사람이야. 브라우저가 웹서버로부터 어떻게 데이터를 가져올지에 대한 [specification 에도 그사람의 이름이 있어.] (역주: 서버와 브라우저가 어떻게 대화하고 데이터를 전달하느냐 정하고, 그 방법을 protocol 이라고 해, 즉 protocol 에 대한 표준 문서 (specification) 에 그 사람의 이름이 있는 것이지)

Wife: 어떻게 동작하는데?

Ryan: 뭐가? 웹이?

Wife: 응.

Ryan: 음. 사실 정말 대단하지. 근데 신기하게도 사람들이 얼마나 대단한지 잘 몰라. 아까 얘기한 protocol, HTTP 라는 프로토콜인데, 이게 정말 많은 일을 하는데, 사람들이 잘 몰라.

Wife: http 그거 브라우저 주소창에 입력할때 쓰는거?

Ryan: 어. 주소의 젤 첫부분은 브라우저가 어떤 프로토콜을 써야될지 정해주는 거야. 브라우저 주소창에 입력하는 것이 사실, 컴퓨터 역사에서 엄청나게 혁명적인 일이지.

Wife: 왜?

Ryan: 우리가 "주소" 라고 부르잖아. 세계 어느 곳에 있는 어떤 것도 이 주소로 찾을 수 있다는 것이지. "주소" 라는 개념이 있어야 웹이 동작할 수 있는 것이지. 지식과 정보 (역주: 당신에겐 쇼핑 아이템들도 중요하겠네..) 를 웹에서 찾아주는 네비게이션 같은 거지.

Wife: 웹 페이지를 찾아준다는 거지?

Ryan: 웹 페이지도 찾아주고 다른 것도 찾아주지. Roy Fielding 이라는 사람이 했다는 research 에서, 주소가 어떤 것들을 표현할 수 있는지에 대해서도 다뤄. 웹은 REST 라는 구조로 만들어져 있어. REST 에서, 주소가 어떤 "자원" 을 가리킬 수 있는지 정리해 놓았어.

Wife: 웹 페이지가 "자원" 이야?

Ryan: 비슷해. 웹 페이지는 자원을 표현해서 보여주지. "자원" 이란건 어떤 개념이야. URL 이라고 브라우저에 입력하는 것 있잖아...

Wife: URL 이 무엇인지는 알아..

Ryan: URL 이 브라우저에게 "자원" 이 어디 있는지 알려줘. 브라우저는 특정 방법으로 표현된 자원을 요청하지. 브라우저는 웹 페이지라는 형태로 표현된 자원을 요청한다고 할 수 있어.

Wife: 그럼 어떤 표현 방법들이 있는데?

Ryan: 사실, 여러개의 표현 방법이 있을 수 있는데, 대부분의 자원은 한가지 형태로만 표현되는 경우가 많아. 다른 포맷 (역주: json, xml 등?) 들이 많이 사용되고 있어서, 앞으로는 다른 형태의 표현 방법도 많이 사용될 것 같아. (역주: 원글은 2004 년에 쓰여졌음.)

Wife: 예를들면 어떤..?

Ryan: 음. Web Service 라고 부르는 개념이 있는데, 사람들마다 다르게 받아들이는 개념이긴 한데, 기본적으로 기계(machine)도 사람들처럼 컴퓨터를 사용할 수 있다는 거야.

Wife: 로봇을 얘기하는 건가?

Ryan: 아니, 기계가 책상에 앉아서 웹 서핑을 한다는 얘긴 아니고. 컴퓨터가 정의된 protocol 으로 다른 컴퓨터들과 얘기할 수 있다는 거지. 사실 컴퓨터끼리 통신하는 건 이미 오래전부터 해왔던 일이긴 한데, 아직, 세상의 모든 컴퓨터가 서로 얘기할 수는 없다는 거지.

Wife: 왜?

Ryan: 왜냐면 첨부터 그렇게 사용하려고 설계된게 아니라서 그렇지. Fielding 과 그의 동료들이 웹을 생각할 때에는, 컴퓨터가 세상의 다른 모든 컴퓨터와 얘기할 수 있게 하는 것이 중요한 이슈였어. 컴퓨터들이 다른 컴퓨터와 통신할 때, 그들 끼리만 이해할 수 있는 통신 방법을 쓸 수도 있잖아.

Wife: 근데, 다른 모든 컴퓨터와 통신하고 싶다는 거지?

Ryan: 응 - 그리고 그 이상이야. 다른 컴퓨터와 대화할 때, 대화하고 있는 컴퓨터가 아닌 또 다른 컴퓨터에 있는 데이터들에 대해서 얘기하고 싶은거야. 좀 복잡한데 잘 들어봐. 한 컴퓨터가 다른 컴퓨터에게 또 다른 컴퓨터에 있는 자원에 대해서 얘기할 수 있는 방법이 필요한 거야.

Wife: 뭐라고?

Ryan: 당신이 동생이랑 얘기하고 있는데, 동생이 빗자루나 뭐 아무거나 빌려달라고 한다고 해봐. 근데 당신한테도 그게 없고, 엄마한테 있어. 그래서 동생한테, 엄마한테 가서 빌리라고 얘기해. 이런일이 살면서 자주 발생하자나 근데 컴퓨터들이 서로 대화하기 시작하면 컴퓨터들게도 이런 대화가 필요한 경우가 생긴다는 거지.

Wife: 그래서 컴퓨터들이 물건들이 어디 있는지 서로 어떻게 얘기하는데?

Ryan: URL 이지 물론. URL 은 컴퓨터 세상에서는 어떤 물건을 표현할 수 있는 "명사" 라고 생각하면 돼. 사람들이 어떤 명사가 어떤 물건을 표현하는지 약속하고 동의해서 사용하는게 중요하잖아?

Wife: 그렇지.

Ryan: 컴퓨터는 다른 모든 컴퓨터가 모두 이해하고 동의할 수 있는 "명사" 라는 개념이 없어. (역주: URL 외에는) 모든 프로그래밍 언어, 데이터베이스, 또 다른 기타 시스템들은 어떤 물건을 표현하는데 각기 다른 방법을 사용하지. URL 이 중요한 것은 이 때문이야. 이 모든 시스템들이 하나의 이름 ("명사") 으로 자원을 표현하게 해주지.

Wife: 근데 내가 웹페이지를 열어 볼때는, 그런 생각은 전혀 안하는데?

Ryan: 아무도 그런생각을 하진 않아. Fielding 과 몇몇의 사람들 빼고는. 그래서 아직도 컴퓨터들이 멍청한거야.

Wife: 대명사나 형용사는?

Ryan: REST 의 다른 큰 영역에 대해서 물어보다니 신가한데?. 동사가 중요해 사실.

Wife: 어머 농담이었는데.

Ryan: 응 근데 중요한 얘기야. 동사는 되게 중요하거든. 프로그래밍에서 중요하게 다루는 polymorphism 이라는 개념이 있어. 쉽게 표현하면, 다른 명사들에 같은 동사를 사용할 수 있다는 거야. (역주: 이름은 같은 동사지만, 다른 뜻의 동사를 사용할 수 있다는 것이겠죠)

Wife: 잘 이해가 안가는데.

Ryan: 커피 테이블을 봐바. 명사로 부르는게 뭐가 있지? 컵, 쟁반, 신문, 리모컨 이 있어. 이걸로 무엇을 할 수 있지?

Wife: 이해가 안되는데..

Ryan: 잡을 수 있지? 들어 올리수 있고. 넘어뜨릴 수도 있고. 태워버릴 수도 있고. 같은 동사를 여기 있는 어떤 물건들에도 적용할 수 있잖아. .

Wife: 응 그렇지. 그래서?

Ryan: 그게 중요하거든. "컵을 집어줘", "신문을 집어줘", "리모컨을 집어줘" 이렇게 같은 동사 "집어줘"를 사용하는게 아니라 명사마다 다른 동사를 써야된다면 어떻겠어?

Wife: 와! 복잡하겠는걸.

Ryan: 우리는 다른 명사에 같은 동사를 적용해도 다 어떤 뜻인지 이해할 수 있어. 어떤 동사들은 특정 명사들에만 적용시킬 수 있는 것들도 있지. 예를 들면, 컵을 운전한다거나, 차를 마신다거나 하는 표현은 말이 안되지. 하지만 어떤 동사들은 거의 모든 명사에 적용이 가능해. GET, PUT, DELETE 이런 것들은 말이야.

Wife: 컵을 DELETE 할 수는 없잖아?

Ryan: 하지만 던져버릴 수는 있지. 농담이였지?

Wife: 응.

Ryan: Fielding 과 그의 친구들이 만든 HTTP 라는 프로토콜은 사실 명사에 동사를 적용시키는 것에 대한 내용이야. 예를들면, 웹페이지를 본다는 것은, 브라우저가 HTTP 의 GET 동사를 당신이 입력한 URL 에 적용하여, 웹페이지를 받아 오는 거야.

웹페이지에는 보통 이미지들이 있잖아? 그 이미지들은 보통 텍스트하곤 분리되어 있는 자원이야. 웹 페이지에 그 이미지들에 대한 URL 들이 있어서, 브라우저가 웹페이지를 받은 후, 이미지를 가져오기 위해 또 HTTP GET 을 하게 되지. 하지만 중요한 것은, 다른 명사들에 같은 동사를 적용할 수 있다는 것이지. 명사가 image, text, video, mp3, slideshow 어떤 것이든 상관 없이 GET 을 사용할 수 있다는 거야.

Wife: GET 이 아주 중요한 동사인가 보네.

Ryan: 응. 브라우저가 하는 일의 대부분은 자원을 GET 하는 것이니까. 브라우저가 다른 작업을 할때는 그리 많지 않아. 그래서 사람들이 HTTP 는 그냥 GET 만 하는 프로토콜이라고 생각하기도 해. 하지만 HTTP 는 사실 동사를 명사에 적용하는 프로토콜이라고 봐야 돼.

Wife: 좋아 알겠어. 근데 이게 뭘 어떻게 바꾼거지? 어떤 명사와 동사를 사용하길 원하는 거야?

Ryan: 명사들은 이미 사용중이긴 한데, 원하는 형태의 포맷으로 사용되고 있진 않아.

크리스마스 선물을 사려고 amazon.com 을 돌아다니고 있다고 해봐. 각 제품을 명사라고 생각하고. 만약 컴퓨터가 이해할 수 있는 방식으로 이 명사들이 표현되어 있으면, 정말 할 수 있는 일들이 많아.

Wife: 컴퓨터가 웹페이지를 우리가 이해하듯이 이해하면 되지 않아?

Ryan: 웹페이지는 사람들을 위해 만들어진 것이야. 컴퓨터는 페이지의 스타일에 대해선 신경 쓰지 않지. 컴퓨터는 데이터만 필요한 것이지. 이상적으로는 각각의 URL 에 대해서 사람이 이해할 수 있는 표현 방식과 컴퓨터가 이해할 수 있는 표현 방식이 있으면 좋겠지. 컴퓨터가 이 자원을 GET 할 때, 이해할 수 있는 형태로 자원을 받을 수 있고, 사람이 GET 을 할 때는 사람이 이해할 수 있는 형태로 자원을 받게 말이야.

Wife: 그럼 사람들이, 모든 페이지를 컴퓨터가 이해할 수 있는 방식으로도 만들어 줘야하나?

Ryan: 가치가 있다면 그렇게 할 수 있지.

개념적으로 얘기한 부분들이 많은데, 실례를 들어 얘기해 볼께. 당신이 선생님이라고 해보자. 학교에 컴퓨터 시스템이 있어서 학생들을 관리한다고 해봐. 학생들이 어떤 수업을 듣는지, 성적은 어떤지, 위급 상황에 누구에게 연락해야 하는지, 가르치기 위해서 선생님들이 사용하는 책들은 어떤 것들이 있는지 여러가지 정보를 관리한다고 해봐. 이 시스템이 웹 기반이라면, 명사들에 대해서 URL 이 있을 거야. 학생, 선생님, 수업, 책, 교실 등등 에 대한 URL 이 있겠지. 브라우저에 URL 을 입력하면 웹페이지가 뜬다고 해봐. 근데 각각의 URL 마다 컴퓨터가 이해할 수 있는 방식으로도 표현이 가능하다면, 이 시스템에 다른 기능을 추가하는 것이 매우 쉬울 거야. 시스템 내부의 다른 서브 시스템들이 서로 대화하기에도 훨씬 편할 것이고 말이지. 각학교의 시험 성적을 수집하거나 하는, 정부에서 운영하는 시스템을 만들수도 있지. 가능성은 무궁무진해.

각 시스템은 HTTP GET 을 이용해서 정보를 가져올 거야. 어떤 시스템이 다른 시스템에게 정보를 추가하고 싶다면, HTTP POST 를 사용할 거야. 정보를 수정하고 싶다면 HTTP PUT 을 이용하지. 데이터가 어떻게 생겨야 하는지만 정하면 이 모든 것들을 할 수 있어.

Wife: 그래서 컴퓨터 한다는 사람들이 작업중인게 이거야? 데이터가 어떻게 생겨야 하는지 정하는거?

Ryan: 아쉽게도 아니야. 많은 사람들은 더 복잡한 것을 만들려고 해. 그들이 생각하는 세상에선, 명사로 세상 모든 물건을 표현할 수도 없고, 동사는 polymorphic 하지도 않아. 이미 사용하고 증명된 기술을 버리고 예전에 실패한 시스템 같은 것들을 만들려고 하고 있어. 우리는 현란한 툴들을 사용하려고 '간단함' 이라는 것을 버리고 있어.

Wife: 왜?

Ryan: 나도 모르겠어

Wife: 뭐라고 한마디 하지 그래?

Ryan: 그러게 언젠가 그래야겠지.


번역 출처 : http://codeflow.co.kr/question/542/how-i-explained-rest-to-my-wife/

원문 : http://www.looah.com/source/view/2284

'etc' 카테고리의 다른 글

2014 코스닥 상장기업 취업박람회 포스터  (5) 2014.10.21
svn connector  (1) 2014.09.23
자바 코드 영타 연습  (0) 2014.06.26
RESTful 웹 서비스에 대해 알아보자  (0) 2013.09.09
Posted by 꼬렙
: