초보 웹 개발자를 위한 스프링 5 프로그래밍 입문
저자 : 최범균

 

CH 3. 스프링 DI

1. 의존이란 ?

  • DI Dependency Injection 의존 주입
  • 객체 간의 의존
  • 의존은 변경에 의해 영향을 받는 관계를 의미한다.
  • 의존하는 대상이 있으면 그 대상을 구현하는 방법이 필요하다.
    • 의존 객체를 직접 생성 ( 이 내용을 공부해보자 ) 
    • DI와 서비스 로케이터

 

 

 

2. DI를 통한 의존 처리

  • 의존하는 객체를 전달받는 방식을 이용하는 DI
public class MemberRegisterService {
	
    // 직접 의존 객체 생성 
    private MemberDao memberDao = new MemberDao();
    
    //생성자를 통해서 의존 객체를 전달 받는 형식
    private MemberDao memberDao;
    public MemberRegisterService(MemberDao memberDao){
    	this.memberDao = memberDao;
    }
    
    ...
}

 

  • 만약 MemberRegisterService 객체를 생성할 때 생성자에 MemberDao 객체를 전달해야 한다.
MemberDao dao = new MemberDao();
// 의존 객체를 생성자를 통해 주입한다.
MemberRegisterService svc = new MemberRegisterService(dao);
복잡해 보이는데 왜 생성자 통해서 의존하는 객체를 주입할까?
 -> 변경의 유연함을 위해서!!

 

 

3. DI와 의존 객체 변경의 유연함

  • 의존 객체를 직접 생성하는 방식 = 필드나 생성자에서 new 연산자를 이용해 객체를 이용해 객체 생성
public class MemeberRegisterService {
	private MemberDao memberDao = new MemberDao();
    ...
}

이것과

public class ChangePasswordService {
	private MemberDao memberDao = new MemberDao();
    ...
}

이렇게 두개의 코드가 있는 상황.

캐시를 이용해 조회속도를 향상 시키고자 하는 상황이 발생...!!

memberDao -> cachedMemberDao 클래스를 만들어야 함~!~!

public class CachedMemberDao extends MemberDao {
	...
}

그렇다면 MemberRegisterService와 ChangePasswordService 모두 MemberDao에서 CachedMemberDao로 바꿔줘야함... ( 객체 생성시마다 하나하나 변경 해주어야 함... )

 

 

동일 상황에서 DI를 사용하면 수정 코드가 줄어든다...!!!  ( 클래스가 여러개여도 의존 주입 되상이 되는 객체를 생성하는 코드가 한곳이라, 객체 생성 코드에서만 변경하면 된다,) 

public class MemberRegisterService{
	private MemberDao memberDao;
    public MemberRegisterService(MemberDao memberDao){
    	this.memberDao = memberDao;
    }
    ...
}


public class ChangePasswordService{
	private MemberDao memberDao;
    public ChangePasswordService(MemberDao memberDao){
    	this.memberDao = memberDao;
    }
    ...
}


// --------------------------
// 위 뒤 클래스의 객체 생성시
// MemberDao memberDao = new MemberDao;
// 만 바꾸면 된다~!~!
MemberDao memberDao = new CachedMemberDao;

MemberRegisterService regSvc = new MemberRegisterService(memberDao);
ChangePasswordService pwdSvc = new ChangePasswordService(memberDao);

 

 

4. 예제 프로젝트 만들기

|---회원 데이터 관련 클래스
|  |---Member
|  |---WrongPasswordException
|  |---MemberDao
|
|---회원 가입 처리 관련 클래스
|  |---DuplicateMemberException
|  |---RegisterRequest
|  |---MemberRegisterService
|
|---암호 변경 관련 클래스
|  |---MemberNotFoundException
|  |---ChangePasswordService

 

 

5. 객체 조립기

  • assembler
  • 앞서 DI 설명 시 생성에 사용할 클래스를 변경하기 위해선, 객체를 주입하는 코드 한 곳만 변경하면 된다고 했다.
    • 실제 객체를 생성하는 코드는 어디에 있을까???
      • main 메소드에 의존 대상 객체를 생성하고 주입하는 방법이 나쁘진 않다. 
      • 더 나은 방법은 객체를 생성하고 의존 객체를 주입해주는 클래스를 따로 작성하는 것이다. (조립)
public class Assembler {

	private MemberDao memberDao;
    private MemberRegisterService memberRegisterService;
    private ChangePasswordService changePasswordService;
    
    // MemberRegisterService와 ChangePasswordService 객체에 대한 의존을 주입한다.
    // MemberRegisterService은 memberDao 객체를 주입받고,
    // ChangePasswordService는 setter를 통해 주입받는다.
    public Assembler(){
    	memberDao = new MemberDao();
        // memberDao = new CachedMemberDao();
        regSvc = new MemberRegisterService(memberDao);
        pwdSvc = new ChangePasswordService();
        pwdSvc.setMemberDao(memberDao);
    }
    ...
}

 

위와 같이 생성한 Assembler를 사용하는 코드는...??

-> Assembler 객체를 생성 - get 메서드를 이용해 필요한 객체를 구함 - 그 객체를 사용

Assembler assembler = new Assembler();
ChangePasswordService changePwdSvc = assembler.getChangePasswordService();
changePwdSvc.changePassword("이메일","비번","newpwd");

 

  • Assembler 클래스의 생성자에서 필요한 객체를 생성하고 의존을 주입한다.
  • 따라서 Assembler 객체를 생성하는 시점에 사용할 객체가 모두 생성된다.
  • 그 후 Assembler가 제공하는 메서드를 이용해서 필요한 객체를 구하고, 그 객체를 사용하는 것이 전형적 패턴이다!

 

 

6. 스프링의 DI 설정

  • 스프링은 MemberRegisterService와 MemberDao와 같은 특정 타입의 클래스만 생성한 Assembler와 달리 범용 조립기 역할을 한다....!!!
  • 스프링을 사용하려면 우선 스프링이 어떤 객체를 생성하고, 의존을 어떻게 주입할지 정의한 설정 정보 작성 필수
  • 설정코드는 주로 config 패키지~
// 스프링 설정 클래스를 의미하는 에노테이션
@Configuration
public Class AppCtx{
	
    // 해당 메서드가 생성한 객체를 스프링 빈이라고 설정하는 에노테이션
    // memberDao 메서드를 이용해서 생성한 빈 객체는 "memberDao"란 이름으로 스프링에 등록
    @Bean
    public MemberDao memberDao(){
    	return new MemberDao();
    }
    
    @Bean
    // MemberRegisterService 생성자를 호출할 때
    // memberDao()메서드를 호출하므로 memberDao()가 생성한 객체를
    // MemberRegisterService 생성자를 통해 주입
    public MemberRegisterService memberRegSvc(){
    	return new MemberRegisterService(memberDao);
    }
    
    @Bean
    public ChangePasswordService changePwdSvc(){
    	ChangePasswordService pwdSvc = new ChangePasswordService();
        // setMemberDao() 메서드를 이용해 의존관계를 주입한다
        pwdSvc.setMemberDao(memberDao());
    	return pwdSvc;
    }

 

 

  • 설정 클래스를 만들었다고 끝이 아니다!!!!!!!
    • 컨테이너를 생성해야한다. ( 컨테이너 : 객체를 생성하고 의존 객체를 주입하는 역할 )
    • // 컨테이너 생성
      ApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);
      
      
      // 컨테이너 생성 후 getBean() 메서드를 이용해 사용할 객체를 구할 수 있다.
      // 컨테이너에서 이름이 memberRegSvc인 빈 객체를 구한다.
      MemberRegisterService regSvc = ctx.getBean("memberRegSvc", MemberRegisterService.class);

 

 

DI 방식 1 : 생성자 방식

  • 생성자를 통해 의존 객체를 주입받아 필드(this.memberDao)에 할당한다
private MemberDao memberDao;

// 생성자를 통해 의존 객체를 주입 받음
public MemberRegisterService(MemberDao memberDao){
	// 주입 받은 객체를 필드에 할당
    this.memberDao = memberDao;
}

public Long regist(RegisterRequest req){
	// 주입 받은 의존 객체의 메서드 사용
    Member member = memberDao.selectByEmail(req.getEmail());
    ...
    memberDao.insert(newMember);
    ...
}

 

 

  • 생성자에 의해 전달할 의존 객체가 두 개 이상이어도 동일한 방식으로 주입하면 된다. 
// 생성자 파라미터가 두개인 예제를 살펴보자~!

public class MemberDao{
	...
    public Collection<Member> selectAll(){
    	return map.values();
    }
}


// =====================================================================
// 생성자로 두 개의 파라미터를 전달받는 클래스 작성
// MemberDao, MemberPrinter 객체를 전달 받는다.
public MemberListPrinter(MemberDao memberDao, MemberPrinter printer){
	this.memberDao = memberDao;
   	this.printer = printer;
}


// ======================================================================

7. @Configuration 설정 클래스의 @Bean 설정과 싱글톤

8. 두 개 이상의 설정 파일 사용하기

9. getBean( ) 메서드 사용

10. 주입 대상 객체를 모두 빈 객체로 설정해야 하나?

'🔥 > Spring' 카테고리의 다른 글

[spring] 빈 라이프 사이클과 범위  (0) 2021.08.31
[spring] 컴포넌트 스캔이란  (0) 2021.08.31
[Spring] DI의 세가지 방법  (0) 2021.08.18
[Spring] 의존성 주입(DI)이란 ?  (0) 2021.08.18

 

풀이

리스트 형태로 입력받는다.

 

lambda를 사용하여 정렬 기준을 정해주는데, 먼저 첫번째 인자(x[0]) 즉, x줄부터 정렬을 하고

그다음 두번째 인자인(x[1]) y줄을 정렬해준다.

 

코드 참조!

import sys
n = int(sys.stdin.readline())
so = []
for i in range(n):
    so.append(list(map(int, sys.stdin.readline().split())))
so.sort(key=lambda x: (x[0], x[1]))
for i in so:
    print(i[0], i[1])

 

 

 

python 정렬함수 참조!

1. sort

원본을 변형시켜 정렬한다. '변수. sort( )' 형태로 사용.

정렬 기준은 문자열은 알파벳, 가나다순이고 숫자는 오름차순이 기본값이다.

2. sorted

정렬된 결과를 반환. 원형을 변형시키지 않는다. 괄호( ) 안에 반복 가능한 iterable 자료형을 입력하여 사용한다. 정렬 기준은 문자열은 알파벳, 가나다순이고 숫자는 오름차순이 기본값이다.

 

3. Parameter

sort, sorted 모두 key, reverse 매개변수를 갖고 있다.

 

3-1. reverse

bool값을 넣는다. 기본값은 reverse=False(오름차순)이다.

reverse=True를 매개변수로 입력하면 내림차순으로 정렬할 수 있다.

 

3-2. key

정렬을 목적으로 하는 함수를 값으로 넣는다. lambda를 이용할 수 있다.

key 값을 기준으로 정렬되고 기본값은 오름차순이다. 

 

여러 개의 요소를 가진 경우, 튜플로 사용할 수 있다.

'🕵️‍♀️ > BOJ' 카테고리의 다른 글

[Python] BOJ 2606 바이러스 (BFS/DFS)  (0) 2021.11.17
코테대비 백준문제추천  (0) 2021.11.05
[Python] BOJ 14719 빗물  (0) 2021.11.04
[Python] BOJ 1149 RGB거리 (dp)  (0) 2021.11.04
[BOJ] Python 백준 2751번  (0) 2021.08.16

1강 클라우드 컴퓨팅과 API의 역할

1.1 클라우드 컴퓨팅

클라우드 컴퓨팅의 탄생
"필요한 IT 자원을 즉시 사용할 수 있는 환경" → 클라우드 컴퓨팅이 제대로 실행

 

공용 클라우드와 사설 클라우드의 차이

사무실의 자동 판매기와 공원의 자동 판매기 / 사설 클라우드와 공용 클라우드

사설 클라우드

  • 해당 기업의 사용자만 접근할 수 있도록 통제
  • 각종 하드웨어 자산들을 확보 필요 
  • 초기 투자 비용 발생 

일정규모의 리소스 활용 예측이 가능할 시

 

공용 클라우드

  • 멀티 테넌트로 상호 간의 간섭 없이 여러 기업의 사용자가 독립적인 형태로 사용
  • 초기 투자 비용 없음
  • 리소스가 필요할 때마다 필요한 만큼만 확보해서 이용

리소스 총량에 큰 변화가 예상되거나 수요 추이 예측이 어려울 시

 

공용 클라우드는 리소스의 사용량에 따라 과금되기 때문에 보통 비용이 선형적으로 증가
사설 클라우드는 리소스가 고갈되기 전까지는 추가 투자가 없기 때문에 단계적으로 증가

 

 

 

 

" Iaas, Paas, Saas "

SaaS Software as a Service

역사적으로 클라우드 서비스는 saas로 부터 시작해 다양해졌다.

애플리케이션 환경을 클라우드의 형태로 서비스한다. ( ex. 개인용 이메일 )

 

 

PaaS Platform as a Service

애플리케이션 개발 환경이나 운영 환경등을 제공한다. ( 데이터베이스, 개발 프레임워크, 컴파일러 )

  • 신속한 개발 착수 가능
  • 특정 클라우드 서비스에서만 제공하는 고유 프레임워크나 데이터 저장소 사용 가능
  • 기존에 사용하던 프레임워크나 데이터베이스를 클라우드 환경에서도 똑같이 사용 가능

 

IaaS Infrastructure as a Service

서버, 네트워크, 스토리지 등의 IT 인프라에 필요한 다양한 가상화된 인프라 제공

자신만의 전용 테넌트 환경 제공

SaaS와 달리 리소스가 물리적 환경과 독립된 형태로 제공이 필요한 IaaS는 가상화 되어 있다.

 

 

 

 

 

 

1.2 클라우드가 실현하는 인프라의 표준화

클라우드에 의한 시스템 구축 절차의 표준화

  • Iaas형 클라우드 골치아픈 물리적 장비의 설정 방법이나 기능의 차이 의식이 필요 없다.
  • 물리적 장비의 차이에 상관 없이 몇 번이든 같은 방법으로 시스템을 구축할 수 있다.
  • 시스템 재구축이 필요한 상황에서도 시행착오 없이 이전의 경험을 살려 효율적 작업 가능
  • 기존 클라우드 인프라의 시스템을 새로운 클라우드 인프라로 옮기는 작업 또한 수월

 

 

인프라의 표준화를 위한 컴포넌트의 추상화

  • 클라우드 환경에서 시스템의 구축 과정을 표준화 할 수 있는 것 -> 시스템 구성 컴포넌트들이 추상화 되어있기 때문
  • 클라우드의 컴포넌트들이 철저하게 사용자가 필요로 하는 기능에 충실하도록 만들어졌다.
  • 물리적 환경에 의존적인 내용엔 신경을 줄이게 되고, 본질적인 설계에 집중할 수 있음
  • 가상 머신 준비시 세부적인 부분 생각 안 해도 된다.

 

 

API에 의한 제어 방법의 표준화

  • 한번 정의한 작업 절차에 따라 몇번이든 반복 구축 가능 -> 물리적 인프라 작업 필요 없음
  • 같은 시스템 구축을 위한 여러 번의 작업을 자동화 할 수 있음 --> API를 사용한 제어 방식
제어 방법 설명
웹 콘솔 GUI을 사용한 제어 웹 브라우저를 사용해서 GUI 방식으로 제어함
명령어를 사용한 제어 클라이언트 툴이 제공하는 명령을 실행하여 제어함
직접 개발한 프로그램을 사용한 제어 직접 개발한 프로그램이 클라우드 API 라이브러리를 활용하여 제어함
자동화 툴을 사용한 제어 클라우드 환경의 자동화 툴을 사용해서 제어함

 

 

 

 

1.3 클라우드 컴퓨팅의 활용

  • 컴포넌트들이 추상화 되어있다 -> 사용자가 원하는 기능을, 원하는 시기에 바로 사용할 수 있다.
  • 시스템을 구축하는 과정이 표준화 되어 있다. -> API사용한 자동화를 통해 빠른 구축.. 신세계

 

 

 

 


2강 클라우드의 대표적인 컴포넌트

 

2.1 클라우드 환경의 전체 그림

테넌트

  • 사전적인 의미로 세입자 (AWS 계정)
  • 클라우드 서비스 이용자는 자신만의 테넌트 환경 가짐

테넌트 구성 예

테넌트 설계시 고려사항
1. 공용 클라우드에서는 테넌트 별로 리소스의 사용량이 합산되어 테넌트별로 사용료가 청구된다.
2. 테넌트별로 사용 가능한 리소스의 상한선이 정해져있다.
3. 같은 테넌트에 속한 가상 네트워크, 가상머신 인스턴스. 가상 스토리지들끼리만 서로 연결될 수 있다.

 

 

 

 

리전

  • 지리적으로 멀리 떨어진 지역에 여러개의 클라우드 인프라 분산 운영
  • 국가나 지역을 식별할 수 있도록 이름을 짓는다 ex. 서울리전, 시드니리전
  • 각 리전들은 서로 독립된 환경 -> 여러 리전에 걸친 가상 네트워크 못 만든다.
  • 사용자 계정이나 테넌트 정보는 여러 리전에 걸칠 수 있다. ->DR환경 만들 수 있음

DR Disaster Recover
재해발생시 다른 리전으로 시스템을 옮겨 사용
사용자가 직접 변경된 리전의 공인 IP 주소로 바꿔 호출하거나 DNS가 변경된 공인 IP 주소를 반환하도록 도메인 등록 정보를 갱신해 주어야 한다.
다른 리전에서도 데이터를 이어 사용할 수 있게 미리 복제해 두어야 하는데, 이때 오브젝트 스토리지를 사용한다.


         (* 오브젝트 스토리지는 모든 리전에서 공통으로 사용 가능하다 )

오픈스택 - 리전기능 O , 클라우드와 기준이 다름
AWS와 같이 여러 나라에 클라우드 인프라를 준비해두고 각 지역 단위로 구성할 수도
or 국내에 여러 개의 데이터 센터를 두고 각 데이터 센터 단위로 리전을 구성할 수도

 

 

 

 

 

가용 영역

  • 한 리전의 클라우드 인프라는 다른 주변 지역의 여러 데이터 센터에 분산될 수 있다 -> 이 데이터 센터는 가용영역!
  • 다른 AZ에 있는 가상 머신 인스턴스와 블록 스토리지는 서로 연결 못함
    • 그 기능을 쓰고 싶다면 복제 기능으로 사용 다른 AZ의 블록 스토리지를 만들어 쓰면 된다.

리전과 가용 영역

오픈 스택 - AZ 개념 O
가용 영역 범위 내로 제한되지 않고 여러 가용 영역에 걸쳐서 더 넓은 범위로도 구성 가능
1. AWS으로 같은 방식으로 데이터 센터 단위로 가용 영역을 구성할 수 있음
   데이터 센터 사이의 네트워크 대역이 충분하지 않으면, 인스턴스 간의 거리가 멀어 원하는 통신 속도 안 나옴
2. 같은 데이터 센터에서 서로 다른 플로어나 랙과 같이 더 작은 단위로 가용영역을 구성할 수 있다.

 

 

 

 

 

 

2.2 네트워크 리소스

라우터

  • 테넌트 안의 가상 네트워크 + 물리적인 외부 네트워크  이 둘을 연결하기 위한 가상 라우터
  • 기본적으로 가상 네트워크 하나당, 하나의 가상 라우터 배치

 

 

 

 

스위치 (서브넷)

  • 가상 라우터가상 머신 인스턴스의 가상 NIC 연결되는 접점
  • 하나의 가상 스위치에 하나의 서브넷이 할당된다.
    • 서브넷 : 가상 머신 인스턴스가 사용할 수 있는 사설 IP 주소의 범위
    • AWS에선 가상 스위치와 서브넷을 하나의 통합된 형태로 취급하며, 서브넷으로 부른다.
  • 하나의 가상 스위치(서브넷)가 하나의 가용 영역에 배치된다.
  • 가상 스위치는 논리적으로 접속 포트 개수를 늘릴 수 있기 때문에 여러 개를 연결할 필요 없다.
    • 가상 스위치에 접속 포트를 추가하면 그 포트에 서브넷 범위 내에 이용가능한 IP 주소 할당

 

 

 

 

공인 IP 주소

  • 가상 네트워크 사용하는 사설 IP 주소는 네트워크 내부에서 사용 가능하지만, 외부에서는 불가능하다.
  • 외부와 통신할 때 가상 라우터의 NAT기능을 사용하여 사설 IP를 공인 IP로 변환 ( 2가지 방법이 있다! )
방법 1 ) IP 마스커레이딩
가상 인스턴스가 외부 네트워크로 접속할 때 가상 라우터가 할당 받은 공인 IP를 공유하는 방식
ex. 가정용 LAN에 연결된 초고속 PC
cf. 가상머신 인스턴스가 가상 스위치에 연결되어 있고 이 가상 스위치가 다시 가상 라우터에 접속되어 있을 때
    내부에서 외부 O |  외부에서 내부 X

방법 2 ) 엘라스틱 IP
미리 확보해 둔 공인 IP 주소를 가상 머신 인스턴스에 할당하는 방식
내부에서 나가는 통신과 들어오는 통신 모두 가능
cf. 한 리전에서 확보한 IP를 다른 리전에서 사용 못함

 

 

 

시큐리티 그룹

  • 가상 머신 인스턴스가 주고 받을 네트워크 패킷에 대해 필터링 기능을 제공하는 역할
  • "모든 가상 머신 인스턴스에 공통으로 적용할 시큐리티 그룹"
  • "웹 서버에 추가 적용할 시큐리티 그룹"
  • 특정 목적에 맞는 공통적 규칙을 미리 정의 해두고 비슷한 역할을 하는 가상 머신에 미리 만들어둔 시큐리티 그룹을 재활용 할 수 있다.
  • 가상 머신 인스턴스가상 스위치의 접속 포트 사이에서 이뤄짐

 

 

 

 

 

2.3 서버 리소스

템플릿 이미지

  1. 가상 머신 인스턴스를 기동하려면 게스트 OS가 설치된 기동 디스크가 필요
  2. 기동 디스크 만들 땐, 사전에 준비된 템플릿 이미지를 선택함
  3. 선택된 템플릿 이미지는 다운로드되어 가상 디스크 형태로 만들어짐
  4. 가상 머신 인스턴스는 이 가상 디스크를 연결하여 사용

* 템플릿 이미지는 클라우드 서비스 제공자가 미리 준비해두기도 하지만, 이용자가 직접 만든 것을 활용할 수 있음

 

 

 

 

인스턴스 유형

  • 가상 머신의 컴퓨팅 성능 및 용량을 결정
  • 각 타입별로 가상 CPU의 개수나 가상 메모리의 용량, 가상 디스크의 용량 등이 정해져 있음
  • AWS에서는 새로운 인스턴스 유형을 사용자 정의로 직접 만들지 못함
오픈스택에서는 테넌트의 권리 권한이 있는 사용자인 경우, 해당 테넌트에서 사용할 인스턴스 유형을 직접 만들거나 변경 할 수 있다. 

설정 가능한 인스턴스 유형의 항목
1. 가상 CPU : 가상 CPU의 개수
2. 메모리 : 가상 메모리의 용량
3. 루트 디스크 : 기동 디스크의 크기
4. 임시 디스크 : 임시 디스크의 크기
5. 스왑 디스크 : 스왑 영역의 크기

 

 

 

 

네트워크 접속과 시큐리티 그룹

  • 가상 머신 인스턴스의 가상 NIC가 네트워크에 연결되려면...
    • 가상 스위치와 연결되어야 하고 시큐리티 그룹이 설정되어야 함
      • 여러 개의 가상 스위치에 연결하고 싶다면, 가상 스위치별로 가상 NIC 여러개 준비!
      • NIC 별로 서로 다른 시큐리티 그룹을 적용하고 싶다면 개별적 설정을 해주면 된다.

 

 

로그인 인증과 키 페어

  • 가상 머신 인스턴스의 게스트 OS에 로그인할 떄 사용자 인증이 필요
  • 기본적으로 SSH의 공개 키 인증 방식이 사용된다.
  • 전용 키 페어를 만들어야 한다. (전용 키 페어 : 공개 키 + 개인 키)
  • 이러한 인증 관련 설정 처리는 게스트 OS안의 Cloud - init을 통해 이루어진다.
    • Cloud - init은 게스트 OS가 처음 기동될 때 지정된 공개키를 받아 SSH의 인증 정볼륨보를 설정하는 역할을 함

 

 

 

 

 

2.4 블록 스토리지 리소스

블록 스토리지의 기본 기능

블록 스토리지 사용 방법

 

블록 스토리지에서 가상 머신 인스턴스 기동하기

앞선 가상 머신 인스턴스 기동시에 템플릿 이미지 복제한 루트 디스크를 사용하는 방법을 살펴보았다.

  • 블록 스토리지의 볼륨에 있는 게스트 OS로 가상 머신 인스턴스를 기동하는 방법이 있다.
  • EBS Boot라 한다.
    • 템플릿 이미지를 복제한 볼륨을 미리 만들어둔다
    • 가상 머신 인스턴스를 기동할 때 미리 복제해둔 볼륨을 지정한다
    • 가상 머신 인스턴스를 종료하더라도 OS 영역의 데이터가 삭제되지 않는다. 재사용 가능~!

 

 

 

2.5 오브젝트 스토리지 리소스

오브젝트 스토리지의 기본 기능

  • 오브젝트 스토리지는 파일 단위로 데이터를 저장하는 기능 제공
  • 덮어쓰기를 통한 갱신 불가능... -> 파일을 삭제하고 새로 변경된 파일을 저장
    • 매우 단순
    • 가용성 높고 처리율 우수
      • 동영상과 같은 정적 콘텐츠 파일(오브젝트)을 저장하는데 적합
  • 오브젝트 스토리지는 장소나 지역에 상관 없이 인터넷을 통해 접속하여 이용 가능
  • 오브젝트 스토리지 서비스를 Amazon S3라 한다. 
  • 보통 오브젝트 보존 영역인 S3 버킷을 리전별로 만든다.  ( 다른 리전의 인스턴스도 사용 가능 )
오브젝트 스토리지에 파일 저장
오브젝트를 담을 수 있는 그릇, 컨테이너S3를 생성해야한다,
각 오브젝트는 key  - value 형식의 메타 데이터를 부여할 수 있는데, 이를 활용하면 특정 목적으로 사용할 파일들을 쉽게 선별할 수 있다.

 

 

 

버저닝과 정적 웹 호스팅

버저닝 Versioning

  • 컨테이너에 저장된 오브젝트에 버전 번호를 붙여 관리하는 기능
  • 오브젝트 스토리지에 같은 이름의 파일 저장해도 새로운 번호로 저장되어 기존 파일 유지 가능

정적 웹 호스팅

  • 오브젝트 스토리지를 간이 웹 서버처럼 사용하는 기능
    • 컨테이너의 접근 권한을 누구나 읽을 수 있는 공용으로 설정한다.
    • 그 안에 정적 HTML 파일들을 저장한다.
    • 이후 웹 브라우저 같은 client가 이 오브젝트에 할당된 url로 접근하면 저장된 html 파일 내용이 나온다.

 

 

 

오브젝트 스토리지의 백업

  • 블록 스토리지의 볼륨을 백업하는 용도로 사용 가능한 오브젝트 스토리지
    • 블록 스토리지의 볼륨 전체를 일정 크기의 볼록으로 분할한다.
    • 분할된 각각의 조각들을 하나의 파일 형태로 간주하고 오브젝트 스토리지에 저장한다.
  • 여러 리전과 가용 영역에서 지리적 제약이 없으므로 리전과 가용 영역 간의 볼륨 복제에도 활용 가능

 

 

 

 

 

 

2.6 웹 애플리케이션 시스템의 구축 예

여러 개의 가용 영역으로 가용성을 확보하기

AWS - 여러 개의 가용 영역으로 가용성을 확보하기
오픈 스택 - 여러 개의 가용 영역으로 가용성을 확보하기

 

오브젝트 스토리지를 사용하여 데이터 보호하기

  •  가상 머신 인스턴스가 장애 발생해 DB 서버가 정지된 경우에도, 데이터가 유실되지 않게 하려면
    • 데이터 블록 스토리지에 저장
    • 오브젝트 스토리지에 정기적으로 백업
백업 전 해당 볼륨을 가상 머신 인스턴스에서 분리해야 함
-> 이때 데이터베이스 사용을 못한다.
    이 시간을 줄이고자 스냅샷을 만들고 스냅샷에서 복제한 볼륨을 백업하면 된다.
혹은, 인스턴스에 백업용 볼륨을 미리 연결해둔 다음, 데이터베이스 소프트웨어의 백업 기능으로 백업용 볼륨에 백업하게 만든다.
  • 장애가 발생해 AZ-1에서 AZ-2로 전환해야 하는 경우
    • 블록 스토리지의 볼륨 역시 가용 영역별로 분리 되어 있다.
    • 따라서 오브젝트 스토리지에 저장한 최신의 백업을 AZ-2의 볼륨으로 복원한 후 서버에서 사용하도록 만들어준다.

Field Injection(필드 주입)

변수 선언부에 @Autowired Annotation을 붙인다.

@Component
public class SampleController {
    @Autowired
    private SampleService sampleService;
}

 

필드주입을 사용하면 안되는 이유

1. 단일 책임(SRP)의 원칙 위반 

의존성을 주입하기가 쉽다.
@Autowired 선언 아래 개수 제한 없이 무한정 추가할 수 있다. Constructor의 parameter가 많아짐과 동시에 하나의 Class가 많은 책임을 떠안는다는 걸 알게된다.

 

2. 의존성이 숨는다. 

DI Container를 사용한다는 것은 Class가 자신의 의존성만 책임진다는게 아니라 제공된 의존성 또한 책임진다. 그래서 Class가 어떤 의존성을 책임지지 않을 때, 메서드나 생성자를 통해(Setter나 Constructor) 확실히 커뮤니케이션이 되어야한다.

하지만 Field Injection은 숨은 의존성만 제공해준다.

 

3. DI container의 결합성과 테스트 용이성

DI Framework의 핵심 아이디어는 관리되는 Class가 DI Container에 의존성이 없어야 한다.

DI Container 없이도 Unit Test에서 Instance화 시킬 수 있고, 각각 나누어서 테스트도 할 수 있다. Container의 결합성이 없다면 관리하거나 관리하지 않는 Class를 사용할 수 있고, 심지어 다른 DI Container로 전환할 수 있다.

하지만, Field Injection을 사용하면 필요한 의존성을 가진 Class를 곧바로 Instance화 시킬 수 없다.

 

4. 불변성

Constructor Injection과 다르게 Field Injection은 final을 선언할 수 없다. 그래서 객체가 변할 수 있다.

 

5. 순환 의존성

Constructor Injection에서 순환 의존성을 가질 경우 BeanCurrentlyCreationExeption을 발생시킴으로써 순환 의존성을 알 수 있다. 

그러나 Field Injection은 스프링 컨테이너 말고는 외부에서 주입할 수 있는 방법이 없다.

순환 의존성?
A Class가 B Class를 참조하는데 B Class가 다시 A Class를 참조할 경우,A Class가 B Class를 참조하고, B Class가 C Class를 참조하고 C Class가 A Class를 참조하는 경우 이를 순환 의존성(Circular Dependency)이라고 부른다.

 

읽기 쉽고 사용이 편하단것 이외엔 장점이...

 

 

 

Setter Injection(수정자 주입)

Setter Injection 선택적인 의존성을 사용할 때 유용하다. 상황에 따라 의존성 주입이 가능하다.

//Setter Injection은 set Method를 정의해서 사용한다.
@Component
public class SampleController {
    private SampleService sampleService;
 
    @Autowired
    public void setSampleService(SampleService sampleService) {
        this.sampleService = sampleService;
    }
}

Setter Injection으로 의존관계 주입은 런타임시에 할 수 있도록 낮은 결합도를 가지게 구현되었다.

 

하지만 Setter Injection을 통해서 Service의 구현체를 주입해주지 않아도 Controller 객체는 생성이 가능하다.

Controller 객체가 생성가능하다는 것은 내부에 있는 Service의 method 호출이 가능하다는 것인데, set을 통해 Service의 구현체를 주입해주지 않았으므로, NullPointerException 이 발생한다.

 

주입이 필요한 객체가 주입이 되지 않아도 얼마든지 객체를 생성할 수 있다는 것이 문제다.

 

이를 해결할 아이가 Constructor Injection이다

 

 

 

 

Constructor Injection(생성자 주입)

//Constructor에 @Autowired Annotation을 붙여 의존성을 주입받을 수 있다.
@Component
public class SampleService {
    private SampleDAO sampleDAO;
 
    @Autowired
    public SampleService(SampleDAO sampleDAO) {
        this.sampleDAO = sampleDAO;
    }
}

@Component
public class SampleController {

	private final SampleService sampleService = new SampleService(new SampleDAO());
    
	...
}

 

생성자 주입을 사용해야하는 이유!!!

(Spring Framework Reference에서 권장하는 방법은 생성자를 통한 주입~!)

생성자를 사용하는 방법이 좋은 이유는 필수적으로 사용해야하는 의존성 없이는 Instance를 만들지 못하도록 강제할 수 있기 때문이다.

 

Spring 4.3버전부터는 Class를 완벽하게 DI Framework로부터 분리할 수 있다.

 

단일 생성자에 한해 @Autowired를 붙이지 않아도 된다.

 

또한 앞서 살펴본 Field Injection의 단점들을 장점으로 가져갈 수 있다.

  • null을 주입하지 않는 한 NullPointerException 은 발생하지 않는다.
  • final 을 사용할 수 있다.
  • 순환 의존성을 알 수 있다.
  • 의존성을 주입하기가 번거로워 위기감을 느낄 수 있다. (이를 바탕으로 SRP원칙을 생각하게 되고 리팩토링하게된다.)

Reference.

link1

출처 : https://sehun-kim.github.io/sehun/springbean-lifecycle/#2

 

스프링의 삼각형
DI IoC AOP

스프링의 기반이 되는 설계 개념인 스프링의 삼각형

 

 

의존성 주입 DI ( Dependency Injection )

Inversion of Control 이라고도 하는 의존 관계 주입(Dependency Injection)이라고도 하며, 어떤 객체가 사용하는 의존 객체를 직접 만들어 사용하는게 아니라, 주입 받아 사용하는 방법이다. (new 연산자를 이용해서 객체를 생성하는 것이라고 생각하면 된다) 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, DI(의존성 주입)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.

출처 :https://velog.io/@gillog/Spring-DIDependency-Injection

A 객체에서 B, C객체를 사용(의존)할 때, A 객체에서 직접 생성 하는 것이 아니라 외부(IOC컨테이너)에서 생성된 B, C객체를 조립(주입)시켜 setter 혹은 생성자를 통해 사용하는 방식 

 

예시로 장난감과 배터리를 들 수 있다. 장난감들은 베터리가 있어야 움직일 수 있으며 즉 베터리에 의존하고 있다. 장난감들에게 베터리를 넣어주는 것을 의존성 주입이라고 생각하면 좋다.

베터리의 일체형인 경우에는 생성자에서만 의존성을 주입해주는 상황이라 베터리가 떨어지게 된다면 다른 베터리로 교체하지 못하고 새로운 것으로 바꿔야 하기 때문에 유연하지 못한 방식이다. 

자바와 같은 경우엔 setter, 생성자를 이용해서 외부에서 주입해주는 상황은 외부에서 베터리를 교체해줄 수 있기 때문에 일체형보다 유연한 상황이다. 

 

 

출처 : https://velog.io/@gillog/Spring-DIDependency-Injection

스프링에서는 객체를 Bean이라고 부르며, 프로젝트가 실행될때 사용자가 Bean으로 관리하는 객체들의 생성과 소멸에 관련된 작업을 자동적으로 수행해주는데 객체가 생성되는 곳을 스프링에서는 Bean 컨테이너라고 부른다.

 

 

 

의존성 주입을 사용하는 이유

1. 재사용성을 높여준다.

2. 테스트에 용이하다.

3. 코드를 단순화 시켜준다.

4. 사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.

5. 종속성이 감소하기 때문에 변경에 민감하지 않다.

6. 결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.

7. 객체간의 의존관계를 설정할 수 있다.

 


Reference.

link1 link2

'🔥 > Spring' 카테고리의 다른 글

[spring] 빈 라이프 사이클과 범위  (0) 2021.08.31
[spring] 컴포넌트 스캔이란  (0) 2021.08.31
[Spring] "회초리단" 스프링 스터디 1차  (0) 2021.08.20
[Spring] DI의 세가지 방법  (0) 2021.08.18
MVC

Model
View
Controller

 

 

개발할 때 3가지 형태로 역할을 나누어 개발하는 방법론을 MVC 패턴이라 한다.

 

 

 

모델 Model

어플리케이션의 정보, 데이터를 나타낸다. 

어플리케이션이 무엇을 할것인지를 정의하며 내부 비지니스 로직을 처리하기 위한 역할을 한다.

모델의 규칙
1. 사용자가 편잡하길 원하는 모든 데이터를 갖고 있어야 한다.
2. view나 controller에 대해서 어떤 정보도 알지 못한다.
3. 변경이 일어나면, 변경 통지에 대한 처리 방법을 구현해야한다. 
더보기

1 -> 화면안의 네모박스에 글자가 표현된다면, 네모박스의 화면 위치 정보, 네모박스의 크기정보, 글자내용, 글자의 위치, 글자의 포맷 정보 등을 가지고 있어야 한다는 것

 

2 -> 데이터 변경이 일어났을 때 모델에서 화면 UI를 직접 조정해서 수정할 수 있도록 뷰를 참조하는 내부 속성값을 가지면 안 된다는 말

 

3 ->모델의 속성 중 텍스트 정보가 변경이 된다면, 이벤트를 발생시켜 누군가에게 전달해야 하며, 누군가 모델을 변경하도록 요청하는 이벤트를 보냈을 때 이를 수신할 수 있는 처리 방법을 구현해야 한다. 또한 모델은 재사용가능해야 하며 다른 인터페이스에서도 변하지 않아야 한다.

 

 

 

뷰 View

화면에 무엇인가를 보여주기 위한 역할

input 텍스트, 체크박스 항목 등과 같은 사용자 인터페이스 요소를 나타낸다. 다시 말해 데이터 및 객체의 입력, 그리고 보여주는 출력을 담당한다. 데이터를 기반으로 사용자들이 볼 수 있는 화면이다.

뷰의 규칙
1. 모델이 가지고 있는 정보를 따로 저장해서는 안된다.
2. 모델이나 컨트롤러와 같이 다른 구성요소들을 몰라야 된다.
3. 변경이 일어나면 변경통지에 대한 처리방법을 구현해야만 한다.
더보기

1 -> 화면에 글자를 표시 하기 위해, 모델이 가지고 있는 정보를 전달받게 될텐데, 그 정보를 유지하기 위해서 임의의 뷰 내뷰에 저장하면 안된다. 단순히 네모 박스를 그리라는 명령을 받으면, 화면에 표시하기만 하고 그 화면을 그릴 때 필요한 정보들은 저장하지 않아야 함!

 

2 -> 모델과 같은 자기 자신의 빼고는 다른 요소는 참조하거나 어떻게 동작하는지 알아서는 안된다. 그냥 뷰는 데이터를 받으면 화면에 표시해주는 역할만 가진다고 보면 된다.

 

3 -> 모델과 같이 변경이 일어났을 때 이른 누군가에게 변경을 알려줘야 하는 방법을 구현해야 한다. 뷰에서는 화면에서 사용자가 화면에 표시된 내용을 변경하게 되면 이를 모델에게 전달해서 모델을 변경해야 할 것이다. 그 작업을 하기 위해 변경 통지를 구현한다.

그리고 재사용가능하게끔 설계를 해야 하며 다른 정보들을 표현할 때 쉽게 설계를 해야 합니다.

 

 

 

 

컨트롤러 Controller

모델이 “어떻게” 처리할 지를 알려주는 역할을 하고, 모바일에서는 화면의 로직처리 부분이다.

화면에서 사용자의 요청을 받아서 처리되는 부분을 구현되게 되며, 요청 내용을 분석해서 Model과 View에 업데이트 요청을 하게 된다. (모델과 뷰의 중개 역할)

컨트롤러의 규칙
1. 모델이나 뷰에 대해서 알고 있어야 한다.
2. 모델이나 뷰의 변경을 모니터링 해야 한다.
더보기

1 -> 모델이나 뷰는 서로의 존재를 모르고, 변경을 외부로 알리고, 수신하는 방법만 가지고 있는데 이를 컨트롤러가 중재하기 위해 모델과 그에 관련된 뷰에 대해서 알고 있어야 한다.

 

2 -> 모델이나 뷰의 변경 통지를 받으면 이를 해석해서 각각의 구성 요소에게 통지를 해야 한다.

또한, 애플리케이션의 메인 로직은 컨트롤러가 담당하게 된다.

 

 

 

MVC가 필요한 이유와 의의

사용자가 보는 페이지, 데이터처리, 그리고 이 2가지를 중간에서 제어하는 컨트롤, 이 3가지로 구성되는 하나의 애플리케이션을 만들면 각각 맡은바에만 집중을 할 수 있게 된다.

공장에서도 하나의 역할들만 담당을 해서 처리를 해서 효율적이듯...

서로 분리되어 각자의 역할에 집중할 수 있게끔하여 개발을 하고 그렇게 애플리케이션을 만든다면, 유지보수성, 애플리케이션의 확장성, 그리고 유연성이 증가하고, 중복코딩이라는 문제점 또한 사라지게 된다. 

 

MVC패턴은 결국 "어떻게 나눌 것인가"에 대한 해답 중 하나다. 어떤 특정한 역할들에 대해 역할분담을 할 때 가이드라인을 제시하는 방법 중 하나가 바로 MVC패턴!!!!!

 

 

 

 

MVC패턴의 한계

MVC에서 View는 Controller에 연결되어 화면을 구성하는 단위요소이므로 다수의 View들을 가질 수 있다. 그리고 Model은 Controller를 통해서 View와 연결되어지지만, 이렇게 Controller를 통해서 하나의 View에 연결될 수 있는 Model도 여러개가 될 수 있다.

즉, 화면에 복잡한 화면과 데이터의 구성 필요한 구성이라면, Controller에 다수의 Model과 View가 복잡하게 연결되어 있는 상황이 생길 수 있다 MVC가 너무 복잡하고 비대해져서, 새 기능을 추가할때마다 크고 작은 문제점을 가지고 소드 분석이나 테스트도 어렵다.... 이런 형태의 MVC를 Massive ViewController (대규모 MVC 어플리케이션) 라고 부른다. 

 

그래서 위의 문제점을 보완한 여러 다양한!! 패턴을 파생시켰습니다.

MVP, MVVM, Viper, Clean Architecture, Flux, Redux, RxMVVM….

 


Reference.

링크1 링크2

'🔥 > 기타 등등 🎸' 카테고리의 다른 글

[git] git flow : 다양한 브랜치 전략  (0) 2021.08.31

정규화의 탄생 배경

한 relation에서 여러 entity의 attribute들을 혼합하게 되면 정보가 중복 저장되며 저장공간을 낭비하게 된다.

또한 이런 중복된 정보로 인해 갱신 이상이 발생하게 된다.

동일한 정보를 한 relation에는 변경하고 나머지 relation에서는 변경하지 않은 경우, 어느 것이 정확한지 알 수 없게 되는 것이다. 

 

이러한 문제를 해결하기 위해 정규화 과정을 거치게 된다.

 

갱신 이상이란...?

1. 삽입 이상 Insertion anomalies
원하지 않는 자료가 삽입된다든지, 삽입하는데 자료가 부족해 삽입이 되지 않아 발생하는 문제점

2. 삭제 이상 Deletion anomalies
하나의 자료만 삭제하고 싶지만, 그 자료가 포함된 튜플 전체가 삭제됨으로 원하지 않는 정보 손실이 발생하는 문제점

3. 수정 이상 Modification anomalies
정확하지 않거나 일부의 튜플만 갱신되어 정보가 모호해지거나 일관성이 없어져 정확한 정보 파악이 되지 않는 문제점

 

 

 

정규화란

관계형 데이터베이스에서 중복을 최소화하기 위해 데이터를 구조화하는 작업이다. 좀 더 구체적으로는 불만족스러운 나쁜 relation의 attribute들을 나누어서 좋은 작은 relation으로 분해하는 작업을 말한다.

나쁜 relation ?
엔티티를 구성하고 있는 애트리뷰트 간에 함수적 종속성(Functional Dependency)을 판단하는데, 각각의 정규형마다 어떠한 함수적 종속성을 만족하는지에 따라 정규형이 정의되고, 그 정규형을 만족하지 못하는 정규형을 나쁜 릴레이션으로 파악한다.

함수적 종속성은..?
애트리뷰트 데이터들의 의미와 애트리뷰트들 간의 상호 관계로부터 유도되는 제약조건의 일종이다. 

 

정규화 과정을 거치게 되면 정규형을 만족하게 된다. 정규형이란 특정 조건을 만족하는 릴레이션의 스키마의 형태를 말하며 제 1 정규형, 제 2 정규형, 제 3 정규형, … 등이 존재한다.

 

제 1 정규형

애트리뷰트의 도메인이 오직 원자값만을 포함하고, 튜플의 모든 애트리뷰트가 도메인에 속하는 하나의 값을 가져야 한다. 즉, 복합 애트리뷰트, 다중값 애트리뷰트, 중첩 릴레이션 등 비 원자적인 애트리뷰트들을 허용하지 않는 릴레이션 형태를 말한다.

제 2 정규형

모든 비주요 애트리뷰트들이 주요 애트리뷰트에 대해서 완전 함수적 종속이면 제 2 정규형을 만족한다고 볼 수 있다. 완전 함수적 종속이란 X -> Y 라고 가정했을 때, X 의 어떠한 애트리뷰트라도 제거하면 더 이상 함수적 종속성이 성립하지 않는 경우를 말한다. 즉, 키가 아닌 열들이 각각 후보키에 대해 결정되는 릴레이션 형태를 말한다.

제 3 정규형

어떠한 비주요 애트리뷰트도 기본키에 대해서 이행적으로 종속되지 않으면 제 3 정규형을 만족한다고 볼 수 있다. 이행 함수적 종속이란 X - >Y, Y -> Z의 경우에 의해서 추론될 수 있는 X -> Z의 종속관계를 말한다. 즉, 비주요 애트리뷰트가 비주요 애트리뷰트에 의해 종속되는 경우가 없는 릴레이션 형태를 말한다.

BCNF(Boyce-Codd) 정규형

여러 후보 키가 존재하는 릴레이션에 해당하는 정규화 내용이다. 복잡한 식별자 관계에 의해 발생하는 문제를 해결하기 위해 제 3 정규형을 보완하는데 의미가 있다. 비주요 애트리뷰트가 후보키의 일부를 결정하는 분해하는 과정을 말한다.

각 정규형은 그의 선행 정규형보다 더 엄격한 조건을 갖는다.

  • 모든 제 2 정규형 릴레이션은 제 1 정규형을 갖는다.
  • 모든 제 3 정규형 릴레이션은 제 2 정규형을 갖는다.
  • 모든 BCNF 정규형 릴레이션은 제 3 정규형을 갖는다.

수많은 정규형이 있지만 관계 데이터베이스 설계의 목표는 각 릴레이션이 3NF(or BCNF)를 갖게 하는 것이다.

 

 

 

 

정규화의 장점

  1. 데이터베이스 변경 시 이상 현상(Anomaly) 제거 위에서 언급했던 각종 이상 현상들이 발생하는 문제점을 해결할 수 있다.
  2. 데이터베이스 구조 확장 시 재 디자인 최소화 정규화된 데이터베이스 구조에서는 새로운 데이터 형의 추가로 인한 확장 시, 그 구조를 변경하지 않아도 되거나 일부만 변경해도 된다. 이는 데이터베이스와 연동된 응용 프로그램에 최소한의 영향만을 미치게 되며 응용프로그램의 생명을 연장시킨다.
  3. 사용자에게 데이터 모델을 더욱 의미있게 제공 정규화된 테이블들과 정규화된 테이블들간의 관계들은 현실 세계에서의 개념들과 그들간의 관계들을 반영한다.

 

 

정규화의 단점

릴레이션의 분해로 인해 릴레이션 간의 연산(JOIN 연산)이 많아진다.

이로 인해 질의에 대한 응답 시간이 느려질 수 있다.

 

조금 덧붙이자면, 정규화를 수행한다는 것은 데이터를 결정하는 결정자에 의해 함수적 종속을 가지고 있는 일반 속성을 의존자로 하여 입력/수정/삭제 이상을 제거하는 것이다. 데이터의 중복 속성을 제거하고 결정자에 의해 동일한 의미의 일반 속성이 하나의 테이블로 집약되므로 한 테이블의 데이터 용량이 최소화되는 효과가 있다.

 

따라서 정규화된 테이블은 데이터를 처리할 때 속도가 빨라질 수도 있고 느려질 수도 있는 특성이 있다.

 

이와 같은 단점이 있다면, 어떤 상황에서 정규화를 진행해야하는가?

반정규화(De-normalization, 비정규화)
반정규화는 정규화된 엔티티, 속성, 관계를 시스템의 성능 향상 및 개발과 운영의 단순화를 위해 중복 통합, 분리 등을 수행하는 데이터 모델링 기법 중 하나이다. 디스크 I/O 량이 많아서 조회 시 성능이 저하되거나, 테이블끼리의 경로가 너무 멀어 조인으로 인한 성능 저하가 예상되거나, 칼럼을 계산하여 조회할 때 성능이 저하될 것이 예상되는 경우 반정규화를 수행하게 된다. 일반적으로 조회에 대한 처리 성능이 중요하다고 판단될 때 부분적으로 반정규화를 고려하게 된다.

* 반정규화의 대상
1. 자주 사용되는 테이블에 액세스하는 프로세스의 수가 가장 많고, 항상 일정한 범위만을 조회하는 경우
2. 테이블에 대량 데이터가 있고 대량의 범위를 자주 처리하는 경우
3. 성능 상 이슈가 있을 경우
4. 테이블에 지나치게 조인을 많이 사용하게 되어 데이터를 조회하는 것이 기술적으로 어려울 경우


(주의, 반정규화를 과도하게 적용하다 보면 데이터의 무결성이 깨질 수 있다. 또한 입력, 수정, 삭제의 질의문에 대한 응답 시간이 늦어질 수 있다.)

Reference.

링크1

Program : 어떤 작업을 위해 실행할 수 있는 파일
Process : 운영체제로부터 자원을 할당받은 작업의 단위
Thread : 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위

 

프로그램이란 파일이 저장장치에 저장되어 있지만 메모리에는 올라가 있지 않은 정적인 상태

 

 

프로세스 Process

  • 메모리에 올라와 실행되고 있는 프로그램의 인스턴스 ( 독립적인 개체 )
  • 운영체제로부터 시스템 자원을 할당받는 작업의 단위
  • 즉, 동적인 개념으로는 실행된 프로그램을 의미한다

 

 

  • 프로세스는 각각 독립된 메모리 영역(Code, Data, Stack, Heap의 구조)을 할당받는다.
  • 기본적으로 프로세스당 최소 1개의 스레드(메인 스레드)를 가지고 있다.
  • 각 프로세스는 별도의 주소 공간에서 실행되며, 한 프로세스는 다른 프로세스의 변수나 자료구조에 접근할 수 없다.
  • 한 프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신(IPC, inter-process communication)을 사용해야 한다. ( Ex. 파이프, 파일, 소켓 등을 이용한 통신 방법 이용 )

 

 

 

스레드 Thread

프로그램이 복잡해지고 프로세스 하나만을 사용해서 프로그램을 실행하기에는 벅차다. 
한 프로그램을 처리하기 위해 프로세스를 여러개 만드는 것은 안정성을 위해 자신에게 할당된 메모리 내의 정보만 접근하도록 유도하는 제약때문에 불가능하다.
따라서 프로세스보다 더 작은 실행 단위의 개념이 등장한다.
  • 프로세스의 실행 단위
  • 프로세스의 특정한 수행 경로
  • 프로세스가 할당받은 자원을 이용하는 실행의 단위

 

  • 스레드는 프로세스 내에서 각각 Stack만 따로 할당받고 Code, Data, Heap 영역은 공유한다.
  • 스레드는 한 프로세스 내에서 동작되는 여러 실행의 흐름으로, 프로세스 내의 주소 공간이나 자원들(힙 공간 등)을 같은 프로세스 내에 스레드끼리 공유하면서 실행된다.
  • 같은 프로세스 안에 있는 여러 스레드들은 같은 힙 공간을 공유한다. 반면에 프로세스는 다른 프로세스의 메모리에 직접 접근할 수 없다.
  • 각각의 스레드는 별도의 레지스터와 스택을 갖고 있지만, 힙 메모리는 서로 읽고 쓸 수 있다.
  • 한 스레드가 프로세스 자원을 변경하면, 다른 이웃 스레드(sibling thread)도 그 변경 결과를 즉시 볼 수 있다.

 


프로세스와 스레드의 작동방식 차이

프로세스가 메모리에 올라갈 때 운영체제로부터 시스템 자원을 할당받는다고 언급했었다. 이 때 운영체제는 프로세스마다 각각 독립된 메모리 영역을, Code/Data/Stack/Heap의 형식으로 할당해 준다. 각각 독립된 메모리 영역을 할당해 주기 때문에 프로세스는 다른 프로세스의 변수나 자료에 접근할 수 없다.

 

 

 

이와 다르게 스레드는 메모리를 서로 공유할 수 있다고 언급했었다. 이에 대해 더 자세히 설명하자면, 프로세스가 할당받은 메모리 영역 내에서 Stack 형식으로 할당된 메모리 영역은 따로 할당받고, 나머지 Code/Data/Heap 형식으로 할당된 메모리 영역을 공유한다. 따라서 각각의 스레드는 별도의 스택을 가지고 있지만 힙 메모리는 서로 읽고 쓸 수 있게 된다.

 

 

여기서 프로세스와 스레드의 중요한 차이를 하나 더 알 수 있게 된다. 만약 한 프로세스를 실행하다가 오류가 발생해서 프로세스가 강제로 종료된다면, 다른 프로세스에게 어떤 영향이 있을까? 공유하고 있는 파일을 손상시키는 경우가 아니라면 아무런 영향을 주지 않는다.

 

그런데 스레드의 경우는 다르다. 스레드는 Code/Data/Heap 메모리 영역의 내용을 공유하기 때문에 어떤 스레드 하나에서 오류가 발생한다면 같은 프로세스 내의 다른 스레드 모두가 강제로 종료된다.

 

 

왜 이런 방식으로 메모리를 공유할까?

스레드는 "흐름의 단위"라고 말했는데, 정확히는 CPU 입장에서의 최소 작업 단위가 된다. CPU는 작업을 처리할 때 스레드를 최소 단위로 삼고 작업을 한다. 반면 운영체제는 이렇게 작은 단위까지 직접 작업하지 않기 때문에 운영체제 관점에서는 프로세스가 최소 작업 단위가 된다.
여기서 중요한 점은 하나의 프로세스는 하나 이상의 스레드를 가진다는 점이다. 따라서 운영체제 관점에서는 프로세스가 최소 작업 단위인데, 이 때문에 같은 프로세스 소속의 스레드끼리 메모리를 공유하지 않을 수 없다.

 


Reference.

참고

참고2

HTTP란

Hyper Text Transfer Protocol
www상에서 정보를 주고받는 프로토콜

 

클라이언트인 웹 브라우저가 서버에 HTTP를 통해 웹페이지나 이미지 정보를 요청하면, 서버는 이 요청에 응답하여 요구하는 정보를 제공하게 된다.

HTTP는 웹 브라우저Client와 서버Server간의 웹페이지 같은 자원을 주고 받을 때 쓰는 통신 규약이다.

HTTP는 텍스트 교환이라 (html페이지도 텍스트!) 누군가 네트워크에서 신호를 가로채 본다면 내용이 노출될 것이다.

이와같은 보안상의 문제를 해결해주는 프로토콜이 HTTPS이다.

 

 

 

" HTTP의 문제점 "

  • HTTP 는 평문 통신이기 때문에 도청이 가능하다.
  • 통신 상대를 확인하지 않기 때문에 위장이 가능하다.
  • 완전성을 증명할 수 없기 때문에 변조가 가능하다.

* 위와 같은 문제점은 암호화하지 않은 다른 프로토콜에도 공통되는 문제점이다.

 

 

1. TCP/IP 는 도청 가능한 네트워크...

 TCP/IP 구조의 통신은 전부 통신 경로 상에서 엿볼 수 있다. 패킷을 수집하는 것 만으로도 도청할 수 있다. 따라서 암호화하여 통신해야한다.

보안 방법

1. 통신 자체를 암호화
SSL 또는 TLS라는 다른 프로토콜을 조합함으로써  HTTP의 통신 내용을 암호화할 수 있다.  SSL을 조합한 HTTP를 바로 HTTPS(HTTP over SSL)라고 부른다.

2. 콘텐츠를 암호화
말 그대로 HTTP를 사용해서 운반하는 내용인 HTTP 메세지에 포함되는 콘텐츠만 암호화하는 것이다. 암호화해서 전송하면 받은 측에서는 그 암호를 해독하여 출력하는 처리가 필요하다.  

 

 

 

2. 통신 상대를 확인하지 않기 때문에 위장이 가능...

HTTP 에 의한 통신에는 상대가 누구인지 확인하는 처리는 없기 때문에 누구든지 리퀘스트를 보낼 수 있다. IP 주소나 포트 등에서 그 웹 서버에 액세스 제한이 없는 경우 리퀘스트가 오면 상대가 누구든지 무언가의 리스폰스를 반환한다. 이러한 특징은 여러 문제점을 유발한다.

 

1. 리퀘스트를 보낸 곳의 웹 서버가 원래 의도한 리스폰스를 보내야 하는 웹 서버인지를 확인할 수 없다.
2. 리스폰스를 반환한 곳의 클라이언트가 원래 의도한 리퀘스트를 보낸 클라이언트인지를 확인할 수 없다.
3. 통신하고 있는 상대가 접근이 허가된 상대인지를 확인할 수 없다.
4. 어디에서 누가 리퀘스트 했는지 확인할 수 없다.
5. 의미없는 리퀘스트도 수신한다. —> DoS 공격을 방지할 수 없다.

 

보완 방법

윗 상자에서 말한 SSL 로 상대를 확인할 수 있다. 
SSL은 상대를 확인하는 수단으로 증명서를 제공하고 있다. 증명서는 신뢰할 수 있는 제 3자 기관에 의해 발행되는 것이기 때문에 서버나 클라이언트가 실재하는 사실을 증명한다. 이 증명서를 이용함으로써 통신 상대가 내가 통신하고자 하는 서버임을 나타내고 이용자는 개인 정보 누성 등의 위험성이 줄어들게 된다.
한 가지 이점을 더 꼽자면, 클라이언트는 이증명서로 본인 확인을 하고 웹 사이트 인증에서도 이용할 수 있다.

 

 

 

3. 완전성을 증명할 수 없기 때문에 변조가 가능하다

여기서 완전성이란 정보의 정확성 을 의미한다. 서버 또는 클라이언트에서 수신한 내용이 송신측에서 보낸 내용과 일치한다라는 것을 보장할 수 없는 것이다. 리퀘스트나 리스폰스가 발신된 후에 상대가 수신하는 사이에 누군가에 의해 변조되더라도 이 사실을 알 수 없다. 이와 같이 공격자가 도중에 리퀘스트나 리스폰스를 빼앗아 변조하는 공격을 중간자 공격(Man-in-the-Middle)이라고 부른다.

 

보완 방법

MD5, SHA-1 등의 해시 값을 확인하는 방법과 파일의 디지털 서명을 확인하는 방법이 존재하지만 확실히 확인할 수 있는 것은 아니다. 확실히 방지하기에는 HTTPS를 사용해야 한다. SSL 에는 인증이나 암호화, 그리고 다이제스트 기능을 제공하고 있다.

 


HTTPS

HTTP에 암호화와 인증과 완전성 보호를 더한 HTTPS

HTTPS는 SSL 의 껍질을 덮어쓴 HTTP 라고 할 수 있다. 즉, HTTPS 는 새로운 애플리케이션 계층의 프로토콜이 아니라는 것이다. HTTP 통신하는 소켓 부분을 SSL(Secure Socket Layer) or TLS(Transport Layer Security)라는 프로토콜로 대체하는 것 뿐이다. HTTP 는 원래 TCP 와 직접 통신했지만, HTTPS 에서 HTTP 는 SSL 과 통신하고 SSL 이 TCP 와 통신 하게 된다. SSL 을 사용한 HTTPS 는 암호화와 증명서, 안전성 보호를 이용할 수 있게 된다.

 

HTTPS 의 SSL 에서는 공통키 암호화 방식과 공개키 암호화 방식을 혼합한 하이브리드 암호 시스템을 사용한다. 공통키를 공개키 암호화 방식으로 교환한 다음에 다음부터의 통신은 공통키 암호를 사용하는 방식이다.

 

 

모든 웹 페이지에서 HTTPS를 사용해도 될까?

평문 통신에 비해서 암호화 통신은 CPU나 메모리 등 리소스를 더 많이 요구한다. 통신할 때마다 암호화를 하면 추가적인 리소스를 소비하기 때문에 서버 한 대당 처리할 수 있는 리퀘스트의 수가 상대적으로 줄어들게 된다.
하지만 최근에는 하드웨어의 발달로 인해 HTTPS를 사용하더라도 속도 저하가 거의 일어나지 않으며, 새로운 표준인 HTTP 2.0을 함께 이용한다면 오히려 HTTPS가 HTTP보다 더 빠르게 동작한다. 따라서 웹은 과거의 민감한 정보를 다룰 때만 HTTPS에 의한 암호화 통신을 사용하는 방식에서 현재 모든 웹 페이지에서 HTTPS를 적용하는 방향으로 바뀌어가고 있다.

 


Reference.

'🔥 > Network' 카테고리의 다른 글

[네트워크] OSI 7계층  (0) 2021.09.09
[네트워크] 웹 통신의 큰 흐름  (0) 2021.08.31
[네트워크] DNS round robin 방식  (0) 2021.08.25
[네트워크] TCP와 UDP 차이점  (0) 2021.08.10
[네트워크] GET, POST 방식의 차이점  (0) 2021.08.01

교수님이 카카오 검색 API를 통해 가져오는 것보다는 raw data를 가공해 직접 추천 알고리즘을 짜는 것이 어떻겠냐는 제안을 해주셨다. 그래서 공공데이터의 소상공인시장진흥공단_상가의 데이터를 가공해서 크롤링을 통해 추천 알고리즘을 짜는 것을 진행해보려한다!

 

수많은 추천 알고리즘이 있지만 코사인 유사도를 이용하면 간단하면서도 그럴싸한 추천 시스템을 만들 수 있다고 한다.

우선 공공데이터를 이용해 어떤 요식업 업체가 있는지 파악하고 카테고리 데이터를 활용해 비슷한 업체의 추천을 받는 것을 도전해보겠다~!

 

 

데이터의 표현

컴퓨터는 처리하고자 하는 데이터를 vector로 다룬다.

머신러닝 분야에서는 두 벡터 (데이터) 간의 유사성을 측정해야 하는 일이 많다. -> ex) 두 문장이 얼마나 유사한지 측정

 

코사인 유사도 

  • 벡터의 크기는 고려하지 않고 두 벡터 사이의 각도만 고려하는 측정법
  • 방향이 얼마나 유사한 지를 1부터 -1 사이의 값으로 표현 ( 방향이 동일한 경우 : 1 )

+ Recent posts