땅울림 썸머 코딩 서버 스프링 3주차

김수환·2024년 7월 21일

모든 것은 어떠한 목적을 위해 발명된다.
스프링의 목적은 '객체지향설계' 이다.
스프링은 framework 형태로 개발자들의 객체지향설계를 인도한다.

객체지향 프로그래밍

실세계를 살때 우리는 대부분 어떤 개념을 객체로 인식한다.
우리가 인식하는 객체라는 단위를 프로그래밍에 적용시키자.

  • 프로그램을 명령어의 목록으로 보는 것이 아니라 객체들의 모임으로 파악하는 것. 각각의 객체들은 메세지를 주고 받고, 데이터를 처리한다.
  • 프로그램을 유연하고, 변경이 용이하게 만들기 때문에 대규모 소프트웨어 개발에 사용된다.

객체지향

오브젝트

객체를 뜻함

넓은 의미로 실세계에 존재하거나 생각할 수 있는 것

우리가 개발을 하면서 접하게 될 프로그래밍에서의 객체는 속성과 기능을 가지는 프로그램 단위를 뜻합니다.

[Ex]

  • Lotto, PurchaseAmount
  • PurchaseController, RankController
  • InputView, OutputView

자바 빈즈(Java Beans)

  • JSP의 표준 액션 태그로 접근할 수 있는 자바 클래스. 즉 자바 객체이다.
  • 값을 가지는 속성(멤버변수)과 값을 설정하는 메소드(setter) 값을 추출하는 메소드(getter)로 이루어져 있다.
  • 자바빈즈는 하나의 JSP 페이지에 종속적으로 사용되는 것이 아니라, 여러 JSP 페이지에서 사용될 수 있다.
  • 비즈니스 로직 부분을 담당하는 자바 프로그램 단위.
  • 빌더 형식의 개발도구에서 가시적으로 조작이 가능하고 또한 재사용이 가능한 소프트웨어 컴포넌트.
  • 쉽게 말 해 JSP 파일 내에서 사용이 가능한 자바 객체라고 생각해도 무방하다.
    출처: https://ccomccomhan.tistory.com/37 [[꼼꼼한 개발자] 꼼코더:티스토리]

관심사의 분리 : SoC

Separation of Concerns

소프트웨어 요소의 상관관계와 설계를 적용하는 것이다. 적절한 SoC를 통해 복잡성은 관리 가능해진다.

하나의 클래스는 하나의 관심사를 다루도록 분리한다

"가능한 모든 것들을 단순하게 만들어라. 더 단순하게가 아니라." _Albert Einstein

[Ex]

  • Lotto : 1~45 사이의 중복되지 않은 숫자 6개
  • PurchaseAmount : 구매 금액
  • Result : 결과
  • PurchaseController : 구매행위를 관리
  • RankController : 등수 매기기를 관리
  • InputView : 입력만
  • OutputView : 출력만

[Ex2]

  • 주방 알바1한테는 요리만 시키고
  • 주방 알바2한테는 설거지만 시키고
  • 홀 알바1한테는 서빙만 시키고
  • 홀 알바2한테는 포장만 시키고

The Principle of Separation of Concerns

SoC 법칙이란 시스템 요소가 단일 목적이고 배타성을 가져야 한다는 것을 명시한다. 그 말은, 어떤 요소도 다른 요소와의 책임을 공유하면 안 되고, 그 요소와 관계가 없는 책임을 포함시킬 수 없다는 것이다.

SoC란 경계를 세우는 것으로서 달성된다. 경계란 주어진 책임 세트를 설명하는 논리적이거나 물리적인 제한이다. 경계란 애플리케이션 내에 핵심 행동을 정의하는 메소드, 객체, 컴포넌트, 서비스 등 의 사용을 의미한다. 혹은 소스 구성에 대한 프로젝트, 솔루션, 폴더 구조를 포함하기도 한다.

혹은 구조를 짜기 위한 애플리케이션 레이어와 티어들을 포함하기도 하고, 프로덕트 릴리즈 구성에 필요한 버전화 되어있는 라이브러리나 설치 파일을 포함하기도 한다.

그러나 Soc를 달성하는 프로세스는 종종 책임 세트의 분리를 내포하기도 한다. 목표는 시스템을 분리되지 않는 파트들로 조각 내는 것이 아니라, 시스템을 반복되지 않고 응집력이 있는 책임들의 세트를 가진 요소들로 구성하기 위함이다.

핵심은, SoC는 질서에 관한 것이다. SoC의 종합적인 목표는 각각의 파트가 의미있고 직관적인 롤을 수행하지만 변화에 적응하는 능력을 극대화시킨, 잘 조직된 시스템을 설립하는 것이다.

[참조]https://velog.io/@seanlion/soc1

스프링 프레임워크 동작구조

IOC

제어의 역전 : Inversion of Controller

프로그램의 제어 흐름 구조가 뒤바뀌는 것

  • 일반적으로 main(), application() 등과 같이 프로그램이 시작되는 지점에서 사용할 객체를 결정, 생성, 호출
  • 제어의 역전에서는 자신이 사용할 오브젝트를 스스로 선택 하지 않고, 제어 권한을 다른 대상에 위임한다.
  • 프레임워크도 제어의 역전 개념이 적용된 대표적인 기술
  • 프레임워크 위에 개발한 클래스를 등록 -> 프레임워크가 흐름을 주도하며 개발자가 만든 코드를 사용

[Ex]

만약 스프링 프레임워크를 활용해서 Lotto를 구현한다면?

[Ex2]

사장님이 직접 주방알바2한테 설거지 거리를 주면서 시키는게 아니라
설거지 거리가 생기면 주방알바2한테 설거지를 주면 된다는 매뉴얼을 만드는것

스프링의 IoC

스프링 빈

스프링이 제어권을 가지고 IoC 방식으로 직접 만들어 관계를 부여하는 객체

[Ex]

  • 주방알바1,2
  • 홀알바

스프링 컨테이너

  • 빈 팩토리 : 스프링에서 빈의 생성과 관계설정과 같은 제어를 담당하는 IoC 객체

  • 애플리케이션 컨텍스트 : IoC 방식에 따라 만들어진 빈 팩토리,

  • 스프링 컨테이너 : 빈 팩토리이자 애플리케이션 컨텍스트 의존관계 주입을 이용하여 애플리케이션을 구성하는 여러 빈들의 생명주기와 서비스 실행 등을 관리하며 생성된 인스턴스들에게 기능을 제공하는 것을 부르는 말이다.

  • 빈 팩토리라고 할 때는 빈을 생성하고 관계를 설정하는 IoC의 기본 기능에 초점을 맞춘 것.

  • 애플리케이션 컨텍스트는 별도의 정보를 참고해서 빈의 생성, 관계 설정 등의 제어를 총괄하는 것 에 초점을 맞춘 것

[Ex]

이미 뒤지는 매뉴얼을 만들어놓은 매니저.

  • 설정정보/ 메타정보 : 스프링 컨테이너를 적용하기 위해 사용하는 메타정보.
    더 궁금하다면?

[Ex]

주방알바1(설거지 담당) 이라는 명찰
이 명찰을 받으면 설거지만 뒤지게 하면 되는거야~~

스프링 컨테이너의 동작방식

  • 애플리케이션에서 IoC를 적용해서 관리할 모든 객체에 대한 생성과 관계설정을 담당한다.
  • 생성, 관계설정에 대한 코드가 없고 설정정보를 통해 생성정보와 관계설정에 대한 정보를 얻는다.
  • @Configuration 어노테이션을 통해 설정정보를 나타낼수 있다.
  • @Bean 어노테이션을 통해 객체 생성정보를 표현할 수 있다.

Spring framework는 매뉴얼 또는 매니저

여러분이 할일은?

  • 무슨 가게를 할지, 어떤 메뉴를 할지 정하면됨
  • 해당되는 알바생을 잘 뽑으면 됨.
    막연하게 주방알바1이 아니라 일 잘하는 애로 뽑아야한다!!

주방알바 1이 인터페이스라면?

  • 일잘하는 일꾼 김수환은 구현체!!
    물론 여러분이 김수환을 만들어야돼여ㅋㅋㅋ

싱글톤

싱글톤 패턴

객체의 인스턴스를 한개만 생성되게 하는 패턴

  • 프로그램 내에서 하나의 객체만 존재해야 한다.
  • 프로그램 내에서 여러 부분에서 해당 객체를 공유하여 사용해야한다.

[Ex]

설거지가 생길때 마다 주방알바를 뽑기 vs 주방알바 하나를 잘 뽑아서 설거지 시키기

  • 후자가 싱글톤

스프링에서의 싱글톤

서버 어플리케이션에서 싱글톤

클라이언트의 요청이 들어올 때 마다 객체를 새로생성
-> 과부하, 서버가 감당할 수 없음

  • 서블릿 클래스당 하나의 객체만 만들어서 클라이언트의 요청에 따라 객체를 공유해서 사용
  • 서블릿 클래스 ?
    서블릿은 웹 요청과 응답의 흐름을 간단한 메서드 호출만으로 체계적으로 다룰 수 있게 해준다. 일단은 간단하게 비즈니스 로직을 처리하는 클래스라고 이해합시다.

싱글톤의 한계

  • 상속 불가
    private 생성자
  • 테스트에 어려움
    생성 방식이 제한적이기 때문에 mock 객체(임시객체)로 대체하기 어려움
  • 서버환경
    클래스 로더 구성에 따라 (jvm의 분산 설치) 하나 이상의 객체가 생성 될 수 있음

싱글톤 레지스트리

스프링은 싱글톤 패턴으로 객체를 생성하고 관리한다.

  • static, private 의 사용과 상관없이 싱글톤 패턴을 사용할 수 있다.
  • 테스트 환경에서 자유롭게 객체를 생성할 수 있다.
  • 객체 지향적 설계와 디자인 패턴을 적용하는 데에 무리가 없다.

싱글톤과 오브젝트의 상태

멀티 스레드 환경에서 여러 스레드가 동시에 접근 할 수 있다.

  • 상태가 없어야한다.
  • 로컬 변수와 파라미터를 이용한다.
  • 독립적인 공간이 할당되기 때문에 여러 스레드가 값을 덮어쓰지 않는다.

스프링 빈의 스코프

객체가 생성되고 존재하고 적용되는 범위

싱글톤 스코프

  • 스프링 빈의 기본 스코프는 싱글톤이다.
  • 컨테이너에 하나의 객체만 만들어지고 강제로 제거하지 않는 한 스프링 컨테이너가 유지되는 동안 존재한다.

그 외의 스코프

  • 프로토타입 스코프
  • 요청 스코프
  • 세션 스코프

DI

의존성 주입 : Dependency Injection

의존성이란?

여배우 -> 남배우 그거
A ----> B : A가 B에 의존한다.
B의 변화가 A에 영향을 미친다.

제어의 역전(IoC)와 DI

IoC를 적용하여 객체지향적인 설계, 디자인 패턴, 컨테이너에서 동작하는 서버 기술을 사용한다.

의존관계 검색과 주입

의존관계 검색

  • 의존관계를 맺을 객체를 결정, 생성 하는 작업은 외부 컨테이너에게 IoC에 위임
  • 객체를 가져올 때는 스스로 컨테이너에게 요청하는 방법을 사용
  • 빈 객체가 아닌경우, test 메소드등 객체를 주입받을 방법이 없는 경우에 사용

[Ex]

음식점에 에어컨이 고장난 경우

  • 알바생이 하는 역할 아니잖아여
  • 에어컨 기사님 부르기

의존관계 주입

의존 관계의 객체를 가져올 때 메소드, 생성자를 통해 주입
빈 객체 사이에서만 가능

[Ex]

서빙담당 -> 요리담당

  • 홀알바1(서빙담당)은 음식이 나와야 서빙을 할 수 있음.
  • 서빙담당한테 어떤 요리담당한테 요리를 받으면 되는지 알려줘야함

[Ex2]

트리의 자식노드는 부모노드에 의존성이 있음
노드는 값에 의존성이 있음
자식노드에 부모노드를 넣어줘야함

생성자를 이용한 주입

생성자에 parameter를 활용하여 주입

[Ex]

Node(Node parNode,int val){
	this.parNode = parNode;
    this.val = val;
}

Setter를 이용한 주입

수정자(Setter) 메소드는 외부에서 객체 내부의 속성값을 변경하려는 용도로 사용

[Ex]

setParent(Node parNode){
	this.parNode = parNode;
}

일반 메소드를 이용한 주입

수정자 메소드처럼 set으로 시작. 여러 개의 파라미터를 받을 수 있음

[Ex]

setParentAndVal(Node parNode,int val){
	this.parNode = parNode;
    this.val = val;
}

Spring Bean, DI, IoC

스프링에 Bean 등록하기

  • Java에서 제공하는 @Bean 어노테이션, XML(설정파일) 등을 통해 설정 정보에 직접 등록했음
  • 등록할 빈이 많아지면 관리가 힘들다.
    설정 정보 없이 자동으로 스프링 빈을 등록 : 컴포넌트 스캔

컴포넌트 스캔

  • @Component 어노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록
  • @ComponentScan 어노테이션이 붙은 클래스가 구현된 인스턴스가 컴포넌트로 인식된 클래스들을 빈으로 등록한다.
    • 스프링 프로젝트를 시작하면 @SpringBootApplication 클래스가 프로젝트의 최상단에 위치하고 있다.
    • @SpringBootApplication어노테이션을 뜯어보면 @ComponentScan어노테이션이 붙었다.

IoC?

싱글톤

컴포넌트 스캔에 의해 자동으로 빈 등록되는데, 이름이 같은 경우 스프링은 오류를 발생시킨다.

  • 스프링은 서버환경에 적용하기 위한 기술이기 때문에 스프링은 빈을 싱글톤으로 생성
  • 스프링이 처음 설계됐던 대규모 엔터프라이즈 서버환경은 서버 하나당 최대로 초당 수십~수백 번씩 브라우저나 여러 시스템으로부터 요청을 받아 처리할 수 있는 높은 성능이 요구되는 환경이었음
  • 하나의 요청을 처리하기 위해 데이터 액세스 로직, 서비스 로직 등의 다양한 기능을 담당하는 오브젝트들이 참여하는 계층형 구조
  • 클라이언트에서 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다면 부하가 걸려 서버가 감당하기 힘듦

애플리케이션에서 제한된, 수 대개 한 개의 오브젝트만 만들어 사용하는 것이 싱글톤 패턴의 원리이다.

DI가 자동으로?

@Autowired 라는 어노테이션을 붙여 의존성을 주입한다.

  • 생성자 주입 : 생성자에 @Autowired 어노테이션을 붙이기
  • setter 주입 : setter에 @Autowired 어노테이션 붙이기
  • 일반메서드 주입 : 메서드에 @Autowired 어노테이션 붙이기
  • 필드 주입 : 의존성이 있는 필드에 @Autowired 어노테이션 붙이기

스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.
Why? 공부해보기.

Object is not just bean in Spring

다시 오브젝트

넓은 의미로 실세계에 존재하거나 생각할 수 있는 것

알바 뿐 아니라 나오는 음식, 접시, 포크, 식탁, 의자 다 오브젝트!!

Domain

domain :
지방 정부의 관할, 학문 영역, 활동 영역, 인터넷 주소 하위 구분 등의 의미로 사용

해결하고자 하는 문제 영역, 핵심 비즈니스 요구사항

문맥에 따른 도메인의 다양한 해석

도메인에 집중하라

  • 해당 비즈니스 영역에 대한 규칙을 더 파악하라
  • 핵심 비즈니스 로직을 보완하라
    (개발자간 소통에선 단순히 "도메인" 이라고만 하면 소통에 어려움이 생길 수 있다고 생각합니다.)

개발 맥락에서 도메인, 도메인 클래스, 도메인 패키지가 지켜야할 규칙

  • 핵심 비즈니스 로직 이외의 것들은 제외되어야 함 (가령 View나 Dto는 패키지 구분 상 domain이 아닙니다)
  • domain 외 요소를 위한 로직이 포함되지 않아야 함. (가령 View 출력을 위한 로직은 domain에 없어야 합니다)

생각해보기

로또 과제에서 도메인은 뭐가 있을까?

Entity

실제, 독립체

  • 데이터 모델링에서 사용되는 객체

도메인에 필요한 정보를 저장하고 관리하기 위한 "thing".
"thing" : 추상적인 의미를 가짐. 학교, 학생처럼 현실에 보이는 개념일 수도, 주문이나 결제처럼 눈에 보이지 않는 개념일 수도 있음.

[학생 엔티티]

학번 이름 전공 평점 ...
1221.... 김수환 컴퓨터공학과 4.45 ...
1219.... 이승철 컴퓨터공학과 1.66 ...
... ... ... ... ...
1224.... 홍명보 체육교육과 3.33 ...
1223.... 박주호 사회복지과 4.45 ...
  • 엔티티 : 학생
  • 인스턴스 : 김수환, 이승철 등 구현체
  • 속성 : 학번, 이름, 전공, 평점 등

엔터티 특징

  • 식별자 필요 (학번)
  • 2개 이상의 인스턴스가 있어야함.
  • 속성이 있어야함.
  • 업무, 즉 도메인에서 관리되어야 하는 집합.(학사관리)

도메인에 필요한 엔티티가 뭐고 해당 엔티티에 어떤 속성들이 필요한지 생각해야 함.

[EX]식당 예시

제육볶음은 엔티티일까 인스턴스 일까?
제육볶음 이라는 메뉴 : 엔티티
주방 요리로봇이 만든 제육볶음 : 인스턴스

엔티티 공부하기

DTO

Data Transfer Object : 데이터 전송 객체

프론트엔드와 백엔드

프론트엔드에서 데이터를 요청 -> 백엔드가 데이터를 응답

[Ex] 식당예시

손님이 제육볶음을 요청(안맵게, 파 많이)

  • 서빙 알바가 요청을 받음
  • 요청을 요리알바에게 전달
  • 요리알바가 요리 후 서빙알바에게 전달
  • 서빙알바는 손님에게 요리를 전달

손님 : 프론트엔드
서빙알바와 요리알바 : 백엔드

[Ex2] 친구 게시글에 댓글을 달기 위해 게시물을 들어가 댓글달기

  • 프론트엔드는 우선 그동안의 댓글 내역을 요청
  • 백엔드는 저장해둔 댓글 내역을 응답
  • 프론트엔드는 응답받은 걸 사용자에게 보여줌
  • 사용자는 댓글을 치고 확인버튼을 누름
  • 프론트엔드는 댓글을 저장해달라고 요청
  • 백엔드는 저장을 하고 저장성공했다고 응답

그래서 DTO가 뭔데?

  • 프론트엔드와 백엔드가 데이터를 주고받을 때 사용하는 객체

[Ex] 식당예시

손님이 제육볶음을 요청(안맵게, 파 많이)

  • 서빙 알바가 요청을 받음
    ..
  • 서빙알바는 손님에게 요리를 전달

여기서 DTO는?
손님의 요청에 맞게 접시에 잘 플레이팅된 제육볶음

손님입장에서는 누가 요리했고 자시고 잘 플레이팅된 제육볶음을 받는게 중요함

댓글이라는 데이터에는 뭐가 필요한가?
댓글 조회 요청 :
(백 -> 프론트)

  • 댓글내용
  • 작성자
  • 좋아요 수
  • 작성시간 등
    댓글 저장 요청
    (프론트 -> 백)
  • 댓글내용
  • 작성자
  • 작성시간 등

DAO

실제로 DB에 접근하여 data를 삽입, 삭제, 조회, 수정 등 CRUD 기능을 수행

DAO는 데이터베이스에 접근하기 위한 로직과 목표하는 비즈니스를 처리하기 위한 로직을 분리시키기 위해 사용한다.

서버와 데이터베이스

[Ex] 식당예시

목표 : 제육볶음
식당내에 식료품 저장창고를 두면 월세 50억이 필요하다고 가정합시다.
50m거리에 창고를 사용하면 월세 500만원이라고 가정합시다.
창고에 왔다 갔다 하는 알바를 하나 더 뽑자 : 창고 알바
-> DAO

자체적으로 서비스의 필요한 데이터를 메모리에 저장한다고 해보자

  • 메모리는 고비용
  • 메모리는 휘발성

데이터베이스를 활용 -> 데이터베이스에 접근하려면 창고 알바가 필요하다.
요리알바가 직접 왔다갔다하는건 너무 비효율적.

스프링 동작 원리

Controller

: 서빙 알바

  • 프론트엔드가 요청을 보냄
  • Dispatcher Servlet이라는 녀석이 요청에 해당하는 Controller 에게 전달
  • Controller는 비즈니스 로직을 처리하여 요청에 해당하는 응답을 반환

DTO를 통한 통신

요청을 받아서 DTO에 담아 반환

Service

: 요리알바
Controller가 요청을 받아 Service에 전달

  • Service가 비즈니스 로직 수행
  • 엔티티의 상태를 변화 시킬 수 있음
    • C : 생성요청이 들어오면 생성
    • R : 조회요청이 들어오면 조회내역 반환
    • U : 수정요청이 들어오면 수정
    • D : 삭제요청이 들어오면 삭제
  • 데이터베이스에 반영

Repository

aka DAO : 창고알바
Service가 비즈니스 로직 수행하여 엔티티 상태를 변화 후 저장
Repository가 상태 변화를 반영하여 데이터베이스에 접근

  • C : 새로 생성된 인스턴스를 데이터베이스에 저장
  • R : 데이터베이스에 접근해서 조회내용 service에 전달
  • U : 수정내용반영해서 데이터베이스에 저장
  • D : 데이터베이스에서 해당 인스턴스 삭제
profile
hello human

0개의 댓글