Spring

[Spring] IoC(제어의 역전), DI(의존성 주입) , Mock 객체

박졔삐 2024. 10. 6. 01:32

 

 

 

좋은 코드를 위한 IoC(제어의 역전), DI(의존성 주입) , Mock 객체

 

 

좋은 코드란?

 

- 논리가 간단해야 한다.

- 중복을 제거하고 표현을 명확하게 한다.

- 코드를 처음보는 사람도 쉽게 이해하고 수정할 수 있어야 한다.

- 의존성을 최소화해야 한다.

- 새로운 기능을 추가 하더라도 크게 구조의 변경이 없어야 한다.

 

 


IoC(제어의 역전)와 DI(의존성 주입)는 스프링 프레임워크의 핵심 개념으로,
애플리케이션의 구성과 객체 생성을 관리하는 방식이자 좋은 코드 작성을 위한

Spring의 핵심 기술 중 하나라고 할 수 있다.

이 두 가지 개념은 스프링이 제공하는 유연성과 테스트 용이성을 높이는 데 중요한 역할을 한다.

 

 

[ IoC(제어의 역전) ]

 

IoC는 애플리케이션의 제어 흐름을 개발자가 아닌 프레임워크가 관리하게 하는 패턴이다.
전통적인 프로그래밍에서는 객체가 직접 다른 객체를 생성하고 의존성을 관리하지만, IoC를 사용하면 
스프링 컨테이너가 객체의 생성과 의존성을 관리한다.
이로 인해 코드의 결합도가 낮아지고 유지보수가 용이해진다.

 



[ DI(의존성 주입) ]


DI는 IoC의 한 형태로, 객체의 의존성을 외부에서 주입하는 방식이다.
의존성 주입은 일반적으로 다음 세 가지 방법으로 이루어진다.

1. 생성자 주입 : 객체가 생성될 때 의존성을 생성자의 매개변수로 전달한다.

@Component
public class UserService {
    private final UserRepository userRepository;

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



2. 세터 주입 : 의존성을 세터 메소드를 통해 주입한다.

@Component
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}




3. 필드 주입 : 의존성을 직접 필드에 주입한다. 이 방법은 권장되지 않지만, 간단한 경우에 사용될 수 있다.

@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;
}




장점

- 유연성 : 의존성을 외부에서 주입함으로써 코드 변경 없이 다른 구현체로 쉽게 교체할 수 있다.
- 테스트 용이성 : Mock 객체를 사용하여 단위 테스트를 쉽게 작성할 수 있다.
- 관심사의 분리 : 비즈니스 로직과 객체 생성 로직을 분리할 수 있다.

 

요약 

IoC와 DI는 스프링 프레임워크의 주요 개념으로, 객체의 생명주기와 의존성을 효율적으로 관리하여
소프트웨어 개발의 유연성과 유지보수성을 높인다. 이 두가지를 이해하면 스프링을 활용한 애플리케이션 개발이
훨씬 수월해질 것이다.

 


[ Mock 객체  ]

 

Mock 객체는 주로 단위 테스트에서 사용되는 객체로, 실제 객체의 동작을 
흉내 내는 테스트 더블(test double)이다. 즉 Mock 객체는 테스트하려는 코드의 의존성을 대체하여, 테스트 환경에서 
특정 동작이나 상태를 제어할 수 있게 해준다.

 


Mock 객체의 특징 

 

1. 행동 정의 : Mock 객체는 특정 메소드가 호출되었을 때 예상되는 행동을 정의할 수 있다.
예를 들어, 어떤 메소드가 호출되면 특정 값을 반환하도록 설정할 수 있다.
2. 상태 검증 : 테스트가 끝난 후, Mock 객체가 예상한 대로 사용되었는지 검증할 수 있다. 즉,
특정 메소드가 호출되었는지, 몇 번 호출되었는지 등을 확인할 수 있다.
3. 의존성 제거 : 실제 의존성이 아닌 Mock 객체를 사용함으로써, 테스트가 의존하고 있는 외부 시스템
(데이터베이스, 웹 서비스 등)의 영향을 받지 않는다. 이는 테스트의 안정성과 속도를 높인다.



예제

 

예를 들어, UserService가 UserRepository에 의존한다고 가정했을 시, 이때 UserRepository의 
Mock 객체를 생성하여 UserService를 테스트할 수 있다.

import static org.mockito.Mockito.*;

public class UserServiceTest {
    
    @Test
    public void testGetUser() {
        // Mock 객체 생성
        UserRepository mockRepository = mock(UserRepository.class);
        UserService userService = new UserService(mockRepository);

        // Mock 객체의 동작 정의
        when(mockRepository.findById(1)).thenReturn(new User(1, "John"));

        // 테스트 실행
        User user = userService.getUser(1);

        // 결과 검증
        assertEquals("John", user.getName());
        verify(mockRepository).findById(1); // 메소드 호출 검증
    }
}



장점

- 독립성 : 외부 시스템에 의존하지 않고도 테스트를 수행할 수 있다.
- 정확성 : 의존성의 동작을 세밀하게 조정하여 트정 상황을 테스트할 수 있다.
- 속도 : 실제 객체를 사용하지 않기 때문에 테스트 속도가 빨라진다.

결론

Mock 객체는 테스트에서 의존성을 관리하고, 안정적이고 빠른 테스트를 가능하게 하는 중요한 도구이다.
이를 통해 더 효율적인 소프트웨어 개발과 유지보수가 가능해진다.


728x90
반응형