본문 바로가기

Spring

Spring(스프링) 이란? 뭘까?

728x90
반응형
SMALL

Spring Framework 가 뭐지?

자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크

 

일상 생활에서 불을 사용하기 위해 '라이터' 나 '성냥' 라는 도구를 사용합니다.

 

라이터 혹은 성냥이 없다면?

 

고대로부터 인류가 사용해온 불 붙이는 방법. 두 물체 사이에 일어나는 마찰의 운동에너지를 열에너지로 변환한다.

 

말그대로 개고생을 해서 불을 피워야합니다.

 

Spring Framework  =  성냥, 라이터

 

개발자들이 개발을 할 때에 Spring Framework가 없다면 처음부터 환경설정도 하고 이것저것 세팅하고 어우.....

 

생각만 해도 끔찍합니다.

 

하지만,

 

Spring Framework를 이용한다면 말이 틀려지죠.

 

조금 더 편리하게 개발자들이 개발을 할수 있도록 이용하는 도구 라고 생각하시면 됩니다.

 

Spring Framework 을 공부하기 전 기본적으로 알아야 하는 사전 지식

1. 웹 프로젝트에 사용되므로 웹 개발에 대한 전반적인 이해가 필요해요.

 

2. 스프링은 자바 기반 프레임워크라서 자바에 대해 기본적으로 알아야 해요.

 

3. 웹 문서를 구성하는 언어 HTML , CSS , JS를 기본적으로 알아야 해요.

 

4. 서버측에서 데이터베이스를 다루기 때문에 데이터베이스의 대한 기본지식을 알아야 해요.

 

 

Spring 핵심 기술

 

1. IOC (Invertion Of Control) 제어 역전

 

2. DI(Dependency Injection) 의존성 주입

 

3. AOP(Aspect-Oriented Programming) 관점 지향 프로그래밍

 

 

IOC는 뭐죠?

 

객체의 생성부터 생명주기의 관리까지 객체에 대한 제어권이 개발자가 아닌 프레임워크에 있다는 뜻이다.

 

 

 

 

과거에는 의존관계의 제어를 개발자가 직접 해줬다.

@Repository
public class StudyRepository {
}

위와 같은 Repository 객체가 있을 때 과거에는 아래와 같이 개발자가 직접 제어했다.

@Service
public class StudyService {
	StudyRepository studyRepository = new StudyRespository();
    }

 

 

Spring 의 IOC 가 적용된 방식 (객체에 대한 제어권이 프레임워크로 넘어간 방식)

@Service
public class StudyService {
	StudyRepository studyRepository;
    
    @Autowired
    public StudyService(StudyRepository studyRepository) {
    	this.studyRepository = studyRepository;
    }
}

 

DI는 뭐죠?

말 그대로 의존적인 객체를 직접 생성하거나 제어하는 것이 아닌,

 

특정 객체에 필요한 객체를 외부에서 결정해서 연결 시키는 것을 의미 한다.

public class One {

    private Two two;
    
    public One() {
        this.two = new Two();
    }
    
    public void HelloWorld() {
        this.two.hello();
    }
}

위 코드를 보면...

 

One 클래스에서 HelloWorld 메소드가 호출되기 위해서는 Two 클래스가 필요하다.

                                         

                                                   ↓(해석)

 

One 클래스는 Two 클래스의 의존성을 가진다. (One 클래스는 Two클래스가 필요하다.)

 

 

※위와 같은 코드는 결합도가 굉장히 높은 코드라고 볼수있다.

 

                                                   

 

Two클래스가 수정되면 One클래스도 Two클래스의 수정부분을 똑같이 수정해줘야 하기 때문이다.

 

 

 

DI 사용법 3가지 !?

 

스프링에서 DI를 할 때에 @AutoWired 라는 어노테이션을 사용합니다.

 

 

1. Field에다 붙이기(Field Injection)

 

2. Setter에다 붙이기(Setter Injection)

 

3. 생성자에다 붙이기(Constructor Injection)

 

 

 

 

Field에다 붙이기(Field Injection)

public class One {

    @Autowired
    private Two two;
    
    public void HelloWorld() {
        this.two.hello();
    }
}

 

장점 

  • 읽기 쉽다.
  • 사용하기 편하다.

 

단점 

  • Constructor Injection과 다르게 Field Injection은 final을 선언할수 없다.
  • 불변성X(객체가 변할 수 있다.)
  • 스프링 컨테이너 말고는 외부에서 주입할 수 있는 방법이 없다.

 

Setter에다 붙이기(Setter Injection)

public class One {

    private Two two;
    
    @Autowired
    public void setTwo(Two two) {
        this.two = two;
    }
    
    public void HelloWorld() {
        this.two.hello();
    }
    
}

장점

  • 런타임시에 할 수 있도록 낮은 결합도를 가지게 구현되어있다.

단점

  • Setter Injection을 통해서 Service의 구현체를 주입해주지 않아도 Controller 객체는 생성가능함으로
    set을 통해 Service의 구현체를 주입해주지 않았으므로, NullPointerException이 발생한다.
  • 주입이 필요한 객체가 주입이 되지 않아도 얼마든지 객체를 생성할수 있다.(오류발생가능성)
    (해결 방법 : Constructor Injection(생성자 주입) )

 

Constructor에다 붙이기(Constructor Injection)

public class One {

    private Two two;
    
    @Autowired
    public One(Two two) {
        this.two = two;
    }
    
    public void HelloWorld() {
        this.two.hello();
    }
}​

장점

  • Null을 주입하지 않는 한 NullPointerException 발생하지 않음.
  • 의존관계 주입을 하지 않은 경우 Controller 객체 생성 불가능. (NullPointerExcpetion 방지)
  • final을 사용하여 객체 변이 방지 (객체 불변성)
  • 컴파일 단계에서 순환 의존성을 발견 해 낼수 있다.
  • 테스트 코드의 작성 용이

 

 

 

AOP는 뭐죠?

 

AOP는 Aspect Oriented Programming의 약자  = 관점 지향 프로그래밍

 

OOP를 보완하는 수단 , 흩어진 Aspect 를 모듈화 할 수 있는 프로그래밍 기법이다.

 

 

공통 기능을 모듈화 하여, 필요할 때 연결함으로써 유지보수 혹은 재사용에 용이 하도록 프로그래밍 하는 것

 

 

쉽게 말하면, 공통된 부분을 좀 더 쉽게 프로그래밍 하는 기법입니다.

예시

public class Hello {
    public String HelloWorld(String name) {
    	//로그 남기는 공통 코드
        System.out.println("log: " + new java.util.Date());
        
        String msg = "helloWorld!!!" + name;
        return msg;
    }
}

위 코드는 실행된 시간의 로그를 남겨주는 코드를 갖고 있습니다.

 

Hello클래스로 부터 분리 하도록 하겠습니다.

public class HelloLog {
    public static void log() {
    	System.out.println("log: " + new java.util.Date());
    }
}

클래스 분리하면 처음에 작성 한 Hello 클래스 코드는 다음과 같이 달라집니다.

public class Hello {
    public String HelloWorld(String name) {
    	HelloLog.log(); //공통코드를 호출하는 코드가 포함됨
        
        String msg = "helloWorld!!!" + name;
        return msg;
    }
}

 

코드가 줄어들긴 했지만, 이 또한 없애고 싶을 때 AOP를 사용합니다.

 

 

프록시를 이용한 AOP

public class HelloWorldProxy extends Hello {
    @override
    publid String HelloWorld(String name) {
    	HelloLog.log(); //공통 코드 실행
        return super.HelloWorld(name); //핵심 코드 실행
    }
}

HelloWorldProxy클래스가 Hello클래스를 상속하고 오버 로딩을 구현했습니다.

다른 데서 Hello 클래스를 호출하면 HelloWorldProxy가 먼저 호출될 것이고,

HelloWorldProxy는 로그를 찍고, Hello 클래스의 핵심 코드를 실행합니다.

 

단점

  • 누군가가 Hello의 A메서드를 호출해야 프록시를 거쳐서 해당 메서드가 호출됨

 

void Test() {
    MethodA();
}

@Transactional
void MethodA() {
    MethodB();
}

@Transactional
void MethodB() {
    ...
}

@Transactional 어노테이션은 해당 메서드를 트랜잭션처럼 동작하게 합니다.

 

외부에서 MethodB 메서드를 호출하면 정상적으로 트랜잭션이 걸립니다.

 

하지만,

 

외부에서 MethodA 메서드를 호출하게되면, MethodA가 내부적으로 MethodB 메소드를 호출하기에

에러는 나지 않지만 MethodB 메소드에 트랜잭션이 정상 작동하지 않습니다.

 

<이유>

내부적으로 메서드를 호출하기 때문에 프록시를 거치지 않아서 @Transactional 어노테이션을 거치지 않게 됩니다.

 

 

스프링에서의 AOP

 

스프링은 애플리케이션을 구현할때 필요한 기능을 제공하는 것을 목적으로 한다.

 

(완전한 AOP 기능을 제공하는것이 목적X)...

728x90
반응형
LIST