본문 바로가기
Java Spring/MVC

[Spring] Spring 시작하기

by GGShin 2022. 6. 17.

Spring 살펴보기

한 번 Spring initalizer로 만든 Spring 파일은 일반 java 파일과 어떻게 다른지 간단하게 살펴보겠습니다. 

Spring initializer로 파일을 만들면 여러 파일들이 한 directory에 생성이 됩니다.

그 중에 main() method가 담긴 파일이 있는데, 일반 java 파일과는 다르게 그 java file의 class에는 

@SpringBootApplication annotation이 붙어있습니다!

그리고 main() method안에는 SpringApplication.run()이 실행되고 있네요! 

 

1
2
3
4
5
6
7
8
9
10
//기본적으로 생성되는 코드!
@SpringBootApplication
public class PracticeApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(PracticeApplication.class, args)
 
    }
}
 
cs

 

@SpringBootApplication은 configuration이 이루어지는 class임을 명시하기 위한 annotation 입니다.
Configuration이 이루어진다는 것은 하나 이상의 @Bean method가 있고, 
auto-configuration과 component scanning이 일어난다는 의미입니다. 

 

.run() method는 ApplicationContext type을 반환합니다. 그렇기 때문에 아래의 코드처럼 ApplicationContext type의 변수로 값을 받을 수 있습니다. Application Context는 bean이 관리되는 공간이라고 하였습니다! 그 중요한 공간이 여기에 생성이 되어 있었네요.

 

ApplicationContext 타입 변수에 getBeanDefinitionNames method를 이용하면 현재 application context에 생성되어 있는 bean의 이름을 확인해 볼 수 있습니다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootApplication
public class PracticeApplication {
 
    public static void main(String[] args) {
 
        ApplicationContext apc = SpringApplication.run(PracticeApplication.class, args);
 
        //현재 application context에 등록되어 있는 bean 이름을 확인할 수 있습니다.
        for(String s : apc.getBeanDefinitionNames()) {
            System.out.println(s);
        }
    }
 
}
cs

 

아직 아무런 bean을 따로 설정하지 않은 상태에서 실행을 해보면,

이미 context 안에 여러 bean들이 생성되어 있음을 확인할 수 있습니다.

 

그리고 그 중에는 SpringApplication을 run하고 있는 class도 bean으로 들어가 있습니다. 

 

Spring에게 관리할 대상들을 알려주기

이전 포스팅에서 Spring은 개발자 대신에 인스턴스를 생성하고 DI를 해준다고 하였습니다. 대신 우리는 Spring이 관리할 class와 의존관계를 알려주어야 합니다. 그렇다면 Spring에게 어떻게 그런 정보들을 알려줄 수 있을까요?

바로 annotation을 통해 알려줄 수 있습니다.

어떤 것을 bean으로 관리할 것인지와 의존 관계를 알려주는 annotation이 있는데 @Component와 @Autowired 입니다.

 

@Component 사용해보기

만약에 class를 새로 생성하고 해당 class를 bean으로 관리하고 싶다면 어떻게 하면 될까요?

Customer라는 class를 생성한 뒤에 bean으로 관리하려면 위에 @Component annotion을 붙여주면 됩니다. 

1
2
3
4
5
6
 
//Customer class 생성 후 @Component 붙여서 Bean으로 관리할 것이라고 명시!
@Component
public class Customer {
}
 
cs

 

@Component 이외에

 

@Service

@Controller

@Repository

 

를 붙여도 bean으로 관리할 수 있습니다. 

 

위의 코드는 @Service의 코드인데, 보면 Service annotation에도 @Component가 붙어있기 때문에 @Service를 사용해도 bean으로 사용할 수 있는 것입니다. @Controller, @Repository도 마찬가지 입니다. 

 

* 다시 root class로 돌아와서 @SpringBootApplication 코드를 살펴보면

@ComponentScan이 붙어있는 것을 확인할 수 있습니다. 

 

이 @ComponentScan을 이용해서 @Component가 붙은 요소들을 전부 찾는 작업이 이루어지게 됩니다

 

@Autowired 사용해보기

 

A 클래스가 B 클래스의 인스턴스를 내부에서 사용하게 되는 경우 A는 B에 의존해있다고 표현합니다.

 

public class A {

  B b = new B();

  public void useB(){
     b.bmethod();
  }

}

 

위 예시에서 보면 class A가 내부에서 B의 인스턴스를 만들고, 그 인스턴스를 이용한 useB()라는 method를 정의하고 있습니다. 하지만 이런식으로 class A에서 바로 B의 인스턴스를 만들게 되면 추후에 B가 아닌 C, D class로 바뀌게 된다거나 (혹은 동적으로 바뀌어야 된다거나) 할 때 해당 부분의 코드를 매번 바꾸어 주어야 하는 번거로움과 버그 생성의 위험이 생기게 됩니다. 그래서 클래스 내부에서가 아닌 외부에서 인스턴스를 만들어 주입해주는 방법을 채택하게 됩니다. 그리고 외부에서 인스턴스를 생성하고 주입하는 것은 Spring의 Application context가 담당합니다. 

 

그럼 의존하고 있다는 것을 Spring에게 알려주어야겠죠? 그 때 사용하는 annotation이 @Autowired입니다. 

 

@Component
public class A {

  @Autowired //dependency에 @Autowired를 붙여줍니다.
  I i; //interface를 사용하여 다형성을 이용해줍니다.
  
  public A(I i) {
  	this.I = i;
  }
 
  public void useI(){
     i.imethod();
  }

}

 

 

이렇게 dependency가 있는 곳에 @Autowired를 붙여주면 됩니다.

그러면 생성자를 통해 의존성이 주입됩니다. (setter로 주입할 수도 있습니다.)

 

여기서 I는 class B가 implements 하고 있는 interface를 나타낸 것입니다. 단순히 DI 관점에서만 생각하면 I로 적힌 부분을 B로 바꾸어 줄 수 있습니다. 하지만 B의 super class를 이용하여 추후에 B가 아닌 C, D,... 등 I를 implements하고만 있다면 해당 자리에 들어가 사용이 될 수 있도록 하기 위해 I로 작성해주었습니다. 이건 추상화를 통해 접근 방식은 일관되게 유지하되 기술을 유연하게 사용할 수 있게 하는 원칙인 PSA에 해당하겠죠?

 

이렇게 Application context가 bean을 우리가 원하는 대로 관리할 수 있도록 알려주고 정해주는 것이 Spring의 기본인 것 같습니다.

가장 기본이 되는 내용을 먼저 살펴보았고, 

앞으로 다양한 annotation들이 있는데 중요하다고 생각되는 것들 위주로 더 공부해 보도록 하겠습니다! 

감사합니다☺️

 

 

반응형