[Spring] IoC와 DI (2)

Noah·2022년 1월 6일
0

Spring

목록 보기
3/8
post-thumbnail

Java Bean

Java Bean 은 데이터를 표현하는 것을 목적으로 하는 자바 클래스이다. 특별한 것은 없고 Java Bean 규약에 맞춰서 만든 클래스를 뜻한다.

Java Bean 규약은 다음과 같다.

  1. 기본 생성자가 존재해야 한다.
  2. 모든 멤버 변수의 접근제어 지시자는 private이다.
  3. 멤버 변수마다 getter/setter가 존재해야 한다.
  4. 멤버 변수의 자료형이 boolean일 경우 is를 붙인다.
  5. 외부에서 멤버 변수에 접근하기 위해서는 메서드를 통해서만 접근할 수 있다.
  6. Serializable(직렬화)가 가능해야 한다.

직렬화

직렬화란 시스템 내부에서 사용하는 객체 혹은 데이터를 외부의 시스템에서도 사용할 수 있도록 변환시키는 것을 말한다.

자바에서는 JVM의 Heap 영역에 상주한 객체를 byte형태로 변환시키거나(직렬화), byte 형태를 다시 자바 객체로 변환하는 것(역 직렬화)을 말한다.

Spring은 뷰 영역에 데이터를 출력하고 싶을 때 Java Bean 규약에 맞춰 만들어진 객체를 사용하고, 객체들을 외부 저장소에 저장하고 전송할 때 사용한다.


IoC와 DI 예제

Main()

package com.example.ioc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
public class IocApplication {

	public static void main(String[] args) {
		SpringApplication.run(IocApplication.class, args);
		ApplicationContext context = ApplicationContextProvider.getContext();

		// Base64Encoder base64Encoder = context.getBean(Base64Encoder.class);
		// UrlEncoder urlEncoder = context.getBean(UrlEncoder.class);

		Encoder encoder = context.getBean(Encoder.class);
		String url = "www.naver.com";
		String result = encoder.encode(url);
		System.out.println(result);

	}
}

Application Context를 통해 IoC에 의해 관리되는 Encoder 인스턴스 객체를 받아 특정 url을 인코딩 하고 결과를 출력하는 함수다. 그렇다면 Application Context란 무엇일까? 먼저 Bean Factory부터 알아보자.

Bean Factory

Bean 객체를 생성하고 관리하는 인터페이스이다. 디자인패턴의 일종인 팩토리 패턴을 구현한 것이다. BeanFactory 컨테이너는 구동될 때 Bean 객체를 생성하는 것이 아니라 클라이언트의 요청이 있을 때 객체를 생성한다.

Application Factory

BeanFactory를 상속받은 인터페이스이다. 부가적인 기능이 많기 때문에 더 많이 사용한다. ApplicationContext 컨테이너는 구동되는 시점에 등록된 Bean 객체들을 스캔하여 객체화한다.


IEncoder Interface

package com.example.ioc;

public interface IEncoder {
    String encode(String message);
}

Encoder Class

package com.example.ioc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Encoder {

    @Autowired
    @Qualifier("base64Encoder")
    private IEncoder iEncoder;

    public Encoder(@Qualifier("base64Encoder") IEncoder iEncoder) {
        this.iEncoder = iEncoder;
    }

    public IEncoder getiEncoder() {
        return iEncoder;
    }

    public void setiEncoder(IEncoder iEncoder) {
        this.iEncoder = iEncoder;
    }

    public String encode(String message) {
        return iEncoder.encode(message);
    }

}

Base64Encoder Class

package com.example.ioc;

import org.springframework.stereotype.Component;

import java.util.Base64;

@Component("base64Encoder")
public class Base64Encoder implements IEncoder {
    public String encode(String message) {
        return Base64.getEncoder().encodeToString(message.getBytes());
    }
}

UrlEncoder Class

package com.example.ioc;

import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

@Component("urlEncoder")
public class UrlEncoder implements IEncoder {
    public String encode(String message) {
        try {
            return URLEncoder.encode(message, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

특정 문자열을 받아 인코딩된 결과를 반환하는 메서드를 가진 인터페이스 IEncoder를 구현한 두 개의 클래스 Base64Encoder, UrlEncoder가 존재한다. 두 개의 클래스 모두 @Component라는 어노테이션을 통해 Bean으로 관리된다.

또한 Encoder 클래스는 IEncoder 타입의 멤버 변수 iEncoder에 의존하며 @Autowired라는 어노테이션을 통해 자신이 의존하는 객체를 IoC에 의해 자동으로 주입받는다.

여기서 @Qualifier 어노테이션이 사용된 이유는 현재 IEncoder 타입의 Bean이 Base64Encoder와 UrlEncoder 두 개가 존재하기 때문에 IoC 입장에선 어떤 Bean을 주입해야 할지 헷갈리게 된다. 따라서 그러한 경우를 방지하기 위해 특정 Bean을 주입하라고 명시해준 것이라고 이해하면 된다.

그 외에 추가적으로 Bean으로 관리되기 위한 어노테이션은 아래와 같이 여러 가지가 존재하고 Spring으로 서버를 구축하는 프로젝트를 진행하면서 차근차근 정리해 보도록 할 것이다.


Bean Annotations

@Bean, @Component, @Controller, @Service, @Repository

  • @Bean은 개발자가 컨트롤할 수 없는 외부 라이브러리를 Bean으로 등록하고 싶은 경우
  • @Component는 개발자가 직접 컨트롤할 수 있는 클래스(직접 만든)를 Bean으로 등록하고 싶은 경우
  • @Controller, @Service, @Repository 등 은 @Component를 비즈니스 레이어에 따라 명칭만 달리 지정해 준 것
profile
개발 공부는 🌳 구조다…

1개의 댓글

comment-user-thumbnail
2022년 1월 6일
답글 달기