20231218 (월) 스프링 입문 시작 + 저번주차 과제물 피드백 반영

2023. 12. 18. 21:02TIL

새주차가 시작되면서 스프링이란 것을 배우기 시작했다.

 

SPRING 이란?

JAVA / Kotlin 기반의 Application Framework 이다.

내가 이해한대로 써보자면 개발자가 개발에만 몰두할수 있도록 다양한 요소들을 제공하는 프로그램인 듯 하다.

 

프레임워크와 비슷한 개념으로 라이브러리라는게 있는데..

라이브러리는 "개발시에 활용가능한 코드 모음" 이라고 이해하면 편하다.

 

그래서 Framework과 Library의 차이가 뭘까요?

  • Application을 기준으로 Application을 호출하는지, 호출을 당하는지 여부로 구분을 할 수 있습니다. 즉, Caller 와 Callee의 차이라고 말할 수 있습니다.
  • Framework는 Application을 호출하는 Caller 역할을하고, Library는 반대로 Application이 호출을 하는 Callee의 역할을 한다고 할 수 있습니다.
  • 결국, Framework은 우리가 Application 관련 코드를 작성하면 이를 알아서 호출해주는 역할을 하고, Library는 우리가 Application 코드를 작성할 때 활용하는 도구라고 보시면 됩니다!

위는 강의자료를 가져온것이고 맨 아랫줄이 가장 중요하다.

 

 

추가로 라이브러리와 짝꿍들 모듈, 패키지

  • Package
    • Package는 관련 클래스 및 인터페이스 집합을 구성하는 네임스페이스입니다. Java, Kotlin에서는 개념적으로 하나의 디렉토리라고 볼 수 있습니다.
  • Module
    • Module은 패키지와 관련 리소스의 모음입니다. 하나의 작은 역할을 담당합니다.
    • 특히, Java Module은 Application 혹은 API 를 별도의 module로써 패키징하는 매커니즘입니다.
  • Library
    • Library는 기능의 집합이라 할 수 있습니다.
    • 여러 개의 모듈로 구성됩니다.
    • 예를 들어, Collections 라이브러리는 Set module, List module, Map module 등으로 구성된다고 말할 수 있습니다.

 


 

Spring 용도의 변화

 

이전에는 HTML / CSS와 같은 리소스를 응답해주는 역할도 하였지만, 현재에는 Data를 주로 응답해주는 역할을 한다. 여기서 Data는 여러 형태가 될 수 있지만, 현재에는 대부분 JSON 포맷을 사용한다.

제이슨은 Key : Value 형태로 이루어져있고,

Key는 문자열, Value에는 문자열을 포함 수, 참/거짓, 배열, 객체, Null 값이 올수 있다.

결론적으로, 현재의 Spring은 Client, Frontend Server의 요청에 따라 적절한 JSON Data를 응답해주는 역할을 주로 한다고 볼 수 있다!

 

그럼 이제 본격적으로 스프링을 파헤쳐보자!

 

스프링은 Web Application 을 만들기에 특화되어있고 이제 과제를 하면서 이 Web Application 을 만들건데,

그렇다면 스프링의 Web Application을 만들기위한 요구사항 뭘까?

  • 유저 혹은 Frontend Application의 요청을 처리하고, 적절한 응답을 줄 수 있어야 합니다.
  • 예외 처리를 할 수 있고, 예외가 발생했을 때 적절한 응답을 줄 수 있어야 합니다.
  • 인증과 인가 처리를 할 수 있어야 합니다.
  • 비즈니스 로직을 처리할 수 있어야 합니다.
  • Transaction 관리 전략이 있어야 합니다.
  • 스토리지 및 다른 외부 시스템과 통신할 수 있어야 합니다.

이 모든걸 종합해 봤을때 예시를 들자면 어떤 홈페이지의 로그인화면 정도가 떠오른다.

이런 요구사항을 충족하기 위해선 Layer를 나눠서 개발을 하는데

 

  • Web Layer
    • Application의 최상위 Layer입니다.
    • Client의 요청을 받고, 응답을 주는 역할을 주로 합니다. (i.e. Controllers)
    • 하위 Layer에서 발생한 예외들을 처리하여 적절한 응답을 줍니다. (i.e. Exception Handlers)
    • 인증과 인가 처리를 담당합니다. (i.e. Filters)
  • Service Layer
    • Web Layer 하위에 존재하는 Layer입니다.
    • Transaction 경계의 역할을 합니다.
    • Application Service, Infrastructure Service로 나뉘어집니다.
      • Application Service: 요청의 처리에 대한 주요 로직을 담당하고, 최종적으로 응답을 WebLayer에 넘겨주는 역할을 합니다.
      • Infrastructure Service: 데이터 베이스, 이메일 서버 같은 외부 서비스와 통신하는 역할을 합니다. Application Service에서 Infrastructure Service를 사용합니다.
  • Repository Layer
    • 가장 하위에 존재하는 Layer입니다.
    • 데이터베이스와 통신하는 역할을 담당합니다.

이렇게 보통 3개로 나뉘어진다.

웹이 서비스레이어를 호출하고 다시 서비스레이어가 리포지레이러를 호출하는 형식

그리고 이 레이어사이의 변수로 넘겨지는게 바로 DTO와 Domain Model

 

우리가 작성하는 부분이 요 3개의 레이어인데

이를 공부하다보면 자주 등장할것이 바로 DI(의존성 주입), IoC(제어의 역전)

 


 

 

DI란?

객체가 자체적으로 의존성을 생성하는것이 아닌 외부에서 주입받는 디자인패턴

추천되는 방식 - Constructor

이외에 방식 - Field, Setter

이제 여기서 이해를 돕기위해 예시 몇가지

DI 가 적용되지 않은 예시
class Dependent() {
    private val dependency = Dependency(arg1, arg2)
}

 

Constructor를 통해 주입받는 예시 (가장 추천되는 방식)

class Dependent(private val dependency: Dependency)
Field를 통해 주입 받는 예시
 
class Dependent() {
    lateinit var dependency: Dependency
}
Setter를 통해 주입받는 예시
class Dependent() {
    private lateinit var dependency: Dependency

    fun setDependency(dependency: Dependency) {
        this.dependency = dependency
    }
}​

 

 IoC란?

객체의 생성과 생명주기를 외부에서 제어하는 디자인패턴

Ioc는 굉장히 넓은 의미로 이를 구현하는 방법중 하나가 DI이다.

  • Framework에서 IoC를 제공할 때, 이를 IoC Container라고 부릅니다. Spring에서는 IoC의 방식중 DI 를 주로 ****사용하기 때문에, 최근에는 DI Container라고 불리기도 합니다.
  • 결국 우리는 이 DI Container를 통해서, 우리가 작성한 Class의 관리를 크게 신경쓰지 않고, Spring에 맡길 수 있는 것입니다 👏

그럼 이제 우리가 스프링을 배우면서 쓸 IoC Container

바로 Spring Bean

내가 전주차들에서 진행한 코딩들 답안을 봤을때 골뱅이 뒤에 오던 문자들이 바로 이런 스프링 빈과 같은 종류였던 것이다.

  • Spring Bean을 등록하는 방법
    • 기본적으로 @Component Annotation을 통해 이루어집니다. Annotation은 Kotlin 및 Java에서 사용되는 메타데이터의 일종으로, @로 시작되며 프로그램 코드에 부가적인 정보를 제공해주는 역할을 합니다. 아래와 같이 클래스를 Spring Bean으로 등록할 수 있습니다.
@Component
class Dependency()
  • Bean Configuration 파일을 활용하는 방법을 통해서도 가능합니다. @Configuration@Bean Annotation을 통해 등록할 수 있습니다.
@Configuration
class DependencyConfiguration() {

    @Bean
    fun exampleDependency(): Dependency {
        return Dependency()
    }
}

 

다른 어노테이션도 많긴 하지만 일단은 배워나가면서 알아가도록 하자

그리고 이런 Spring Bean을 관리하는 방법 Bean Scopes

여기서 이제 이전에 배우려다가 말았던 싱글턴이 나온다.

 

  • Bean Scope는 Bean의 생명주기를 말합니다. Bean은 기본적으로 객체기 때문에, Instance가 생성됩니다. 이 Instance의 생명주기를 결정하는 것이 바로 Bean Scope라 할 수 있습니다.
  • Bean Scope는 기본적으로 Singleton으로 설정됩니다. Singleton은 하나의 디자인 패턴으로, 특정 클래스가 인스턴스화 될 때 해당 클래스의 인스턴스가 하나만 생성되도록 보장하는 패턴입니다. 즉, Spring에서 기본적으로 Bean은 IoC Container당 하나만이 생성되고, IoC Container와 생명주기를 같이합니다.
  • 이렇게 Singleton이 기본 Bean Scope가 되는 이유가 무엇일까요? 제일 큰 이유는 성능 향상과 자원 관리에 있습니다. Instance를 만들고 초기화 하는 것도 비용이기 때문에, 이미 만들어진 Instance를 재사용한다면 전체적인 성능이 향상됩니다. 또한, 재사용으로 인해 메모리 자원을 효율적으로 사용할 수 있습니다.
  • Singleton이기 때문에 주의해야하는 점도 있습니다. 기본적으로 Bean은 내부에 상태정보를 갖지 않는 Stateless 방식으로 생성되어야 합니다. 상태를 갖게 되고 동시에 두 개 이상의 요청이 해당 상태를 변경하려 했을때 예측하지 못한 상태로 변할 수 있기 때문입니다.
  • Singleton 이외에 다른 생명주기들 또한 개발자가 직접 설정이 가능합니다.
    • Prototype: Instance를 요청할 때마다 새로운 Instance를 생성합니다.
    • Request: Bean의 생명주기를 단일 HTTP request와 함께합니다. 즉, 각 Http 요청이 올때마다 빈이 생성되고 사라집니다.
    • Session: Bean의 생명주기를 Http session과 함께합니다.
    • Application: Bean의 생명주기가 ServletContext와 함께합니다. 언뜻보면 Singleton과 무엇이 다르냐 할 수 있지만, 하나의 Application에서 여러 DispatchServlet을 등록할 수 있기때문에 명확히 다릅니다.
    • 아래처럼 Annotion을 통해 Scope를 설정할 수 있습니다.
import org.springframework.stereotype.Component
import org.springframework.context.annotation.Scope
import org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE


@Component
@Scope(SCOPE_PROTOTYPE)
class Dependency()

 

많이 길지만 요약하자면 "기본적으로 Signleton으로 Bean의 Instance를 관리하고, 필요할 시에는 개발자가 직접 Prototype, Request, Session, Application 등을 써서 Bean의 생명주기를 설정할 수 있다." 이다.

 

 

일단 이렇게 월요일 입문강의를 모두 수강하고 문제도 몇개 풀어봤다.

확실히 그냥 강의듣는거 보다는 이렇게 직접 적고 하나하나 읽어가는게 이해가 잘 된다.

 

이후에는 이전에 받은 피드백을 생각해보면서 답안코드를 내 손으로 쳐보았다.

 

 

오늘의 한마디 : 앞으로 당분간은 팀도 안바뀌는 것 같다. 이번 팀과도 두루두루 친해질수 있으면 좋겠다.