[Spring] Core(1)

드코딩·2024년 7월 16일
0

Spring

목록 보기
1/6
post-thumbnail

Hello Spring!!을 기념으로 스프링 기록 첫 시작

DI (Dependency Injection)


DI란 의존성을 주입한다는 의미이다.
최근에 자바도 공부하고 SOLID 원칙을 정리하고 맞이한 DI는 좀 익숙하다.
나는 의존성 주입을 OCP 원칙을 쉽게 지키도록 도움을 주는 것 같다.

의존성 주입 예제 코드

// 의존성을 가지고 있는 클래스
class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void createUser(User user) {
        userRepository.save(user);
    }
}

// 의존성을 가지고 있는 클래스
class UserRepository {
    public void save(User user) {
        // 사용자 정보를 저장하는 코드
    }
}

// 의존성을 주입받는 클래스
class Application {
    public static void main(String[] args) {
        // 의존성을 직접 생성하여 주입
        UserRepository userRepository = new UserRepository();
        UserService userService = new UserService(userRepository);

        User user = new User("ho", "ho@example.com");
        userService.createUser(user);
    }
}

위 코드에서는 UserService는 UserRepository를 생성자에서 만들어 사용하고 있는데
이를 의존하고 있다고 표현할 수 있다.

UserService에서 사용되는 userRepository는 Application 클래스에서 UserRepository()를 생성하고
생성된 userRepository를 userService 생성자에 전달(주입)하는 과정이 있다.

한마디로 클래스 내부에서 사용되는 객체를 파라미터로 받아 할당받아 사용하는 것을 의존성을 주입한다고 한다.

의존성을 주입받지 않는 코드

class UserService {
    private final UserRepository userRepository;
		
		//의존성을 주입 받지 않음
    public UserService() {
        this.userRepository = new UserRepository();
    }
    

    public void createUser(User user) {
        userRepository.save(user);
    }
}

파라미터로 받지 않고 클래스 내부에서 직접 생성하여 할당한다면 의존성을 주입하지 않음!!

내가 생각하는 의존성 주입 장점

현재 예제코드에서는 UserRepository 타입의 객체를 주입 받아서 사용했지만
이를 Repository 라는 interface로 만들어 구현해서 사용한다면
다른 Repository를 구한 MemberRepositroy를 만들어 사용할 때 OCP 원칙을 잘 지킨
UserService 내부는 수정하지 않고 바꿀 수 있는점이 장점으로 작용할 것 같다.

IoC (Inversion of Control)


IoC는 잊고 있었지만 그 어색한 번역 제어의역전은 뭔가 기억에 남아있었다.
그래서 제어의 역전이 뭔데요...

IoC란?
검색해보니 아래와 같은 답변을 많이 확인할 수 있었다.

객체의 생성 및 관리 책임을 개발자에서 전체 애플리케이션 또는 프레임워크에 위임하는 디자인 원칙

여기서 개발자에서 전체 애플리케이션, 프레임워크에 위임한다?
그게 어떻게 가능하지? 라는 생각과 함께 잘 와닿지 않았다.

그래서 스프링의 예제 코드를 IoC 예제코드를 만들면서 이해해 보았다.
아까 DI에서 예시로 사용한 의존성 주입 코드를 IoC를 적용한다면 아래와 같을 것이다.

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
        //어디에서 코드로 의존성을 주입하는 코드가 없음
    }

    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }

    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }

    @RestController
    public class UserController {
        private final UserService userService;

        public UserController(UserService userService) {
            this.userService = userService;
        }

        @PostMapping("/users")
        public void createUser(@RequestBody User user) {
            userService.createUser(user);
        }
    }
}

스프링부트를 만나면 위와 같이 작성하여 개발자가 직접 객체를 만들어 의존성을 주입하지 않아도 된다.
예제 코드를 보면 말도 안되는
객체의 생성 및 관리 책임을 개발자에서 전체 애플리케이션 또는 프레임워크에 위임하는 디자인 원칙
이 가능하다는 것을 알 수 있었다.

내가 생각하는 IoC란?

위에 정리한 IoC를 동의하고 명확하게 이해할 수 있었다.
하지만 프레임워크 단으로 보지 않고 IoC의 의미 그대로를 객체 레벨에서 이해하고 생각해보고자 했다.

<생각 내용>
의존성 주입을 주입한다는 것은 A객체가 사용할 B객체를 파라미터로 할당한다는 것인데
B객체가 동일한 상위타입가진 C객체로 변경되면 다형성으로 인해 객체의 퍼포먼스(사용효과)가 바뀐다.


제어의 역전을 객체를 사용하는 제어권의 소유자가 바뀐다고 바라본다면?
A객체는 주입되는 객체에 따라서 퍼포먼스가 바뀌기에 A객체의 제어권이
"자신에게 없는거 아닐까?" 그럼 제어의 역전이라고 볼 수 있겠다.
그럼 DI는 IoC에 도움을 주는구나!

내 의견이 엄청 맞다고는 생각하지 않지만 IoC를 이해하는데 노력한 내용을 적어보았다.

다시 돌아와서 스프링,스프링부트가 어떻게 대신 객체를 관리해주는가?!

Bean과 Spring Container

Bean과 Container를 사용해서 스프링에서는 객체를 관리해준다.

Bean이 뭔가요?

개발자가 만들어준 클래스는 스프링에서 관리 해주기 위하여 Bean이라는 이름의 객체로 만들어서 관리한다.
이렇게 Bean으로 등록된 객체는 스프링 컨테이너에 의해 생성, 관리 , 주입된다.!

Spring Container

IoC Container, DI Container, Spring Container 등등 부르는 용어가 다양한 것 같다.
나는 둘다 공평하게 Spring Container가 적절한 명칭같다.
그래서 이 컨테이너는 Bean들을 담아서 관리하는 창고와 같이 사용된다.
개발자가 객체를 요청하면 컨테이너에 보관중인 Bean 꺼내어 의존성을 주입하여 사용된다.


⭐틀린 내용 수정,지적은 언제나 환영합니다.⭐

0개의 댓글

관련 채용 정보