728x90
반응형

[Spring Framework] Annotation-based Configuration이란? Spring 설정을 더 간결하게!

 

[Spring Framework] Annotation-based Configuration이란? Spring 설정을 더 간결하게!

[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI [Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI[Spring Framework] 스프링 IoC 컨테이너 이해

crushed-taro.tistory.com

1. Dependency Injection

1. Dependency Injection이란?

1. Dependency Injection

Dependency Injection(의존성 주입, 이하 DI)은 객체 간의 의존 관계를 빈 설정 정보를 바탕으로 컨테이너가 자동적으로 연결해주는 것을 말한다. 이를 통해 객체 간의 결합도를 낮출 수 있으며 이로 인해 유지보수성과 유연성이 증가한다.

 

2. 의존 관계와 결합도

public class A {
	
	private B b = new B();

}

public class B {

}

class A가 class B를 필드로 가질 때 A는 B에 의존하게 된다.

public class A {

	/* 컴파일 에러 발생 */
	private B b = new B();

}

/* 클래스명이 B에서 NewB로 변경 */
public class NewB {
	
}

존성이 강하다는 것은 한 객체가 변경되면 이에 의존하는 다른 객체들도 함께 변경되어야 한다는 것을 의미한다.B가 NewB 로 변경되면 해당 클래스를 필드로 가지고 있는 A 도 변경되어야 할 것이다. 이처럼 객체 간의 의존 관계가 강하게 묶여있을 때 결합도 가 높다고 표현한다. 이로 인해 유지보수성과 유연성이 저하될 수 있다.

public class A {

	/* 상위 타입을 필드로 설정 */
	private B b;

	/* 직접 객체를 생성하지 않고 생성자를 통해 전달 받음 */
	public A(B b) {
		this.b = b;
	}

}

/* 상위 타입으로 사용할 인터페이스 */
public interface B {

}

/* 인터페이스의 구현 클래스 */
public class NewB implements B {

}

이전의 코드와 비교하면 NewB 라는 구체적인 구현체의 타입을 사용하는 대신 B 라는 상위 인터페이스 타입으로 필드를 선언했다. 또한 직접 객체를 생성하는 구문도 없어졌고 생성자를 통해 전달 받도록 했다. 이렇게 변경하면 실제로 사용하는 구현체가 NewB 에서 또 다른 타입으로 변경 되더라도 A 의 코드는 변경 될 필요가 없다. 의존 관계가 느슨해지고 결합도가 낮아졌다고 할 수 있다.

 

2. DI 방법 알아보기

아래 코드는 테스트에 공통적으로 사용 할 AccountPersonalAccountMemberDTO 클래스이다.

  • Account
public interface Account {

    /* 잔액 조회 */
    String getBalance();

    /* 입금 */
    String deposit(int money);

    /* 출금 */
    String withDraw(int money);

}

 

  • PersonalAccount
@Data
public class PersonalAccount implements Account {

    private final int bankCode;       //은행코드
    private final String accNo;       //계좌번호
    private int balance;              //잔액

    @Override
    public String getBalance() {

        return this.accNo + " 계좌의 현재 잔액은 " + this.balance + "원 입니다.";
    }

    @Override
    public String deposit(int money) {

        String str = "";

        if(money >= 0) {
            this.balance += money;
            str = money + "원이 입금되었습니다.";
        } else {
            str = "금액을 잘못 입력하셨습니다.";
        }

        return str;
    }

    @Override
    public String withDraw(int money) {

        String str = "";

        if(this.balance >= money) {
            this.balance -= money;
            str = money + "원이 출금되었습니다.";
        } else {
            str = "잔액이 부족합니다. 잔액을 확인해주세요.";
        }

        return str;
    }

}

 

  • MemberDTO
  •  
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MemberDTO {
	
    private int sequence;                 //회원번호
    private String name;                  //이름
    private String phone;                 //휴대폰번호
    private String email;                 //이메일
    private Account personalAccount;      //개인계좌

}

=> Account(계좌) 인터페이스를 구현한 PersonalAccount(개인계좌) 클래스가 있고 MemberDTO 는 Account 타입을 필드로 가지고 있다. (MemberDTO 는 Account 타입에 의존한다.)

 

1. XML Configuration

1. 생성자(Constructor) 주입

<bean id="account" class="PersonalAccount">
		<constructor-arg index="0" value="20"/>
    <constructor-arg index="1" value="110-234-567890"/>
</bean>

<bean id="member" class="MemberDTO">
		<constructor-arg name="sequence" value="1"/>
    <constructor-arg name="name" value="홍길동"/>
    <constructor-arg name="phone" value="010-1234-5678"/>
    <constructor-arg name="email" value="hong123@gmail.com"/>
    <constructor-arg name="personalAccount">
		    <ref bean="account"/>
    </constructor-arg>
</bean>

 

bean 태그의 클래스 속성은 인터페이스 타입이 아닌 구현 클래스 타입으로 작성해야 한다. 따라서 account 빈 등록 시 class 속성에는 Account 인터페이스가 아닌  PersonalAccount 클래스를 사용한다.

MemberDTO  Account 타입을 의존하고 있기 때문에 member 빈 등록 시 account 빈을 참조하도록 <constructor-arg> 태그의 ref 속성을 작성한다. 생성자를 통해 의존성 객체를 전달하여 의존성을 주입하고 있으므로 이를 생성자 주입 이라 한다.

/* XML 설정 파일을 기반으로 ApplicationContext 객체 생성 */
ApplicationContext context 
	= new GenericXmlApplicationContext("section01/xmlconfig/spring-context.xml");

/* MemberDTO 타입의 빈 가져오기 */
MemberDTO member = context.getBean(MemberDTO.class);

/* MemberDTO의 PersonalAccount 객체 출력 */
System.out.println(member.getPersonalAccount());
/* 10000원 입금 */
System.out.println(member.getPersonalAccount().deposit(10000));
/* 잔액 출력 */
System.out.println(member.getPersonalAccount().getBalance());
/* 5000원 출금 */
System.out.println(member.getPersonalAccount().withDraw(5000));
/* 잔액 출력 */
System.out.println(member.getPersonalAccount().getBalance());

/*
PersonalAccount(bankCode=20, accNo=110-234-567890, 
	balance=110-234-567890 계좌의 현재 잔액은 0원 입니다.)
110-234-567890 계좌의 현재 잔액은 0원 입니다.
10000원이 입금되었습니다.
110-234-567890 계좌의 현재 잔액은 10000원 입니다.
5000원이 출금되었습니다.
110-234-567890 계좌의 현재 잔액은 5000원 입니다.
*/

 

2. 세터(Setter) 주입

<bean id="account" class="PersonalAccount">
		<constructor-arg index="0" value="20"/>
    <constructor-arg index="1" value="110-234-567890"/>
</bean>

<bean id="member" class="MemberDTO">
		<property name="sequence" value="1"/>
    <property name="name" value="홍길동"/>
    <property name="phone" value="010-1234-5678"/>
    <property name="email" value="hong123@gmail.com"/>
    <property name="personalAccount" ref="account"/>
</bean>

/*
PersonalAccount(bankCode=20, accNo=110-234-567890, 
	balance=110-234-567890 계좌의 현재 잔액은 0원 입니다.)
110-234-567890 계좌의 현재 잔액은 0원 입니다.
10000원이 입금되었습니다.
110-234-567890 계좌의 현재 잔액은 10000원 입니다.
5000원이 출금되었습니다.
110-234-567890 계좌의 현재 잔액은 5000원 입니다.
*/

<property> 태그는 setter 메소드를 통해 빈 객체의 값을 초기화하는 설정이다.

  • name : 필드명
  • value : 필드에 담을 값
  • ref : 참조할 빈의 id

MemberDTO 는 Account 타입을 의존하고 있기 때문에 member 빈 등록 시 account 빈을 참조하도록 <property> 태그의 ref 속성을 작성한다. Setter 메소드를 통해 의존성 객체를 전달하여 의존성을 주입하고 있으므로 이를 세터 주입 이라 한다.

빈 객체를 초기화 하는 방법이 생성자 또는 setter 메소드라는 차이는 있으나 테스트 코드의 결과는 동일하다

 

2. Java Configuration

1. 생성자(Constructor) 주입

@Bean
public Account accountGenerator() {

		return new PersonalAccount(20, "110-234-567890");
}

@Bean
public MemberDTO memberGenerator() {

		/* MemberDTO 생성자를 통해 Account를 생성하는 메소드를 호출한 리턴 값을 전달하여 bean을 조립할 수 있다. */
		return new MemberDTO(1, "홍길동", "010-1234-5678", "hong123@gmail.com", accountGenerator());
}

MemberDTO 는 Account 타입을 의존하고 있기 때문에 memberGenerator 빈 등록 시 accountGenerator 빈을 참조하도록 MemberDTO 생성자의 인자로 accountGenerator 메소드 호출의 결과(PersonalAccount bean 객체)를 전달한다. 생성자를 통해 의존성 객체를 전달하여 의존성을 주입하고 있으므로 이를 생성자 주입 이라 한다.

/* Java 설정 파일을 기반으로 ApplicationContext 객체 생성 */
ApplicationContext context 
	= new AnnotationConfigApplicationContext(ContextConfiguration.class);

/* MemberDTO 타입의 빈 가져오기 */
MemberDTO member = context.getBean(MemberDTO.class);

/* MemberDTO의 PersonalAccount 객체 출력 */
System.out.println(member.getPersonalAccount());
/* 10000원 입금 */
System.out.println(member.getPersonalAccount().deposit(10000));
/* 잔액 출력 */
System.out.println(member.getPersonalAccount().getBalance());
/* 5000원 출금 */
System.out.println(member.getPersonalAccount().withDraw(5000));
/* 잔액 출력 */
System.out.println(member.getPersonalAccount().getBalance());

/*
PersonalAccount(bankCode=20, accNo=110-234-567890, 
	balance=110-234-567890 계좌의 현재 잔액은 0원 입니다.)
110-234-567890 계좌의 현재 잔액은 0원 입니다.
10000원이 입금되었습니다.
110-234-567890 계좌의 현재 잔액은 10000원 입니다.
5000원이 출금되었습니다.
110-234-567890 계좌의 현재 잔액은 5000원 입니다.
*/

 

2. 세터(Setter) 주입

@Bean
public Account accountGenerator() {

		return new PersonalAccount(20, "110-234-567890");
}

@Bean
public MemberDTO memberGenerator() {

    MemberDTO member = new MemberDTO();
    member.setSequence(1);
    member.setName("홍길동");
    member.setPhone("010-1234-5678");
    member.setEmail("hong123@gmail.com");
		/* setter를 통해 Account를 생성하는 메소드를 호출한 리턴 값을 전달하여 bean을 조립할 수 있다. */
    member.setPersonalAccount(accountGenerator());

    return member;
}

/*
PersonalAccount(bankCode=20, accNo=110-234-567890, 
	balance=110-234-567890 계좌의 현재 잔액은 0원 입니다.)
110-234-567890 계좌의 현재 잔액은 0원 입니다.
10000원이 입금되었습니다.
110-234-567890 계좌의 현재 잔액은 10000원 입니다.
5000원이 출금되었습니다.
110-234-567890 계좌의 현재 잔액은 5000원 입니다.
*/

MemberDTO 는 Account 타입을 의존하고 있기 때문에 memberGenerator 빈 등록 시 accountGenerator 빈을 참조하도록 setPersonalAccount 메소드의 인자로 accountGenerator 메소드 호출의 결과(PersonalAccount bean 객체)를 전달한다. setter를 통해 의존성 객체를 전달하여 의존성을 주입하고 있으므로 이를 세터 주입 이라 한다.

빈 객체를 초기화 하는 방법이 생성자 또는 setter 메소드라는 차이는 있으나 테스트 코드의 결과는 동일하다.

 

정리

DI는 객체 간의 의존 관계를 빈 설정 정보를 바탕으로 컨테이너가 자동적으로 연결해주는 것이다. 이를 통해 객체 간의 결합도를 낮출 수 있으며 이로 인해 유지보수성과 유연성이 증가한다.

  • XML 빈 설정 시에는 <constructor-args> 또는 <property> 태그의 ref 속성에 의존성 주입할 bean의 이름을 설정한다.
  • Java 빈 설정 시에는 생성자, setter 메소드의 인자 값으로 의존성 주입할 bean의 메소드 호출 반환 값을 전달한다.
728x90
반응형
728x90
반응형

[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI

 

[Spring Framework] Spring IoC 컨테이너 사용법 완벽 정리 | 실전 예제로 이해하는 DI

[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의 [Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리 [Spring Framework] Spring Framework란? 개

crushed-taro.tistory.com

1. IoC Container

1. Annotation-based Configuration

1. @ComponentScan이란?

  • base package로 설정 된 하위 경로에 특정 어노테이션을 가지고 있는 클래스를 bean으로 등록하는 기능이다.
  • @Component 어노테이션이 작성 된 클래스를 인식하여 bean으로 등록한다.
  • 특수 목적에 따라 세부 기능을 제공하는 @Controller, @Service, @Repository, @Configuration 등을 사용한다.
어노테이션 설명
@Component 객체를 나타내는 일반적인 타입으로<bean> 태그와 동일한 역할
@Controller 프리젠테이션 레이어. 웹 어플리케이션에서 View에서 전달된 웹 요청과 응답을 처리하는 클래스
EX) Controller Class
@Service 서비스 레이어, 비즈니스 로직을 가진 클래스
EX) Service Class
@Repository 퍼시스턴스(persistence) 레이어, 영속성을 가지는 속성(파일, 데이터베이스)을 가진 클래스
EX) Data Access Object Class
@Configuration 빈을 등록하는 설정 클래스

Spring 사진 1

 

2. @Component 어노테이션으로 자동 빈 등록하기

@Component
public class MemberDAO {

    private final Map<Integer, MemberDTO> memberMap;

    public MemberDAO() {
        memberMap = new HashMap<>();

        memberMap.put(1, new MemberDTO(1, "user01", "pass01", "홍길동"));
        memberMap.put(2, new MemberDTO(2, "user02", "pass02", "유관순"));
    }

    /* 매개변수로 전달 받은 회원 번호를 map에서 조회 후 회원 정보를 리턴하는 메소드 */
    public MemberDTO selectMember(int sequence) {
        return memberMap.get(sequence);
    }

    /* 매개변수를 전달 받은 회원 정보를 map에 추가하고 성공 실패 여부를 boolean으로 리턴하는 메소드 */
    public boolean insertMember(MemberDTO newMember) {

        int before = memberMap.size();

        memberMap.put(newMember.getSequence(), newMember);

        int after = memberMap.size();

        return after > before;
    }
}

bean으로 등록하고자 하는 클래스 위에 @Component 어노테이션을 기재하면 스프링 컨테이너 구동 시 빈으로 자동 등록된다.

  • 이름을 별도로 지정하지 않으면 클래스명의 첫 문자를 소문자로 변경하여 bean의 id로 자동 인식한다.
  • @Component("myName") 또는 @Component(value="myName") 의 형식으로 bean의 id를 설정할 수 있다.

 

3. @ComponentScan 어노테이션으로 base packages 설정하기

@ComponentScan(basePackages="project")
public class ContextConfiguration {}

@ComponentScan어노테이션의 basePackagese 속성에 입력한 패키지가 빈 스캐닝의 범위가 된다.

 

스프링 컨테이너에 빈 스캐닝을 통해bean이 자동으로 등록 되고 생성 되었는지 확인한다.

ApplicationContext context 
	= new AnnotationConfigApplicationContext(ContextConfiguration.class);

/* getBeanDefinitionNames : 스프링 컨테이너에서 생성 된 bean들의 이름을 배열로 반환한다. */
String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
		System.out.println("beanName : " + beanName);
}

/*
...생략
beanName : contextConfiguration
beanName : memberDAO
*/

 

4. excludeFilters

@ComponentScan 의 excludeFilters속성을 이용해서 일부 컴포넌트를 빈 스캐닝에서 제외할 수 있다.

  • Type으로 설정하는 방법
@ComponentScan(basePackages="project",
	excludeFilters={
		@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, 
		classes={MemberDAO.class})
})
public class ContextConfiguration {}

 

  • Annotation 종류로 설정하는 방법
@ComponentScan(basePackages="project",
	excludeFilters={
		@ComponentScan.Filter(type=FilterType.ANNOTATION, 
		classes={org.springframework.stereotype.Component.class})
})
public class ContextConfiguration {}

 

  • 표현식으로 설정하는 방법
@ComponentScan(basePackages="project",
	excludeFilters={
		@ComponentScan.Filter(type=FilterType.REGEX, 
		pattern={"annotationconfig.java.*"})
})
public class ContextConfiguration {}

 

빈 스캐닝에MemberDAO클래스가 제외되어 아래 코드를 실행하면 해당 이름을 가진 빈이 없다는 오류가 발생한다.

ApplicationContext context = new AnnotationConfigApplicationContext(ContextConfiguration.class);

String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
		System.out.println("beanName : " + beanName);
}

MemberDAO memberDAO = context.getBean("memberDAO", MemberDAO.class);

/*
...생략
beanName : contextConfiguration
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No bean named 'memberDAO' available
*/

 

5. includeFilters

@ComponentScan 의 includeFilters성을 이용해서 일부 컴포넌트를 빈 스캐닝에 포함 시킬 수 있다.

@ComponentScan(basePackages="project",
	useDefaultFilters=false,
	includeFilters={@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, 
		classes= {MemberDAO.class})
})
public class ContextConfiguration {}

useDefaultFilters 속성의 기본 값은 true로 @Component 종류의 어노테이션을 자동으로 등록 처리 해준다. 해당 속성을 false로 변경하면 컴포넌트 스캔이 일어나지 않게 된다.

별도로 includeFilters 속성을 정의해 컴포넌트 스캔이 발생하도록 한다.

excludeFilters에서 설정하는 방식과 동일하므로 종류별 예시는 생략한다.

 

아래 코드를 실행하면 빈 스캐닝에서MemberDAO클래스가 포함되어 해당 이름을 가진 빈을 확인할 수 있다.

ApplicationContext context 
	= new AnnotationConfigApplicationContext(ContextConfiguration.class);

String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
		System.out.println("beanName : " + beanName);
}

/*
...생략
beanName : contextConfiguration
beanName : memberDAO
*/

 

6. XML에서 Component Scan 설정

아래와 같이 XML 설정 파일에서 Component Scan의base package를 설정할 수도 있다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
													 http://www.springframework.org/schema/beans/spring-beans.xsd 
													 http://www.springframework.org/schema/context 
													 https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="project"/>

</beans>

<context:component-scan> 태그는 context 네임스페이스의 기능이기 때문에 context: 접두어가 필요하다.

또한 XML 설정 파일의 기본 네임스페이스가 beans로 설정 되어 있기 때문에 context 네임스페이스 추가가 필요하다.

 

base package@Component 어노테이션을 작성한 MemberDAOclass를 배치해 두고 아래와 같은 코드를 실행하면 빈이 등록 되어있음을 확인할 수 있다.

ApplicationContext context 
	= new GenericXmlApplicationContext("section03/javaannotation/spring-context.xml");

String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
		System.out.println("beanName : " + beanName);
}

/*
beanName : memberDAO
...생략
*/

 

아래와 같이 <context:component-scan> 태그 내부에 <exclude-filter> 또는 <include-filter> 태그를 정의할 수 있다.

<include-filter> 의 경우 동일한 방식으로 정의하므로 생략하였다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
													 http://www.springframework.org/schema/beans/spring-beans.xsd 
													 http://www.springframework.org/schema/context 
													 https://www.springframework.org/schema/context/spring-context.xsd">

	<context:component-scan base-package="project">
        <context:exclude-filter type="assignable" expression="common.MemberDAO"/>
  </context:component-scan>

</beans>

 

스캐닝에서MemberDAO클래스가 제외되어 아래 코드를 실행하면 해당 이름을 가진 빈이 없다는 오류가 발생한다.

ApplicationContext context 
	= new GenericXmlApplicationContext("section03/javaannotation/spring-context.xml");

String[] beanNames = context.getBeanDefinitionNames();
for(String beanName : beanNames) {
		System.out.println("beanName : " + beanName);
}

MemberDAO memberDAO = context.getBean("memberDAO", MemberDAO.class);

/*
...생략
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException
: No bean named 'memberDAO' available
*/

 

정리

  • XML 설정은 전통적으로 사용하던 방식으로 최근에는 Java 설정이 선호된다.
  • 개발자가 직접 컨트롤 가능한 Class의 경우, @Component를 클래스에 정의하여 빈 스캐닝을 통한 자동 빈 등록을 한다.
  • 개발자가 직접 제어할 수 없는 외부 라이브러리는 @Bean을 메소드에 사용하여 수동 빈 등록을 한다.
    • 다형성을 활용하고 싶은 경우에도 @Bean을 사용할 수 있다.
 

Java-based Container Configuration :: Spring Framework

This section covers how to use annotations in your Java code to configure the Spring container.

docs.spring.io

728x90
반응형
728x90
반응형

[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의

 

[Spring Framework] 스프링 IoC 컨테이너 이해하기 | 정의

[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리 [Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리[Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드

crushed-taro.tistory.com

1. IoC Container 사용하기

  • 아래 코드는 테스트에 공통적으로 사용할MemberDTO클래스이다.
@Data
@AllArgsConstructor
public class MemberDTO {

    private int sequence;     //회원번호
    private String id;        //아이디
    private String pwd;       //비밀번호
    private String name;      //이름

}

 

1. XML - based Configuration

1. GenericApplicationContext

GenericXmlApplicationContext Spring IoC Container 중 하나이다. XML 형태의 Configuration Metadata를 사용하여 Bean을 생성한다.

/* GenericXmlApplicationContext 클래스를 사용하여 ApplicationContext를 생성한다. 
 * 생성자에 XML 설정 메타 정보를 인자로 전달한다. */
ApplicationContext context 
	= new GenericXmlApplicationContext("spring-context.xml"
		/*XML Configuration Metadata 파일 경로*/);

 

2. XML 기반 Configuration Metadata

XML 형태의 Configuration Metadata 파일은 다음과 같이 작성할 수 있다. 다음 예제에서는MemberDTO클래스의 객체를 Bean으로 등록하고 있다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
													 http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="member" class="MemberDTO">
				<!-- int 타입의 첫 번째 파라미터에 1 값을 전달 -->
        <constructor-arg index="0" value="1"/>
	      <!-- String 타입의 id 파라미터에 "user01" 값을 전달 -->
        <constructor-arg name="id" value="user01"/>
        <!-- String 타입의 세 번째 파라미터에 "pass01" 값을 전달 -->
        <constructor-arg index="2"><value>pass01</value></constructor-arg>
				<!-- String 타입의 name 파라미터에 "홍길동" 값을 전달 -->
        <constructor-arg name="name"><value>홍길동</value></constructor-arg>
    </bean>

</beans>

 

  • <beans>그는 Bean 설정 정보를 담고 있는 메타데이터를 정의하는 태그이다.
    • xmlns : XML Namespace를 정의
    • xmlns:xsi : XML Schema Instance Namespace를 정의
    • xsi:schemaLocation : XML Schema Location을 정의
    • XML Schema는 XML 문서의 구조와 유효성을 검사하기 위한 언어로, XML Schema Definition(XSD) 파일을 통해 정의
  • <beans> 태그 내부에 <bean>그를 사용해 하나의 bean 설정 정보를 작성할 수 있다.
    • id : Bean의 이름을 정의
    • class : 객체의 클래스를 지정
  • <constructor-arg> 태그는 생성자를 호출할 때 전달할 인자를 정의한다. 만약 <bean> 태그 내부에 아무 것도 작성하지 않으면 기본 생성자를 사용한다는 의미이다.
    • index : 메서드의 파라미터 순서(index)로 전달
    • name : 파라미터 이름으로 전달
    • value : 파라미터 값으로 전달

 

3. GenericApplicationContext(스프링 컨테이너) 생성 테스트

GenericApplicationContext에 bean등록 되고 생성 되었는지 확인한다.

  • bean의 id를 이용해서 bean을 가져오는 방법
MemberDTO member = (MemberDTO) context.getBean("member");
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

  • bean의 클래스 메타 정보를 전달하여 가져오는 방법
MemberDTO member = context.getBean(MemberDTO.class);
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

  • bean의 id와 클래스 메타 정보를 전달하여 가져오는 방법
MemberDTO member = (MemberDTO) context.getBean("member");
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)

 

2. Java-based Configuration

1. AnnotationConfigApplicationContext

AnnotationConfigApplicationContext는 Spring IoC Container 중 하나이다. Java Configuration 형태의 Configuration Metadata를 사용하여 Bean을 생성한다.

/* AnnotationConfigApplicationContext클래스를 사용하여 ApplicationContext를 생성한다. 
 * 생성자에 @Configuration 어노테이션이 달린 설정 클래스의 메타 정보를 전달한다. */
ApplicationContext context 
	= new AnnotationConfigApplicationContext(ContextConfiguration.class);

 

2. Java 기반 Configuration Metadata

Java Configuration 형태의 Configuration Metadata 파일은 다음과 같이 작성할 수 있다. 다음 예제에서는MemberDTO래스의 객체를 Bean으로 등록하고 있다.

@Configuration
public class ContextConfiguration {

    @Bean(name="member")
    public MemberDTO getMember() {

        return new MemberDTO(1, "user01", "pass01", "홍길동");
    }

}

 

@Configuration 어노테이션은 해당 클래스가 빈을 생성하는 클래스임을 표기한다.

 

  • @Bean 어노테이션은 해당 메소드의 반환 값을 스프링 컨테이너에 빈으로 등록한다는 의미이다.
    • 이름을 별도로 지정하지 않으면 메소드 이름을 bean의 id로 자동 인식한다.
    • @Bean("myName") 또는 @Bean(name="myName") 의 형식으로 bean의 id를 설정할 수 있다.

 

3. AnnotationConfigApplicationContext(스프링 컨테이너) 생성 테스트

AnnotationConfigApplicationContext에 bean 이 등록 되고 생성 되었는지 확인한다.

MemberDTO member = context.getBean("member", MemberDTO.class);
System.out.println(member);

//MemberDTO(sequence=1, id=user01, pwd=pass01, name=홍길동)
728x90
반응형
728x90
반응형

[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리

 

[Spring Framework] Spring Framework란? 개요와 핵심 구성 모듈 정리

[Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드 [Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드[Servlet] 자바 서블릿과 네트워크 | 요청

crushed-taro.tistory.com

1. IoC Container

1. IoC & IoC Container 정의

1. IoC(Inversion of Control)란?

제어의 역전(IoC, Inversion of Control)은 일반적인 프로그래밍에서, 프로그램의 제어 흐름 구조가 뒤바뀌는 것을 의미한다.
  • ⇒ 객체의생성과 관리, 객체 간의 의존성 처리을 프레임워크에서 대신 처리해주는 것이 IoC의 대표적인 예이다.

 

2. IoC Container란?

IoC Container는 IoC를 구현한 구체적인 프레임워크를 말한다. IoC Container를 사용하면 객체의 생성, 초기화, 의존성 처리 등을 자동으로 수행할 수 있다. 
  • ⇒ 대표적인 IoC Container로는 Spring Framework의ApplicationContext가 있다.

 

Spring 사진 1

 

2. Spring IoC Container

1. Bean이란?

Bean은 Spring IoC Container에서 관리되는 객체를 말한다. 
  • 스프링은 Bean을생성하고, 초기화하고, 의존성 주입하고, 제거하는 등의 일을 IoC Container를 통해 자동으로 처리할 수 있다.

 

2. Bean Factory란?

BeanFactory는 Spring IoC Container의 가장 기본적인 형태로, Bean의 생성, 초기화, 연결, 제거 등의 라이프사이클을 관리한다. 
  • 이를 위해Configuration Metadata를 사용한다.

 

3. Configuration Metadata란?

BeanFactory가 IoC를 적용하기 위해 사용하는 설정 정보다.
  • ⇒ 설정 메타 정보는 IoC 컨테이너에 의해 관리 되는 Bean 객체를 생성하고 구성할 때 사용 된다.

Spring 사진 2

 

4. Application Context란?

BeanFactory를 확장한 IoC 컨테이너로 Bean을 등록하고 관리하는 기능은 BeanFactory와 동일하지만, 스프링이 제공하는 각종 부가 기능을 추가로 제공한다.

 

Spring 사진 3

 

  • ListableBeanFactory : BeanFactory가 제공하는 모든 기능을 포함한다.
  • ApplicationEventPublisher : 이벤트 처리(Event Handling) 기능을 제공한다.
  • MessageSource : 국제화(i18n) 를 지원하는 메세지를 해결하는 부가 기능을 제공한다.
  • ResourceLoader : 리소스 핸들링(Resource Handling) 기능을 제공한다.
  • GenericXmlApplicationContext : ApplicationContext를 구현한 클래스. XML MetaData Configuration을 읽어 컨테이너 역할을 수행한다.
  • AnnotationConfigApplicationContext : ApplicationContext를 구현한 클래스. Java MetaData Configuration을 읽어 컨테이너 역할을 수행한다.
728x90
반응형
728x90
반응형

[Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드

 

[Servlet] Servlet에서 Thread가 어떻게 작동하는가? 웹 개발자를 위한 완벽 가이드

[Servlet] 자바 서블릿과 네트워크 | 요청과 응답이 오가는 과정을 파헤쳐보자 [Servlet] 자바 서블릿과 네트워크 | 요청과 응답이 오가는 과정을 파헤쳐보자[Servlet] Servlet과 JSP로 구현하는 MVC 패턴 | J

crushed-taro.tistory.com

1. Spring Framework

1. Spring Framework 개요

1. Spring Framework란

스프링 프레임워크는 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크로서 간단히 스프링이라고도 한다. 동적인 웹 사이트를 개발하기 위한 여러 가지 서비스를 제공하고 있다. 또한 대한민국 공공기관의 웹 서비스 개발 시 사용을 권장하고 있는 전자정부 표준프레임워크의 기반 기술로서 쓰이고 있다.
Spring 공식 사이트

https://spring.io/

 

Spring | Home

Cloud Your code, any cloud—we’ve got you covered. Connect and scale your services, whatever your platform.

spring.io

 

2. Spring Framework의 특징

  • 오픈 소스이다.
    • 다양한 실제 사용 사례를 기반으로 지속적인 피드백을 제공하는 크고 활동적인 커뮤니티가 있어 오랜 시간에 걸쳐 성공적으로 진화하는 데 도움이 되었다.
  • Java 엔터프라이즈 애플리케이션을 쉽게 만들 수 있다.
    • 애플리케이션의 요구 사항에 따라 다양한 종류의 아키텍처를 생성할 수 있는 유연성과 함께 엔터프라이 환경에서 Java 언어를 수용하는 데 필요한 모든 것을 제공한다.
  • 프레임워크의 기본 원칙에 충실하다.
    • 강력한 이전 버전과의 호환성을 유지한다.
    • 유연성을 수용하며 작업 수행 방법에 대해 독선적이지 않다. 다양한 관점에서 다양한 애플리케이션 요구 사항을 지원한다.
    • 모든 수준에서 선택권을 제공한다. Spring을 사용하면 가능한 한 늦게 디자인 결정을 연기할 수 있다. 예를 들어 코드를 변경하지 않고 구성을 통해 지속성 공급자를 전환할 수 있다.
    • 의미 있고 최신이며 정확한 javadoc을 강조한다. 패키지 간의 순환 종속성이 없는 깨끗한 코드 구조를 주장할 수 있는 극소수의 프로젝트 중 하나이다.

 

2. Spring Framework 구성 모듈

Spring 사진 1

 

1. Spring Core Container

1. Spring Core Container

Spring Core Container는 스프링에서 가장 기본적이며 중요한 모듈 중 하나이다. 이 모듈은 스프링에서 객체의 생성과 관리를 담당한다. 스프링의 DI(Dependency Injection)과 IoC(Inversion of Control) 개념이 구현되어 있다. 이를 이용하여 코드의 재사용성과 유지보수성을 높일 수 있다. 

 

2. AOP(Aspect Oriented Programming) / Aspects / Instrumentation / Messaging

1. AOP(Aspect Oriented Programming)

AOP는 객체지향 프로그래밍에서의 코드 중복을 제거하고 코드를 재사용하기 위한 프로그래밍 기법이다. 기존의 코드를 변경하지 않고 새로운 기능을 추가하는 방식으로 사용한다. 스프링에서는 AOP를 이용해 로깅, 트랜잭션, 보안 등의 기능을 제공한다.

 

2. Aspects

  • 별도의 spring-aspects 모듈AspectJ의 통합을 제공한다.

 

3. Instrumentation

  • Instrumentation은 자바 프로그램의 동작을 관찰하고 조작하는 기술이다. 스프링에서는 Instrumentation을 이용해 클래스 로딩, 메소드 실행 등의 작업을 추적하고 변경할 수 있다.

 

4. Messaging

  • Apache Kafka 및 RabbitMQ와 같은 메시지 브로커의 통합을 통해 메시징 아키텍처를 지원한다. 메시지 채널, 메시지 처리기 및 메시징 기반 응용 프로그램을 생성할 수 있는 메시지 끝점에 대한 추상화가 포함된다. 또한 이 모듈을 사용하면 메시지 채널에서 메시지를 수신하고 처리할 수 있는 메시지 구동 POJO(Plain Old Java Objects)를 생성할 수 있다.

 

3. Data Access / Integration

1. JDBC(JAVA DataBase Connectivity)

JDBC는 Java에서 데이터베이스와 연결할 수 있는 API이다. JDBC는 데이터베이스에 대한 쿼리를 실행하고 결과를 처리할 수 있는 메서드와 클래스를 제공한다. 이를 통해 Java 애플리케이션에서 데이터베이스를 쉽게 사용할 수 있다.

 

2. ORM(Object Relation Mapping)

ORM은 객체 지향 프로그래밍에서 관계형 데이터베이스와의 상호작용을 추상화하는 프로그래밍 기술이다. 이를 통해 개발자는 객체를 직접 다루면서 데이터베이스를 조작할 수 있다. ORM 프레임워크는 객체와 데이터베이스 간의 매핑을 담당하며, 데이터베이스 쿼리를 생성하고 실행하는 등의 작업을 대신 수행한다. 

 

3. Transaction Management

트랜잭션은 데이터베이스 상태를 변경하는 작업의 단위이다. 여러 개의 쿼리가 트랜잭션으로 묶이면, 모든 쿼리가 성공하면 변경 내용이 데이터베이스에 반영되고, 하나라도 실패하면 변경 내용이 취소된다. 이런 트랜잭션을 보다 쉽게 처리하기 위해 스프링에서는 트랜잭션 관리 기능을 제공한다. 이를 이용하면 선언적 트랜잭션 처리, 프로그램적 트랜잭션 처리 등을 할 수 있으며, 트랜잭션 속성을 XML이나 어노테이션을 이용해 설정할 수 있다. 

 

4. OXM(Object XML Mapping)

OXM(Object XML Mapping)은 자바 객체와 XML 문서 간의 매핑을 지원하는 모듈이다. 개발자는 XML 문서를 직접 작성할 필요 없이, 자바 객체를 이용하여 간단하게 XML 문서를 생성하고 읽을 수 있다. 

 

5. Java Messaging Service(JMS)

Java Messaging Service(JMS)는 자바에서 메시지를 주고 받을 수 있는 API이다. 이 API를 사용하면 분산 시스템에서 메시지를 교환할 수 있다. JMS는 메시지 전송과 수신을 위한 스펙과 메시지의 속성을 정의하기 위한 API를 제공한다. 메시지를 보내는 쪽에서는 메시지를 생성하고 목적지를 지정한 다음, JMS Provider를 통해 메시지를 보낸다. 메시지를 받는 쪽에서는 메시지를 수신하고 처리한다. JMS는 대부분의 메시지 지향 미들웨어(MOM)에서 사용된다.

 

4. Web

1. Servlet

Servlet은 웹 애플리케이션 서버에서 실행되는 자바 클래스이다. 클라이언트의 요청을 처리하고, 응답을 생성하는데 사용된다. Servlet은 JSP(JavaServer Pages)와 함께 Java EE(Java Platform, Enterprise Edition)의 Web API를 구성한다. 스프링에서는 Servlet API를 이용하여 웹 어플리케이션을 개발할 수 있다.

 

2. Web

Spring Web MVC는 스프링에서 제공하는 웹 어플리케이션 개발을 위한 MVC 패턴 구현 모듈이다. 웹 어플리케이션을 개발할 때, 요청과 응답을 처리하며 페이지 이동을 관리하는 컨트롤러, 데이터를 처리하고 화면에 출력하는 뷰, 비즈니스 로직을 수행하는 모델로 구분하여 개발하는 것이 일반적이다. 이러한 구조를 MVC 패턴이라고 한다. 대부분의 웹 프레임워크에서 제공하는 MVC 패턴의 구현체이며, 스프링에서도 이를 지원한다. Spring Web MVC는 이러한 컨트롤러, 뷰, 모델을 개발하는 데 도움을 주며, 특히 유연한 URL 매핑 기능을 제공하여 URL과 컨트롤러를 매핑시키는 작업을 쉽게 수행할 수 있다.
Spring WebFlux는 스프링 5에서 추가된 모듈로, 비동기 웹 어플리케이션 개발을 위해 Reactive Streams를 지원하는 모듈이다. 기존의 Spring Web MVC와는 달리, Servlet API에 의존하지 않고, Netty, Undertow, Servlet 3.1+ 컨테이너와 같은 네이티브 리액티브 서버를 사용하여 개발할 수 있다. Spring WebFlux는 Reactor를 이용하여 비동기 프로그래밍을 지원하며, 이를 통해 높은 처리량과 확장성을 제공한다.

 

3. WebSocket

WebSocket은 HTTP와 달리 양방향 통신을 지원하는 프로토콜이다. 이를 이용하면 서버와 클라이언트 간의 실시간 양방향 통신이 가능하다. 스프링에서는 웹 소켓을 지원하기 위해 Spring Websocket 모듈을 제공한다. Spring Websocket 모듈은 STOMP(Subscribable-Text-Oriented Messaging Protocol) 프로토콜을 이용하여 WebSocket을 구현한다. STOMP는 WebSocket을 이용하여 메시지를 주고 받을 때 사용되는 메시지 프로토콜이다. Spring Websocket 모듈은 메시지 브로커와 연동하여 구현할 수 있으며, 브로커를 이용하여 메시지를 보내고 받을 수 있다. 이를 이용하면 다수의 사용자 간의 실시간 채팅, 게임 등의 기능을 구현할 수 있다.

 

4. Portlet

Portlet은 웹 페이지를 구성하는 데 사용되는 모듈이며, 클라이언트의 요청에 따라 동적으로 로드된다. Portlet은 일반적인 웹 애플리케이션과 달리, 특정 Portlet 컨테이너에서 실행되어야 하며, Portlet 컨테이너는 웹 서버에서 분리되어 실행된다. Spring Portlet MVC는 Spring MVC와 비슷한 방식으로 동작하며, Portlet 컨테이너에서 실행되는 Portlet 컨트롤러, 뷰, 모델을 개발할 수 있다.

 

5. Test

1. Test

  • spring-test 모듈은 JUnit 또는 TestNG를 사용하여 Spring 구성 요소의 단위 테스트 및 통합 테스트를 지원한다.
    • Spring ApplicationContexts의 일관된 로딩과 해당 컨텍스트의 캐싱을 제공한다.
    • 코드를 별도로 테스트하는 데 사용할 수 있는 모의 개체를 제공한다.

 

6. Languages

1. Groovy 지원

  • Groovy JVM에서 실행되는 스크립트 언어이다. Java와 완벽하게 호환되며, Java와 같은 문법을 사용하면서도 보다 간결한 코드를 작성할 수 있다. Groovy는 Gradle 등의 빌드 툴에서 널리 사용되어, Java 개발 프로세스에서 자주 사용된다.

 

2. Kotlin 지원

  • Kotlin JVM에서 실행되는 프로그래밍 언어로, 자바와 완벽하게 상호운용이 가능하다. 자바보다 간결한 문법과 람다 표현식, 널 안전성 등의 기능을 제공하여 개발 생산성을 높일 수 있다. 스프링에서는 Kotlin을 공식적으로 지원하며, 스프링 부트에서도 Kotlin을 이용한 개발을 쉽게 할 수 있다.
728x90
반응형

+ Recent posts