Service Oriented - 해당되는 글 9건

Creating a Graphical Client for Twitter

In this tutorial, you use the NetBeans IDE to create a simple, graphical, REST-based client that displays Twitter public timeline messages and lets you view and update your Twitter status. The application uses Swing and NetBeans IDE's support for Twitter's SaaS operations.

Running client displaying Twitter messages

If you do not have a Twitter account, go to twitter.com and create an account before proceeding with this tutorial.

A complete sample of this application is available for download. Click here to download the sample.

Contents

Content on this page applies to NetBeans IDE 6.5

To complete this tutorial, you need the following software and resources.

Software or Resource Version Required
NetBeans IDE Java download bundle, Version 6.5
Java Development Kit (JDK) Version 6 or version 5
User name and password for a Twitter account

Designing the JFrame

In this step you create the GUI elements that will display the Twitter public timeline, your user icon, and where you read and update your status. The GUI elements are all wrapped in a JFrame. You do not have to lay out the GUI elements exactly as described in this section. This layout is a suggestion only. For example, you may add more functionality. However you need to create at least all the elements described in this tutorial.

To design the JFrame:

  1. Choose File > New Project. The New Project wizard opens. Select the Java category, then a Java Application project. Click Next.
  2. Name the project TwitterSwingClient. Select a Project Location. Unselect Create Main Class. (The JFrame will be the main class.) Click Finish.
    New Project wizard showing fields for creating the TwitterSwingClient project
  3. The IDE creates the TwitterSwingClient project, which appears in the Projects window. Right-click the TwitterSwingClient project node and choose New > JFrame Form (or New > Other > Swing GUI Forms > JFrame Form). The New JFrame Form wizard opens.
  4. Name the form TwitterJFrame and create a package for it called twitterclient. Click Finish.
    New JFrame Form wizard showing fields for creating TwitterJFrame
  5. The IDE opens TwitterJFrame in the editor, in the Design view. Here you have a palette of all the Swing components you can drag and drop into the JFrame.
    Twitter J Frame in the Design view of the Editor
  6. Click on the Button icon under Swing Controls in the Palette. Drag and drop it into the bottom right corner of the JFrame. Note that the button displays jButton1, which is the name of this JButton object.
    JFrame showing newly added jButton1
  7. Right-click jButton1 and select Edit Text from the context menu. Change the display text to "Update."
  8. Drag and drop a Label (jLabel1) to the bottom left corner of the JFrame. Change its display text to "Icon." Your user icon will be displayed in this label.
  9. Drag and drop a Text Field (jTextField1) between the Label and the Button. Change its display text to "Status." Click on the right border of the text field and stretch it across towards the button. Blue guidelines appear showing you suggested distances from the button.
  10. Right-click on jLabel1 and select Properties from the context menu. The jLabel1 Properties dialog opens. Set the labelFor property to point to jTextField1. (This increases accessibility.)
  11. Find the properties Maximum Size, Minimum Size, and Preferred Size. Set each of these properties to [48,48], to match the 48px X 48px dimensions of Twitter icons.
    Properties of j Label 1 in Twitter J Frame, showing Maximum, Minimum, and Preferred sizes set to 48, 48
  12. Drag and drop a Scroll Pane into the upper part of the JFrame. Drag its borders to expand it to fill most or all of the space above the text field and button. (You may leave a margin if you want to add more functionality later, such as the menu in the sample.)
  13. Drag and drop a List into the Scroll Pane. A sample list of items appears. Save TwitterJFrame. The JFrame should look like the following image:
    Twitter J Frame in the Design view, with all basic GUI elements

You now have all the basic GUI components for the Swing client. It is time to add the first Twitter SaaS (Software as a Service) operation.

Showing Your User Status

In this section you create a new method and add the Twitter getUserTimeline operation to this method. The getUserTimeline operation gets your user icon and your current status. You then add code to the method to display your icon and status in jLabel1 and jTextField, respectively. Finally you add a line to the JFrame's constructor to initialize the method.

To show your user status:

  1. Switch to the Source view of TwitterJFrame.
  2. In the code, add a few empty lines above the main method.
    Code of Twitter J Frame showing empty lines added above main method
  3. In the empty space, type in the following code to create the method initUserInfo.
    private void initUserInfo() {


    }
  4. Open the Services window in the IDE. Under Web Services, navigate to Twitter > What Are You Doing Service > [statuses] > [user_timeline.{format}] > getUserTimeline.
    Services window with Web Services tree showing Twitter getUserTimelineById operation chosen
  5. Drag and drop getUserTimeline into the method body of initUserInfo. The Customize GET SaaS Service dialog opens. Type "1" for the value of count, because you only want to see the last status message. Exit the value cell for count and click OK. (If you do not exit the cell before you click OK, your change will not be saved. Alternatively, you can change the value of count in the code.)
    Properties dialog for get User Timeline operation
  6. The IDE generates code for the getUserStatusById operation. The IDE also creates the org.netbeans.saas package, which contains the RESTful communication code, and the org.netbeans.saas.twitter package, which contains the authenticaton code and the Twitter WhatAreYouDoingService class. The IDE adds an import statement for this class to TwitterJFrame.

    Note: In the Sample, objects and variables in this method such as format and result are numbered format2, result2, etc, because the getUserTimeline code was added after the getPublicTimeline code.

    private void initUserInfo() {

    try {
    String since = null;
    String sinceId = null;
    String page = null;
    String count = "1";
    String format = "xml";

    RestResponse result = TwitterWhatAreYouDoingService.getUserTimeline(since, sinceId, page, count, format);
    if (result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses) {
    twitter.whatareyoudoingservice.twitterresponse.Statuses resultObj = result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    } else if (result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.NilClasses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.NilClasses) {
    twitter.whatareyoudoingservice.twitterresponse.NilClasses resultObj = result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.NilClasses.class);
    }
    //TODO - Uncomment the print Statement below to print result.
    //System.out.println("The SaasService returned: "+result.getDataAsString());
    } catch (Exception ex) {
    ex.printStackTrace();
    }

    }
  7. In the generated code, locate the if block.
    if (result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses) {
    twitter.whatareyoudoingservice.twitterresponse.Statuses resultObj = result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    }
  8. At the end of the if block, insert code that gets your user status text and icon URL and uses this data to display your status in jTextField1 and jLabel1.
    if (result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses){
    twitter.whatareyoudoingservice.twitterresponse.Statuses resultObj = result.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    StatusType st = resultObj.getStatus().get(0);
    jTextField1.setText(st.getText().trim());
    UserType user = st.getUser();
    String iconSrc = user.getProfileImageUrl();
    URL iconUrl = new URL(iconSrc);
    ImageIcon icon = new ImageIcon(iconUrl, user.getScreenName());
    jLabel1.setIcon(icon);

    }
  9. Press Ctrl-Shift-I to add import statements. A dialog opens with a choice of URL classes to import. Select the default, java.net.URL.
  10. At the top of the TwitterJFrame class, locate the constructor. Add the line initUserInfo(); to the constructor's body.
    public class TwitterJFrame extends javax.swing.JFrame {

    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    initComponents();
    initUserInfo();
    }

After you set up authentication, you can run the project. Right-click the project node and select Run from the context menu. An application opens showing your user icon and status.

Running application, showing user icon and status

Setting Up Twitter Authentication

There are two ways you can set up your application to log into Twitter:

To set up automatic login, open org.netbeans.saas.twitter.twitterwhatareyoudoingserviceauthenticator.properties. Type in your username and password and save the file.

Setting the authentication credentials in the authenticator properties file

If you do not set up these properties, a preconfigured login screen appears when you run the application.

Warning: On Windows XP and linux, there are problems rendering the preconfigured login screen. To work around this problem, either set up automatic login or use an alternative login screen. An alternative login screen is provided in the sample. To use the alternative login screen:

  1. Copy the sample's twitterclient.AuthDialog.java to your own twitterclient package.
  2. Replace your version of org.netbeans.saas.twitter.TwitterWhatAreYouDoingServiceAuthenticator.java with the version in the sample.

Adding the updateStatus Operation

In this section you add the Twitter updateStatus operation to JButton1 (the "Update" button), which you created when you designed the JFrame. You also add the code so that when the button is clicked, the client gets the text from JTextField1 (the "Status" field) and sends it to Twitter.

To add the updateStatus operation:

  1. Return to the Design view of TwitterJFrame. Double-click the Update button in the JFrame. The editor switches back to the Source view, in the body of the jButton1ActionPerformed method, which the IDE just created for you.
    TwitterJFrame in Source view, with cursor in middle of newly created jButton1ActionPerformed method
  2. Open the Services window. Under Web Services, navigate to Twitter > WhatAreYouDoingService > Statuses > [update.{format}] > updateStatus.
    Services window showing Web Services tree with Twitter update Service operation selected
  3. Drag and drop the updateStatus operation into the method body of jButton1ActionPerformed. The Customization POST SaaS dialog appears. Accept the defaults and click OK. The IDE generates the code for the updateStatus operation into the method body.
  4. In the generated try block, locate the line String status = "";. Change it to String status = jTextField1.getText().trim();. (Try changing it with code completion!) This gets the text typed into the text field and puts it in the status object that is sent by POST to Twitter.

The application can now update your Twitter status, when you are authenticated.

Displaying Usernames and Statuses in the JFrame

Now you set up the application to display the usernames and public statuses of everyone in the Twitter public timeline.

Creating a TimerTask

To update the display of the Twitter public timeline automatically, wrap the execution code in a TimerTask. Write the TimerTask wrapper first and then fill it in with execution code. Otherwise your code will be full of error warnings.

To create the TimerTask:

  1. Open TwitterJFrame in the Sources view of the editor.
  2. Find the class declaration and the constructor.
    public class TwitterJFrame extends javax.swing.JFrame {

    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    initComponents();
    initUserInfo();
    }
  3. In the method body of the constructor, above initComponents();, instantiate the java.util.Timer class. The parameters name the Timer thread "Twitter Updater" and specify that it cannot be run as a daemon.
    public class TwitterJFrame extends javax.swing.JFrame {

    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    Timer t = new Timer("Twitter Updater`", false);

    initComponents();
    initUserInfo();
    }
  4. Right-click anywhere in the editor and select Fix Imports from the context menu, or press Ctrl-Shift-I. A dialog opens and gives you a choice of classes to import. Add an import statement for java.util.Timer.
  5. Below the instantiation of Timer, create a new Timer.scheduleAtFixedRate method. The method's parameters are a TimerTask object, the delay before it first runs the task, and the frequency with which it runs the task. Set the method to wait 1.5 seconds and run every 75 seconds. The exact code follows, in bold. An empty line is left where you put the execution code. Note that you have to add an import statement for java.util.TimerTask.
    public class TwitterJFrame extends javax.swing.JFrame {

    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    Timer t = new Timer("Twitter Updater`", false);
    t.scheduleAtFixedRate(new TimerTask() {


    }, 1500, 75000);

    initComponents();
    initUserInfo();
    }

The TimerTask wrapper code is now complete. Next you add the execution code.

Adding a run Method With the getPublicTimeline Operation

To display usernames and statuses, the application first gets this data from Twitter. Twitter SaaS provides the getPublicTimeline operation for getting public usernames and statuses. To execute the getPublicTimeline operation when the application runs, the operation needs to be inside a run method. Finally, because the application displays the usernames and statuses in a JList, the application needs to add the results of getPublicTimeline as elements of a DefaultListModel object.

To add a run method with the getPublicTimeline operation:

  1. Above the TwitterJFrame constructor, create a DefaultListModel object named statuses.
    public class TwitterJFrame extends javax.swing.JFrame {

    private DefaultListModel statuses = new DefaultListModel();



    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
  2. Right-click anywhere in the editor and select Fix Imports from the context menu, or press Ctrl-Shift-I. This action adds an import statement for DefaultListModel.
  3. In the body of the TimerTask object, create a new run method. Use the @Override annotation to override the run method in main.
    public class TwitterJFrame extends javax.swing.JFrame {

    private DefaultListModel statuses = new DefaultListModel();





    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    Timer t = new Timer("Twitter Updater`", false);
    t.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run(){

    }

    }, 1500, 75000);
    initComponents();
    initUserInfo();
    }
  4. Open the Services window. In the Web Services tree, navigate to Twitter > What Are You Doing Service > [statuses] > [public_timeline.{format}] > getPublicTimeline.
    Services window showing Twitter getPublicTimeline operation
  5. Drag and drop getPublicTimeline into the body of the run method. A dialog box opens where you can customize the parameters of the GET operation. Accept the defaults and click OK. The IDE adds a try block with getPublicTimeline into your code.
    public class TwitterJFrame extends javax.swing.JFrame {

    private DefaultListModel statuses = new DefaultListModel();

    /** Creates new form TwitterJFrame */
    public TwitterJFrame() {
    Timer t = new Timer("Twitter Updater`", false);
    t.scheduleAtFixedRate(new TimerTask() {

    @Override
    public void run() {

    try {
    String format2 = "xml";

    RestResponse result2 = TwitterWhatAreYouDoingService.getPublicTimeline(format2);
    if (result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses) {
    twitter.whatareyoudoingservice.twitterresponse.Statuses result2Obj = result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    } else if (result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.NilClasses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.NilClasses) {
    twitter.whatareyoudoingservice.twitterresponse.NilClasses result2Obj = result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.NilClasses.class);
    }
    //TODO - Uncomment the print Statement below to print result.
    //System.out.println("The SaasService returned: "+result2.getDataAsString());
    } catch (Exception ex) {
    ex.printStackTrace();
    }


    }
    }, 1500, 75000);
    initComponents();
    initUserInfo();
    }
  6. In the try block, locate the if block.
    if (result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses) {
    twitter.whatareyoudoingservice.twitterresponse.Statuses result2Obj = result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    }
  7. At the end of the if block, insert code that adds a list element to statuses (your DefaultListModel object created in Step 1) for every Status object that the method gets from Twitter.
    if (result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class) instanceof twitter.whatareyoudoingservice.twitterresponse.Statuses) {
    twitter.whatareyoudoingservice.twitterresponse.Statuses result2Obj = result2.getDataAsObject(twitter.whatareyoudoingservice.twitterresponse.Statuses.class);
    for (final StatusType st : result2Obj.getStatus()) {
    SwingUtilities.invokeLater(new Runnable() {

    public void run() {
    statuses.addElement(st);
    }
    });
    }

    }
  8. Press Ctrl-Shift-I to add an import statement for StatusType.

The code for getting statuses from the Twitter public timeline is now complete. Next you write a new class that returns a Component with list elements rendered in GUI components.

Creating a List Cell Rendering Component

Now you have code that gets Status objects from the Twitter Public Timeline and creates a list element for each status. However, you cannot display these raw list elements in a JList. You need to pass the data into GUI components . To accomplish this, create a new JPanel that implements javax.swing.ListCellRenderer. This JPanel returns a java.awt.Component object with the username and status passed in JLabels. You can customize the appearance of the JLabels in the JPanel.

To add a list cell rendering Component:

  1. Right-click the project's node and choose New > JPanel Form. The New JPanel Form wizard opens.
  2. Name the JPanel Item and place it in the twitterclient package.
    New JPanel Form wizard showing panel named Item and package twitterclient
  3. Click Finish. Item.java opens in the Design view of the editor.
  4. Drag and drop a Label and a Text Pane into the JPanel. The Label will display the username and the Text Pane will display that user's status message.
  5. Position the Label and the Text Pane to match how you want the data to be displayed. In the following image, the username is on the left top while the status text is below and slightly indented. The sample project has the data on the top left and the username on the bottom right. Leave enough empty space in the JPanel below the Text Pane for the Text Pane to expand when it contains longer text.
    Layout of jlabels displaying username and status text
  6. Right-click on the JLabel element and select Properties from the context menu. In the Properties, you can change the font, the color, the alignment and other qualities. Set the labelFor property to point to jTextPane1. This improves accessibility. Experiment with the properties of the label until you like the appearance. In the following image, the font color is set to blue in the Foreground property.
    JLabel properties dialog with Foreground set to blue
  7. Open the Properties dialog of the JTextPane and experiment with its appearance.
  8. Change to the Source view for Item.java. Find the Generated Code block and expand it. This shows you the code generated by the IDE when you set the properties of the JLabel and JTextPane.

    In the following image, note the blue color setting for JLabel1. Can you see what properties are set for the JTextPane?

    Code generated in Item.java by setting JLabel properties in the Design view
  9. Find the class declaration and add the code implements ListCellRenderer.
    public class Item extends javax.swing.JPanel implements ListCellRenderer {
  10. Press Ctrl-Shift-I. This action adds an import statement for javax.swing.ListCellRenderer. A warning appears saying that you need to implement all abstract methods.
  11. Add a few empty lines between the generated code block and the variable declarations. Into that space, add the following code, which implements the abstract method getListCellRendererComponent. (You can copy and paste the code, or you can try to reproduce it with code completion.) This code replaces the default label texts "username" and "text" with the Text, User, and ScreenName objects you get with the Twitter StatusType class. The code then returns an instance of Component with these new JLabel text values.
    public Component getListCellRendererComponent(JList list, Object value, int index, boolean sel, boolean focus) {
    StatusType st = (StatusType) value;
    jTextPane1.setText(st.getText());
    jLabel1.setText("<html>" + st.getUser().getScreenName() + "</html>");
    return this;
    }
  12. Press Ctrl-Shift-I. This adds import statements for the StatusType and Component classes. Save Item.java.

Now you have an Item class that returns a Component object with username and status displayed in a JLabel and a JTextPane. Next you modify TwitterJFrame to use this Component.

Displaying the Component in TwitterJFrame

In order to display the Component object created in Item.java, the JList in TwitterJFrame has to use Item.java as its cell renderer.

  1. Return to TwitterJFrame. In the Design view, select the JList. Right-click and open its Properties.
    Properties dialog for the JList element in TwitterJFrame
  2. Select the model property. Press Ctrl-Space. The custom property editor opens, showing the default text displayed in the list.
    J list custom property editor
  3. In the "Set jLlist1's model property using:" drop-down menu, select Custom Code. A text field appears where you type in the properties for jLabel1.setModel. Type statuses in the field and click OK.
    jList custom property editor showing setModel(statuses) chosen in the cusom code editor
  4. In the Properties dialog, select cellRenderer and press Ctrl-Space. The custom property editor opens.
  5. In the "Set jList1's cellRenderer property using:" drop-down menu, select Custom Code. A text field appears where you type in the properties for jList1.cellRenderer. Type new Item() and click OK.
    J List custom cell renderer properties editor showing new Item chosen

Your client application is now complete! Save all files and run the application. (Right-click project node and select Run.) The application opens, showing a list of public timeline messages and a field with your own status.

Running client displaying Twitter messages

More Exercises

Here are a few more ideas for you to explore:

  • Change your Twitter user icon (in a browser) and run the client again. Does the new icon appear?
  • Add a toolbar with some functions to the JFrame.
  • Add a new Scroll Pane with a new List that displays your friends' statuses, using the What Are You Doing Service > [statuses] > [friends_timeline.{format}] > getFriendsTimeline operation. The code is similar to the code for displaying the public timeline.

See Also

For more information about using NetBeans IDE to create and consume web services and to design GUIs, see the following resources:

To send comments and suggestions, get support, and keep informed on the latest developments on the NetBeans IDE Java EE development features, join  the nbj2ee@netbeans.org mailing list
      Service Oriented  |  2009. 3. 9. 16:34




Exposing a MySQL Database with RESTful Web Services

This tutorial shows you how to use NetBeans IDE to expose a MySQL database as a RESTful web service endpoint. You will deploy the "sakila" sample database on GlassFish v2 using the RESTful Web Services plugin. In this tutorial, you learn to create:

  • A database connection to MySQL
  • A new data source using that connection
  • Entity classes from the MySQL database
  • RESTful web services from those entity classes

Contents

Content on this page applies to NetBeans IDE 6.1 and 6.0

To follow this tutorial, you need the following software and resources.

Software or Resource Version Required
NetBeans IDE Web & Java EE download bundle 6.1 or 6.0
Java download bundle 6.5
Java Development Kit (JDK) version 6 or
version 5
The latest stable MySQL (download).
The "sakila" sample MySQL database (download).
Java EE-compliant web or application server Tomcat web server 6.0 and/or
GlassFish application server v2

Both Tomcat and GlassFish can be installed, optionally, with the Web and Java EE distribution of NetBeans IDE. Alternatively, you can visit the GlassFish downloads page or the Apache Tomcat downloads page.

This tutorial also requires the RESTful Web Services plugin. In the IDE, go to the Plugin Manager, under the Tools menu, and check whether the RESTful Web Services Plugin is installed, under the Installed tab. If it is not, install it from the Available Plugins tab, as shown below:

restful from plugin manager

Introduction

MySQL is the world's most popular open source database software, with over 100 million copies of its software downloaded or distributed throughout its history. With superior speed, reliability, and ease of use, MySQL has become the preferred choice of corporate IT Managers because it eliminates the major problems associated with downtime, maintenance, administration and support.

The IDE supports rapid development of RESTful web services from databases, by the creation and exposure of entity classes. RESTful web services are services based on HTTP header operations. Building web services using the RESTful approach is emerging as a popular alternative to using SOAP-based technologies for deploying services on the internet, due to its lightweight nature and the ability to transmit data directly over HTTP.

To celebrate the announcement that Sun Microsystems is acquiring MySQL, Arun Gupta originally created this demonstration, showing how a MySQL database could be exposed as a RESTful web service using the IDE.

Before you use this tutorial, you should see the following:

Creating a Database Connection

The IDE contains the MySQL Connector/J JDBC Driver, allowing you to connect to a MySQL database. The goal of this exercise is to create that connection.

  1. Start your MySQL database.
    • On Windows, type the command mysqld-nt --user root --password=your_root_user_password. You must be in the MySQL bin directory or the bin directory must be on your path. If you get an error that mysql could not connect to localhost, start the MySQL service (Control Panel > Administrative Tools > Services).
    • On UNIX systems, type the command ./bin/mysqld_safe from the MySQL directory.
  2. Start the IDE. Open the Services tab. Expand Databases > Drivers. Look for the MySQL driver. If it is not there, right-click the Drivers node, choose New Driver and fill in the dialog with the path to your MySQL Connector/J driver.

    Servers tab showing drivers
  3. Right-click on the MySQL (Connector/J) driver node and choose Connect Using... The New Database Connection dialog opens.
  4. Leave the Name and Driver fields with default values. For Database URL, type jdbc:mysql://localhost:sakila. For User Name, type root, and for Password type your "root" user password. The dialog should resemble the following. Click OK when done.
    Creating new database connection for My SQL

Setting Up a Web Application Project

The goal of this exercise is to create a new Web Application project. This project will contain entity classes and RESTful web services.

  1. Choose File > New Project (Ctrl-Shift-N) from the main menu. Under Categories, select Web. Under Projects, select Web Application and click Next.
  2. Type sakila in the Project Name field. Note that the Context Path becomes /sakila.
  3. Specify the Project Location to any directory on your computer. You can accept the default location.
  4. Under Server, select GlassFish. GlassFish is a Java EE5-certified application server and is bundled with the Web and Java EE insallation of NetBeans IDE. If you use a server other than GlassFish, such as the bundled Tomcat web server, you may need to configure the server, which is outside the scope of this tutorial.
  5. Leave the Set as Main Project option selected and click Finish. The IDE creates the Sakila project folder. The project folder contains all of your sources and project metadata, such as the project's Ant build script. The HelloWeb project opens in the IDE. The welcome page, index.jsp, opens in the Source Editor in the main window. You can view the project's file structure in the Files window (Ctrl-2), and its logical structure in the Projects window (Ctrl-1).
    Empty project logical structure

Generating Entity Classes from a Database

The goal of this exercise is to generate entity classes from the sakila database.

  1. Right-click the sakila node and choose New > Entity Classes from Database, as shown below:


    starting entity classes from db wizard

  2. In the Database Tables panel, select New Data Source from the Data Source drop-down field. The Create Data Source dialog opens.
  3. Type jndi/sakila in the JNDI Name field. From the Database Connection drop-down field, select jdbc:mysql://localhost/sakila [root on Default schema], as shown below. Click OK. The dialog closes and you return to the Database Tables panel.

    Create Data Source dialog
  4. Under Available Tables, click "film" and then click Add >. The Database Tables page should now look like the image below. Click Next.

    selecting database tables
  5. The Entity Classes page opens. Click Create Persistence Unit... Accept all the defaults shown below and click Create. You return to the Entity Classes page.
    Create Persistence Unit dialog
  6. Under Package, type sakila. The Entity Classes page should now appear as follows:
    completed new entities classes page
  7. Click Finish. The IDE creates the entity classes.

  8. Look in the Projects window. You should now see the following:
    Projects view showing sakila package

Configuring the Persistence File

In Generating Entity Classes from a Database, you created a perstence unit. The configuration of this persistence unit is stored in the file persistence.xml. In your Projects view, you can find persistence.xml in your project, in the Configuration Files node.

You need to change this persistence file to pass the username and password. Open the XML tab. Edit the file to include toplink.jdbc.user and toplink.jdbc.password properties. It matches the following snippet (the parts you add or change are boldface):

<persistence-unit name="sakilaPU" transaction-type="JTA">
<jta-data-source>jndi/sakila</jta-data-source>
<properties>
<property name="toplink.jdbc.user" value="root"/>
<property name="toplink.jdbc.password" value="your_root_user_password"/>
</properties>

</persistence-unit>

Generating RESTful Web Services from Entity Classes

The goal of this exercise is to generate RESTful web services from the entity classes that we generated in the previous section.

  1. Right-click the package that contains the entity classes and choose New > RESTful Web Services from Entity Classes, as shown below:
    choosing the wizard
  2. In the New RESTful Web Services from Entity Classes wizard, click Add All. You should now see the following:
    choosing the entity classes
  3. Click Next. The Generated Classes panel opens. Accept all defaults and click Finish. The IDE now creates the RESTful web services.

    The RESTful Web Services node in the Projects window displays all the RESTful web services in your project. The value between the square brackets, such as [/films/], is the value for the URI template. You can also navigate to the source file by doubling clicking on this node. This view also displays all the HTTP methods and Sub-resource locator methods. Again, you can navigate to the methods by double clicking on the nodes.

Now that our entity classes and RESTful web services have been generated, let's test our application. The IDE provides a useful utility for testing RESTful web services. We will make use of it in the next section.

Testing the RESTful Web Services

The goal of this exercise is to try out our application.

  1. Right-click the project node and choose Test RESTful Web Services, as shown below:
    Test RESTful services context menu item in Project tab

    The server starts and the application is deployed. Finally, the browser should display your application, with a link for each of the web services:
    RESTful service tester

    On the left-hand side is the set of root resources. Here they are named languages and films.

  2. Click Films and then click Test or the URL "http://localhost:8080/sakila/resources/films/". The result is the RESTful representation of the Film table. The default representation shows 10 records from the table where each entry returns the id of the film and a reference to the detailed entry.

    table of films

You can view more entries by appending /?max=n to the URL. For example, "http://localhost:8080/sakila/resources/films/?max=40" shows the first 40 entries. Additional fields from the table can be displayed by adding getter methods to the "converter.FilmRefConverter" class, such as:

@XmlElement
public String getTitle() {
return entity.getTitle();
}
The getTitle method returns the film title in addition to the fields already returned. The different columns in the table can be viewed by going to the "Services" tab and expanding the sakila database connection created earlier:



The modified output (with film title included) looks like this:

More Exercises

Here are a few more ideas for you to explore:

  • Create RESTful representations of other tables using the steps described above.
  • Display the data from different tables in a jMaki-wrapped Yahoo or Dojo data table as explained in TOTD #10.
  • Display the data retrieved from the database in a JSP page as described in Hello JPA World.
  • Create a CRUD application using jMaki Data Table as described in TOTD #15 or Screencast #Web10.

A JRuby-on-Rails application using MySQL is explained here. TOTD #9 explains how JDBC connection pooling in GlassFish can be used for a JRuby-on-Rails application using MySQL.

The key message here is MySQL can be very easily used with GlassFish and NetBeans IDE makes it possible.


See Also

For more information about using NetBeans IDE 6.0 to develop Java EE applications, see the following resources:

To send comments and suggestions, get support, and keep informed on the latest developments on the NetBeans IDE Java EE development features, join the nbj2ee@netbeans.org mailing list.

      Service Oriented  |  2009. 3. 9. 16:33




REST (Representational State Transfer)는 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식이다. 이 용어는 로이 필딩(Roy Fielding)의 2000년 박사학위 논문에서 소개되었다. 그는 하이퍼텍스트 전송 프로토콜 (HTTP)의 주요 저자들 가운데 한사람이다. 그 뒤로 이 개념은 네트워킹 문화에 널리 퍼졌다

엄격한 의미로 REST는 네트워크 아키텍처 원리의 모음이다. 여기서 네트워크 아키텍처 원리란 리소스를 정의하고 리소스에 대한 주소를 지정하는 방법에 대한 개괄을 말한다. 간단한 의미로는, 도메인 지향 데이터를 HTTP위에서 SOAP이나 쿠키를 통한 세션 트랙킹 같은 부가적인 전송 레이어 없이, 전송하기 위한 아주 간단한 인터페이스를 말한다. 이 두 가지의 의미는 당연히 겹치는 부분과 충돌되는 부분이 있다. 필딩의 REST 아키텍처 형식을 따르면 HTTP 프로토콜을 사용하지 않은채로 또 월드 와이드 웹에서 전송하지 않고도 아주 커다란 소프트웨어 시스템을 설계하는것도 가능하다. 또한 리모트 프로시져 콜을 이용하는 대신에 간단한 XMLHTTP 인터페이스(REST 원리에 부합하지는 않지만)를 이용해 설계하는것도 가능하다. 현실 세계에서의 REST 용어에 대한 이러한 두가지 의미는 기술 토론에서 종종 혼란을 야기한다.

필딩의 REST 원리를 따르는 시스템은 종종 RESTful이란 용어로 지칭된다. 열정적인 REST 옹호자들은 스스로를 RESTafrians 이라고 부른다

From Wikipedia : http://ko.wikipedia.org/wiki/REST

어렵군...ㅋ

따라 해보자....
http://www.ibm.com/developerworks/kr/library/tutorial/x-restatompp/?S_TACT=105AGX55&S_CMP=EDU

REST 서비스 작성하기

자바 기술과 Atom Publishing Protocol로 REST 서비스 만들기

본 튜토리얼은 REST(Representation State Transfer)와 Atom Publishing Protocol(이하 APP)의 개념에 대해 토론하고 서비스에 이것들을 적용하는 방법을 다룹니다. 또한 Java™ 기술을 사용하여 REST/APP 기반 서비스를 구현하는 방법도 살펴봅니다.

목표

본 튜토리얼에서는 다루는 사항은 다음과 같다.

  • REST 기초와 APP 이면의 기본 개념
  • 조직에 이 기술을 적용하여 자바 서블릿 기반 시스템을 통해 HTTP 요청 및 응답을 주고 받는다.
  • 포드캐스트, 블로그 엔트리, 이미지 저장소, 달력 엔트리 등을 위해 리소스 데이터에 접근하고 수정한다

Representational State Transfer

REST는 월드 와이드 웹처럼 자원을 정의하고 접근하는 메커니즘을 기반으로 한 네트워크가 가능한 시스템을 만드는 아키텍처 원칙과 소프트웨어 아키텍처 스타일의 집합이다. Roy Fielding의 논문(참고자료 참조)에서 정의된 용어인 REST는 부수적인 시맨틱 레이어나 세션 관리를 추가하지 않고도 HTTP 같은 프로토콜로 데이터를 전달하는 프레임워크를 설명하는 데 전반적으로 쓰인다.

REST 는 클라이언트 서버 시스템에 참여하는 구성요소(component) 간에 관심의 분리(separation of concerns)를 엄격히 정의하여 관련된 구현을 간단하게 만든다. 또한 네트워크로 연결된 시스템에서 커뮤니케이션 시맨틱을 단순화하여 확장성과 성능을 높인다. REST는 자율적인 요청에 의존해 메시지를 교환하는데, 이 때 요청은 클라이언트와 서버가 요청 컨텍스트를 이해할 수 있도록 모든 컨텍스트를 포함해야 한다. REST 기반 시스템에서는 가능한 적은 요청 세트를 사용하여 표준 미디어 타입을 교환한다.

REST 원칙은 URI(Uniform Resource Identifiers)를 사용하여 주어진 자원 표현의 위치를 알아내고 접근한다. 표현 상태(representational state)라 알려진 자원 표현은 만들어질 수도, 찾아올 수도, 수정될 수도, 삭제될 수도 있다. 예를 들어 REST를 적용하여 문서를 발행해 독자들이 이 문서를 읽을 수 있게 할 수 있다. 언제든 문서를 발행할 때는 웹 URL을 보여줘야 한다. 그래야 독자들이 그 문서의 정보(표현 상태)에 접근할 수 있다. 문서를 읽는 사람은 URL만 알면 문서 정보를 읽을 수 있고 승인이 있다면 정보를 수정할 수 있다.

Roy Fielding이 설명했듯이 REST의 기본 원칙 중 하나는 HTTP처럼 웹과 관련된 기존 기술, 표준, 프로토콜을 활용할 수 있다는 것이다. 기존 기술 및 프로토콜에 의존하므로 REST는 대다수의 기타 웹 기반 메시징 표준보다 쉽고 간단하게 사용할 수 있다. 효과적인 정보 교환을 위해 약간의 오버헤드만 있으면 되기 때문이다.

Fielding에 따르면 REST 기반 대화는 무상태 대화(stateless conversation) 내에서 동작하기 때문에 RSS, RDF, OWL, Atom 같은 등록 기반의 기술이 쉽게 보급될 수 있게 영향을 미쳤다. 여기에서 콘텐츠는 이미 등록한 클라이언트에 전달된다.

REST의 기본 개체

REST는 다음 기본 개체를 정의한다.

  • 데이터 요소: 데이터, 식별자(URI와 URL), HTML 문서, XML 문서, 이미지와 같은 데이터 표현
  • 컴포넌트: 아파치(Apache) httpd와 마이크로소프트® IIS(Internet Information Serivces) 같은 고유 서버, 스퀴드(Squid)와 CGI 같은 게이트웨이(gateways), 건틀렛(Gauntlet)과 넷스케이프(Netscape) 프록시 같은 프록시, 웹 브라우저나 모바일 기기 같은 사용자 에이전트
  • 커넥터: libwww 같은 클라이언트 커넥터, NSAPI 같은 서버 커넥터, 브라우저 캐시 같은 캐시 등

그림 1은 기본 REST 개체와 그것들이 전형적인 네트워크 시스템과 어떻게 상호작용하는지 보여준다. 이 때 커넥터에 의해 전달되거나 받게 되는 요청은 서버나 데이터베이스 같은 주어진 개체와 엮인다는 것에 주의하자. 커넥터는 주어진 프로토콜에서 전달하는 업무를 담당하므로 커넥터가 특정 프로토콜을 위해 존재하지 않는 한 개체는 어떤 프로토콜에서나 같은 방식으로 요청을 전달하거나 받는다.


그림 1. REST 개체 간 상호작용
REST 개체 간 상호작용

그림에서 볼 수 있듯이 이런 시스템의 커넥터는 컴포넌트 간에 통신할 수 있게는 프로토콜 포트로 구체화된다. REST 시스템에서 컴포넌트는 여러 개의 클라이언트 또는 서버 커넥터를 가지고 다른 컴포넌트와의 통신을 처리한다.


REST와 HTTP

Fielding의 논문에 따르면 HTTP 기반 REST 시스템에서는 GET, PUT, POST, DELETE라는 표준 HTTP 메서드를 사용하여 자원의 표현 상태에 접근해야 한다.

  • GET : 발행자가 소비자에게 자원의 현재 표현 상태를 전달할 때 이 메서드를 사용한다.
  • PUT : 소비자가 발행자에게 자원의 수정된 표현 상태를 전달할 때 이 메서드를 사용한다.
  • POST : 소비자가 발행자에게 자원의 표현 상태를 전달할 때 이 메서드를 사용한다.
  • DELETE : 자원의 표현 상태를 삭제 상태로 변경해야 하는 정보를 전달할 때 이 메서드를 사용한다.
서블릿과 JSP™(JavaServer Pages) 같은 자바 서버 기술은 표준 HTTP 메서드를 지원한다. 이제 이 기술들을 확장하여 자바 기술을 사용한 REST 기반 시스템에서 APP를 지원하는 방법에 대해 살펴보겠다

The Atom Publishing Protocol

APP 는 HTTP 기반 프로토콜로 자원을 발행, 삭제, 갱신하는 기능을 한다. APP는 발행, 갱신 등이 가능한 자원과 피드를 포함하는 인트로스펙션(introspection) 문서와 컬렉션(collection) 문서의 인스턴스를 전달하기 위해 HTTP 프로토콜이 제공하는 (GET, PUT, POST, DELETE 같은) 기본 기능을 사용하는 개념을 강조한다. 자원과 피드가 발견된 후 관련된 URI는 발행과 수정에 사용된다. 멤버 피드에는 블로그 엔트리, 포드캐스트, 위키 문서, 달력 이벤트 등이 있다. APP는 또한 데이터베이스 서버, 문서와 내용 관리 서비스, 소프트웨어 저장소 같은 폭넓은 데이터 저장 서비스를 위한 프론트 엔드 API로 쓰이고 연구되고 있다.

APP는 REST 개념과 기술을 사용하여 의미적으로 풍부한 콘텐츠 교환에 쓰이는 여러 메커니즘을 정형화기 위해 인기있는 아톰 배급 포맷(Atom Syndication Format) 위에 구축된다. 프로토콜은 컬렉션이 라 알려진 웹 자원 컨테이너에서 작동한다. 컬렉션은 인트로스펙션 문서에서 발견되는 것을 나타낸다. 모든 컬렉션에는 멤버 자원이 들어 있다. 이것들은 생성, 접근, 수정, 삭제를 위한 최종 타깃이다. 컬렉션과 이 멤버 자원 간의 상호작용은 일반적인 HTTP 동사(verb)를 기반으로 한다.

  • GET: 컬렉션이나 멤버 자원 표현을 찾아오는 데 쓰인다.
  • POST: 새 멤버 자원을 만드는 데 쓰인다.
  • PUT: 멤버 자원을 갱신하는 데 쓰인다.
  • DELETE: 멤버 자원을 삭제하는 데 쓰인다.

APP의 기본 개체

APP는 다음과 같은 기본 개체를 정의한다.

  • 인트로스펙션 문서: 인트로스펙션 문서는 application/atomserv+xml 미디어 타입을 가지고 컬렉션의 임의 서버 정의 그루핑인 workspaces를 기술한다. 컬렉션은 하나 이상의 작업공간에 나타날 수 있다. Listing 1은 전형적인 인트로스펙션 문서의 예다.


    Listing 1. 전형적인 인트로스펙션 문서
                                
    <?xml version="1.0" encoding="utf-8" ?>
    <service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
    - <workspace>
    <atom:title>Main Site</atom:title>
    - <collection href="http://localhost:8080/atompub/services/collections/main">
    <atom:title>My Main Page</atom:title>
    <accept>application/atom+xml;type=entry</accept>
    <categories fixed="yes" />
    </collection>
    <collection href="http://localhost:8080/atompub/services/collections/pics">
    <atom:title>My Pictures</atom:title>
    <accept>*/*</accept>
    <categories fixed="yes" />
    </collection>
    </workspace>
    - <workspace>
    <atom:title>Documents</atom:title>
    - <collection href="http://localhost:8080/atompub/services/collections/docs">
    <atom:title>My Documents</atom:title>
    <accept>application/atom+xml;type=entry</accept>
    <categories fixed="yes" />
    </collection>
    </workspace>
    </service>

    위에 보인 인트로스펙션 문서는 두 개의 작업공간으로 서비스를 정의한다. 첫 번째 작업공간은 "Main Site"라 부르는데 "My Main Page"와 "My Picture"라는 두 개의 컬렉션을 정의한다. "My Main Page" 컬렉션은 http://localhost:8080/atompub/services/collections/main에, "My Pictures" 컬렉션은 http://localhost:8080/atompub/services/collections/pics에 있다. 두 번째 작업공간인 "Documents"는 "My Documents"라는 하나의 컬렉션을 가지고 있고 이는 http://localhost:8080/atompub/services/collections/docs에 있다.

  • URI: 자원 식별자
  • IRI: 국제 자원 식별자 (참고자료 참조)
  • 멤버 자원: IRI나 URI가 지정하는 엔트리 자원 또는 미디어 자원으로 알려진 데이터 객체 또는 서비스. 엔트리 자원은 아톰 엔트리 문서로 표현된다. 미디어 자원은 어떤 미디어 타입에서든 표현을 가질 수 있다. 미디어 자원은 미디어 링크 엔트리를 사용하여 컬렉션 내에서 기술된다.
  • 표현: 요청이나 응답에 의해 전달되는 주어진 자원의 상태
  • 컬렉션: 특정 URI에 의해 식별된 멤버 자원의 컨테이너. 컬렉션은 아톰 피드로 표현된다. 컬렉션에서 새 엔트리를 만들려면 클라이언트는 컬렉션의 URI에 HTTP POST 요청을 보낸다. 새 엔트리에는 특정 URI가 부여되어 위치 레퍼런스로 사용된다. 컬렉션에서 엔트리를 수정하려면 클라이언트는 그 URI를 사용하여 자원을 찾아오고 수정을 한 후 PUT을 사용하여 자원의 수정된 표현을 서버로 옮긴다. 컬렉션에서 멤버 자원을 삭제하려면 멤버 자원의 URI로 HTTP DELETE 요청을 보낸다. 컬렉션의 모든 멤버는 컬렉션 문서에 따라 updated 속성을 가져야 한다.
  • 작업공간: 명명된 컬렉션 그룹
  • 서비스 문서/요소: 인트로스펙션 문서의 최상위 요소로 하나 또는 그 이상의 컬렉션 기능과 위치를 기술하고 작업공간으로 묶음
  • 카테고리 문서: 컬렉션에서 허용되는 카테고리를 기술하는 문서
다음 장에서는 자바 기술을 확장하여 REST 기반 시스템에서 APP를 지원하는 방법에 대해 알아보겠다

심화학습

HTTP 프로토콜을 거쳐 자원을 전달하는 시스템에 REST 원칙을 적용하는 데 자바 프로그래밍 언어를 사용할 수 있다. APP를 사용하여 이런 시스템을 확장하고 블로그 엔트리, 포드캐스트, 위키 페이지, 달력 엔트리 등을 사용하여 자원 접근 및 조작을 용이하게 할 수 있다. 본 튜토리얼에서는 자바 서블릿 기반 시스템을 사용하여 웹 애플리케이션 내에서 기본 REST와 APP를 적용하여 HTTP 요청 및 응답을 거쳐 자원을 전달하는 방법에 대해 보여준다.

아톰 프로토콜 명세는 클라이언트가 APP 엔드포인트를 인트로스펙트하는 데 사용할 수 있는 XML 문서를 정의한다. 인트로스펙션 문서는 주어진 엔드포인트 URI에 있는 모든 컬렉션의 목록을 가진다. 그러므로 APP가 가능한 서비스를 사용하는 첫 단계서비스 엔드포인트의 URI에서 가능한 컬렉션과 각 컬렉션이 포함할 수 있는 멤버 자원의 타입이 무엇인가를 결정하는 것이다. 인트로스펙션 문서를 찾아오려면 클라이언트는 GET 요청을 서버에 보낸다. 그리고 나면 서버는 서비스를 제공하는 컬렉션의 위치 URI를 포함하는 인트로스펙션 문서로 클라이언트에 응답한다.

인트로스펙션 문서에 있는 각각의 컬렉션 요소는 컨테이너가 컬렉션에 있는 각 멤버 자원의 정보에 저장됐다는 것을 나타낸다. 인트로스펙션 문서 안의 각 컬렉션은 특별한 URI를 가진다. 이 URI에 HTTP GET 요청을 보내면 컬렉션에 포함된 멤버 자원에 관한 정보를 포함하는 아톰 피드 문서를 반환해야 한다.

컬렉션에서 새 멤버 자원 엔트리를 만들려면 클라이언트는 컬렉션에 추가할 멤버 자원의 표현 상태와 함께 컬렉션 URI에 HTTP POST 요청을 보낸다. 새 멤버 자원 엔트리는 자신만의 URI를 받는데 이 URI로 각 멤버 자원 엔트리의 표현 상태를 찾아오도록 질의할 수 있다. 멤버 자원 엔트리를 수정하려면 클라이언트는 멤버 자원의 URI에 HTTP GET 요청을 함으로써 자원을 찾아오고 원하는 수정을 GET 요청이 반환하는 자원의 표현 상태로 만든다. 그리고 나서 HTTP PUT 요청을 사용하여 수정된 표현 상태를 컬렉션에 다시 보낸다. 컬렉션에서 멤버 자원 엔트리를 지우는 것은 클라이언트가 해당 멤버 자원 URI에 HTTP DELETE 요청을 할 때 유용하다.

REST를 사용하는 간단한 APP 애플리케이션

본 튜토리얼의 예제 애플리케이션은 컨트롤러 서블릿을 사용하여 들어오는 요청을 처리하고 결과 응답을 내보내도록 설계됐다. 들어오는 요청은 REST 기반 서비스 프레임워크로 발송되고(dispatch) 여기서 APP 인트로스펙션 문서, 컬렉션, 멤버 자원 상에서 기능을 처리할 수 있다.

REST 기반 APP 프레임워크는 그림 2처럼 클래스와 인터페이스를 포함한다.


그림 2. REST/APP 애플리케이션 프레임워크의 구성요소
REST/APP 애플리케이션 프레임워크의 구성요소

이 클래스 다이어그램에서 보는 것처럼 FrontController 서블릿은 대다수의 주요 REST 개체를 위한 중요한 레퍼런스다. FrontController 서블릿이 요청을 받으면 커넥터와 상호작용하여 각 요청의 비즈니스 로직을 처리할 BusinessService 객체를 위치시키는 데 쓰이는 ServerComponent 객체를 찾아온다. javax.activation 패키지에 있는 클래스를 사용하여 구현되는 Representation 인터페이스는 자원을 정의한다.

이제 각각의 주요 REST 엔티티와 APP 엔티티가 각 엔티티를 나타내는 특정 자바 컴포넌트와 함께 예제 프레임워크 안에서 어떻게 상호작용하는지에 관해 설명하겠다.

REST 컴포넌트

REST 컴포넌트는 주어진 시스템에서 역할에 따라 정의된다. 반복하자면 REST 시스템의 전형적인 컴포넌트는 다음과 같다.

  • 사용자 에이전트: 사용자 에이전트에 다시 응답하는 서버 컴포넌트 형태로 요청을 초기화하는 컴포넌트. 사용자 에이전트는 모바일 기기, 웹 브라우저 등이 될 수 있다.
  • 원 서버: 원(origin) 서버는 자원의 컬렉션을 위해 주어진 이름공간을 포함한다. 그리고 포함된 자원의 상태 표현을 관리한다. 사용자 에이전트에서 요청을 받고 목표 컬렉션이나 멤버 자원 상에서 필요한 동작을 수행한다. 그리고 나서 컬렉션 문서나 자원의 표현 상태로 사용자 에이전트에 응답한다.

자바 언어에서 마커 인터페이스를 사용해 REST 컴포넌트를 나타내야 할지도 모른다.

public interface Component
{
}

자바 언어의 서버 컴포넌트는 어떤 자원 컨텍스트가 참조되는지에 의해 메서드와 속성을 드러낼 것이다. Listing 2를 보자.


Listing 2. REST ServerComponent 인터페이스(자바 언어)
                    
public abstract class ServerComponent
implements Component
{
private java.util.HashMap<String, Context> contexts =
new java.util.HashMap<String, Context>();

abstract public Context addContext(String contextRootPath,
String contextPath);

public java.util.Iterator<String> getContextPaths()
{
return contexts.keySet().iterator();
}

public Context getContext(String contextPath)
{
return contexts.get(contextPath);
}

protected java.util.HashMap<String, Context> getContexts()
{
return contexts;
}
}

ServerComponent 클래스가 주어진 내용을 루트/문서 경로에 어떻게 매핑을 하는지에 주목하자. 필요에 따라 각 특정 서버 컴포넌트는 루트/문서 경로를 주어진 컨텍스트에 매핑하는 데 사용한다. 예를 들어 HTTP에 한정된 서버 컴포넌트는 Listing 3처럼 HTTP에 한정된 내용을 관리할 것이다.


Listing 3. REST ServerComponent 인터페이스(HTTP)
                    ;
public Context addContext(String contextRootPath, String contextPath)
{
Context context = getContexts().get(contextPath);
if (context == null)
{
context = new HTTPContext(contextRootPath, contextPath);
getContexts().put(contextPath, context);
}

return context;
}

HTTP에 한정된 컨텍스트는 각각의 주요 HTTP 메서드를 정의하는 인터페이스를 구현하고 목표한 컬렉션과 멤버 자원 표현 요청을 신속히 처리하는 수단을 제공한다. Listing 4는 HTTP GET 메서드 구현의 예를 보여준다. 특정 수직 도메인 서비스나 멤버 자원 피드의 자세한 비즈니스 로직은 특정 비즈니스 서비스 구현 내에서 캡슐화된다.


Listing 4. REST HTTP-컨텍스트 예
                    
public Representation handleGet(Request request)
throws ContextRequestException
{
String uri = ((HTTPRequest)request).getRequest().getRequestURI();
if (uri.startsWith(contextPath))
{
uri = reqURI.substring(contextPath.length());
}

BusinessService businessService =
ServiceLocator.locateService(contextRootPath, contextPath, uri);

Representation representation = null;

try
{
representation = businessService.read(request);
}
catch (ServiceExecutionException e)
{
e.printStackTrace();
throw new ContextRequestException(e);
}

return representation;
}

Listing 4에서 GET 요청은 요청에서 URI를 처음 추출함으로써 처리되고 URI를 사용하여 원하는 비즈니스 서비스의 위치를 찾는다. 그리고 나서 비즈니스 서비스는 요청을 처리하기 위해 호출된다.

REST 컴포넌트는 두 개씩 묶이고 커넥터 객체를 통해 각각 상호작용한다.


REST 커넥터

REST 의 커넥터는 REST 컴포넌트 사이에 통신하기 위해 속성과 메서드를 정의한 일반적인(generic) 인터페이스를 노출한다. 커넥터는 커뮤니케이션 프로토콜의 한 부분이나 엔드포인트를 나타낸다. 커넥터를 구현하여 클라이언트 커넥션이나 서버 커넥션을 나타낼 수 있다. 사용자 에이전트는 클라이언트 커넥터를 사용하여 원(origin) 서버에 대한 요청을 초기화한다. 원 서버는 서버 커넥터에 의존하여 사용자 에이전트에서 들어오는 요청을 처리하고 컬렉션이나 멤버 자원의 표현 상태로 응답한다.

Listing 5에서 인터페이스는 주어진 포트에 서버 컴포넌트를 추가하기 위해 하나의 메서드를 정의한 커넥터를 보여준다.


Listing 5. REST 커넥터 인터페이스
                    
public interface Connector
{
public ServerComponent addServer(int port);
}

factory 클래스는 프로토콜에 한정된 커넥터를 관리하는 데 유용하다. factory 클래스는 상황이 지시한 대로 factory 커넥터를 묶을 수 있다. Listing 6은 커넥터 factory 클래스의 예를 제공한다.


Listing 6. REST 커넥터 팩토리 예
                    ;
public static Connector getConnector(Protocol protocol)
throws ConnectorException
{
String key = protocol.getScheme();
Connector instance = instances.get(key);

if (instance == null)
{
if (key.equalsIgnoreCase(Protocol.HTTP.getScheme()))
{
instance = new HTTPConnector();
instances.put(key, instance);
}
else
{
throw new ConnectorException("Invalid protocol: "
+ protocol.getScheme());
}
}

return instance;
}

HTTP에 한정된 서버 커넥터를 위한 커넥터 인터페이스는 Listing 7처럼 특정 포트에 HTTP에 한정된 서버 컴포넌트를 추가하기 위한 속성과 메서드를 정의한다.


Listing 7. REST 서버 커넥터 예
                    
public ServerComponent addServer(int port)
{
return new HTTPServerComponent(port);
}

커넥터는 사용자 에이전트와 원 서버 사이의 통신을 가능하게 한다. 원 서버는 서버 컴포넌트에 의해 나타나며 멤버 자원을 포함하고 관리한다. 더 자세한 내용은 다음 절에서 다루겠다.


REST 자원 표현

사용자 에이전트가 요청을 하면 URI는 목표한 컬렉션이나 요청의 멤버 자원을 식별하는 원 서버로 전달된다. 원 서버를 나타내는 서버 컴포넌트가 요청을 받으면 요청에서 URI를 추출하고 요청을 처리하는 데 필요한 동작을 수행한다. 멤버 자원을 목표로 하는 요청은 자원의 표현 상태를 만들거나 읽거나 수정하거나 삭제할 수 있다. 그리고 나서 필요하다면 자원의 표현 상태 결과를 반환한다.

HTTP 요청을 처리할 컴포넌트 만들기

사용자 에이전트에서 원 서버로, 그리고 다시 사용자 에이전트로 HTTP 요청을 처리하는 데 필요한 컴포넌트를 만들고 접근하려면 다음 단계를 밟아야 한다.

  1. 서버 커넥터를 만들고 나서 이를 적절한 HTTP 서버 컴포넌트에 추가한다.
  2. 주어진 서버 컨텍스트를 위해 HTTP 컨텍스트를 추가하거나 이에 접근한다.
  3. 서버 컴포넌트는 들어오는 사용자 에이전트 요청을 받아 목표한 비즈니스 서비스로 보낸다.
  4. 비즈니스 서비스가 생성하는 자원을 나타내는 데이터 모델을 만들고 파퓰레이트한다. 그리고 이를 목표 자원의 표현 상태로 캡슐화한다.
  5. 자원의 표현 상태를 사용자 에이전트에 다시 보낸다.

그림 3은 이 과정을 보여준다.


그림 3. REST 프레임워크 제어 흐름
REST 프레임워크 제어 흐름

DataHandler 클래스 확장하기

JAF(JavaBean Activation Framework)는 멤버 자원의 상태를 효과적으로 나타낼 수 있는 컴포넌트인 javax.activation.DataHander 클래스를 제공한다. DataHandler 컴포넌트를 사용하여 자원을 표현내면 임의의 콘텐츠 타입이 들어 있는 이종 자원을 똑같은 일반적인 인터페이스로 나타낼 수 있다.

Listing 8에서 보여주는 추상 클래스는 DataHandler 클래스를 확장하여 멤버 자원을 나타내는 객체의 일반적인 기본 클래스를 제공한다.


Listing 8. 추상 Representation 클래스
                    
public abstract class Representation extends javax.activation.DataHandler
{
public Representation(DataSource dataSource)
{
super(dataSource);
}
}

본 튜토리얼의 목적처럼 아톰 피드 자원을 캡슐화하는 Representation 인터페이스의 특정 구현은 Listing 9처럼 만들 수 있다.


Listing 9. Representation 클래스
                    
public class FeedRepresentation extends Representation
{
public static final String MEDIA_TYPE = "application/atom+xml";
public static final String CONTENT_TYPE = MEDIA_TYPE + "; charset=utf-8";

public FeedRepresentation(File file)
{
super(new FeedDataSource(file, CONTENT_TYPE));
}

public String getContentType()
{
return CONTENT_TYPE;
}
}

Listing 9를 보면 피드 자원은 FeedRepresentation 클래스 내에서 캡슐화된다. 이 클래스는 FeedDataSource 클래스를 사용하여 파일 자원의 입출력 동작을 처리한다.


구현을 위해 속성과 메서드 정의하기

JAF 또한 임의의 컬렉션 데이터를 보여주는 자원에 의해 구현된 속성과 메서드를 정의하는 인터페이스인 javax.activation.DataSource를 제공한다. 인터페이스는 메서드를 제공하여 자원과 자원의 데이터에서 작동하는 입출력 스트림의 콘텐츠 타입을 보여준다. DataHandler는 객체를 사용하여 DataSource 인터페이스를 구현함으로써 똑같은 일반 인터페이스를 통해 기본적인 자원에 접근한다.

FeedDataSource의 각 구현은 기초를 이루는 자원 저장 메커니즘(예로 데이터베이스, 파일 시스템)에 의존하여 피드 데이터를 저장하고 찾아온다. Listing 10처럼 FeedDataSource 구현은 파일 시스템에 의존한다.


Listing 10. 파일 기반의 FeedDataSource 클래스
                    
public class FeedDataSource
implements DataSource
{
private File file = null;
private String contentType = "";

public FeedDataSource(File file, String contentType)
{
this.file = file;
this.contentType = contentType;
}

public String getContentType()
{
return contentType;
}

public InputStream getInputStream()
throws IOException
{
return new FileInputStream(file);
}

public String getName()
{
return file.getName();
}

public OutputStream getOutputStream()
throws IOException
{
return new FileOutputStream(file);
}

}

Listing 10에서 파일 자원은 FeedDataSource 클래스 내에서 캡슐화된다. 이 클래스는 주어진 파일 자원의 입/출력 기능을 수행한다.


FrontController 서블릿 구현하기

FrontController 서블릿을 구현하여 다양한 컴포넌트, 커넥터, 컨텍스트 클래스와 상호작용함으로써 사용자 에이전트로부터 들어오는 요청을 처리한다. 그리고 나서 서블릿이 나타내는 요청에 적합하면 서블릿은 비즈니스 서비스에서 생성된 자원의 표현 상태와 함께 사용자 에이전트에 응답한다.

Listing 11은 표준 HttpServlet doGet() 메서드를 처리하는 예를 보여준다. 목표를 요청하는 컨텍스트는 추출되고 요청 데이터를 처리하는 서버 컴포넌트를 찾아오는 데 쓰인다.


Listing 11. FrontController 서블릿 클래스를 위한 doGet() 메서드
                    
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException
{
HTTPConnector connector =
(HTTPConnector)Connectors.getConnector(Protocol.HTTP);
HTTPServerComponent serverComponent =
(HTTPServerComponent)connector.addServer(request.getServerPort());

String contextRootPath = this.getServletContext().getRealPath("/");
String contextPath = request.getContextPath() + "/"
+ this.getServletName();
serverComponent.addContext(contextRootPath, contextPath);

Representation representation = null;

try
{
representation =
serverComponent.getContext(request,
this).handleGet(new HTTPRequest(request));
}
catch (Exception e)
{
e.printStackTrace();
throw new ServletException("Error: " + e);
}

new HTTPResponse(response).write(representation.getContentType(),
representation.getInputStream());
}

Listing 11에서 FrontController 클래스의 doGet 메서드는 요청을 받고 처리하는 방법을 보여준다. HTTP 프로토콜의 커넥터는 서버 컴포넌트를 추가하고 찾아오는 데 사용된다. 목표한 자원 컨텍스트 객체는 서버 컴포넌트에서 찾아온다. 그러면 자원 컨텍스트 객체는 GET 요청을 처리하는 데 쓰인다. Resource 표현 객체는 자원 컨텍스트 객체에 의해 반환된다. 그리고 나서 표현 객체는 HTTPResponse 클래스를 사용하여 요청자에 다시 전달된다.


비즈니스 로직 구현하기

BusinessService 클래스를 사용하여 특정 APP 컬렉션의 멤버 자원을 나타내는 모델 데이터를 반환할 비즈니스 로직을 구현한다. BusinessService 클래스는 로직을 구체화한다. 이 때 로직은 특정 컬렉션과 자원 표현에서 컬렉션이나 멤버 자원의 아톰 피드에 적절한 javax.activation.DataHandler 클래스 구현과 javax.activation.DataSource 인터페이스로 작동한다.

Listing 12는 아톰 피드 자원의 컬렉션을 캡슐화하는 비즈니스 서비스의 예를 제공한다.


Listing 12. 피드 컬렉션 비즈니스-서비스 클래스
                    
public class CollectionService
implements BusinessService
{
// todo: read RESOURCES_DIR from config or system property
//
private static final String RESOURCES_DIR = "resources";

private String contextRootPath = "";

private String contextPath = "";

public CollectionService(String contextRootPath,
String contextPath)
{
this.contextRootPath = contextRootPath;
this.contextPath = contextPath;
}

protected String getContextPath()
{
return contextPath;
}

protected String filePathFromRequest(Request httpReq)
{
return contextRootPath + RESOURCES_DIR
+ ((HTTPRequest) httpReq).getRequest().getPathInfo();
}

protected void writeToFile(Request request,
File file,
boolean append)
throws IOException,
FileNotFoundException
{
System.out.println("writeToFile called");

InputStream inStream = ((HTTPRequest) request).getInputStream();
byte[] dataBuf = new byte[4096];

FileOutputStream outStream = new FileOutputStream(file, append);
int bytesRead = 0;
while ((bytesRead = inStream.read(dataBuf)) > 0)
{
System.out.println("Writing [" + bytesRead + " bytes]");
outStream.write(dataBuf, 0, bytesRead);
}

outStream.flush();
outStream.close();
}

public Representation create(Request request)
throws ServiceExecutionException
{
System.out.println("CollectionService.create()");

// todo: create feed from structured storage with DAO
//
String filePath = filePathFromRequest(request);
File file = new File(filePath);

try
{
boolean append = false;
writeToFile(request, file, append);
}
catch (Exception e)
{
e.printStackTrace();
throw new ServiceExecutionException(e);
}

FeedRepresentation representation = new FeedRepresentation(file);

return representation;
}

public Representation read(Request request)
throws ServiceExecutionException
{
System.out.println("CollectionService.read()");

// todo: read feed from structured storage with DAO
//
String filePath = filePathFromRequest(request);
File file = new File(filePath);
if (file.exists() == false)
{
throw new ServiceExecutionException("Feed file ["
+ filePath + "] does not exist.");
}

FeedRepresentation representation = new FeedRepresentation(file);

return representation;
}

public Representation update(Request request)
throws ServiceExecutionException
{
System.out.println("CollectionService.update()");

// todo: update feed from structured storage with DAO
//
String filePath = filePathFromRequest(request);
File file = new File(filePath);
FeedRepresentation representation = new FeedRepresentation(file);

try
{
boolean append = (file.exists() ? true : false);
writeToFile(request, file, append);
}
catch (Exception e)
{
e.printStackTrace();
throw new ServiceExecutionException(e);
}

return representation;
}

public void delete(Request request)
throws ServiceExecutionException
{
System.out.println("CollectionService.delete()");

// todo: delete feed from structured storage with DAO
//
String filePath = filePathFromRequest(request);
System.out.println("CollectionService.delete() - resolving feed file ["
+ filePath + "]");
File file = new File(filePath);
System.out.println("CollectionService.delete() - feed file resolved");
if (file.exists())
{
System.out.println("CollectionService.delete() - deleting feed file");

if (file.delete() == false)
{
System.out.println("CollectionService.delete() - feed deletion failed");
throw new ServiceExecutionException("Error deleting feed ["
+ filePath + "]");
}
System.out.println("CollectionService.delete() - feed deletion succeeded");
}
else
{
System.out.println("CollectionService.delete() - feed file ["
+ filePath + "] does not exist");
}
}
}

Listing 12는 아톰 피드 자원의 컬렉션을 캡슐화하는 비즈니스 서비스 클래스의 예를 제공한다. 이 클래스는 물리적 파일을 각 피드 자원의 소스로 사용한다. 각 피드 자원에 관한 동작은 "CRUD" 메서드(create, read, update, delete)에 의해 정의된다. 이 동작의 일반적인 추상화는 메서드 서명이나 서비스 인터페이스에 영향을 주지 않고 기초가 되는 물리적 소스를 변경할 수 있도록 한다.

특정 피드 자원의 컬렉션을 나타내는 비즈니스 서비스를 가지고 있다면 이제 사용자 에이전트는 적절한 비즈니스 서비스에 대한 요청을 처리하는 원 서버의 FrontController에 요청을 보낼 수 있다. 비즈니스 서비스는 목표한 자원에서 실행되면서 필요한 비즈니스 로직을 수행한다. 목표 자원은 논리의 명령에 따라 생성, 접근, 갱신, 삭제를 실행한다. 요청에서 발생되는 목표 멤버 자원의 표현 상태는 FrontController 서블릿에 다시 전달된다. 이 서블릿은 필요하다면 HTTP 응답 형태로 사용자 에이전트로 다시 중계된다.


요약하기

REST 는 기존 프로토콜과 표준을 사용하여 데이터나 서비스를 나타내는 자원에서 작동하는 분산 시스템을 만드는 소프트웨어 아키텍처 스타일이자 원칙의 집합이다. REST는 추가적인 시맨틱 레이어나 세션 관리에 의존하지 않고 HTTP 같은 프로토콜에 데이터를 전달하는 프레임워크를 기술하는 데 진화해 왔다.

APP는 데이터나 서비스를 나타내는 자원에 접근, 작성, 수정하는 HTTP 기반 프로토콜이다. APP는 HTTP 프로토콜이 제공하는 표준 동작(GET, PUT, POST, DELETE)을 사용하여 멤버 자원의 컬렉션을 인트로스펙트하고 블로그 엔트리, 이미지, 문서, 달력 엔트리 등을 나타내는 멤버 자원을 조작한다.)

본 튜토리얼에서는 기본 REST와 APP를 다뤘다. 또한 엔터프라이즈 시스템 내에 REST를 적용하는 법을 배웠다. 멤버 자원의 표현 상태와 컨테이너에 접근 및 조작을 수월하게 하기 위해 APP를 사용하여 자바 서블릿 기반 시스템을 통해 HTTP 요청과 응답을 주고 받았다.


필자소개

Jeff Hanson

Jeff Hanson은 윈도우 오픈독(Windows OpenDoc) 프로젝트의 선임 엔지니어 및 노벨 Route 66 프레임워크의 책임 아키텍트 등을 포함 20년 이상 소프트웨어 업계에서 경력을 쌓아왔다. 현재 Max International에서 CTO로 재직 중이며 웹 서비스, 마이크로 포맷, XML, 자바/J2EE, PHP, 모바일 기술, 윈도우 API를 사용해 시스템을 설계하고 만드는 업무를 담당하고 있다. Jeff는 .NET versus J2EE Web Services: A Comparison of Approaches, Pro JMX: Java Management Extensions, Web Services Business Strategies and Architectures 등 많은 저서와 기사를 쓰고 있다.


다 읽었다.. --;;






      Service Oriented  |  2009. 3. 9. 14:28




2007 8 21

서비스 지향 아키텍처(SOA) 많은 비즈니스 변형 노력의 중심에 있습니다. 많은 기업들은 점증적으로 SOA로의 변형을 시도하고 있고, 귀중한 레거시 IT 시스템들을 서비스 공급자로서 참여시키고 있습니다. 솔루션 아키텍트는 변형을 도모하는 수단으로서 SOA 인프라스트럭처를 제공해야 뿐만 아니라, 기업 중심의 비즈니스 연산들을 강력하고 순응적인 것으로 유지해야 하는 도전에 직면해 있습니다. 여러분의 기업은 SOA 일부가 있는 엔터프라이즈 정보 관리 전략을 개발하고 모든 비즈니스 연산에서 전체적인 데이터 콘텐트 일관성을 관리해야 합니다. 이와 같은 변화 과정에 대해 알아보고 디자인 전략을 공부해 봅시다.

머리말

여러분의 비즈니스가 거의 비슷하다면, 비즈니스 전략과 핵심 경쟁력 분석은 비즈니스 리엔지니어링과 IT 현대화에 초점을 맞춰야 한다. 일반적인 산물이(엔터프라이즈의 핵심 측면에서 ) 서비스 지향 비즈니스로의 변형 SOA 대한 의존성이다. 비즈니스 연산은 현재 IT 시스템이 엔지니어링 되고 서비스 공급자로서 통합되어야 하는 서비스 세트를 중심으로 설계된다. 변형 역시 새로운 서비스 공급자를 도입한다. 목표는 내부 워크플레이스 포털 애플리케이션 또는 인터넷 커머스 애플리케이션 같은 새로운 복합 애플리케이션들을 구현하여 특수한 비즈니스 필요를 채우는 것이다.

이렇게 도전이 되는 변형의 일부로서, 엔터프라이즈는 많은 중요한 비즈니스와 IT 프로그램에 개입되어 있다. 주요한 변형에는 다음이 포함된다.

  • 비즈니스 서비스 모델 중심의 엔터프라이즈 아키텍처 정렬.
  • 비즈니스 서비스 모델의 관련 부분들을 실현할 있는 서비스 기반 IT 인프라스트럭처의 도입.
  • 레거시 IT 시스템이 변형, 확장, 래퍼 적용을 통해 서비스 기반 IT 인프라스트럭처로 통합될 있도록 .
  • IT 애플리케이션들을 지원하는 효율적이고 유연한 구현을 가능케 하는 강력한 디자인 개발 환경 딜리버리 프로세스.

이러한 변형의 산물들은 구현상의 문제를 만들어 낸다. 엔터프라이즈는 변형의 의도를 전달하고 변화를 적용하여 유연성을 실현할 있는지를 확인해야 한다. 이러한 변형 노력은 다음의 원리를 따른다.

  • 엔터프라이즈는 강력하고 순응적인 비즈니스 연산을 제공해야 한다.
  • 전체 비즈니스 서비스 모델과 IT 시스템 구현이 변형 원리에 순응할 있도록 하는 거버넌스 프로세스와 디자인 권한이 필요하다.
  • 엔터프라이즈는 비즈니스와 IT 서비스 관리의 통합적인 뷰를 통해 측정과 응답성 변화가 이루어 있도록 해야 한다.

일부 엔터프라이즈는 전체 조직에 걸쳐 SOA 비즈니스 변형을 있다. 이러한 방식은 기본적인 변형 인도물에 대한 도전을 시사하고 있지만, 결과적으로, 부차적인 변형 인도물을 성장시키고 개발하기에는 쉽다. 이러한 유형의 시나리오는 엔터프라이즈에 비즈니스 IT 변화를 이룩하고자 하는 최고위 간부들이 전략적인 문제를 지원하기로 결정할 발생한다.

그러나, 대부분의 엔터프라이즈 변형은 점증적이고 거대하며 전략적이다. 레거시 IT 시스템들은 리엔지니어링 되어, 다른 IT 시스템들을 결합하여 고객 주문 프로세싱을 단순화 하는 , 새로운 비즈니스 연산 지원에 참여할 있어야 한다. 이러한 IT 시스템들은 현재 갖고 있는 모든 또는 대부분의 기능을 계속해서 수행한다. SOA 변형의 범위 에서의 비즈니스 연산들도 여전히 지속된다.

변형 시나리오에서, SOA IT 인프라스트럭처에 대해 신중한 구현 디자인을 모색해야 한다. 이러한 IT 시스템 내에서의 데이터 프로세싱은 범위 밖에서의 데이터 프로세싱에 영향을 주고, 프로세싱에 의해 영향을 받는다. 전체적인 데이터 프로세싱 환경은 전체 비즈니스 연산에 대하 강력함과 순응성을 유지해야 한다.

그림 1 예제는 개의 레거시 시스템들이 서비스 프로바이더가 되도록 엔지니어링 되는 모습을 보여준다

그림 1. 새로운 SOA 환경에서의 레거시 IT
 

그림 1에서, 비즈니스 변형 프로그램이 SOA 인프라스트럭처를 구현했고, 비즈니스 서비스들은 여기에서 퍼블리시 되고 새로운 애플리케이션에 의해 소비될 있다. 이러한 인프라스트럭처에는 일반적으로, 소프트웨어 다중 프로토콜 연결, 비동기식 동기식 메시지 플로우 관리, 메시지 트랜슬레이션, 규칙 실행, 프로세스 구성법을 실행하는 미들웨어가 포함된다. 이러한 서비스들을 사용하는 복합 애플리케이션들이 구현되었고, 레거시 시스템들은 새로운 서비스들을 호출함으로써 강화되었다.

SOA에서의 프로세스와 정보 아키텍처

SOA 인프라스트럭처를 구현하기 위해, 비즈니스 서비스 모델(business service model) 생성, 관리, 향상된다. IBM® Service Oriented Modeling and Architecture (참고자료) 같은 기술들은 이러한 모델을 개발하는데 사용된다. 전형적인 엔터프라이즈에서, top-down 분석, bottom-up 분석, 목표 서비스 모델링이 포함된다. 변형의 목표는 새로운 비즈니스 연산과 지원하는 IT 애플리케이션들의 구현을 실행하는데 사용되는 프로세스 정보 아키텍처로 귀결된다.

  • 프로세스 아키텍처 엔터프라이즈 연산을 받치고 있는 비즈니스 프로세스를 형성하기 위해 결합될 있는 액션의 기능적 계층이다. 인간 시스템, 시스템 시스템의 플로우 컨트롤을 책임진다. 예를 들어, 고객이 제품 주문을 하고 제품의 전달을 기다리는 상태가 되는 동안 필요한 액션들이 포함된다.
  • 정보 아키텍처 엔터프라이즈 연산에 상태와 의미를 제공하기 위해 액세스, 조작, 저장되는 관련 데이터 콘텐트 세트이다. 데이터 콘텐트의 정보 관리를 수행한다. 단순한 액세스 이벤트나 프로세스 플로우 정황이든 상관이 없다. 제품 개발 라이프 사이클 동안 소비 생성되는 데이터와 콘텐트가 하나의 예이다.

프로세스와 정보 아키텍처 뷰포인트는 프로세스-데이터(CRUD) 매트릭스 같은 것을 통해서 개발 제시된다. 이들은 서비스 아키텍처를 구성하는 많은 서비스들을 정의한다. 서비스는 메시지 데이터가 전달된 곳에서 호출되는 연산 세트이다. 서비스 구현은 영속 스토리지나 액세스를 사용하여 데이터나 콘텐트를 조작하는 프로세싱을 수행하고 결과를 리턴한다. 서비스는 동기식 비동기식으로 사용될 있고, 호출은 통합 인프라스트럭처에 의해 일반적으로 중재된다. 완전히 분리된 시스템에서, 일부 서비스들은 변경 사항들이 상태를 처리하도록 한다. (예를 들어, 요청된 정보가 제공될 , 고객 X 대한 새로운 주소의 유효성 검사가 수행된다.) 다른 서비스들은 정보 상태가 바뀌도록 하면서, 데이터와 콘텐트가 향후 서비스 이벤트가 의존할 있는 원하는 상태가 되도록 조작한다. (예를 들어, 새로운 선적 주소가 고객 X 적용된다.)

레거시 데이터 프로세싱 문제

레거시 IT 시스템들은 의심할 여지 없이 엔터프라이즈의 서비스 공급자 구현의 일부이고 SOA 인프라스트럭처로 통합된다. 레거시에는 전통적인 메인프레임 프로세싱 뿐만 아니라, 엔터프라이즈 리소스 플래닝(ERP) 애플리케이션, /외부 애플리케이션, 워크플로우 애플리케이션, 스캐닝 프린팅 시스템 등이 포함된다. 이러한 레거시 시스템들이 사용되고 서비스-공급자 구현으로 결합되기 위해서는 많은 일들이 발생할 있다.

  • 프로세싱 함수는 노출되고 액세스 되어 서비스 공급자 구현에 결합된다. 이는 CICS® 트랜잭션의 SOAP 래퍼처럼, 새로운 프로토콜과 호출 메커니즘을 통해 트랜잭션을 노출하는 것을 의미한다.
  • 함수들은 트랜잭션을 노출할 프로세싱 무결성을 관리하도록 리엔지니어링 되어야 한다. 트랜잭션은 기존에 존재했던 또는 이상의 기존 트랜잭션을 호출하기 위해 생성되어야 한다. 서비스 세분성 전략은 그러한 서비스의 호출 디자인에 영향을 미친다.
  • 특정 프로세싱 함수는 데이터 프로세싱이 서비스 공급자 구현을 통해 호출되는 새로운 함수에 의해 수행되기 때문에 스위치를 꺼야 한다.
  • 기존 액세스 권한과 보안 감사 요구 사항들은 새로운 액세스 메커니즘을 위해 실행되어야 한다.
  • 기존 시스템의 서비스 품질(Quality of Service (QoS)) 기준은 확장 또는 보충되어야 한다. 예를 들어, 오프라인 일괄 프로세싱 윈도우는 대리 프로세싱 솔루션에 의해 다루어져야 한다.
  • SOA 기존 시스템에 새롭고 예측할 없는 부하를 가져오는데, 이는 기존 프로세스에 부정적인 영향을 미친다.

레거시 IT 시스템들이 SOA 참여하고자 하는 노력으로 노출될 , 변형의 범위 밖에서 비즈니스 연산을 지원하는 특정 함수들이 데이터 프로세싱을 지속한다. 여기에는 일반적으로 데이터 동시성과 동기화 문제를 이해하고 다룰 있어야 한다.

사용자는 계속해서 원래의 애플리케이션 수단을 사용하여 레거시 IT 시스템을 호출한다. 주로 사용자 인터페이스(메인프레임 터미널 또는 애플리케이션의 UI) 통해서 호출한다. SOA SOA 생태계 주위로 흐르는 메시지를 기술하기 위해 사용되는 데이터 스키마에 의존한다. 이러한 데이터 스키마들은 서비스 연산의 협업 세트 내에서 통합되는 물리적인 데이터 메시지로서 실현된다. 여기에는 런타임 데이터 트랜슬레이션, 의미 매핑, 또는 메시지 데이터의 추가 등이 포함된다. 데이터는 기반 레거시 IT 시스템에 의해 사용 처리된다.

SOA에서 실행될 있는 프로세스 세트는 특정 상태로 되어 있어야 하는 데이터와 콘텐트에 의존한다. SOA 함수와 레거시 IT 시스템들을 통한 병렬 프로세싱은 상태 모델에 불안정하게 만들 뿐이다.

그림 1 예제에서, 변형은 고객의 보험 정책을 설정하고 관리하는 단순한 프로세싱 기능을 갖고 있는 새로운 인터넷 애플리케이션을 실행했다. 새로운 애플리케이션들은 고객과의 연락을 실행하고 보험 정책이 갱신될 갱신 처리를 제공한다. 하지만, SOA 범위 밖에 있는 기존 비즈니스 연산들은 문제를 일으킬 있다. 고객들은 거주지를 옮겼던 경로에 따라 회사에 공지할 있는 수단이 있다. 새로운 인터넷 애플리케이션을 통해 정책이 처음 구매되었더라도, 고객은 SOA 애플리케이션을 사용하여 회사에 주소 변경을 알리지 않고, 대신 편지를 보낼 있다. 오피스(back- office) 프로세스는 고객의 새로운 주소가 고객 관리(CRM) 시스템에만 적용되도록 한다. 기존의 CRM 시스템의 일괄 프로세싱이 Insurance Contract Administration 시스템을 고객 데이터로 업데이트 한다. 새로운 SOA 기반 시스템은 거의 실시간 트랜잭션으로 설계되므로, 데이터 동기화 타이밍 문제가 발생한다. 새로운 애플리케이션은 오래된 주소의 갱신에 대해 고객과 연락을 시도할 있고, 응답 콘텍스트 인식 SOA 애플리케이션이 새로운 주소에 있는 사람에게 연락하여 오래된 정책을 취소하고 새로운 정책을 설정한다

서비스 공급자

SOA 아키텍트의 역할은 서비스 실행 인프라스트럭처의 디자인과 구현과 관련되어 있다. SOA 모델링 기술은 프로세스와 정보 아키텍처가 소비할 서비스를 결정하고, 서비스 공급자와 연락하고, 프로세싱 실행과 데이터 프로세싱의 일부로서 서비스 연산을 호출하는 애플리케이션을 구현할 있게 도와준다. 서비스 소비자는 동의된 계약에 따라 데이터를 처리하고 관리하는 서비스 공급자가 서비스를 구현하는 방식은 신경 쓰지 않는다.

특정 시나리오에서, 모델이 작동한다. 특히, 여러분이 서비스 공급자 구현을 기업 외부에서 아웃소싱 했을 경우에 그렇다. 글에서는 오늘날 많은 기업들이 SOA 채택하면서 겪게 되는 특수하지만 공통적인 시나리오에 초점을 맞춘다.

현실은, SOA 변형에서 전체적인 솔루션 아키텍트는 많은 책임을 갖고 있고, 특히 점증적인 변형을 해야 하는 기업의 경우 특히 그렇다. 이러한 책임은 기업 거버넌스 프로세스의 영역 안에서 수행된다. ("SOA 거버넌스" [developerWorks, 2005 8]).

우선, 솔루션 아키텍트는 SOA 인프라스트럭처의 디자인과 구현에 관련되어 있다. 여기에는 서비스 공급자 구현의 일부를 형성하는 소프트웨어 시스템으로서 작동할 레거시 IT 시스템을 구분하는 것이 포함된다. 번째, 솔루션 아키텍트는 서비스 소비 애플리케이션을 조합할 있는 개발 프로세스와 환경을 제공한다. 여기에는 디자인 패턴과 표준, 툴링 환경이 포함된다. 셋째, 솔루션 아키텍트는 비즈니스와 IT 아키텍처를 구성할 있어야 한다. 비즈니스 아키텍트는 기능과 콘트랙트와 관련하여 비즈니스 전략을 짜야 한다. IT 아키텍처는 전체적인 비즈니스 연산을 지원하는데 필요한 IT 시스템을 제공할 것이다. 대형 엔터프라이즈 내에서, 이는 전략적 애플리케이션의 대형 포트폴리오가 된다

디자인 전략

전체적인 엔터프라이즈 순응성을 실행하는 강력한 정보 관리 아키텍처를 구현하기 위해서는 문제를 다룰 많은 디자인 전략과 원리를 생각해야 한다.

비즈니스 프로세스 분석에 있어서 범위 변경 계획

변형 프로그램 동안, 일반적으로 시스템 분석과 디자인이 바람직하지 못한 데이터 프로세싱 시나리오를 발견하게 된다. 이전에 범위에서 벗어났던 비즈니스 연산들은 다시 범위로 가져와서 새로운 시스템을 수용할 있도록 수정될 있다. 새로운 SOA 기반 시스템들은 고객 상세를 업데이트 하는 추가 프로세싱 단계 같은 변화된 비즈니스 연산을 위해 내부 애플리케이션을 제공해야 한다.

레거시 엔터티 변화를 퍼블리시 등록하기

동의된 엔터티와 애트리뷰트 데이터가 서비스 공급자로서 참여하는 레거시 IT 시스템에서 변화될 , 추가 프로세싱은 SOA 알리도록 개발되어야 한다. 이상적으로 이것은 실시간으로 되어야 하지만, 스케줄링이 일괄 액티비티가 된다. 데이터 기록이 바뀔 탐지하는 레거시 IT 시스템으로 계측 코드를 적용하는 데는 비용이 많이 들고, 오래되고 구조가 형편없는 애플리케이션 코드에서는 거의 불가능 하다.

엔터프라이즈가 수행해야 하는 가지는 레거시 시스템이 소유한 데이터와 관련 당사자에게 변화를 공지하는 시스템 기능을 평가하는 것이다. SOA 중요한 데이터가 자주 변하고 이것이 레코드 레벨 이벤트 트리거를 생성하는 시스템의 무능력과 결합한다면 레거시 시스템의 리엔지니어링 또는 대체를 다시 고려해야 한다. 비즈니스 서비스의 QoS 계획된 엔지니어링 노력으로 정렬되어야 한다 핵심 서비스 데이터의 일괄 프로세싱에서 실시간 메시지 중심 프로세싱으로 옮기는 같은, 엔지니어링 향상을 통해, QoS 시간이 흐르면서 향상되고 있다는 것을 나타내야 한다.

정보 서비스 쿼리 facade

정보 관리 서비스는 데이터 또는 콘텐트에 적용될 있는 단순한 액션들을 나타내야 한다. 쿼리 facade 정보가 액세스 되고 조작되는 방법을 숨기고, 물리적 IT 시스템들이 얼마나 많이 있는지도 숨긴다. 기본적으로, 쿼리 facade 데이터 통합을 이룩하기 위해 개의 패턴을 구현할 있다. 엔터프라이즈 내에 다양한 시나리오와 레거시 시스템들 때문에 서비스를 구현하는데 가지가 사용될 것이다.

  • 데이터를 쿼리로 가져오기. 천천히 변하는 정보를 데이터 스토어(웨어하우스) 가져오고, 그곳에서 데이터에 대해 작동한다. Extract, Transform, Load (ETL) 기술들이 여기에서 사용될 있다.
  • 쿼리를 데이터로 가져오기. 빠르게 변화하는 트랜잭션 데이터의 경우, 액션은 이를 조작할 있는 물리적 소스로 가야 한다. 커넥터와 어댑터 기술을 사용하여 액세스 있다. (읽기 업데이트)

SOA 내에서, 실제 쿼리 facade federation population (참고자료 섹션의 데이터 통합 애플리케이션 패턴 참조) 같은 다양한 패턴들을 사용하여 구현되고, Service Data Objects Data Access Services (참고자료) 같은 기술을 사용하여 구현된다. 다양한 서비스 구현을 위한 전체적인 디자인 패턴("서비스 지향 아키텍쳐와 통합을 위한 패턴 언어, Part 1" [한국 developerWorks, 2005 7]) 이러한 결정에 영향을 미친다. 하지만, 이러한 문제 공간에서, 구현 디자인은 확장되어 서비스를 더욱 지능적인 것으로 만든다. 엔터티 데이터 변경 사항을 퍼블리시 하는 레거시 시스템을 위한 솔루션이 정비된 상황에서(QoS), 정보 시스템은 변경 사항을 등록하고 변경 사항들을 각각의 물리적 시스템에 적용해야 한다.

이것은 엔터티 결정을 완성하는 아키텍처의 장소이다. 어떤 레거시 IT 시스템이 마스터로 간주되어야 할까? 여기에서 마스터 데이터 관리 기술은 구현을 도울 있고, 옵션과 결정들은 레거시 시스템의 통합 기능과 균형을 맞추어서 아키텍처 정의의 중요한 부분이 되어야 한다.

비즈니스 규칙 배치

SOA로의 변형에는 통합 미들웨어와 새로운 복합 애플리케이션들을 포함하고 있는 새로운 IT 인프라스트럭처가 도입된다. 비즈니스 규칙들은 하나의 애플리케이션 안에서만 이상 제한되지 않는다. 상태는 비즈니스 규칙의 실행을 통해 효과적으로 관리된다. 정보 관리 디자인을 개발하는 것의 일환으로 비즈니스 규칙 로직의 유형과 위치가 이해되어야 한다.

SOA 내에서 비즈니스 규칙의 유형에는 다음이 포함된다.

  • 참조 무결성 규칙
  • 애플리케이션 작동 규칙
  • 크로스 애플리케이션 통합 규칙
  • 트랜잭션 프로세싱 비즈니스 로직 규칙
  • 저장 프로시저 같은 데이터 엔터티 프로세싱 규칙

전략은 비즈니스 규칙을 다시 만드는 것이 아닌 재사용이 되어야 한다. SOA 도입으로 기존의 비즈니스 규칙과 새로운 비즈니스 규칙을 실행하는 것을 신중하게 생각해야 한다. 규칙 로직 자체는 특정 프로세싱 시나리오를 위해 무결성을 관리하기 위해 호출될 있는 서비스로서 노출되어야 한다.

잠재적인 디자인 전략 영향

이와 같은 디자인 결정에 다다르면 여러분이 고려해야 하는 솔루션에 미치는 영향은 다음과 같다.

  • 더블- 프로세싱. SOA 도입으로 인해 하나의 비즈니스 영역에서 얻어진 효율성은 추가 데이터 엔트리 태스크(그리고 데이터 엔트리 에러의 위험) 비례하여 균형이 맞춰져야 한다. 하지만, 이것은 데이터-동기화 타이밍 시나리오를 대처하기 위한 유일한 옵션이다. 이러한 시나리오는 보통 가볍게 취해진다. 엔터프라이즈는 밤마다 수행되는 일괄 업데이트의 시간 지연을 피하기 위해 이벤트 중심 더블 (keying) 수행하는 인원수를 확립해야 한다. 데이터 동기화를 보조할 시스템에서 자동화된 인터페이스를 개발하는 비용도 계산해야 한다. 자동화된 인터페이스를 구현하는데 필요한 시간이 전체적인 딜리버리 타임 스케일을 구성하는지 여부도 평가해야 한다.
  • 불필요한 피드백 루프. CRM 시스템에서의 고객 기록 업데이트는 SOA로의 수동 또는 자동 호출로 이어져서 영역 KR 고객 데이터 변경에 대해 다른 애플리케이션에 알려야 한다. 고객을 업데이트 하려면, SOA 정보 서비스를 호출하고, 이는 자체로 원래의 CRM 시스템을 호출하고 고객 데이터를 업데이트 한다. 정보 서비스 아키텍처는 사용 모델에 기반하여 업데이트 고객 다른 스타일을 구현해야 한다.
  • 범위 이동. SOA 범위가 정의될 , 레거시 IT 시스템에 대한 지식의 부족과 프로세스 정보 관리 기능도 변하게 된다. 서비스 모델의 파생은 레거시 분석을 이끌어 내고, 보다 미묘한 SOA 인프라스트럭처 구현이 필요하다는 것을 드러낸다. 전체적인 비즈니스 서비스와 엔지니어링 프로그램의 전체 범위를 정의하기 전에 단계를 플래닝 해야 한다.

결론

글에서는 SOA로의 성공적인 비즈니스 변형 프로그램을 제공하는 것에 초점을 맞추었다. SOA로의 비즈니스 변형의 문제는 매우 많다. 대부분의 기업들은 새로운 복합 애플리케이션들이 구현될 있는 SOA 인프라스트럭처를 도입함으로써 점증적인 변형을 시도하고 있다. 이들은 레거시 IT 시스템들을 사용하여 서비스 공급자를 구현한다.

강력하고 순응적인 연산을 기업이 유지하려면, 변형 프로그램은 엔터프라이즈 정보 관리 솔루션을 개발해야 한다. 솔루션은 SOA에서의 레거시 IT 시스템들에서 데이터의 일관성과 동기화 문제를 다루어서 정보 서비스들이 안전하게 노출될 있도록 해야 한다.

SOA 변형을 제공하는 책임이 있는 솔루션 아키텍트는 전체적인 엔터프라이즈 아키텍처 예산의 정황 속에서 SOA 필요와 레거시 IT 시스템의 기능에 균형을 맞춰야 한다. 데이터 통합을 위한 기술과 데이터 관리는 정보 관리 솔루션을 위한 구현 전략에 포함된다

감사의

글을 검토해 Rick Robinson, Patrick Dantressangle, Bob Lojek, Claudio Cozzi 감사의 말을 전하고 싶다.

 

참고자료

교육


제품 기술 얻기


토론

 

필자소개

Jeremy Caine IBM Global Business Services IT 아키텍트이자 기술 전략 컨설턴트이다. 대형 비즈니스 변형과 시스템 통합 프로그램과 관련한 일을 하고 있으며, 복잡한 IT 시스템, 기술 솔루션, 엔터프라이즈 애플리케이션 통합 전략 분야를 담당하며, 고객 층은 금융 서비스와 정부이다. 월드와이드 IBM 기술 커뮤니티에서 활발하게 활동하고 있다. IBM 아키텍처 교육 팀의 리더이자 멤버이다.

 

Joe Hardman IBM Global Business Services IT 아키텍트이다. SOA 애플리케이션 아키텍처와 보안 전문가이다. 최신 프로젝트로는 cahoot 인터넷 뱅킹과 Polaris imarket 등이 있다. 현재 글로벌 정유 회사에서 SOA 프로그램을 맡고 있다.

 

      Service Oriented  |  2007. 8. 28. 13:42




[출처 :SONIC]
      Service Oriented  |  2007. 4. 7. 15:40




- 퍼온 이유... --;
SOA의 관련 된 생각을 정리하면서 쓴 글...

[1편] SOA와 Service의 정의
[2편] BPM을 통한 서비스 분류하기
[3편] ESB를 이용하여 Service Enabling 하기
[4편] SOA 잘 돌리기(계획) <-- 이 부분을 대신해서 퍼왔다...

거버넌스라는 내용을 정리하기엔... 개념이 너무 없다..  다시 이야기해서 정리할 것이 없다는 이야기.... 차츰 좋은 내용들을 읽어 가면서... 개념을 탑재하자!
==========================================================================================

[SOA 거버넌스 입문]


관리: 공식적인 IBM 정의 및 SOA 관리가 필요한 이유


Bobby Woolf, IBM Sofware Services for WebSphere, IBM

2006 년 8 월 07 일

아이비엠이 서비스 지향 아키텍처 관리를 정의한 방식에 대해 알아보고 서비스 지향 아키텍처 관리란 무엇인지, 관리가 서비스 지향 아키텍처 프로젝트 성공에 중요한 이유를 배워봅시다.

관리 및 관리에 대한 필요성

서비스 지향 아키텍처(SOA)는 비즈니스 모델과 최적으로 잘 맞는 소프트웨어 애플리케이션을 개발하는 데 있어 매력적인 기술이다. 하지만 SOA는 IT 부서 및 팀원 가운데만이 아니라, 비즈니스 및 정보기술(IT) 간에 요구되는 협력 및 조정 수준을 증가시켰다. SOA 관리는 이런 협력 및 조정수준을 제공하고 주로 서비스 및 SOA 애플리케이션을 지원하는 방식을 지정하고 관리하는 태스크 및 과정을 다룬다.

이 글에서, 관리 및 관리가 무엇인지, 관리 및 관리가 중요한 이유 등에 대해 알아본다. 우리는 다음과 같은 SOA 관리의 중요한 특징에 대해 검토할 것이다.

아울러 SOA 애플리케이션에서 SOA 관리가 필요한 이유에 대해 확실히 알아야 한다. 또한 여러분의 조직이 자체적으로 SOA 관리 방식을 구축하는 방식에 대해서도 어느 정도 알게 될 것이다.

관리 없는 생활

관리에 대해서 얘기하기 전에, 회사 IT 부서에서 일반적으로 벌어지는 상황에 대해 생각해 보자. 즉 관리가 없을 때 벌어지는 상황에 대해 생각해 보자.

서비스 제공을 원할 경우

당신이 통화량을 다른 나라 통화로 바꾸는 멋진 서비스를 개발했다고 해보자. 당신은 작업하고 있는 순서-처리 프로그램에서의 다른 위치에 서비스가 필요해 프로그램의 임의의 위치에서부터 호출하는 재사용 함수로 코드를 작성한다. 또 다른 프로그램에서도 서비스가 필요해, Java . jar에 코드를 넣어 서비스를 필요로 하는 임의의 프로그램의 클래스경로에 추가한다. 하지만 서비스를 기동하는 데 오랜 시간이 걸린다는 점이 서비스에서 나타나는 문제다.Yahoo 통화 변환기 웹 사이트상에 개제된 서비스와 같이 통화-환율로 서비스를 초기화해야 하기 때문이다. 통화량을 변환해야 될 때마다, 이 단계는 서비스를 초기화하는 데 시간이 너무 오래 걸린다. 따라서 당신은 자체적인 작은 프로그램에 변환기를 호스트한다. 이 작은 프로그램은 작동을 시작하고 초기화하고, 항상 실행하고 원격 API를 통해 프로그램의 일부에서 호출된다. 아마도 API는 HTTP 웹 서비스에 대한 SOAP로 구현되거나 단지 IIOP에 대한 RMI를 지원하는 원격 Enterprise JavaBeans(EJB) 인터페이스에 불과할 것이다.

지금 가지고 있는 건 통화량 변환기 서비스다. 당신의 몇 가지 프로그램에서 사용하고 있을 뿐만 아니라, 부서 내의 동업자들도 통화량 변환기 서비스를 선호해 자신들의 프로그램에서 그 서비스를 호출하기 시작한다. 머지 않아 들어본 적이 없어 잘 알지 못하는 당신 회사의 다른 부서에 있는 프로그램도 그 서비스를 사용하고 있다. 변환기가 많이 실행되고 있어, 응답시간이 느려진다. 따라서, 당신의 매니저에게 서비스를 호스트할 더 강력한 머신을 구매하라고 설득한다. 매니저는 자신의 예산에서 돈을 쓰는 것에 대해서 좋아하지 않는다. 매니저가 들은 또 다른 머신은 그저 단순한 기능만 하기 때문이다. 하지만 그를 설득한다.

어느 주말, 전혀 들어보지 못한 회사의 누군가에게서 집에 전화가 왔기 때문에 당신은 머신이 충돌했다는 사실을 알게 된다. 그 사람은 회사로 와서 변환기를 다시 작동시킬 것을 요구한다. 나중에 매니저가 적절한 방식으로 현재 환율이 업데이트되지 않아 또 다른 부서에서 변환기에 대한 불만들을 접수했다고 말한다. 그는 당신이 변환기를 고치길 원하지만 또한 실제 업무 시간을 낭비하지 않길 원한다. 이 경우 당신은 어떻게 책임을 지게 될까?

어느날 당신이 "이거 어쩌란 말이야."라고 말했다 치자. 그래서, 변환기에 대해 더 이상 책임을 지지 않고 변환기를 셧다운시켰다고 해보자. 변환기 고장에 대한 책임자를 찾으려고 하는 사람들로부터 불만사항이 있는 수많은 이메일이 회사전체에 유포되기 시작한다. 상당히 가치있는 프로그램들이 컨버터 없이는 작동되지 않는다고 항의하는 이메일이 수두룩하다. 고객은 화가 났고 회사는 돈을 잃고 있다. 재수 없게도, 모든 사람이 그 책임자가 당신이었다는 것을 알게 될 때 당신은 해고될지도 모른다. 이런 일이 어떻게 해서 발생된 걸까?

서비스 소비를 원할 경우

이제 플립쪽을 고려해 보자. 당신은 이 회사에서 다른 직원으로, 상품 카탈로그 애플리케이션을 연구한다. 다른 나라에 있는 사용자들이 자기 나라의 통화로 상품의 비용을 보길 원한다. 동업자들은 당신에게 각 상품의 가격을 사용자 국가의 통화로 바꾸는 호출 서비스에 대해 얘기한다. 당신은 그 서비스를 시험한 다음, 작동된다는 것을 충분히 확신하게 된다. 그래서 호출 서비스를 사용해 당신의 애플리케이션을 구현한다. 당신의 매니저는 기록시간에 작동되는 호출 서비스 기능 때문에 만족해 한다. 고객들은 그 기능을 좋아하고 당신의 웹 사이트 상의 판매 실적은 현저하게 증가한다.

그리고 난 뒤 어느 주말, 당신의 웹 사이트 가동이 중단됐다. 웹 사이트에서 다른 나라 통화로 표시가 안 되는 바람에, 매니저는 당신에게 전화를 걸어 프로그램을 수리하라고 말한다. 당신은 호출서비스에 대해 말한 동업자에게 집에서 전화를 건다. 반면, 판매 부사장 대리는 당신에게 소비자들이 불만을 가지고 있다고 통지한다. 당신은 호출서비스를 분명히 작성한 친구에게 이 사실을 말한다. 대리는 그 친구에게 전화를 절어 회사로 와서 당장 호출서비스를 작동시키라고 요구한다. 반면에 당신은 애플리케이션에 아무런 문제가 없었는데도, 단순히 호출서비스 때문에 카탈로그 애플리케이션 작동이 중지되어 곤란한 지경에 빠진다. 어떻게 해서 이런 일로 당신이 잘못하게 되었는가?

그래서 SOA 관리가 필요한 것이다. 이 경우 효과적인 관리가 부족해서 생기는 문제들이다. 서비스 제공 사업자와 서비스 소비자 둘 다 흥정한 것보다 훨씬 더 많은 책임이 있다. 이와 같은 곤란한 상황이 발생되지 않고도 서비스들을 어떻게 이용할까?




위로


SOA 관리란?

관리가 비효율적일 때 일어나는 현상들을 봤다. IT 관리가 더 나은 경우 IT 관리가 IT가 어떻게 전보다 더 낫게 작동될까? 먼저 우리는 관리가 무엇인지, 그리고 관리가 IT 및 서비스에 영향을 주는 방식에 대해 이해해야 한다.

일반적으로, 관리는 그룹이 함께 작업하기로 동의한 방식을 수립하고 시행하는 것을 의미한다. 특히 두 가지 관리 측면이 있다.

  • 사람들에게 권한을 부여할 책임, 권한 및 커뮤니케이션 체인을 수립하고 결정을 내릴 권리를 가진 사람을 결정하는 측면
  • 평가, 정책, 제어 메커니즘을 수립해 사람들로 하여금 자신의 역할 및 책임을 수행하도록 하는 측면

관리는 다음과 같은 방식으로 관리와 구분된다.

  • 관리란 결정을 내리는 권한 및 책임을 가진 사람을 결정하는 것을 의미한다.
  • 관리란 결정을 내리고 실행하는 과정이다.

따라서 관리란 할 임무를 말하고, 관리는 임무가 수행되고 있는지 확인하는 작업이다.

관리의 특수한 형태는 IT관리로 다음과 같은 역할을 수행한다.

  • IT와 관련된 결정 권리를 수립함
  • IT 결정을 내리고 실행하는 방식을 평가, 조절하는 데 사용되는 메커니즘 및 정책을 수립함

즉, IT 관리는 IT 부서에서의 책임자 및 부서에서 그와 같은 책임을 수행하는 사실을 아는 방식에 관한 것이다.

SOA는 관리에 다음과 같은 고유의 측면`을 추가한다.

  • 서비스의 생명주기에 중점을 둔 IT 관리 확장역할을 하면서 SOA 의 비즈니스 가치를 확고히 함
  • 회사 내의 기존 서비스 변화를 모니터, 정의 및 허가하는 사람을 결정함

관리는 일반 IT에서보다 SOA에서 더 중요한 문제가 되고 있다. SOA에서, 서비스 소비자와 서비스 제공 사업자는 다른 과정에서 실행하고 다른 부서들에 의해 개발되고 관리된다. 뿐만 아니라 이들이 서로 함께 일하기 위해선 많은 협력이 필요하다. SOA가 성공하려면, 다중 애플리케이션은 공통 서비스를 공유해야 한다. 이는 이와 같은 서비스를 일반이 이용할 수 있고 재사용되는 데 있어 서비스 소비자 및 제공 사업자가 서로 협력해야 한다는 것을 의미한다. 이와 같은 것들이 관리에 관한 문제들이고 단일 애플리케이션 시대, 심지어는 재사용 코드 및 구성요소 시대 때보다 훨씬 복잡하다.

회사에서 비즈니스와 IT를 더 잘 맞추기 위해 SOA를 사용하고 있을 때 전체적인 IT 관리를 향상시키기 위해, SOA 관리를 사용하는 것이 이상적이다. 회사가 SOA의 장점을 실현하고자 한다면, SOA 관리를 사용하는 것이 중요하다. SOA가 성공하려면, SOA 비즈니스 및 기술 관리는 선택이 아니라 필수가 되어야 한다.

실제의 SOA 관리

실제로, SOA 관리로 재사용 서비스가 개발되고 서비스의 설계 및 개발 방식 및 아울러 시간에 따른 서비스의 변화 방식까지 수립한다. SOA 관리로 서비스 공급업체와 서비스 소비자 간의 계약을 수립하고 소비자에게 기대하는 것, 이 계약을 통해 서비스 소비자들에게 기대하는 것, 서비스 제공 사업자들이 해야 될 임무들에 대해 명시한다.

SOA 관리에서는 서비스를 설계하지 않고 서비스를 설계할 방식을 안내할 뿐이다. 이 관리로 SOA와 관련된 까다로운 수많은 질문을 해결하는 데 도움이 된다. 질문들은 다음과 같다. 어떤 서비스가 유용한가? 서비스의 신뢰도는? 서비스 지원기간은? 변하지 않는 서비스를 신뢰할 수 있는가? 서비스가 변하길 원할 경우엔 어떻게 할까? 아니면 새로운 기능을 추가하는가? 서비스 노출을 결정한 이유만으로, 서비스를 영원히 지원할 의무가 있다는 것을 의미하는가? 서비스 소비를 결정한 경우, 서비스가 내일도 셧다운되지 않을 거라고 자신하는가?

SOA 관리는 기존 IT 관리 기술 및 실례에 근거해 구축된다. 자바2 플랫폼인 엔터프라이즈 에디션(J2EE)와 같은 객체-지향 기술을 사용할 경우, IT 관리의 가장 중요한 측면은 코드 재사용이다. 코드 재사용은 또한 IT 관리의 어려움을 잘 설명한다. 모든 사람들은 재사용 자산이 좋다고 생각한다. 하지만 재사용 자산을 실제로 쓸모있게 하는 게 어렵다. 재사용 자산을 개발하기 위해 누가 지불하겠는가? 개발 팀은 자산을 다시 재사용하기 위해 실지로 노력할 것인가? 모든 사람이 정말로 재사용 재산에 관한 단일기능에 동의할 수 있을까? 또는 모든 사람이 결국 실지로 재사용되지 않는 자신만의 맞춤형 버전을 소유할 것인가? SOA 및 서비스는 이와 같은 관리 문제를 더욱 중요하게 부각시켜 문제의 결과를 더욱 의미심장하게 만든다.

관리는 기술적, 비즈니스 문제보다는 정치적 문제에 가깝다. 기술은 인터페이스 및 호출 인터페이스를 맞추는 것에, 비즈니스는 고객에게 제공할 기능에 초점을 두고 있다. 기술과 비즈니스는 요구조건에 중점을 두고 있다. 관리는 그와 같은 측면에 관여하기도 하지만, 모든 사람들이 같이 협력하면서 개별적인 작업이 서로 어긋나지 않는다는 점을 확고히 하는 데 더 중점을 두고 있다. 관리로 결정의 결과가 아닌 내린 결정 및 결정을 내릴 주체를 결정한다.

두 당사자인 소비자와 공급업테는 같이 협력하는 방식에 합의해야 한다. 이와 같은 합의는 서비스 레벨 계약서(SLA), 서비스 제공 사업자가 달성하고 서비스 소비자가 따르기로 합의한 측정 가능한 목표에 표현된다. 이 계약서는 당사자들간의 계약서와 비슷하고 사실 법적인 계약서일 수 있다. 적어도, SLA에는 서비스 제공 사업자의 의무 및 소비자의 기대에 대해 명확히 나타나 있다.

SOA로 기업의 성공을 보장하는 정책을 수립, 감독하는 우수연구센터(center of excellence, COE) 및 전문가 이사회에서 SOA 관리를 규정한다. COE는 서비스의 식별 및 개발, SLA의 수립, 레지스트리 관리 및 효과적인 관리를 제공하는 기타 대책들에 관한 정책을 수립한다. COE 임원들은 이런 정책들을 실행에 옮기고, 팀에게 서비스 및 복합 애플리케이션 개발에 대해 조언하고 지원한다.

일단 관리 COE가 정책을 수행하고 나면, 이러한 정책을 관리하는 데 기술을 사용한다. 기술은 SLA를 정의하지 않지만, 신뢰성을 시행, 평가하는 데 사용된다. 예를 들어, 기술을 통해 서비스를 호출할 고객 및 고객의 서비스 호출 시기에 대해 제한할 수 있다. 또한 기술을 통해 서비스 가치가 하락되었다고 소비자에게 경고를 주며, 서비스의 가용성 및 응답 시간을 측정한다.

엔터프라이즈 서비스 버스(ESB) 및 서비스 레지스트리를 조합시키는 것을 통해서야말로 기술로 관리 정책을 시행하는 좋은 상황이 된다. 서비스를 노출해 일정 ESB만 서비스를 호출할 수 있다. ESB/레지스트리 조합은 소비자의 접근기능을 제어하고 사용률을 모니터, 측정하고 SLA 신뢰성을 측정한다. 이런 식으로 서비스는 비즈니스 기능의 제공에, ESB/레지스트리 조합은 관리 측면에 중점을 두고 있다.

관리는 SOA의 단점에 있어 희생양이 될 수 있다. 성능면에서 보면 관리는 발생하는 모든 문제에 관한 압도적인 관심사일 뿐만 아니라 변명거리로 등장하고 의문이 되는 모든 솔루션에 대한 정당화 구실을 할 수 있다. SOA 토론(말싸움장으로 변함)장으로 일방적인 의견만 제시할 뿐이고 당신은 유익한 모든 대화가 중단되는 것을 보게 된다. 관리를 지혜롭게 사용해 관리에 관한 문제로 다른 사항들이 발목잡히지 않는 상태에서 SOA를 잘 작동시키도록 하는 것이 SOA에서 주어진 과제다.




위로


SOA 관리의 측면

SOA 관리는 단지 관리의 단일 집합일 뿐만 아니라, 함께 조합되는 많은 실례들의 집합이다. 각각의 SOA 관리 측면은 다음 글에서 더 자세하게 토론할 만한 가치가 있다. 지금 하는 이와 같은 토론은 단지 간단한 개요에 불과하다. 몇 가지 관리에 관한 측면에 대한 더 자세한 사항은 참고자료를 참조하라.

서비스 정의

SOA 관리의 가장 기본적인 측면은 서비스 생성과정을 감독하는 것이다. 서비스를 반드시 식별하고 서비스 기능을 설명하고, 서비스 기능을 조사하며 서비스 인터페이스를 설계해야 한다. 관리 COE는 이와 같은 작업을 수행하지 않을 수도 있지만 이런 작업이 수행 중인지는 확인한다. COE는 서비스를 생성하고 서비스를 필요로 하는 팀을 구성해 이들의 필요를 충족시키고 이중 노력을 피하도록 한다.

서비스여야 하지만 그렇지 않을 수도 있는 불분명한 것이 종종 있다. 함수는 일련의 반복 비즈니스 태스크를 일치시켜야 한다. 서비스 경계에선 재사용 가능하고 컨텍스트가 없는 기능을 소중히 보호해야 한다. 인터페이스는 서비스의 기능을 노출하지만 서비스의 구현 방식은 숨기고 구현 방식이 변경되거나 대체 구현방식을 허용하도록 해야 한다. 서비스를 처음서부터 설계할 때 비즈니스를 모방하기 위해 설계한다. 서비스가 기존 기능을 포함할 경우 좋은 비즈니스 인터페이스를 생성하고 구현하는 게 더 어려울 수도 있다.

서비스 경계를 정의하는 잠재적인 어려움 가운데서 흥미로운 예는 트랜잭션 경계를 설정하는 곳이다. 서비스는 보통 자체 트랜잭션에서 실행되고 기능이 완전히 작동되든지, 완전히 원래대로 되돌아가던지 여부를 확고히 한다. 하지만 서비스 조정자(조정자 또는 구성자)는 단일 트랜잭션(이상적으로 WS-AtomicTransactions와 같은 특정 상호작용을 통해)에서 다중 서비스의 호출을 원할 수도 있다. 이런 작업은 호출자의 트랜잭션에 관여할 수 있도록 트랜잭션 지원기능을 노출하는 서비스 인터페이스가 필요하다. 하지만 그와 같은 노출과정은 호출자에 대한 신뢰가 필요하며, 서비스 제공 사업자에는 위험할 수도 있는 것이다. 예를 들어, 서비스 제공 사업자는 서비스를 제공할 리소스를 잠글 수도 있다. 하지만 호출자가 트랜잭션을 전혀 끝내지 않을 경우 (트랜잭션 커미트 실패 또는 되돌아가기), 서비스 공급업체는 리소스 잠금기능을 확실히 푸는 데 어려움을 겪게 된다. 이 상황에서 보듯, 서비스 및 지배자 영역을 결정하는 것은 때로는 쉬운 일이 아니다.

서비스 전개 생명주기

서비스는 순간적으로 생성돼 영원히 존재하는 건 아니다. 임의의 소프트웨어와 마찬가지로, 서비스를 계획하고, 설계하고, 구현하고, 전개하고, 유지보수하고, 궁극적으로 폐기처분해야 한다. 애플리케이션 생명주기는 공개되어 있고 조직의 많은 부분에 영향을 미친다. 하지만 다중 애플리케이션은 단일 서비스에 따라 다르기 때문에 서비스의 생명주기 영향은 더 크다.

레지스트리의 사용을 고려해 볼 때 서비스의 생명주기는 더욱 분명해진다. 새로운 서비스를 레지스트리에 추가할 때는 언제인가? 레지스트리에 있는 모든 서비스가 필연적으로 유용하고 서비스를 사용 준비가 되었는가? 폐기처분된 서비스는 레지스트리에서 제거되어야 하는가?

모든 서비스 및 조직에 적절하게 다 맞는 생명주기는 하나도 없는 반면, 일반적인 서비스 개발 생명주기에는 5가지 주요단계가 있다.

  1. 계획 식별되고 설계 중인 새로운 서비스는 아직 구현되지 않았거나 구현 중이다.
  2. 테스트 일단 구현하면 서비스를 테스트해야 한다 (순식간에 더 많은 테스팅 작업이 이루어짐). 능동적인 서비스인 것처럼 서비스를 사용하는 생산 시스템에서 수행되어야 하는 테스팅도 있다.
  3. 사용단계 이 단계는 이용 가능한 서비스 및 일반적으로 서비스라고 생각되는 것들에 대한 단계다. 이용가능한 서비스 단계며 서비스는 실제로 실행, 작동된다. 서비스를 아직 폐기처분하지 않았다.
  4. 사용중지 이 단계는 아직도 능동적이지만 더 이상 오래 가지 않을 서비스를 나타낸다. 소비자에게 서비스 사용을 중지하라는 일종의 경고다.
  5. 폐지 서비스의 마지막 단계로 서비스가 더 이상 제공되지 않는다. 레지스트리에서 한 때 능동적이었지만 이제는 더 이상 이용가능하지 않은 서비스를 기록할 수도 있다. 이런 단계는 필연적이지만 서비스 제공 사업자 및 소비자들이 종종 계획하지 않은 단계다.

서비스 폐지로, 효과적으로 서비스 버전 설정이 해제된다. 서비스 폐지일을 미리 계획, 공표해야 한다. 서비스를 폐지하기 오래 전 서비스의 사용을 중지해 프로그램면에서 소비자들에게 다음 프로그램을 계획할 수 있도록 경고를 주어야 한다. SLA에서 서비스 사용중지 및 폐지에 대한 스케줄을 지정해야 한다.

여기서 한 가지 빠진 것으로 보이는 단계가 바로 "유지보수" 단계다. 유지보수 단계는 서비스가 사용단계일 때 발생한다. 이 단계에서 서비스는 도로 테스트 단계로 넘어와 적절한 기능 여부를 재확인한다. 하지만 이런 단계는 능동 서비스 제공 사업자에 의존하는 기존 사용자들에게는 문제가 될 수 있다.

유지보수 단계는 기대한 것보다 덜한 서비스에서 발생한다. 서비스 유지보수는 종종 기존 서비스 변경이 아닌 새로운 서비스 버전 생성 등을 포함한다.

서비스 비저닝

서비스가 이용가능하면 곧바로 서비스 사용자들은 서비스 변화를 필요로 한다. 버그를 수정해야 하고 새로운 기능을 추가해야 하고 인터페이스를 재설계하고 필요없는 기능을 제거해야 한다. 서비스는 비즈니스를 반영한다. 따라서 비즈니스가 변하면 서비스도 변해야 한다.

하지만 기존 서비스 사용자들과 함께 서비스를 잘 변화시켜서 서비스의 성공적인 운영에 걸림돌이 되지 않도록 해야 한다. 동시에 서비스의 안정성을 추구하는 기존 사용자들의 필요로 인해 부가적인 기능추가를 바라는 사용자들의 필요를 막아선 안 된다.

서비스 비저닝은 이런 상충되는 목표를 충족시킨다. 서비스 비저닝으로 기존 서비스에 만족하는 사용자들은 서비스를 변화시키지 않은 상태에서 계속 사용하게 되면서도 서비스가 진화해 새로운 요구조건에 있는 사용자들의 필요를 충족시킨다. 현 서비스 인터페이스 및 기능은 한 버전으로 보존되지만 새로운 서비스는 다른 버전으로 소개된다. 버전 호환성으로 한 버전을 예상하는 소비자는 다르지만 호환성이 있는 버전을 호출하게 된다.

버져닝은 이와 같은 문제를 해결하는 데 도움이 되지만, 새로운 문제인 서비스 이전에 관한 필요성을 야기시킨다.

서비스 이전

소비자는 서비스 비저닝으로도 서비스에 의존할 수 없다. 특히 서비스에서 원하는 버전을 영원히 이용하면서 지원할 수는 없다. 결국 서비스 제공 사업자는 서비스 제공을 중단시켜야 한다. 버전 호환성으로 이와 같은 서비스 사용중단일을 연기하는 데 도움이 되지만 그래도 서비스 사용중단을 취소할 수는 없다. 비저닝으로 서비스 개발 생명주기가 줄어드는 것은 아니지만 다음 세대에 걸쳐 그 생명주기는 끝나게 된다.

소비자가 서비스 사용을 개시할 경우, 비저닝으로 서비스 종속성을 생성하며 그 종속성은 관리되어야 한다. 새로운 서비스 버전으로의 계획적, 주기적 이전을 위해 종속성 관리 기술을 이용한다. 이와 같은 방식으로, 소비자는 서비스에 추가된 부가적 기능을 이용하게 된다.

하지만 가장 좋은 관리를 가진 기업의 경우에서도, 서비스 제공 사업자는 소비자 서비스 이전에만 의존할 수 없다. 레거시 코드, 인력, 예산, 우선권 등 여러 가지 이유로, 서비스를 제때 이전하지 않는 소비자들이 있다. 결국 서비스 제공 사업자가 서비스 버전을 영원히 지원해야 하는가? 모든 사람들이 이미 서비스를 이전한 뒤 그 다음 날, 서비스 사업자가 단순히 서비스 버전 설정을 해제할 수 있을까?

두 경우 다 바람직하지 못하다. 서비스 전개 생명주기에서도 설명했듯이, 모든 서비스 버전에 대한 계획된 사용정지 및 폐지 스케줄만이 제일 좋은 방안이다.

서비스 레지스트리

서비스 제공 사업자가 자신의 서비스를 어떻게 알리고 이용하게 할 수 있을까? 서비스 소비자는 호출하고 싶은 서비스를 어떻게 찾을 수 있을까? 이러한 것들은 서비스 레지스트리에 관한 영역이다. 서비스 레지스트리는 이용가능한 서비스 및 서비스를 호출하기 위한 주소에 대한 목록을 보여준다.

서비스 레지스트리는 또한 서비스의 여러 버전을 조정한다. 서비스 소비자와 서비스 제공 사업자는 소유하고 있거나 필요한 버전을 지정하면 서비스 레지스트리는 소비자가 희망한 버전의 제공 사업자를 나열한다. 서비스 레지스트리는 버전 호환성을 관리하고, 버전 간의 호환성을 추적하고, 소비자의 희망 버전 또는 호환 버전에 관한 제공 사업자를 나열한다. 뿐만 아니라, 테스트(이전에 설명함) 및 사용중지 단계와 같은 서비스 상태를 지원하며, 서비스를 훤하는 소비자에게 유용한 서비스 상태로 서비스를 생성한다.

소비자가 서비스 사용을 개시할 때, 서비스에 대한 종속성이 생성된다. 각 소비자가 전체적으로 기업을 통해 의존해야 할 서비스를 분명히 알고 있을 경우, 이와 같은 의존성은 탐지되기 힘들고 더군다나 관리하는 건 더 어렵다. 서비스 레지스트리는 서비스 및 서비스 제공 사업자에 대한 목록을 만들 뿐만 아니라, 소비자와 서비스 간의 종속성을 추적한다. 이와 같은 추적 기능으로 다음과 같은 질문 (이 서비스를 사용하는 사람은?) 을 해결한다. 종속성에 대해 인지하는 레지스트리는 서비스를 사용정지해야 될 때와 같이 서비스 제공 사업자 변경에 관해 소비자에게 공지한다.

서비스 메시지 모델

서비스 호출에 있어 서비스 소비자 및 제공 사업자는 메시지 포맷에 있어 일치를 봐야 한다. 개발 팀들이 각기 소비자 및 제공 사업자 메시지 포맷을 설계할 때, 이들은 공통 메시지 포맷에 대한 일치를 보는데 쉽게 어려움을 느낀다. 전형적인 서비스를 이용한 여러 가지 애플리케이션 및 여러 가지 서비스를 이용한 전형적인 애플리케이션으로, 메시지 포맷 수를 나열하면 메시지 포맷에 대해 단순한 일치를 보는 게 얼마나 노력을 요하는 일인지 알게 된다.

여기서 메시지 포맷에 대한 혼란을 없애는 공통적인 방식은 표준 데이터 모델을 이용하는 것이다. 표준 데이터 모델은 임의의 한 애플리케이션과는 무관하고, 모든 애플리케이션에서 공유하는 데이터 포맷의 공통집합이다. 이런 식으로는, 애플리케이션으로 메시지 포맷에 대해 일치를 보지 않아도 된다. 다만 애플리케이션은 공통적으로 기존 표준 데이터 모델을 사용한다. 표준 데이터 모델은 메시지에 있는 데이터 포맷을 나타낸다. 따라서, 헤더 필드, 메시지 유료 부하가 포함된 데이터의 종류, 그 데이터가 나열되는 방식 등의 메시지 포맷의 나머지 부분에 대한 일치가 필요하다. 하지만 표준 데이터 모델로 이와 같은 부분에 대한 일치를 보기엔 아직 멀었다.

중앙 관리 이사회는 표준 데이터 모델을 개발시키는 중립 당사자로서의 역할을 한다. 애플리케이션을 조사하고 서비스를 설계하는 일환으로, 이 이사회는 또한 서비스 호출 시 사용되는 공통 데이터 포맷을 설계한다.

서비스 모니터링

서비스 제공 사업자가 작업을 중단할 경우, 이를 어떻게 알겠는가? 서비스 제공업자가 사용하는 서비스를 사용하는 애플리케이션의 작동이 중단되고, 서비스를 사용하는 사람들의 불만이 나오기 시작할 때까지 기다리겠는가?

다중 서비스를 결합한 애플리케이션인 복합 애플리케이션은 서비스 제공 사업자가 믿는 서비스만큼 믿을만하다. 다중 복합 애플리케이션은 한 서비스를 공유하기 때문에, 단 하나의 서비스 오류도 많은 애플리케이션에 영향을 줄 수 있다. 소비자가 의존하는 신뢰성 및 성능을 설명하기 위해 SLA를 정의해야 한다. 소비자가 정의된 SLA를 충족시키는 것을 확고히 하려면 서비스 제공 사업자를 감시해야 한다.

이와 관련된 문제는 문제 해결에 관한 것이다. 복합 애플리케이션 작동이 정지된 경우 그 이유는 무엇인가? 아마도 사용자가 연결하는 애플리케이션 헤드 및 UI의 작동이 정지되었기 때문일 수도 있다. 하지만 헤드는 잘 작동되어도, 헤드에서 사용하는 서비스 일부 또는 그 서비스에서 사용하는 서비스의 일부가 제대로 작동이 안 되어서 그럴 수도 있다. 이와 같이 각 애플리케이션의 작동 방식 뿐만 아니라, 각 서비스(사업자 집합으로서의)의 작동 방식 및 개별 사업자 운영방식 등에 대해 감시하는 게 중요하다. 단일 비즈니스 거래에 있어 서비스 간의 이벤트 상관성은 상당히 중요하다.

이와 같은 모니터링은 문제가 발생되기 전 문제를 탐지하고 예방하는 데 도움이 된다. 이를통해 부하 불균형 및 정전 등을 탐지할 뿐만 아니라 이런 현상들이 심각할 경우, 경고 기능도 제공하고 자동적으로 문제를 해결하려는 시도도 생기게 된다. 모너터링으로 시간 당 서비스 사용률을 측정해, 요즘 인기를 얻고 있는 서비스를 예측하는 데 도움이 되고, 이를 통해 용량을 증가시켜 서비스를 작동할 수 있게 한다.

서비스 소유권

다중 복합 애플리케이션에서 한 서비스를 사용하는 경우, 그 서비스에 대해 누가 책임지는가? 그 사람 또는 그 사람이 소속된 조직에서 모든 복합 애플리케이션에 관한 책임을 지는가? 애플리케이션 중 한 애플리케이션이라면 어떤 것인가? 다른 사람들은 그 조직이 서비스를 소유해야 한다고 생각하는가? 서비스 소유권의 모호한 세계로 당신을 환영한다.

임의의 공유 리소스는 서비스 소유권이 neighborhood park, 재사용 자바 프레임워크 또는 서비스 제공 사업자 중 어떤 것인지 정보를 얻고 나타내는 게 쉽지 않다. 하지만 필요한 공동 리소스는 임의의 참여자가 지불한 비용 외의 값을 제공한다. 공용 도로 시스템을 생각해 보면 된다.

종종 기업은 자체적으로 비즈니스 운영에 있어 사원 보고구조 및 재정 등을 조직한다. SOA에서 그와 같은 동일운영을 하는 기업의 IT를 조직하는 경우에, 일정한 분야의 운영을 책임지는 부서는 비즈니스 운영에 있어 IT 개발 및 런타임에 대해서도 책임진다. 그 부서는 그와 같은 서비스를 소유한다. 하지만 SOA및 복합 애플리케이션은 기업의 엄격한 계층적 보고 및 재정 구조를 따르지 않고 IT 책무에 있어 갭 및 중복영역을 생성한다.

이와 관련된 문제는 사용자 역할이다. SOA는 IT 및 비스니스를 일치시키는 데 주로 중점을 두고 있고 기업 재활용에도 중점을 두고 있다. 조직에 있는 수많은 사람들은 서비스의 미래, 차후 서비스의 작동방식, 차후 서비스의 활용방식 등에 대해 얘기한다. 비즈니스 분석가, 기업 설계자, 소프트웨어 설계자, 소프트웨어 설계가 및 IT 관리자 등이 이와 같은 역할들을 맡는다. 모든 이런 역할들은 서비스가 기업의 필요를 충족시키고, 서비스가 제대로 작동되는지에 관한 여부에 대해 관련이 있다.

SOA로 기업의 비즈니스를 반영한다. 일반적으로, 이는 SOA를 기업에 맞게 변형시킨다는 것을 의미한다. 하지만 이와 같은 경우에서도, SOA에 맞는 비즈니스를 변화시키는 게 필요할 수도 있다. 이런 상황이 가능하지 않은 경우에는, 여러 부서간의 협력이 증대되어 공통 서비스 개발에 관한 짐을 함께 공유하는 것이 필요하다. 실지로, 서비스를 소유하고 이를 관리하는 조직간 상임위원회에서 이와 같은 협력을 이뤄낼 수 있다.

서비스 테스팅

서비스 전개 생명주기는 팀이 서비스를 사용하기 전 서비스가 제대로 작동하고 있다고 확인하는 기간인 테스트 단계를 포함한다. 서비스 제공 사업자가 서비스를 테스트해 제대로 작동하고 있다는 것을 입증하면, 소비자 또한 서비스를 테스트해야 할까? 모든 서비스 제공 사업자들이 동일하게 조건의 엄격한 적용을 통해 서비스를 테스트할까? 서비스가 변하면 서비스를 다시 재테스트할까?

SOA는 개개의 서비스 기능을 테스트할 기회 및 의도대로 서비스가 작동되는 것에 대한 가능성을 증가시킨다. 하지만 SOA는 또한 SOA에서 사용하는 서비스가 일관적으로 적절히 작동된다는 것을 그다지 믿지 않는 각각의 새로운 소비자들이 동일한 기능을 계속 테스트할 수 있는 기회를 제공한다. 반면, 복합 애플리케이션은 여러 서비스를 공유하기 때문에 단일 버그 서비스는 별로 관련이 없어 보이는 일정한 범위의 애플리케이션에 악영향을 줄 수도 있어, 프로그래밍 오류로 인한 결과가 확대될 수도 있다.

SOA에 관한 재사용 장점들을 더 살리기 위해서는 서비스 소비자 및 제공 사업자가 적절한 레벨의 서비스 제공 사업자 테스팅에 합의하고 합의한 대로 테스팅 수행을 확고히 해야 한다. 그런 다음, 서비스 소비자는 서비스 자체의 기능 및 서비스에 대한 연결만을 테스트하면 되고 아울러 광고에 나온 대로 서비스가 작동된다고 가정할 수 있다.

서비스 보안

아무라도 임의의 서비스를 호출할 수 있는가? 일정 사용자가 쓰는 서비스를 통해 모든 사용자가 모든 데이터를 접속하도록 해야 하나? 서비스 소비자 및 제공 사업자 간에 교환되는 데이터를 보호해야 할까? 서비스는 가장 의심이 많은 사용자나 가장 멍청한 사용자의 필요를 충족시킬 만큼 안전해야 할까?

보안이란 문제는 사실 어렵지만 임의의 애플리케이션에서의 필요충분조건이다. 인가된 사용자에게만 기능을 제한하고 정보 가로채기를 하지 못하도록 데이터를 보호해야 한다. SOA는 기능(즉, 서비스)에 대해 더 많은 액세스 포인트를 제공함으로써, 복합 애플리케이션에서의 취약성을 크게 증가시킬 가능성이 있기 때문이다.

SOA를 통해 심지어는 서비스를 재사용할 필요가 없는 소비자에 의해서도 쉽게 재사용 가능한 서비스를 생성한다. 인가된 사용자들 중에서조차도, 서비스를 통해 접속되는 모든 데이터에 대해 모든 사용자가 접속하는 것은 아니다. 예를 들어, 은행계좌를 처리하는 서비스의 경우, 코드를 통해 다른 사용자의 계좌로 접속된다 할지라도 특수 사용자 계좌만 이용가능하다. 데이터 기밀성, 무결성, 부인방지를 위해 동일한 서비스를 사용하는 다른 소비자에 비해 보안에 대한 필요가 훨씬 큰 소비자도 있다.

서비스 호출기술은 이러한 모든 보안기능을 제공할 수 있어야 한다. 허가된 소비자들에게만 서비스 접속을 허용해야 한다. 사용자 신원을 여러 서비스에 전달하고 사용해 데이터 접속을 허가한다. 데이터 보호에 대한 질을 범위 내의 정책으로 나타내야 한다. 이렇게 하면 소비자들은 최소한의 보호레벨 및 최대한의 기능을 표현하게 되고, 부가적인 지원기능을 포함하는 적절한 서비스 제공 사업자와 일치해 짝을 이루게 된다.




위로


요약: SOA 성공에 중요한 관리

이 글에서는 SOA 관리가 SOA를 사용하는 기업의 성공에 중요한 이유를 언급했다. 관리는 책무 수립 및 해당 당사자 권한 부여하기 등을 포함하는 반면 관리는 관리 정책이 실제로 일어나는지 여부를 확인하는 것을 포함한다. 관리 설정이 아닌 관리 수행을 위해 기술을 활용한다. 서비스를 호출하는 동안 관리되는 관리는 ESB에 의해 효과적으로 관리되어, 서비스 제공 사업자 및 소비자의 책무를 단순화한다.

SOA 관리는 다음을 포함해 많은 기능이 있다.

  • 서비스의 영역, 인터페이스 및 경계를 포함한 서비스 정의
  • 생명주기 단계를 포함한 서비스 전개 생명주기
  • 호환성을 포함한 서비스 비저닝
  • 사용중지 및 폐지 단계를 포함한 서비스 이전
  • 종속성을 포함한 서비스 레지스트리
  • 표준 데이터 모델을 포함한 서비스 메시지 모델
  • 문제 해결을 포함한 서비스 모니터링
  • 회사 조직을 포함한 서비스 소유권
  • 이중 테스팅을 포함한 서비스 테스팅
  • 여러 가지 허용되는 보호기능을 포함한 서비스 보안

이와 같은 각각의 기능에 관한 적절한 대처법에 대한 내용은 그 자체로 하나의 글이 될 수 있다.

감사의 글: 필자는 이 글에 정보를 제공해 준 IBM 동료인 Steve Graham, Arnauld Desprets, Randy Langel, Kerry Holley, All Arsanjani, Emily Plachy, Bob Vanorsdale, Jon Richter, Mandy Chessell, Mark Cocker, Mark Ernest, Steven Adler 및 Fill Bowen에게 감사의 말을 전하고 싶다.




위로


참조

다음은 유용한 참고자료 목록이다.

SOA 관리

서비스 정의

서비스 비저닝

서비스 레지스트리

서비스 메시지 모델

서비스 모니터링

서비스 소유권

서비스 테스팅

서비스 보안

기사의 원문보기




위로


참고자료




위로


필자소개

Bobby Woolf

Bobby Woolf는WebSphere에 관한 IBM 소프트웨어 서비스 임원이고 고객이 WebSphere 상품으로 성공을 이룰 수 있도록 도와주는 컨설턴트이기도 하다. 그는 Enterprise Integration Patterns(기업 통합 패턴) The Design Pattern Smalltalk Companion(설계패턴 스몰토크 동료) 의 공동저자다. Bobby는 고객이 IBM Rational Application Developer를 이용해 IBM WebSphere Application Server에 대한 애플리케이션을 개발하는 작업을 돕고 있고 다양한 컨퍼런스에서 종종 연사로 나가서 강의하기도 한다.(bwoolf@us.ibm.com

<출처 : http://www.ibm.com/developerworks/kr/library/ar-servgov.html#servdep >
      Service Oriented  |  2007. 3. 29. 22:42




[1편] SOA와 Service의 정의
[2편] BPM을 통한 서비스 분류하기
[3편] ESB를 이용하여 Service Enabling 하기
[4편] SOA 잘 돌리기(계획)

[3편] ESB를 이용하여 Service Enabling 하기

우리는 "[2편] BPM을 통한 서비스 분류하기"를 통해서 어떻게 서비스를 분류해 낼지에 대해 이야기를 했다. 실질적인 업무의 예를 들지 못한것이 아쉬움으로 남는다. - 추후 적절한 예시가 있으면 업데이트 하겠다.

3편에서는 둥실 둥실 떠있는 서비스 들을 어떻게  Enable 시킬 것인가?

예를 들면, 대출 신규 신청이란 어플리케이션이 있다고 가정하자.

이 업무를 수행하기 위해서
1. 고객정보 조회
2. 대출 신규신청
3. 고객 담보대출 신용도 조회
4. 대출 신규신청 취소
5. 승인 / 반려

위의 5가지 서비스가 도출 되었다고 가정하자.
기존의 방식으로 J2EE Application으로 구현한 경우 아래의 그림과 같이 될것이다.


사용자 삽입 이미지

기존방식으로 구현


J2EE 어플리케이션 내에서 복잡한 로직을 구현함으로 여러개의 비즈니스들과 타이트하게 연결되어 있다.

만일, 기존 서버스가 변경이 되면 어플리케이션에서 변경이 쉽지 않고, 대응 또한 쉽지 않다.

위와 같은 어플리케이션은 SOA가 추구하는 목적에 위배되는 구조이다.
사용자 삽입 이미지

SOA가 추구하는4가지 목표(from oracle)


(공동이용 가능한, 조립가능하고, 재사용가능하고, 약결합된...)

SOA가 추구하는 4가지 목표 에 위배되는 어플리케이션 구조이다.

그럼 위의 예를 SOA가 추구하는 목표에 부합되도록 변경해보자.

사용자 삽입 이미지

ESB를 사용한 구현

위의 그림은 ESB를 활용하여 <신규대출 신청>이란 업무를 재구성한 것이다.

이와 같이 J2EE App에서 ESB를 통해 서비스에 대한 결과를 얻을수 있고, 내부적인 비즈니스 서비스에 대한 연결은 ESB를 통하여 구현하면, <신규대출신청> 이란 어플리케이션과 각 서비스간의 Loosely Coupled한 구조로 연결될 수 있고, 또한 서비스의 재사용이 가능하며, <신규대출신청>이란 업무에 새로운 서비스가 추가 또는 삭제될 때에도 자유로이 대응할 수 있다.
자세히 표현되지는 않았지만, 기본적으로 ESB에서 서비스에 연결될때는 표준프로토콜을 사용하는 것이 일반적이다.( 특정 프로토콜이 사용되는 경우도 있다.)

ESB를 활용하여 구성된 서비스를 enabling 시킴으로서 SOA의 목표에 부합될 수 있는 환경을 구축할 수 있다.

      Service Oriented  |  2007. 3. 20. 11:17




[1편] SOA와 Service의 정의
[2편] BPM을 통한 서비스 분류하기(계획)
[3편] ESB를 이용하여 Service Enabling 하기(계획)
[4편] SOA 잘 돌리기(계획)


[1편] 에서  SOA와 Service의 정의에 대해 알아봤다.

그럼 이제 그 까탈스러운 서비스를 어떻게 도출해 낼것인가! 그 방법에 대해서 이야기 하자.

1) 서비스 도출 방법

사용자 삽입 이미지

Process Hierachy


 기본 사상은 이렇다.
해당 업무에 대한 메가 프로세스
                                       |-- 프로세스 체인
                                                    |--------프로세스
                                                                    |------- 서비스
                                                                                   |----- 기능

이러한 단계로 접근한다.

언뜻봐도.. 프로세스 적인 접근이다.- 다시말하면 BPM적인 접근이란 것임

왜 서비스를 접근 할때 뜬금없이 BPM적인 접근이냐? 라고 반문하는 사람도 많을 것이다.

2) SOA의 접근방법
일반적으로 , SOA를 접근하는 방법에는 두가지다.

Top-Down 방식 과 Bottom-Up방식 (관련토론)이다.- 아래 그림 참조
사용자 삽입 이미지

Top-Down방식(source:IBM)

사용자 삽입 이미지

Bottom-Up (source:IBM)




























그림에서 보시면 아시겠지만..

1)Top-Down 방식은 Business Process에서 부터 접근을 하고, 2)Bottom-Up방식은 존재하는 중요 어플리케이션에서부터 출발을 한다.

다시 이야기  하자면 1) 번 방식은 비즈니스 현황 분석을 통해서 하위의 서비스로 접근하는 방식이고,
2)번 방식은 존재하는 중요 어플리케이션을 통해 서비스가 될만한 것이 무엇인지 접근하는 방식이다.

여기서, 1편에서 언급했던 CBD에 대한 기억이 떠오른다.

2001년 한참 CBD기반 프로젝트를 하던중  "Component Size에 대한 이슈"
- 도대체 어디까지 컴포넌트로 봐야하는거야?
- 이거 컴포넌트가 너무 작은거 아냐? 또는 너무 큰거아냐?
- 적당한 사이즈로 가야지...!

만일 Service도 중요 어플리케이션을 서비스의 대상으로 삼고 접근한다면... 위의 예와 같은 문제에 봉착할 것이다.

여기서 다시한번 상기하자!

SOA의 목표를!!  "비즈니스에 대한 IT의 민첩성을 증대하는것!"

사용자 삽입 이미지

SOA의 필요성


3) SOA와 BPM의 관계

필자는 BPM은 SOA를 가능하게 하는 Key Solution이라는 생각이다.
사용자 삽입 이미지

BPM과 SOA의 관계

<출처 :IBM>

4) Summary
 
  최근 기업은 다품종 소량생산이라는 변화 속에서 고객 Needs에 맞도록 비즈니스가 변화해야하는 과제를 안고있다. 이와 같은 기업환경은 IT에게도 비즈니스에 따른 변화를 요구하고 있다.

기업은 주기적인 신제품을 출시해야하고, 사용자 트랜드의 변화에 대응할수 있는 상품을 출시해야한다.
기업 업무가 IT 기반으로 이루어 짐으로 IT가 대응해주지 못하면 변화된 비즈니스를 창출 할 수 없는것이 현실이다. 
또한 변경된 비즈니스에 대해서 최적화되었는지?
                 비즈니스가 변경됨에 따라 어떤 이득이 있었는지?
                 비즈니스가 앞으로 어떻게 변화 될 것인지?
등에 대한 평가 및 예측이 가능해야 할 것이다.
이러한 부분을 Architecture 만으로 극복해 낼 수는 없을 것이다.
BPM을 통해 분석과 예측이 가능한 시스템으로 진화 해야 할 것이다.

따라서, 필자는 위의 1,2 번에서 언급했던것 처럼 SOA의 접근은 프로세스 기반으로 접근해야 한다라고 생각한다.

결국 ," BPM Based SOA"만이 비즈니스에 대한 IT의 적절한 대안이 될것이다.


  
      Service Oriented  |  2007. 3. 15. 17:50




[1편] SOA와 Service의 정의
[2편] BPM을 통한 서비스 분류하기(계획)
[3편] ESB를 이용하여 Service Enabling 하기(계획)
[4편] SOA 잘 돌리기(계획)
IT 세상은 "SOA"라는 세글자를 외치는 벤더들로 북적이고 있다.

요즘하는 프로젝트는 왠만하면 SOA 기반이다.

어떤것이 SOA 기반인가?

1. Service Oriented 해야한다.
  
2. 비즈니스에 대한 민첩성을 가져야 한다.

3. 재사용성을 가지고 있어야 한다.

등등.....  많은 의미들을 담고 있다.

그럼 여기서 잠깐 SOA의 정의 대해서 정리를 해보자.
관점: SOA란..
비즈니스 경영자 또는 비즈니스 분석가 IT 자산들(기능들)을 구성하고 솔루션을 구현하고 이들을 고객과 파트너에게 노출하는데 사용될 수 있는 서비스 세트이다.
엔터프라이즈 아키텍트 모듈성, 캡슐화, 약결합, 영역의 분리, 재사용, 구성 등, 솔루션의 전체적인 특성을 다루는 아키텍처 원리와 패턴이다.
프로젝트 매니저 거대한 병렬 개발을 지원하는 개발 방식이다.
테스터 또는 품질 보증 엔지니어 전체적인 시스템 테스팅을 모듈화 하고 단순화 하는 방식이다.
소프트웨어 개발자 웹 서비스 같은 표준, 툴, 기술들을 겸비한 프로그래밍 모델이다.

[출처]: SOA를 아키텍처 스타일로서 정의하기

위의 정의 처럼 SOA는 어떤 Role에서 바라보느냐에 따라 각각 다르다.

위에서 나열한 1,2,3 번의 의미는 광범위한 정의라 해야 하겠다.

SOA가 목적하는 바 또는 화두로 떠오르는 된 것은 비즈니스의 변화( 시대의 변화, 사용자의 변화, 소비 구조의 변화등..) 에 IT가 적절하게 대응하지 못하는 데 있다.

이렇게 민첩하지 못한 IT에 날개를 달고자 SOA가 등장한 것이다.

그 의도는 IT의 매래와 발전에 활력소를 제공하지만, 그것을 구체화 시켜야 하는 입장에서는 쉽게 손이 가지 않는다.
첫째, Service 가 무엇인가?
사용자 삽입 이미지

조삼모사



한참 SOA에 대한 고민하던 시절 (지난해로 기억된다.) 필자가 유행하던 조삼모사를 패러디한것이다.

개발자 커뮤니티인 okjsp에도 올렸지만, 별 호응은 없었다..(내심 재미있어서 올렸건만)

이렇듯, 고객도 IT 업체도 무엇이 서비스 인지 확실하게 언급을 못했다.

따라서 Service Oriented가 가능 할 수 있으랴?

그럼 서비스의 특징에 대해서 알아 보자.

서비스는 

"플랫폼에 종속되지 않는 표준 인터페이스를 통해서 기업의 업무를 표현한 Loosely Coupled 하고 상호 조합 가능한 소프트웨어 컴포넌트"

출처 : 조대협님의 JCO 발표자료

[서비스의 특징]
1. Re-usable (재사용성)
   -  Business에 대한 민첩성을 높이기 위해서 Business Process가 추가 또는 변경되었을 때 기존 자원을 활용할 수 있도록 하기 위함.

2. Contract-Based(계약 기반)
   - 서비스 Repository 사용시에 어떤 서비스가 어떤 내용을 가지는에 대한 정보를 알수 있도록 한다.

3. Self Contained and Modular (자급자족해야하고, 모듈화 되어야한다.)
   - 독립성을 확보하기위해 다른 서비스에 의존성을 배제하고, 가용성을 높이기 위해 모듈화 되어야한다.

4. Loosely Coupled (약결합)
   - 기존의 어플리케이션이 강결합(Tightly Coupled) 을 가짐으로 민첩성을 발휘할 수 없었다. 따라서 Service는 조합이 가능하도록 약결합되어야 한다.
  - 구현체에 독립적인 인터페이스를 가져야 한다.

5. Discoverable ( 발견할 수 있어야 한다)
   - Registry에 metadata/ semantic 을 가지고 등록되어야 한다.
   - 위치에 상관없이 찾을 수 있어야 한다.

참으로 까탈스러운 서비스라 하지 않을 수 없다.

하지만, 이 조건을 만족하지 못한다면.... SOA 기반이란 이름으로 구축하더라도.. 그 효능을 찾을 수 없을 것이다.

단, 이러한 서비스는 예전에 CBD 에서 이야기 하는 Component 와는 그 성격과 정의가 다른 것이다.

"WORA(Write once, run anywhere)"라는 개념을 탑재하지 않고 있다는 것이다.

서비스는 각 업무 도메인 별로 그 의미가 다르다는 것이다.


[P.S] 본 내용은 필자의 개인적인 사상에 입각하여 정리한 내용이니, 내용에 대해서 지적해 주시거나,
         태클을 거실분들은 확실히 걸어주시면 감사하겠습니다.
      Service Oriented  |  2007. 3. 14. 17:22



archidream's Blog is powered by Daum