[ 2022.10.28 TIL-스프링 설정 및 의존성 주입 ]

Coosla·2022년 10월 28일
1

TIL

목록 보기
3/29
post-thumbnail

Spring 환경 설정

✏️ 스프링 라이브러리 추가

  • 스프링 라이브러리 추가
    • 프로젝트를 javaEE 버전으로 생성
    • build.gradle 파일에 depenency 추가
      dependencies {
      	// 기존 javaEE에서 Servlet으로 변경
      	compileOnly('javax.servlet:javax.servlet-api:4.0.1')
      
      	testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
      	testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
      	
      	// 스프링 설정
      	implementation group: 'org.springframework', name:'spring-core', version: '5.3.19'
      
      	implementation group: 'org.springframework', name:'spring-context', version: '5.3.19'
      
      	implementation group: 'org.springframework', name:'spring-test', version: '5.3.19'
      }
  • Lombok 라이브러리 추가
    dependencies {
    	스프링 라이브러리 설정...
     	
    	// Lombok
    	compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
    	annotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
    	// 테스트 환경에서도 사용할 수 있게 설정 추가
    	testCompileOnly group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
    	testAnnotationProcessor group: 'org.projectlombok', name: 'lombok', version: '1.18.24'
    }
  • Log4j2 라이브러리 추가
    • build.gradle 설정
      dependencies {
      	스프링 라이브러리 설정 ...
       	
      	Lombok 설정 ...
      
      	// Log4j2 
      	implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.19.0'
      	implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.19.0'
      	implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.19.0'
      }
    • log4j2.xml 파일
      <?xml version="1.0" encoding="UTF-8" ?>
      <configuration status="INFO">
      	<Appenders>
      		<Console name="console" target="SYSTEM_OUT">
      			<PatternLayout charset="UTF-8" pattern="%d{hh:mm:ss} %5p [%c] %m%n" />
      		</Console>
      	</Appenders>
      
      	<loggers>
      		<logger name="org.springframework" level="INFO" additivity="false">
      			<appender-ref ref="console"/>
      		</logger>
      
      		<logger name="org.zerock" level="INFO" additivity="false">
      			<appender-ref ref="console" />
      		</logger>
      
      		<root level="INFO" additivity="false">
      			<AppenderRef ref="console"/>
      		</root>
      	</loggers>
      </configuration>
  • JSTL 라이브러리 추가
    dependencies {
    	스프링 라이브러리 설정 ...
     	
    	Lombok 설정 ...
    
    	Log4j2 설정 ...
    	
    	// JSTL
    	implementation group: 'jstl', name: 'jstl', version: '1.2'
    }

의존성 주입

✏️ 의존성 주입하기

  • 스프링 프레임워크는 자체적으로 객체를 생성하고 관리하면서 필요한 곳으로 객체를 주입하는 역할

  • 설정 파일이나 어노테이션을 이용해 의존성 주입

  • root-context.xml

    • MVC 설정과 관련된 여러 처리를 담당하는 파일
    • 빈 객체들을 관리하는 문서
    • 라이브러리를 bean 태그를 이용해 빈 객체를 생성하고 주입하는 방식으로 사용
      ...
      
      <bean class="org.zerock.springex.sample.SampleDAO"></bean>
      
      <bean class="org.zerock.springex.sample.SampleService"></bean>
      
      ...

  • 테스트 해보기

    • root-context 파일에 Test 클래스에서 사용하는 빈 객체가 없으면 UnsatisfiedDependencyException 오류 발생
      @Log4j2
      // JUnit5 버전에서 spring-test를 이용하기 위한 설정
      // JUnit4 버전은 @Runwith
      @ExtendWith(SpringExtension.class)
      // 스프링 설정 정보 로딩
      @ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/root-context.xml")
      public class SampleTests {
      
         // 의존성 주입 관련 어노테이션
         @Autowired
         private SampleService sampleService;
      
         @Test
          public void testService1(){
              log.info(sampleService);
              Assertions.assertNotNull(sampleService);
          }
      }

✏️ 간단한 의존성 주입 과정

  • 스프링이 시작되면 빈 객체를 관리하기 위해 ApplicationContext가 생성

  • root-context에 bean태그나 context:component-scan 태그를 통해 빈객체 생성 및 관리 시작

  • 코드를 실행하다 @Autowired를 만나면 스프링이 생성된 빈객체에 존재하는지 확인 후 존재하면 해당 부분에 주입

✏️ 의존성 주입할 때 사용하는 어노테이션

  • @Autowired
    • 필요한 의존 객체의 타입에 해당하는 빈 객체를 찾아 주입해주는 역할을 함.
    • 의존성 주입을 할 대상을 찾지 못하면 애플리케이션 구동에 실패
    • 주입 방법
      • 생성자 주입
      • Setter 주입
      • 필드 주입
  • @Contoller
    • MVC 컨트롤러를 나타냄
    • View를 반환
    • @RestController도 있는데 데이터를 반환
  • @Service
    • 서비스 계층의 객체를 나타냄
  • @Repository
    • DAO와 같이 데이터를 나타냄
  • @Component
    • 일반 객체나 유틸리티 객체를 나타냄

✏️ 의존성 주입 방식

  • 생성자 주입 방식
    • 생성자에 의존성 주입을 받고자 하는 필드를 나열하는 방식
    • 생성자 주입 방식 규칙
      • 주입 받아야하는 객체의 변수는 final로 작성
      • 생성자를 이용해서 해당 변수를 생성자 파라미터로 지정
    • 장점
      • 필수적으로 사용해야하는 레퍼런스 없이 인스턴스를 만들지 못하도록 강제
      • 생성자가 하나면 @Autowired없이 주입 가능
      • 순환 참조 의존성을 알수 있음
      • 생성자에 많은 의존성이 추가될 경우 리팩토링 시점을 감지할 수 있음
      • 의존성 주입 대상 필드를 final로 불변 객체 선언 가능
      • 테스트 코드 작성시 생성자를 통해 의존성 주입이 용이
    • 단점
      • 어쩔 수 없는 순환 참조일 경우 생성자 주입으로 해결하기 어려움
  • Setter 주입 방식
    • Setter 메소드에 의존성을 주입하는 방식
    • 장점
      • 의존성이 선택적으로 필요한 경우에 사용
      • 생성자에 모든 의존성을 기술하면 과도하게 복잡해질 수 있는 것을 선택적으로 나눠 주입할 수 있게 부담을 덜어줌
      • 생성자 주입 방법과 Setter 주입 방법을 적절하게 상황에 맞게 분배하여 사용 가능
    • 단점
      • 의존성 주입 대상 필드가 final 선언 불가
  • 필드 주입 방식
    • 필드에 의존성을 주입하는 방식
    • 장점
      • 가장 단순
    • 단점
      • 의존 관계가 눈에 잘보이지 않고 추상적, 의존 관계가 과도하게 복잡해줄 수 있음
      • 단일 책임 원칙에 반함
      • DI 컨테이너와 강한 결합을 가져와 외부 사용에 용이하지 않음
      • 의존성 주입 필드에 final 선언 불가

✏️ 인터페이스로 느슨한 결합

  • 느슨한 결합(Loose Coupling)
    • 객체와 객체의 의존 관계의 실제 객체를 몰라도 가능하게 하는 방식
  • 인터페이스를 이용해 여러 빈 객체를 구현했을 때 발생하는 문제
    • 해당 타입의 객체가 여러개 존재해서 발생
    • 해결하기 위해 @Primary 또는 @Quaifier를 사용
  • @Primary 어노테이션
    • 같은 타입의 빈 객체에 우선순위를 부여
    • 스프링이 해당 빈 객체를 찾을 때 먼저 확인을 진행
  • @Qualifier 어노테이션
    • 빈 객체에 이름을 지정하여 특정 이름을 가진 빈 객체를 주입

스프링 웹 프로젝트 설정

  • 스프링 웹 관련 라이브러리 추가
    implementation group: 'org.springframework', name: 'spring-webmvc', version: '5.3.23'
  • web.xml 설정
    // 서블릿 이전에 서블릿을 초기화
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>
     
    // 웹 애플리케이션 설정
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

참고

스프링

profile
프로그래밍 언어 공부 정리

0개의 댓글