์‹œ์Šคํ…œ(System)

๋ณต์žก์„ฑ์€ ์ฃฝ์Œ์ด๋‹ค. ๊ฐœ๋ฐœ์ž์—๊ฒŒ์„œ ์ƒ๊ธฐ๋ฅผ ์•—์•„๊ฐ€๋ฉฐ, ์ œํ’ˆ์„ ๊ณ„ํšํ•˜๊ณ  ์ œ์ž‘ํ•˜๊ณ  ํ…Œ์ŠคํŠธํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ ๋‹ค.

์‹œ์Šคํ…œ ์ œ์ž‘๊ณผ ์‹œ์Šคํ…œ ์‚ฌ์šฉ์„ ๋ถ„๋ฆฌํ•˜๋ผ.

  • ์†Œํ”„ํŠธ์›จ์–ด ์‹œ์Šคํ…œ์€ ์ค€๋น„ ๊ณผ์ •๊ณผ ๋Ÿฐํƒ€์ž„ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
  • ์‹œ์ž‘ ๋‹จ๊ณ„๋Š” ๋ชจ๋“  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ’€์–ด์•ผ ํ•  ๊ด€์‹ฌ์‚ฌ์ด๋‹ค.
  • ๊ด€์‹ฌ์‚ฌ ๋ถ„๋ฆฌ๋Š” ์šฐ๋ฆฌ ๋ถ„์•ผ์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋˜๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์„ค๊ณ„ ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜๋‹ค.
public Service getService() {
    if (service == null)
        service = new MyServiceImpl(...); // ๋ชจ๋“  ์ƒํ™ฉ์— ์ ํ•ฉํ•œ ๊ธฐ๋ณธ๊ฐ’์ผ๊นŒ?
    return service;
}

์ดˆ๊ธฐํ™” ์ง€์—ฐ(Lazy Initialization) ํ˜น์€ ๊ณ„์‚ฐ ์ง€์—ฐ(Lazy Evalution)์ด๋ผ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. ์‹ค์ œ๋กœ ํ•„์š”ํ•  ๋•Œ๊นŒ์ง€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆํ•„์š”ํ•œ ๋ถ€ํ•˜๊ฐ€ ์—†์–ด์ง„๋‹ค. ๋”ฐ๋ผ์„œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹œ์ž‘ํ•˜๋Š”๋ฐ ์•„์ฃผ ๋น ๋ฅด๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ์—๋„ null์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํ•˜์ง€๋งŒ ์„œ๋น„์Šค๋Š” MyServiceImpl ํด๋ž˜์Šค์— ์˜์กดํ•˜๊ฒŒ ๋œ๋‹ค. MyServiceImpl์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ์˜์กด์„ฑ์„ ํ•ด๊ฒฐํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ์ด ์•ˆ๋˜๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰์—๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

๋งŒ์•ฝ MyServiceImpl ๊ฐ์ฒด๊ฐ€ ๋ฌด๊ฑฐ์šด ๊ฐ์ฒด๋ผ๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ Mock Object๋ฅผ serviceํ•„๋“œ์— ๋Œ€์ž…ํ•ด์•ผ ํ•˜๋ฉฐ, ์ด๋Š” ๊ธฐ์กด์˜ runtime ๋กœ์ง์— ๊ด€์—ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋„ ๋ฐœ์ƒํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ์ƒ์„ฑ/์‚ฌ์šฉ์˜ ๋ถ„์‚ฐ์€ ๋ชจ๋“ˆ์„ฑ์„ ์ €ํ•ดํ•˜๊ณ  ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ ์ž˜ ์ •๋ˆ๋œ ๊ฒฌ๊ณ ํ•œ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ „์—ญ์ ์ด๊ณ  ์ผ๊ด€๋œ ์˜์กด์„ฑ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ์œ„์™€ ๊ฐ™์€ ์ž‘์€ ํŽธ์˜ ์ฝ”๋“œ๋“ค์ด ๋ชจ๋“ˆ์„ฑ์˜ ์ €ํ•ด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ๋ง‰์•„์•ผ ํ•œ๋‹ค.

Main ๋ถ„๋ฆฌ

์•„๋ž˜์˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ์ƒ์„ฑ๊ณผ ๊ด€๋ จ๋œ ์ฝ”๋“œ๋Š” ๋ชจ๋‘ main์ด๋‚˜ main์ด ํ˜ธ์ถœํ•˜๋Š” ๋ชจ๋“ˆ๋กœ ์˜ฎ๊ธฐ๊ณ  ๋‚˜๋จธ์ง€ ์‹œ์Šคํ…œ์€ ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ๊ณ  ๋ชจ๋“  ์˜์กด์„ฑ์ด ์—ฐ๊ฒฐ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

ํŒฉํ† ๋ฆฌ(Factory)

์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ์ƒ์„ฑ์— ๊ด€๋ จ๋œ ๋ถ€๋ถ„์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฒฐ์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ๊ทธ๋Ÿฐ ๋ถ€๋ถ„์€ Factory Pattern์„ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฒฐ์ •ํ•˜์ง€๋งŒ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์˜ ์—ฐ๊ด€์„ฑ์„ ์ œ๊ฑฐํ•œ๋‹ค.

์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)

์ œ์–ด ์—ญ์ „(Inversion of Control IOC)์„ ์ ์šฉํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค. ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ์ฑ…์ž„์„ ์ง€๋Š” main์ด๋‚˜ ํŠน์ˆ˜ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณดํ†ต setter๋ฉ”์„œ๋“œ๋‚˜ ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค.

๊ฐ€์žฅ ๋„๋ฆฌ ์•Œ๋ ค์ง„ ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ๋Š” ์ž๋ฐ” DI ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ๊ฐ์ฒด ์‚ฌ์ด ์˜์กด์„ฑ์€ XML์„ ํ†ตํ•ด ์ •์˜ ๋œ๋‹ค.

ํ™•์žฅ

๋‚ด์ผ์€ ์ƒˆ๋กœ์šด ์Šคํ† ๋ฆฌ์— ๋งž์ถฐ ์‹œ์Šคํ…œ์„ ์กฐ์ •ํ•˜๊ณ  ํ™•์žฅํ•˜๋ฉด ๋œ๋‹ค. ์ด๊ฒƒ์ด ๋ฐ˜๋ณต์ ์ด๊ณ  ์ ์ง„์ ์ธ ์• ์ž์ผ ๋ฐฉ์‹์˜ ํ•ต์‹ฌ์ด๋‹ค. ๊นจ๋—ํ•œ ์ฝ”๋“œ๋Š” ์ฝ”๋“œ ์ˆ˜์ค€์—์„œ ์‹œ์Šคํ…œ์„ ์กฐ์ •ํ•˜๊ณ  ํ™•์žฅํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ ๋‹ค.

์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” EJB2๋ฅผ ์ƒ์†๋ฐ›์•„ ๊ตฌํ˜„ํ•œ Bussiness Logic์ด๋‹ค.

/* Code 2-1(Listing 11-1): An EJB2 local interface for a Bank EJB */
package com.example.banking;
import java.util.Collections;
import javax.ejb.*;
public interface BankLocal extends java.ejb.EJBLocalObject {
 String getStreetAddr1() throws EJBException;
 String getStreetAddr2() throws EJBException;
 String getCity() throws EJBException;
 String getState() throws EJBException;
 String getZipCode() throws EJBException;
 void setStreetAddr1(String street1) throws EJBException;
 void setStreetAddr2(String street2) throws EJBException;
 void setCity(String city) throws EJBException;
 void setState(String state) throws EJBException;
 void setZipCode(String zip) throws EJBException;
 Collection getAccounts() throws EJBException;
 void setAccounts(Collection accounts) throws EJBException;
 void addAccount(AccountDTO accountDTO) throws EJBException; }
 /* Code 2-2(Listing 11-2): The corresponding EJB2 Entity Bean Implementation */
 package com.example.banking;
 import java.util.Collections;
 import javax.ejb.*;
 public abstract class Bank implements javax.ejb.EntityBean {
   // Business logic...
   public abstract String getStreetAddr1();
   public abstract String getStreetAddr2();
   public abstract String getCity();
   public abstract String getState();
   public abstract String getZipCode();
   public abstract void setStreetAddr1(String street1);
   public abstract void setStreetAddr2(String street2);
   public abstract void setCity(String city);
   public abstract void setState(String state);
   public abstract void setZipCode(String zip);
   ublic abstract Collection getAccounts();
   public abstract void setAccounts(Collection accounts);
   public void addAccount(AccountDTO accountDTO) {
    InitialContext context = new InitialContext();
    AccountHomeLocal accountHome = context.lookup("AccountHomeLocal");
    AccountLocal account = accountHome.create(accountDTO);
    Collection accounts = getAccounts(); accounts.add(account);
    }
    // EJB container logic public
    abstract void setId(Integer id);
    public abstract Integer getId();
    public Integer ejbCreate(Integer id) { ... }
    public void ejbPostCreate(Integer id) { ... }
    // The rest had to be implemented but were usually empty:
    public void setEntityContext(EntityContext ctx) {}
    public void unsetEntityContext() {}
    public void ejbActivate() {}
    public void ejbPassivate() {}
    public void ejbLoad() {}
    public void ejbStore() {}
    public void ejbRemove() {}
   }

์œ„์— ์ฝ”๋“œ๋Š” EJB2์˜ ์ปจํ…Œ์ด๋„ˆ์— ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋œ๋‹ค. ํ•„์š”์—†๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์†๋ฐ›์•„์•ผ ํ•˜๋ฉฐ ๋ฉ๊ทธ๋Ÿฌ๋‹ˆ ๋‚จ์•„์žˆ๋‹ค. ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ผ๋Š” ๊ฐœ๋…์กฐ์ฐจ ๋ฟŒ๋ฆฌ๊ฐ€ ํ”๋“ค๋ฆฐ๋‹ค.

ํšก๋‹จ(cross-cutting) ๊ด€์‹ฌ์‚ฌ

EJB2๋Š” ๊ด€์‹ฌ์‚ฌ๋ฅผ ๊ฑฐ์˜ ์™„๋ฒฝํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•ด ๋ƒˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŠธ๋žœ์žญ์…˜, ๋ณด์•ˆ, ์ผ๋ถ€ ์˜์†์ ์ธ ๋™์ž‘๊นŒ์ง€ ๋ถ„๋ฆฌํ•ด๋ƒˆ๋‹ค. ์ด๋Ÿฐ ๊ด€์  ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Aspect-Oriented Programming AOP)์„ ์˜ˆ๊ฒฌํ–ˆ๋‹ค๊ณ  ๋ณด์ธ๋‹ค.

์ž๋ฐ” ํ”„๋ก์‹œ

  • ์ž๋ฐ” ํ”„๋กœ์‹œ๋Š” ๋‹จ์ˆœํ™˜ ์ƒํ™ฉ์— ์ ํ•ฉํ•˜๋‹ค. ๊ฐœ๋ณ„ ๊ฐ์ฒด๋‚˜ ํด๋ž˜์Šค์—์„œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ์„ ๊ฐ์‹ธ๋Š” ๊ฒฝ์šฐ๋Š” ์ข‹์€ ์˜ˆ๋‹ค.
  • ํ”„๋กœ์‹ API์—๋Š” InvocationHandler๋ฅผ ๋„˜๊ฒจ ์ค˜์•ผ ํ•œ๋‹ค.
  • ์ฝ”๋“œ๋Š” ์ƒ๋‹นํžˆ ๋งŽ์œผ๋ฉฐ ์ œ๋ฒ• ๋ณต์žกํ•˜๋‹ค. โ†’ ๊นจ๋—ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์–ด๋ ต๋‹ค.

์ˆœ์ˆ˜ ์ž๋ฐ” AOP ํ”„๋ ˆ์ž„ ์›Œํฌ

์œ„์˜ ๊ทธ๋ฆผ์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

/* Code 3-3: Code 3-2์˜ ํ™œ์šฉ๋ฒ• */
 
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("app.xml", getClass()));
Bank bank = (Bank) bf.getBean("bank");

๊ตฌ์กฐ ์ •์˜๋ฅผ ์œ„ํ•œ xml์€ ๋‹ค์†Œ ์žฅํ™ฉํ•˜๊ณ  ์ฝ๊ธฐ ํž˜๋“ค ์ˆ˜๋Š” ์žˆ์ง€๋งŒ Java Proxy๋ณด๋‹ค๋Š” ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๋‹ค. ์ด ๊ฐœ๋…์€ ์•„๋ž˜์— ์„ค๋ช…ํ•  EJB3์˜ ๊ตฌ์กฐ ๊ฐœํŽธ์— ํฐ ์˜ํ–ฅ์„ ๋ฏธ์ณค๋‹ค. EJB3์€ xml์™€ Java annotation์„ ์‚ฌ์šฉํ•ด cross-cutting concerns๋ฅผ ์ •์˜ํ•˜๊ณ  ์„œํฌํŠธํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

์•„๋ž˜์™€ ๊ฐ™์ด EJB2๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฝ”๋“œ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฒฐํ•ฉ๋„๊ฐ€ ๋‚ฎ์•„์ง„ ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

/* Code 3-4(Listing 11-5): An EBJ3 Bank EJB */
 
package com.example.banking.model;
 
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
 
@Entity
@Table(name = "BANKS")
public class Bank implements java.io.Serializable {
    @Id @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;
 
    @Embeddable // An object โ€œinlinedโ€ in Bankโ€™s DB row
    public class Address {
        protected String streetAddr1;
        protected String streetAddr2;
        protected String city;
        protected String state;
        protected String zipCode;
    }
 
    @Embedded
    private Address address;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="bank")
    private Collection<Account> accounts = new ArrayList<Account>();
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public void addAccount(Account account) {
        account.setBank(this);
        accounts.add(account);
    }
 
    public Collection<Account> getAccounts() {
        return accounts;
    }
 
    public void setAccounts(Collection<Account> accounts) {
        this.accounts = accounts;
    }
}
  • ์˜์†์„ฑ ์ •๋ณด๋Š” ํ•„์š”ํ•˜๋‹ค๋ฉด XML๋ฐฐ์น˜ ๊ธฐ์ˆ ์ž๋กœ ์˜ฎ๊ฒจ๋„ ๊ดœ์ฐฎ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์ˆœ์ˆ˜ํ•œ POJO๋งŒ ๋‚จ๋Š”๋‹ค.

AspectJ ๊ด€์ 

  • AspectJ๋Š” AOP๋ฅผ ์‹คํ˜„ํ•˜๊ธฐ ์œ„ํ•œ full-featured tool์ด๋ผ ์ผ์ปฌ์–ด์ง„๋‹ค.
  • 8~90%์˜ ๊ฒฝ์šฐ์—๋Š” Spring AOP์™€ JBoss AOP๋กœ๋„ ์ถฉ๋ถ„ํ•˜์ง€๋งŒ AspectJ๋Š” ํ›จ์”ฌ ๊ฐ•๋ ฅํ•œ ์ˆ˜์ค€์˜ AOP๋ฅผ ์ง€์›ํ•œ๋‹ค.
  • ๋‹ค๋งŒ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ํˆด, ์–ธ์–ด ๊ตฌ์กฐ, ๊ด€์Šต์ ์ธ ์ฝ”๋“œ๋ฅผ ์ตํ˜€์•ผ ํ•œ๋‹ค๋Š” ๋‹จ์ ๋„ ์กด์žฌํ•œ๋‹ค.
  • ์ตœ๊ทผ ์†Œ๊ฐœ๋œ โ€œannotation-form AspectJโ€๋กœ ์ธํ•ด ์ ์šฉ์— ํ•„์š”ํ•œ ๋…ธ๋ ฅ์€ ๋งŽ์ด ์ค„์–ด๋“ค์—ˆ๋‹ค๊ณ  ํ•œ๋‹ค.
  • AOP์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ [AspectJ], [Colyer], [Spring]๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค.

ํ…Œ์ŠคํŠธ ์ฃผ๋„ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์ถ•

  • ์ฝ”๋“œ ๋ ˆ๋ฒจ์—์„œ๋ถ€ํ„ฐ ์•„ํ‚คํ…์ณ์™€ ๋ถ„๋ฆฌ๋œ(decouple๋œ) ํ”„๋กœ๊ทธ๋žจ ์ž‘์„ฑ์€ ๋‹น์‹ ์˜ ์•„ํ‚คํ…์ณ๋ฅผ test driveํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค์–ด ์ค€๋‹ค.
  • ์ฒ˜์Œ์—๋Š” ์ž‘๊ณ  ๊ฐ„๋‹จํ•œ ๊ตฌ์กฐ์—์„œ ์‹œ์ž‘ํ•˜์ง€๋งŒ ํ•„์š”์— ๋”ฐ๋ผ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์„ ์ถ”๊ฐ€ํ•ด ์ •๊ตํ•œ ์•„ํ‚คํ…์ณ๋กœ ์ง„ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋˜ํ•œ decouple๋œ ์ฝ”๋“œ๋Š” user story, ๊ทœ๋ชจ ๋ณ€ํ™”์™€ ๊ฐ™์€ ๋ณ€๊ฒฝ์‚ฌํ•ญ์— ๋” ๋น ๋ฅด๊ฒŒ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์šฐ๋ฆฌ๋ฅผ ๋„์™€ ์ค€๋‹ค.
  • ๋„๋ฆฌ์–ด BDUF(Big Design Up First)์™€ ๊ฐ™์€ ๋ฐฉ์‹์€ ๋ณ€๊ฒฝ์ด ์ƒ๊ธธ ๊ฒฝ์šฐ ๊ธฐ์กด์˜ ๊ตฌ์กฐ๋ฅผ ๋ฒ„๋ ค์•ผ ํ•œ๋‹ค๋Š” ์‹ฌ๋ฆฌ์  ์ €ํ•ญ, ์•„ํ‚คํ…์ณ์— ๋”ฐ๋ฅธ ๋””์ž์ธ์— ๋Œ€ํ•œ ๊ณ ๋ฏผ ๋“ฑ ๋ณ€ํ™”์— ์œ ์—ฐํ•˜์ง€ ๋ชปํ•œ ๋‹จ์ ๋“ค์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋œ๋‹ค.

์ด์ƒ์ ์ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ณ๋Š” ๊ฐ๊ฐ POJO๋กœ ๋งŒ๋“ค์–ด์ง„ ๋ชจ๋“ˆํ™”๋œ ๊ด€์‹ฌ ๋ถ„์•ผ ์˜์—ญ(modularized domains of concern)์œผ๋กœ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•œ๋‹ค. ๋‹ค๋ฅธ ์˜์—ญ๋ผ๋ฆฌ๋Š” Aspect์˜ ๊ฐœ๋…์„ ์‚ฌ์šฉํ•ด ์ตœ์†Œํ•œ์˜ ๊ฐ„์„ญ์œผ๋กœ ํ†ตํ•ฉ๋˜์–ด์•ผ ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ์•„ํ‚คํ…์ณ๋Š” ์ฝ”๋“œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ test-driven๋  ์ˆ˜ ์žˆ๋‹ค.

์˜์‚ฌ ๊ฒฐ์ •์„ ์ตœ์ ํ™”ํ•˜๋ผ

์ถฉ๋ถ„ํžˆ ํฐ ์‹œ์Šคํ…œ์—์„œ๋Š”(๊ทธ๊ฒƒ์ด ๋„์‹œ์ด๊ฑด ์†Œํ”„ํŠธ์›จ์–ด์ด๊ฑด) ํ•œ ์‚ฌ๋žŒ์ด ๋ชจ๋“  ๊ฒฐ์ •์„ ๋‚ด๋ฆด ์ˆ˜๋Š” ์—†๋‹ค. ๊ฒฐ์ •์€ ์ตœ๋Œ€ํ•œ ๋งŽ์€ ์ •๋ณด๊ฐ€ ๋ชจ์ผ ๋•Œ๊นŒ์ง€ ๋ฏธ๋ฃจ๊ณ  ์‹œ๊ธฐ๊ฐ€ ๋˜์—ˆ์„ ๊ฒฝ์šฐ ํ•ด๋‹น ํŒŒํŠธ์˜ ์ฑ…์ž„์ž(์—ฌ๊ธฐ์„œ๋Š” ์‚ฌ๋žŒ์ด ์•„๋‹Œ ๋ชจ๋“ˆํ™”๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋œปํ•œ๋‹ค)์—๊ฒŒ ๋งก๊ธฐ๋Š” ๊ฒƒ์ด ๋ถˆํ•„์š”ํ•œ ๊ณ ๊ฐ ํ”ผ๋“œ๋ฐฑ๊ณผ ๊ณ ํ†ต์„ ๋œ์–ด์ค„ ๊ฒƒ์ด๋‹ค.

๋ชจ๋“ˆํ™”๋œ ๊ด€์‹ฌ ๋ถ„์•ผ๋กœ ์ด๋ฃจ์–ด์ง„ POJO ์‹œ์Šคํ…œ์˜ (๋ณ€ํ™”์— ๋Œ€ํ•œ)๋ฏผ์ฒฉํ•จ์€ ๊ฐ€์žฅ ์ตœ์‹ ์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์ ์‹œ์— ์ตœ์ ์˜ ์„ ํƒ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค€๋‹ค. ๊ฒฐ์ •์— ํ•„์š”ํ•œ ๋ณต์žก๋„ ๋˜ํ•œ ๊ฒฝ๊ฐ๋œ๋‹ค.

๋ช…๋ฐฑํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ์„ ๋•Œ ํ‘œ์ค€์„ ํ˜„๋ช…ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ผ

๋งŽ์€ ์†Œํ”„ํŠธ์›จ์–ด ํŒ€๋“ค์€ ํ›จ์”ฌ ๊ฐ€๋ณ๊ณ  ์ง๊ด€์ ์ธ ๋””์ž์ธ์ด ๊ฐ€๋Šฅํ–ˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๊ทธ์ € ํ‘œ์ค€์ด๋ผ๋Š” ์ด์œ ๋งŒ์œผ๋กœ EJB2 ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ํ‘œ์ค€์— ์‹ฌ์ทจํ•ด โ€œ๊ณ ๊ฐ์„ ์œ„ํ•œ ๊ฐ€์น˜ ์ฐฝ์ถœโ€์ด๋ผ๋Š” ๋ชฉํ‘œ๋ฅผ ์žƒ์–ด ๋ฒ„๋ ธ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ‘œ์ค€์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„์ด๋””์–ด์™€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ , ์ ์ ˆํ•œ ๊ฒฝํ—˜์„ ๊ฐ€์ง„ ์‚ฌ๋žŒ์„ ๊ตฌํ•˜๊ธฐ ์‰ฌ์šฐ๋ฉฐ ์ข‹์€ ์•„์ด๋””์–ด๋ฅผ ์บก์Šํ™”ํ•˜๊ธฐ ์‰ฝ๊ณ , ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—ฎ๊ธฐ ์‰ฝ๋‹ค.

์‹œ์Šคํ…œ์€ ๋„๋ฉ”์ธ ํŠนํ™” ์–ธ์–ด๊ฐ€ ํ•„์š”ํ•˜๋‹ค

์ข‹์€ DSL์€ ๋„๋ฉ”์ธ ์˜์—ญ์˜ ๊ฐœ๋…๊ณผ ์‹ค์ œ ๊ตฌํ˜„๋  ์ฝ”๋“œ ์‚ฌ์ด์˜ ์†Œํ†ต์˜ ๊ฐ„๊ทน์„ ์ค„์—ฌ ๋„๋ฉ”์ธ ์˜์—ญ์„ ์ฝ”๋“œ ๊ตฌํ˜„์œผ๋กœ ๋ฒˆ์—ญํ•˜๋Š” ๋ฐ์— ์˜ค์—ญ์„ ์ค„์—ฌ์ค€๋‹ค. DSL์„ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ ๋ฉ์–ด๋ฆฌ์™€ ๋””์ž์ธ ํŒจํ„ด์˜ ์ถ”์ƒ๋„๋ฅผ ๋†’์—ฌ ์ฃผ๋ฉฐ ๊ทธ์— ๋”ฐ๋ผ ์ฝ”๋“œ์˜ ์˜๋„๋ฅผ ์ ์ ˆํ•œ ์ถ”์ƒํ™” ๋ ˆ๋ฒจ์—์„œ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

DSL์€ โ€œ๋ชจ๋“  ๋‹จ๊ณ„์—์„œ์˜ ์ถ”์ƒํ™”โ€์™€ โ€œ๋ชจ๋“  ๋„๋ฉ”์ธ์˜ POJOํ™”โ€๋ฅผ ๊ณ ์ฐจ์›์  ๊ทœ์น™๊ณผ ์ €์ฐจ์›์  ๋””ํ…Œ์ผ ์ „๋ฐ˜์— ๊ฑธ์ณ ๋„์™€ ์ค€๋‹ค.

๊ฒฐ๋ก 

์‹œ์Šคํ…œ์€ ๊นจ๋—ํ•ด์•ผ ํ•˜๋ฉฐ ๋ชจ๋“  ์ถ”์ƒํ™” ๋‹จ๊ณ„์—์„œ ์˜๋„๋Š” ๋ช…ํ™•ํžˆ ํ‘œํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

Reference