참고도서 : 현대 네트워크 기초 이론

최종 업데이트 : 2024-03-26


 

1.3 이더넷

이더넷 애플리케이션

이더넷은 대표적인 유선 네트워크 기술로, 최대 100Gbps의 높은 속도와 수km까지 지원하도록 발점함에 따라 서버와 대규모 데이터 저장장치에 사용하는 필수적인 기술이 됐다.

 

가정 내 이더넷

  • 이더넷은 아직까지 거의 모든 가정용 네트워크 구성에 포함된다. 특히 전력선 통신 (PLC, Power Line Carrier) 과 이더넷 전원 장치(PoE, Power over Ethernet) 이 확장에 많은 기여를 했는데, 전력선 모뎀은 기존 전원선을 통신 채널로 사용해 전력 신호 위에 이더넷 패킷을 전송한다. PoE는 이더넷 데이터 이블로 전력을 공급한다.

사무실 내 이더넷

  • 일반적인 사무실 환경에서 대부분의 데이터 트래픽은 모바일 장치를 지원하기 위해 와이파이로 전송되지만, 이더넷이 여전히 인기를 유지하는 이유는 고속으로 많은 장치를 지원하며 도청이 어려워 보안 측면에서 우수하기 때문이다. 따라서 와이파이와 이더넷의 조합이 가장 일반적인 아키텍처다.

기업 내 이더넷

  • 이더넷의 큰 장점은 동일한 프로토콜과 서비스 품질, 보안 표준을 유지하며 거리와 속도 측면에서 네트워크 확장이 가능하다는 점인데 10Mbps-100Gbps까지 지원하는 다양한 케이블과 이더넷 하드웨어를 통해 멀리 떨어진 건물 사이에서도 쉽게 네트워크를 확장할 수 있다. 모든 하드웨어와 통신 소프트웨어가 동일한 표준을 따르기 때문에 속도와 제조사가 제각각인 장비를 조합하는 것은 어렵지 않다. 최대 100km 떨어진 이더넷 네트워크에 접속할 때에도 같은 프로토콜을 사용할 수 있다.

데이터 센터 이더넷

  • 대량의 데이터를 처리하기 위해서는 매우 높은 전송 속도가 필요한데, 데이터 센터 네트워크에서도 이더넷이 가장 많이 사용된다. 전통적으로는 인피니밴드(Infiniband)와 광채널 등을 사용했으나 현재 이더넷은 최대 100Gbps까지 지원하기 때문에 기업 네트워크 전체를 이더넷 프로토콜만으로도 구현하는 방법도 많이 사용되고 있다.
  • 일반적으로 먼저 함께 배치된 서버와 스토리지 장치 사이의 네트워크 infrastructure 구축에 고속 이더넷 광케이블과 스위치가 사용된다. 그리고 백플레인 이더넷을 사용하기도 하는데, 구리 케이블을 사용하여 아주 짧은 거리에서 100Gbps까지 전송할 수 있으므로 여러 서버 모듈이 단일 랙에 저장되는 블레이드서버에 적합한 기술이다.

광역 네트워킹 이더넷

  • 이더넷은 T1 전용선, 동기식 디지털 계층(SDH, Synchronous Digital Hierarchy), 비동기 전송 방식(ATM, Asynchronous Transfer Mode) 등 다양한 광역 액세스 기술을 대체하고 있으며 캐리어 이더넷이라고 불리기도 한다.
  • 전통적인 광역 네트워킹 이더넷과 비교했을 때 캐리어 이더넷이 속도 측면에서 훨씬 다양한 선택을 제공하고 이더넷 기술 중에 가장 빠르게 성장하고 있으며, 향후 핵심 기술이 될 것으로 전망된다.

 

기술 표준

IEEE 802 LAN 표준위원회의 802.3 그룹이 이더넷 LAN 표준을 맡고 있다.

 

이더넷 데이터 속도

이더넷 속도를 연대순으로 정리하면 아래와 같다.

 

1Gbps 이더넷

초기의 10Mbps 표준은 사무실 환경에서 사용하기 충분했으나 1990년대 초반 이후 LAN 트래픽이 늘어나자 더 높은 속도가 필요했다. 그 이유는 아래와 같다.

1. 다수의 중앙 집중식 서버에서 대량의 데이터를 읽어올 필요가 많아졌고, 서버 성능이 증가함에 따라 네트워크가 병목이 됐다. 

2. 대용량의 데이터 파일을 교환해야 했다. 소프트웨어 개발과 CAD 애플리케이션이 있다.

3. 기업에서 처리할 작업이 많아짐에 따라 다수의 LAN을 백본 네트워크로 연결한 구조가 등장했다.

 

 

10Gbps 이더넷

1Gbps 표준 규격이 나온지 얼마 지나지 않아 10Gbps 이더뎃이 필요해졌고 인트라넷과 인터넷 트래픽의 증가가 주된 이유였다.

  • 네트워크 연결 개수의 증가
  • 단말 연결 속도의 증가
  • 고품질 동영상 등 많은 대역폭이 필요한 애플리케이션의 증가
  • 웹/애플리케이션 호스팅 트래픽 증가

네트워크 관리자들은 초기에 대용량 스위치들 사이에 고속 로컬 백본을 제공하기 위해 10Gbps 이더넷을 사용했고, 대역폭의 수요가 증가함에 따라 서버팜, 백본, 캠퍼스규모 망 등 전체 네트워크에 설치되기 시작했다. ISP와 네트워크 사업자(NSP, Network Service Provider)는 10Gbps 이더넷 기술로 캐리어급 스위치와 라우터 사이의 초고속 링크를 매우 낮은 비용으로 생성할 수 있다.

캠퍼스 및 인터넷 접속 거점 (PoP, Points of Presence) 등 지리적으로 분산된 LAN 구간을 연결하는 MAN과 WAN 구성에도 사용된다.

 

100Gbps 이더넷

인터넷 연동노드, 고성능 컴퓨팅, 주문형 비디오 (VOD, Video On Demand) 전송을 지원하기 위해 10Gbps보다 높은 데이터 속도가 필요했고 속도가 서로 다른 네트워크와 단말의 요구사항을 고려해 새 표준에서는 두 종류의 속도가 필요했다.

 

촉진 요인

- 데이터 센터/인터넷 미디어 공급자 : 인터넷 미디어 콘텐츠 및 웹 애플리케이션의 성장

- 매트로 비디오/서비스 공급자 : 주문형 비디오는 10Gbps 이더넷/ 코어 네트워크의 개발을 주도하는 주 요인이다.

- 기업 LAN : 음성/비디오/데이터 융합과 통합 커뮤니케이션의 성장 > 하지만 아직까지 대부분의 기업은 1Gbps 혹은 1Gbps+10Gbps의 조합에 의존하고 있다.

- 인터넷 연동 노드 / ISP 코어 라우팅

 

  • 일반적으로 블레이드 서버는 10Gbps 이더넷 스위치를 통해 다른 장비들과 연결되고, 스위치들은 대개 랙에 탑재되어 TOR (Top-Of-Rack) 스위치로 불린다. 이 용어는 실제로 랙 최상단의 위치하지 않아도 서버 액세스 스위치와 같은 의미로 통용되고 있다. 
  • 매우 큰 데이터센터의 경우 수많은 렉을 10Gbps 스위치로 연결하는 것이 점차 어려워지기 때문에 늘어나는 트래픽 부하를 감당하기 위해 랙 간 연결과 NIC를 활용한 외부 연결을 처리할 10Gbps 이상의 스위치가 필요하다.

 

 

25/50Gbps 이더넷

25Gbps 물리 레인을 4개 사용하는 것이나 50Gbps를 2개 사용함으로써 100Gbps를 구현할 수 있다. 구글, MS등 주요 클라우드 사업자의 주도로 25Gbps 이더넷 컨소시엄이 만들어졌고 성능 향상과 NIC-ToR 스위치 간의 Gbps당 연결 비용 절감을 목적으로 하는 이더넷 규격을 지원하기 위한 목적이었다.

이 컨소시엄의 규격은 1레인 25Gbps 이더넷, 2레인 50Gbps 이더넷 링크 프로토콜을 규정함으로써 10Gbps 및 40Gbps 이더넷 링크보다 최대 2.5배의 고성능을 낼 수 있다.

400Gbps 이더넷

대역폭의 수요는 끝없이 늘어나고 있다. 아직 일정은 미정이지만 IEEE 에서는 400Gbps 이더넷 표준을 위해 여러 기술적 옵션을 검토 중이다.

 

2.5/5Gbps 이더넷

이더넷이 높은 데이터 속도에 대한 표준화가 진행된 반면, 낮은 데이터 속도의 표준화에 대해서도 니즈가 있었다. 상대적으로 낮은 속도의 기술은 MGBASE-T 라고 불리며 IEEE와 별도로 표준화를 주관하고 있다.

이 속도는 주로 IEEE 802.11ac 무선 트래픽을 유선 네트워크로 지원하기 위한 목적이다.  1Gbps 이상의 대역폭이 필요한 곳에서 사용되기 시작하는 3.2Gbps 와이파이 표준이다. 1Gbps 이더넷으로 감당할 수 없지만, 10Gbps까지는 필요 없다.

만약 해당 이더넷들이 1Gbps와 동일한 케이블을 사용할 수 있게 된다면 802.11ac 무선 규격을 지원하는 고성능 액세스 포인트에 맞는 속도를 개선하게 된다.

 

 

참고도서 : 현대 네트워크 기초 이론

최종 업데이트 : 2024-03-25


 

1.1 네트워크 생태계

전체 네트워크 생태계의 존재 목적은 최종 사용자(end user)에게 서비스를 제공하기 위한 것이다. 사용자 플랫폼으로는 고정형, 휴대형, 모바일 모두 가능하며 사용자들은 네트워크 기반 서비스/콘텐츠에 네트워크 액세스 장비를 통해 접속한다. 예를 들면 와이파이, 셀룰러 모뎀, 디지털 가입자 회선 모뎀 등이 있으며 이러한 장비들을 통해 인터넷에 직접 연결하거나 공용 네트워크를 통해 네트워크 사업자와 연결한다.

 

애플리케이션 공급자는 사용자 플랫폼에서 실행되는 애플리케이션을 제공한다. 애플리케이션 서비스 공급자는 자신의 플랫폼에서 실행되는 애플리케이션 소프트웨어의 서버 또는 호스트 역할을 제공한다. 소프트웨어의 전통적인 예로는 웹서버, 이메일서버, 데이터베이스 서버 등이 있으며 최근의 예로는 클라우드 컴퓨팅 사업자가 있다.

 

주목할만한 현대 네트워크 기술은 아래와 같다.

  • 데이터 센터 네트워킹 : 대규모 기업 데이터 센터와 클라우드 사업자 데이터센터는 수많은 서버들로 구성되어 있다. 일반적으로 데이터 트래픽의 80%는 내부 네트워크 트래픽이고 20%는 외부 네트워크를 통해 사용자에게 전달된다.
  • IoT 또는 포그 네트워킹 : 기업의 사물 인터넷망은 수천만 개의 장치들로 구성되는데 이러한 장치들이 주고받는 방대한 데이터는 대부분 기계와 기계 사이의 트래픽이다.

 

1.2 네트워크 아키텍처 사례

글로벌 네트워크 아키텍처

중심부에는 IP backbone 혹은 코어 네트워크가 위치하고 있는데, 일반적으로 코어 라우터라고 하는 수많은 광케이블로 연결된 고성능 라우터들로 이뤄진다. 대개 파장 분할 다중화(WDM) 기술을 사용해 각기 다른 광파장 대역을 차지하는 논리적 채널들을 동시에 전송한다.

  • 라우터(router) : 한 네트워크에서 다른 네트워크로 데이터 패킷을 전달하는 네트워크 장치. 네트워크 계층 정보와 라우팅 프로토콜이 만드는 라우팅 테이블에 따라 포워딩이 결정된다. 라우터에서 패킷 포맷은 표준 IP 프로토콜 등 라우팅이 가능한 프로토콜을 따라야 한다.
  • 코어 라우터 (core router)  : 네트워크 주변부가 아닌 중심부에 위치한 라우터로, 인터넷 백본을 구성하는 라우터이다.

그 주변부에는 외부 네트워크와 사용자들로 연결되는 라우터가 있고, 엣지 라우터라고 불린다. 이는 기업 네트워크에서 라우터와 스위치들을 IP 백본이나 고속 WAN (Wide Area Network) 등의 외부 리소스에 연결하기 위해 사용된다. 

  • 엣지 라우터 (edge router) : 네트워크 주변부에 위치한 라우터이다.
    기업 네트워크

대규모 기업 네트워크는 광회선으로 연결된 스위치들이 있는 두 개의 네트워크가 고속의 전용 WAN으로 연결되며, 이와 같은 WAN에서 IP기반의  MPLS가 일반적으로 사용되는 스위치 프로토콜이며, 광역 이더넷도 또다른 옵션이 될 수 있다. 기업 내 장비들은 방화벽을 구현하기 위해 방화벽 기능이 있는 라우터를 통해 IP 백본 또는 인터넷에 연결된다.

 

 

 

작은 기업의 네트워크 구성도는 인터넷에 접속하는 라우터는 케이블, DSL 연결 또는 고속 전용선을 통해 연결된다.

 

 

 

개별 가정 가입자의 경우 대표적으로 전화선을 통한 고속 연결을 제공하는 DSL 모뎀과 케이블 연결, 기타 무선 연결 등이 있다. 각 경우마다 신호 인코딩, 오류제어, 가입자 네트워크 내부 구조 등 여러가지 이슈가 있다.

 

스마트폰과 태블릿 등의 모바일 장치는 셀룰러 네트워크를 통해 인터넷에 연결하는데, 셀룰러 네트워크는 광회선과 같은 고속 연결로 인터넷에 연결된다.

 

 

일반 네트워크 계층 구조

 

일반적으로 네트워크 설비는 대개 액세스-분배-코어 3계층 구조로 설계된다.

최종 사용자와 가장 가까운 것은 액세스 네트워크이다. 일반적으로 로컬 영역 네트워크 (LAN) 또는 캠퍼스 규모의 네트워크이며 LAN 스위치와 대규모 LAN에서 스위치 간 연결을 제공하는 IP라우터로 구성된다. L3 스위치도 LAN에서 흔히 사용된다. 데스크톱, 노트북, 모바일 장치 등의 장비가 연결될 수 있다.

 

로컬의 장비들은 액세스 라우터를 통해 분배 네트워크로 연결되고 액세스 네트워크의 트래픽을 주고받으며 엣지 라우터 처럼 동작한다. 대규모 로컬 설비에서는 내부 라우팅 기능만을 지원하는 추가 액세스 라우터가 있는 경우도 있다. 분배 네트워크의 엣지 라우터액세스 네트워크에지 라우터와 연결되는데, 이들은 라우팅과 연결정보 및 트래픽 정보를 교환한다. 이처럼 라우터끼리 협력하는 절차를 피어링 (peering) 이라고 한다. 또한 코어 네트워크로 향하는 트래픽을 집선해 코어 네트워크의 과도한 피어링을 방지함으로써 라우터의 수가 제한되고 메모리, CPU, 전송용량을 절약하는 효과가 있다.

 

코어 네트워크는 백본 네트워크라고도 불리며 지리적으로 분산된 분배 네트워크를 연결하고 기업 네트워크 범위 밖의 외부 네트워크로 액세스를 제공한다. 일반적으로 초고성능 라우터, 대용량 전송회선, 중복성과 용량을 위해 클러스터링된 다수의 라우터를 사용하며 대규모 데이터베이스 서버나 사설 클라우드 장비와 같은 대용량 서버 시스템에 접속할 수 있도록 설계되어 있다.

 

네트워크 계층 구조는 모듈화 설계의 한 가지 좋은 예로, 각 계층의 요구 사항에 따라 네트워크 장비의 용량, 특성, 기능이 최적화되도록 설계된다.

 

 

해당 포스팅은 오레일리의 책, 클라우드 아키텍트 트랜스포메이션을 보며 정리한 내용입니다.

최종 업데이트 : 2024-01-12


 

클라우드 네이티브는 단순한 도구 모음 이상의 의미가 있다. 완벽한 아키텍처로, 컴퓨팅을 최대한 활용하는 클라우드 애플리케이션을 구축하기 위한 철학적인 접근 방식이다.

 

 

" 클라우드 네이티브"는 " 클라우드 " 가 아니다.

클라우드 컴퓨팅을 단순히 "클라우드"라 하면 인터넷을 통해 인프라스트럭처를 주문형 방식으로 제공하는 것을 의미한다. AWS, GCP, Azure 등의 클라우드 서비스 플랫폼에서 제공하는 경우가 많으므로 실제로 소비하는 자원에 대해서만 요금을 지불할 수 있다.

 

클라우드 네이티브는 위의 모든 클라우드 기반 구성요소를 클라우드 환경에 최적화된 방식으로 조립하기 위한 아키텍처이다. 서버가 아닌 서비스에 대한 것이며, 기업의 목표는 사례에 적합한 클라우드 기술을 효율적으로 선택하는 데 있다.

클라우드 네이티브 마이그레이션 목적에 도달하기 위한 경로는 수없이 많고, 조직의 요구에 따라 다양한 방법이 있기 때문에 방향을 잃어버리기 쉽다. 이를 위해서는 전체 구현 및 배포 전에 설계를 이해하고 우선순위를 정해야 한다.

 

클라우드 네이티브 패턴 언어를 개발하는 것은 유용하고 재사용 가능한 로드맵을 작성하는 다음 단계이다. 개발자가 best practice를 논의하고 학습,적용할 수 있도록 공통 context를 식별하고 협의하기 위한 언어가 필수적이다.

 

 

클라우드 네이티브 개요

클라우드 네이티브 컴퓨팅이란, 오픈소스 소프트웨어 스택을 사용해 애플리케이션을 마이크로서비스로 배포, 각 부분을 자체 컨테이너에 패키징, 컨테이너를 동적으로 조정해 리소스 활용도를 최적화하는 것이다.
-CNCF(Cloud Native Computin Foundation)-

 

기본적으로 클라우드 네이티브는 특정한 접근 방식의 이름이며, 아키텍처는 CI를 할 때 IaaS에 의존한다. 일반적인 목표는 속도 향상이며, 이를 통해 새로운 아이디어를 몇 시간 내 운영 환경에 투입할 수 있다. 실제로 클라우드 네이티브로 마이그레이션하는 대부분의 기업은 속도를 주요 이동 요인으로 꼽는다.

 

클라우드 네이티브를 어떻게 알 수 있을까?

클라우드 네이티브의 기본 원칙을 컨테이너 패키징, 동적 관리 및 모듈식 분산 아키텍처라 하는 경우가 많지만 실제로는 다섯가지의 아키텍처 원칙과 두가지 문화적 원칙이다.

 

<아키텍처 원칙>

  • 컨테이너화 : 애플리케이션과 종속성/운영 환경을 함께 캡슐화해 단일 패키지로 구성할 수 있다. 테스트, 이동/배포가 쉬워진다.
  • 동적 관리 : 온디맨드 방식으로 유연하게 프로비저닝할 수 있는 서비스를 사용한다. 일반적인 public cloud에서는 사용한 리소스에 대해서만 비용을 지불한다.
  • 마이크로서비스 : 애플리케이션을 분리된 소규모 구성 요소 서비스의 집합으로 서비스한다. 각 마이크로서비스는 다른 서비스와 독립적으로 작동하며 최종 사용자에게 영향을 미치지 않는다. 마이크로서비스는 팀이 동시에 개발하면서 독립적으로도 개발할 수 있도록 해 개발 속도를 높이는 데 도움을 준다.
  • 자동화 : 유지보수 및 업데이트와 같은 수동 작업을 스크립트나 코드로 교체해 원활하고 안정적으로 수행할 수 있다.
  • 오케스트레이션 : 컨테이너형 애플리케이션의 배포, 확장 및 관리를 자동화해 모든 것을 하나로 묶는다. 특히, 쿠버네티스 또는 오케스트레이션 도구를 사용하여 인프라 전반에서 컨테이너의 로드 밸런싱, 스케일 업다운 등의 작업을 제어 및 자동화한다.

<문화적 원칙>

  • 위임 (Delegation) : 개인이 안전하게 변경하도록 필요한 도구, 교육 및 재량권을 제공하고 되도록 자율적으로 배포 및 모니터링하게 한다.
  • 동적 전략 : 팀에게 전략을 전달하지만 결과에 따라 전략을 수정할 수 있다. 이것이 클라우드 네이티브가 제공하는 빠르고 실험적인 배포의 궁극적인 목적이다.

 

궁극적으로 클라우드 네이티브는 어디에서가 아니라 어떻게 생성하고 제공하느냐에 대한 것이다. 클라우드 네이티브의 목적은 실용적인 접근이다. CD처럼 빠르고 현대적인 소프트웨어 방식과 연동하여 시간을 단축하고, 쉽게 확장하며 효율적으로 운영하기 위함이다. 또한 클라우드 네이티브 아키텍처를 통해 복잡한 시스템을 독립적 팀이 구축한 소규모 구성 요소로 나눌 수 있다. 기존의 모놀리식 애플리케이션의 복잡성과는 다르다.

가장 중요한 점은 클라우드 네이티브가 위험을 줄이는 데 도움이 된다는 것이다. 빠르지만 작고, 변경이 잘못될 경우 폭발 반경을 제한하고, 변경사항을 즉시 롤백하는 방식이다.

 

서비스에 대한 모든 것

퍼블릭 클라우드 기반 서비스가 제공하는 서비스 유형이다.

  • IaaS (Infrastructure as a Service) : 외부 하드웨어, 데이터 스토리저 및 네트워킹을 포함한다. 인프라를 소유하며, 임대하면 중앙 아키텍처팀의 기능으로 한정되지 않아 각 팀의 창의성을 극대화할 수 있다.
  • PaaS (Platform as a Service) : 모든 가상화된 인프라를 관리하고 유지해 운영 및 플랫폼 팀의 부하를 크게 줄일 수 있다.
  • SaaS (Software as a Service) : 기존 비즈니스 소프트웨어에서 가상 인프라 관리 도구에 이르기까지 모든 구성 요소 애플리케이션을 선택할 수 있다. 이 모든 애플리케이션은 웹을 통해 제공/운영되며, 프로바이더는 보안, 가용성, 성능을 보장한다.
  • CaaS (Container as a Service) : 컨테이너 엔진, 오케스트레이션 및 모든 기본 컴퓨팅 리소스를 클라우드 프로바이더의 서비스로 사용자에게 제공할 수 있다.
  • As a Service : 위에 언급된 서비스 외에도 많은 서비스들이 생겨나고 있으며, 조금씩 발전하고 있다.

 

클라우드 네이티브 원칙의 이해

앞서 이야기한 클라우드 네이티브의 다섯가지 원칙에 대해 이야기해보려 한다.

컨테이너화

서비스 기반 아키텍처를 정의한 후에는 모든 곳, 모든 사람을 위해 컨테이너화해야 합리적이다 컨테이너는 응용 프로그램을 실행하는 데 필요한 모든 것을 포함하는 경량의 독립 실행형 소프트웨어 패키지다. 모든 의존성을 가지고 코드를 패키징해 어느 컴퓨팅 환경에서든 실행할 수 있다.

이런 가상 시스템은 애플리케이션과 애플리케이션을 자체 운영 체제에 이르기까지 어느 플랫폼에서든 실행할 수 있는 독립형 유닛으로 격리시킨다. 전 세계적으로 동일한 컨테이너를 IaaS를 통해 호스팅하고 배포할 수 있으므로 운영이 유연하고 안정적이며 빠르다.

동적 관리

컴퓨팅, 네트워크 및 스토리지 리소스는 사전 비용 없이 표준화된 API를 사용해 온디맨드 방식으로 프로비저닝되며, 실제 비즈니스 요구에 실시간으로 대응할 수 있다. 컴퓨팅, 네트워크 및 스토리티 리소스 운영은 전문 기술이 필요한 어려운 작업이기에 기술 습득은 시간이 많이 걸리고 비용이 많이 든다. 하지만 속도가 더 중요하기에 클라우드 플랫폼을 통해 고가용성, 안정성 및 보안 표준에 따른 리소스 수명 주기가 자동으로 관리되는 것을 기대할 수 있다.

마이크로서비스

마이크로서비스 아키텍처는 대규모 애플리케이션이 모듈식 구성 요소 또는 서비스 제품군으로 구축되는 애플리케이션 개발에 대한 접근 방식이다. 각 서비스는 고유 프로세스를 실행하고 자체 데이터베이스를 관리한다. 마이크로서비스는 API를 통해 통신하며 각 서비스를 독립적으로 분리,재구성,재배포 및 관리할 수 있다.

또한 소프트웨어를 구축하기 위해 비계층적 기능적 접근 방식을 취하여 모놀리식 엔티티를 더 작은 개별 조각으로 분할하고 프로세스를 독립적으로 제공할 수 있다.

각 마이크로서비스는 특정 목적에 가장 적합한 언어로 작성될 수 있으며, 필요에 따라 독립적으로 scale-up 또는 scale-down할 수 있다. 그리고 모놀리식 애플리케이션과 달리, 블래스트 래디우스(the blast radius) 는 마이크로서비스의 기록에 포함된다.

- 블래스트 래디우스 : 스케일업과 스케일다운이 발생한은 최대/최소 범위

자동화

스크립트 또는 코드에서의 수동작업은 자동화된 단계로 대체된다. 그 예로 테스트 프레임워크, 구성 관리, CI/CD 도구 등이 있다. 자동화는 반복적인 작업과 운영 통합 절차를 통해 휴먼에러를 제한하고 시스템 신뢰성을 향상시킨다. 그로 인해 인간은 유지보수 작업 대신 비즈니스에 집중할 수 있게 됐다.

클라우드 네이티브를 적용할 때 자동화를 하지 않으면 혼란에 빠지기 쉽다. 클라우드 마이그레이션 이후 기업은 더욱 빠르게, 자주 배포하게 되는데 배포 프로세스를 완전히 자동화하지 않으면 온프레미스 서버를 운영하지 않아 새롭고 빠른 운영주기로 배포하는 데 시간을 사용할 수 있다. 배포 빈도가 높을수록 실수할 가능성도 높다. 

배포 자동화는 지속적인 CI/CD를 단순하게 만들고, 자동화된 테스트를 통해 이슈가 되기 전에 문제를 조기 발견할 수 있다.

오케스트레이션

MSA(MicroService Architecture) 구축 이후 컨테이너화를 마친 후에 각 컨테이너들을 조율해야 한다. 엔터프라이즈 레벨 애프리케이션은 여러 컨테이너에 걸쳐있으며, 이러한 컨테이너는 여러 서비스를 포함해 포괄적인 컨테이너 인프라를 구성하는 여러 서버 호스트에 구축해야 한다.

오케스트레이션은 아키텍처를 계획할 때 공통 패턴을 사용할 수 있도록 지원하므로 엔지니어링 노력이 줄어든다. 개발자는 낮은 수준의 추상화를 해결하는 데 자유로워지고 아키텍처에 집중할 수 있다.

쿠버네티스가 이러한 것을 담당하며 cloud native migration에서 마지막으로 수행되는 중요한 일이다. 오케스트레이터를 먼저 구현하면 어렵다. 따라서 클라우드 인프라, 동적관리, 자동화 등의 다른 클라우드 네이티브 원칙을 먼저 수립해야 한다.

 

모든 것을 함께 조정하라

 

 

다섯가지 원칙 모두 필수적이지만 마이크로서비스는 그 중 제일 중요하다

마이크로서비스는 중심적인 역할을 한다. 컨테이너, 동적관리, 자동화, 오케스트레이션은 MSA와 결합해야만 진정한 힘을 발휘한다.

마이크로서비스가 클라우드 네이티브 원칙의 중심인 이유는 마이크로서비스가 모든 기업의 차별화 요소인 비즈니스 로직을 캡슐화한다는 점이고, 기업은 이를 통해 고객에게 가치를 제공하는 프로세스를 나타낼 수 있다.

 

무엇이 잘못될 수 있을까?

누구나 퍼블릭 클라우드 서비스에 회원가입을 한 다음 AWS, GCP, Azure 등의 서비스를 사용할 수 있다는 것은 놀라운 일이다. 경쟁은 점점 더 치열해지고, 가격은 떨어지고, 기능들은 늘어나고 있다.

하지만 그 대신 문제점 또한 쉽게 발생할 수 있는데 크게 아래와 같다.

  • 분산 시스템이 복잡해서 어렵다.
  • 방대한 도구 및 플랫폼으로 구성된 클라우드 네이티브 에코 시스템이 상대적으로 미성숙하다.
  • 변화하는 기술과 전달되는 기대치에 맞춰 조직 문화를 발전시키지 못했다.

 

 

분산 시스템의 충격

사용자는 빠르게 심리스하며 상시 접속 가능한 환경을 원한다. 이러한 기대를 충족시키고자 클라우드 네이티브의 많은 기능들은 발전해왔다. 분산 시스템에 대해 생각할 수 있는 방법은 여러 독립적 기능을 함께 사용하여 최종 사용자에게 단일 통합 환경으로 제공하는 것이다.

분산 시스템의 주요 이점은 신뢰성이다. 컴퓨팅 프로세스가 전체 시스템 네트워크에 분산되어 있을 때 서로 독립적으로 발생한다.

배포를 통해 필요에 따라 노드와 기능을 쉽게 추가할 수 있어 시스템의 확장성이 크게 향상된다.

그러나 이 모든 이점은 복잡성을 수반한다. 시스템이 복잡해지면 설계, 구축, 디버깅이 어려워지고 장애는 필수적이다. 이러한 장애를 이해하기 위해 정교한 관측성이 필수적이다.

 

미성숙함으로 인한 충격

퍼블릭 클라우드 플랫폼은 솔루션으로 제공되지만 플러그 앤 플레이와는 거리가 멀다. 전체 솔루션이라고 주장하지만 정말 모든 기능이 있지는 않다.

클라우드 네이티브는 계속 발전하므로 서비스 환경도 계속 발전하고 있다.

요약

클라우드에서 최선의 결과를 얻으려면 마이크로서비스, 컨테이너, 오케스트레이션, 자동화 등의 클라우드 네이티브 아키텍처를 사용해야 한다. 자동화는 가장 먼저 시행되어야 한다.

마이크로서비스와 클라우드 서비스는 그를 위한 핵심 요소이다. 

클라우드 네이티브는 강력하고 전도유망한 기술이다. 이 이점을 활용하려면 클라우드 네이티브 아키텍처의 원리를 기반으로 견고한 기반을 구축해야 한다.

 

127.0.0.1과 localhost는 기본적으로 동일한 것을 가리키는데, 이들은 모두 로컬호스트를 나타낸다.

그러나 사용 목적에 따라 약간의 차이가 있을 수 있다.

 

좌측은 웹페이지에서 Localhost 접속 사진, 우측은 127.0.0.1 접속 사진이다.

 

 

127.0.0.1

- 127.0.0.1은 IPv4 주소 중 하나로, 로컬 루프백 (Loopback) 주소이며 네트워크에서 현재 시스템을 가리킨다. 

   - 여기서 IPv4는 Internet Protocol version 4의 약어로 32비트로 구성되어 있어, 일반적으로 4개의 8비트로 표현된다. (127.0.0.1)

- 이 주소는 TCP/IP 네트워크 스택에서 자체 테스트 및 통신을 위해 예약되어 있다. 즉, 네트워크 스택이 자체적으로 통신을 테스트하기 위해 예약된 주소로, 데이터를 보내면 해당 데이터가 동일한 시스템으로 다시 돌아오게 된다.

- 주로 개발 및 테스트의 목적으로 사용되며, 직접 IP 주소를 사용하는 경우에는 주로 이를 사용한다. 시스템이 네트워크에 연결되어 있더라도 로컬에서 독립적으로 동작하는 응용프로그램을 테스트할 때 사용된다.

- 요약하자면, 127.0.0.1은 자기 자신을 가리키는 특수한 IP 주소로 웹서버, 데이터베이스, 응용 프로그램 등을 테스트하고 디버깅하는 데 사용된다.

 

localhost

- localhost는 호스트 이름이며, 일반적으로 시스템의 로컬 루프백주소인 127.0.0.1 IP 주소를 가리킨다.

- 호스트 이름을 사용할 때, DNS 조회를 통해 127.0.0.1 주소로 매핑된다.

- localhost는 주로 IP 주소를 직접 기억할 필요 없이 읽기 쉽고 기억하기 쉬운 형태로 로컬 시스템을 가리킬 때 사용된다.

- 예를 들어 웹 개발중에 로컬 웹 서버를 구동하고 웹 브라우저에서 http://localhost:8080 과 같은 주소로 접속할 수 있다.

 

 

결론

실제로 대부분의 경우에 이 둘은 상호 교체가 가능하며, 웹 브라우저나 다른 네트워크 응용프로그램에서 로컬 호스트로 연결할 때 둘 다 사용된다. 예를 들어 브라우저에서 "http://localhost" 또는 "http://127.0.0.1"로 접속하는 것은 동일한 로컬 시스템에 대한 접속을 의미한다.

localhost를 사용하는 것이 일반적으로 더 편리하고 쉽지만, 특정 상황에서는 직접 IP 주소를 사용해야할 때가 있을 수 있다.

 

파이썬에서 환경을 설정할 때 패키지를 설치하고 실행하게 된다. 

깃허브에 릴리즈된 수많은 오픈소스들을 봐도 보통 특정 프로젝트(코드)를 실행하기 위한 환경에 대한 정보가 제공되거나 requirements.txt가 함께 제공되는 것을 확인할 수 있다.

http://github.com/clovaai/deep-text-recognition-benchmark

 

requirements.txt 란?

python 프로젝트 파일(.py)이 실행되는 데 필요한 패키지 정보들이 담긴 문서로, 다른 가상환경이나 다른 파이썬 환경에서 python 종속성을 따라 똑같은 환경을 구성할 수 있도록 도움을 준다. 이름을 꼭 requirements.txt로 네이밍할 필요는 없지만 대다수의 프로젝트에서 파이썬 패키지 리스트를 저장하는 파일을 requirements.txt 로 사용하고 있어 암묵적인 약속(?)의 네이밍이라고 생각하면 편하다.

import datetime.datetime as dt
import pytz

tz = pytz.timezone('Asia/Seoul')
date_now = dt.now(tz)
print(date_now)

위와 같은 간단한 코드를 실행하려고 해도 datetime/pytz 패키지가 설치되어있지 않거나, 혹은 둘 다 설치되어있다고 해도 두 패키지의 의존성이 맞지 않으면 실행되지 않을 수 있기 때문에 패키지의 수가 많아질수록 서로 의존성을 해치지 않는지를 확인해야 한다. 

보통 가상환경을 통해 테스트하거나, 프로젝트별 가상환경을 따로 만들어서 실행하는 것이 일반적이다.

 

이 때, 주의해야 할 것이 conda 와 pip 를 혼동하지 않는 것이다. conda로 가상환경을 만들어서 사용하는 사람이라면 혼동하는 실수를 할 수도 있다. 둘 다 python 패키지를 관리하는 도구이지만 몇가지 차이점이 있다.

Conda

- python 뿐만 아니라 다양한 언어 (C, C++ 등)의 패키지를 관리할 수 있는 통합 패키지관리자로, 환경을 관리하고 패키지 의존성을 해결하는 데 특화되어 있다.

- 미리 컴파일된 바이너리 패키지를 사용하여 설치/업데이트/삭제를 수행하므로 컴파일 과정이 필요없다.

Pip

- 주로 python 패키지를 설치하고 관리하는 데 사용된다. PyPI(Python Package Index)에서 패키지를 가져와 설치한다. 

- 패키지를 소스코드로부터 설치하므로 해당 패키지에 필요한 컴파일러 및 의존성이 필요할 수 있다.

 

conda 패키지의 버전 정보 확인 : anaconda 사이트

 

python 패키지의 버전 정보 확인 : pypi 사이트

같은 패키지명이라도 각자 다른 버전을 제공하는 것을 확인할 수 있다.

 

주의!! Conda와 pip는 각자의 패키지 관리 및 의존성 해결 전략을 가지고 있기 때문에, Conda에서 pip로 변환할 때 몇 가지 주의사항이 있다.

일반적으로 pip 명령어로 requirements.txt를 추출할 때

pip freeze > requirements.txt

 

위의 명령어를 사용하게 되는데, pip로 install 했다면 정상적으로 보였을 내용들이,

 

conda를 사용하여 패키지를 설치했다면 아래와 같은 상황이 발생할 수 있다.

이런 에러가 발생하는 이유는 conda로 설치한 패키지를 pip를 이용하여 freeze 하려고 했기 때문에 경로에 대한 내용이 기재되어 출력되는 현상이 발생하는 것이다. conda용 requirements.txt 커맨드는 따로 존재한다.

conda list -e > requirements.txt

 

 

위의 커맨드를 실행하면 

2번 이미지

위와 같은 형태로 다시 requirements.txt가 다르게 생성이 되는 것을 확인할 수 있다. 그러나 위의 커맨드를 사용한 requirements.txt의 내용은 뒤에 요상한 형태의 내용들이 붙어있는 것을 볼 수 있다. 이는 conda로 부터 붙어오는 

이 내용을 pip requirements.txt로 변환하고 싶다면

pip list --format=freeze > requirements.txt

로 변환이 가능하다. 다만 주의해야할 것은 이대로 install하게되면 conda<>pip 간의 다른 패키지 관리 시스템으로 dependecy issue/error가 발생할 수 있다.

 

만약 2번 이미지의 requirements.txt 을 리눅스 환경 내의 콘다에서 사용하고 싶다면, 

가상환경을 activate 한 다음 아래의 커맨드를 입력하면 정상적으로 환경이 설치되는 것을 확인할 수 있다.

conda install --file requirements.txt

 

그 외에, pip 명령을 사용하여 conda의 버전을 설치하고 싶다면, 

pip install --no-deps -r requirements.txt

 

pip이 의존성을 자동으로 해결하지 않도록 설정하여 설치할 수 있다.

 

가장 간단한 방법은 conda를 사용하여 파일에 명시된 패키지들을 직접 설치하는 것이다.

conda create -n <environment_name>  -f requirements.txt

 

경우에 따라 pip와 conda를 함께 사용하여 패키지를 설치해야할 수있는데, conda로 관리되는 패키지와 pip로 관리되는 패키지가 공존할 수 있다.

# Conda로 관리되는 패키지 설치
conda install --file requirements_conda.txt

# Pip으로 관리되는 패키지 설치
pip install -r requirements_pip.txt

 

만약 pip install 하기 위한 패키지명이 필요하다면 requirements.txt의 디렉토리로 접속한 뒤 정규식을 통해 pip-requirements.txt로 추출할 수 있다.

sed -En 's/^([a-zA-Z0-9\-]+)=([0-9\.]+)=.*/\1==\2/p' requirements.txt > pip-requirements.txt

 

conda 커맨드를 사용하여 추출한 requirements.txt와 conda 커맨드 > 정규표현식으로 추출한 pip-requirements.txt의 내용을 비교하면 아래와 같이 다른 것을 확인할 수 있다.

 

반대로 pip freeze로 추출한 requirements.txt를 conda 환경에서 인스톨하는 경우라면 

conda install pip
pip install -r requirements.txt

위의 커맨드를 사용하여 설치할 수 있다.


나의 경우는 아래와 같은 방법을 사용하여 해결할 수 있었다.

1. 우선, pip freeze 커맨드로 requirements 뽑기

pip freeze > requirements.txt

2. 위의 커맨드로 뽑은 requirements는 일부 라인 끝에 @로 시작하는 내용이 붙어있기 때문에 제거한다. sed 명령어와 정규표현식을 활용해서 수정하기

sed -i.bak '/@/d' requirements.txt

3. 수정한 내용의 requirements를 설치하기

pip install -r requirements.txt

 

이러한 접근 방식들을 사용하여 conda에서 pip로 환경을 전환하며 최소한의 의존성 충돌을 유지할 수 있을 것이다.

 

레퍼런스 참고 : 사이트

문제

dbeaver에서 한글 깨짐 현상 발생하여 인코딩 문제임을 알아차렸다. 

 

 

해결방법 

home에서 shift + cmd + G 키를 눌러 DBeaver를 검색한다.

 

 

Applications > DBeaver > Contents 디렉터리로 들어가면 아래와 같이 나오고 이 중 Eclipse 폴더로 들어간다.

 

 

dbeaver.ini 파일을 연다. 

 

vscode로 파일을 열면 아래와 같이 적혀있다.

 

마지막줄에 아래와 같이 추가해준다.

-Dfile.encoding=utf8

 

 

정상적으로 한글이 보인다.

 

만약, 이렇게 해도 해결이 되지 않는다면 이는 인코딩 문제가 아닌 것이다. utf-8로 정상적으로 인코딩이 되어있지만, byte로 되어있는 문자열을 string 그대로 출력해줘서 그런 것이다. 이럴 때는 아래와 같은 SQL 문을 통해 변경하여 확인해야 한다.

HEX(column name)

 

 

hex() 는 SQL 내장 함수로, 주어진 문자열의 문자를 16진수로 반환한다. input 문자열을 바이트로 간주하고, 각 바이트를 16진수로 표현한 후 문자열로 반환한다. 

SELECT HEX(name) AS NameValue FROM info;

위의 문법은 infof라는 테이블에서 name이라는 이름을 가진 column의 값을 NameValues 라는 컬럼으로 변경한다.

실전 시계열 분석을 보며 정리했습니다.

 

[Last updated : 2022-09-14]

정의

시계열 분석은 시간 순서대로 정렬된 데이터에서 의미있는 요약과 통계 정보를 추출하는 것이다. 과거 행동 진단뿐만 아니라 미래 행동 예측에도 사용된다. 

 

1.1 다양한 응용 분야의 시계열 역사

'과거가 미래에 어떤 영향을 주는가?' 와 같은 인과관계를 다루는 질문으로 시계열 분석에 대해 일축할 수 있다.

 

1.1.1 시계열 문제로서의 의학

존 그란트(John Graunt)는 1500년대 초반부터 사망 기록 연구를 시작하여, 특정 연령대에 있는 사람이 다음 생일 전에 사망할 확률을 구했다. 그란트는 처음으로 사람의 건강을 문서에 기록한 통계학자이다. 하지만 당시에는 찬밥 신세를 받았다.

그 이유는 당시 생리학, 해부학이 훨씬 우세하다는 여론이었고 통계적 방법이 임상적 관찰보다 낫다는 근거가 부족했다. 그리하여 시계열 분석이 의학에 도입된 시기는 다른 분야보다 훨씬 늦다. 아주 장기간에 걸쳐 규칙적으로 과학 시설로 관측된 데이터가 있어야 하기 때문이다.


의료 기구

환자에 대한 시계열 분석은 통계적 차원의 연구보다 훨씬 일찍 시작되었다. 1901년 심전도 (ECG) 가 발명되었고, 1924년 뇌전도 (EEG) 가 발명된 덕분에 시계열 분석을 의료 진단에 적용할 수 있었다. 하지만 해당 장비를 통해서는 오랜 시계열 데이터를 생성하지 못하기 때문에, 분석에 한계가 있었다. 다행히 최근 기술의 발달로 다양한 웨어러블 센서 기기가 등장하며 데이터 수집이 예전보다 쉬워졌고, 이로 인해 더 많은 시계열 데이터가 측정되어 의학의 발전에 기여할 수 있었다.

1.1.2 일기예보

고대 시절부터 기상에 대한 관심은 많았으며, 다양한 관측법과 기록을 통해 보관되어왔다. 하지만 과거에는 과학적인 기록법이 없었기 때문에, 1850년대가 되어서야 기상 기록을 위한 시설을 갖출 수 있었다. 이 시설을 기반으로 날씨가 측정되기 시작하였고 요즘날 사용되는 일기예보에 활용되는 의미있는 데이터셋을 생성할 수 있었다. 

 

1.1.3 경제성장 예측

19세기 말~20세기 초의 금융 위기는 불안감을 초래했고, 이러한 불안감은 경제 예측의 필요성을 야기시켰다. 경제를 순환 시스템에 비유할 수 있다는 생각에서 영감을 얻어 많은 경제학자들은 이러한 예측을 통해 경제 추락을 피할 수 있다고 생각하였다.

경제 데이터를 추적하기 위한 다양한 공공기관이 설립되었고, 오늘날 대부분 국가에서는 경제성장, 재앙, 호항과 불황 주기 등을 파악하거나 방지하는 데 유용한 데이터를 제공하고 있다. 예를 들어 오늘날 많이 사용되는 국내 총생산(GDP) 도 경제 지표의 한 분류로 볼 수 있다.

 

주식 시장

증권 거래소의 데이터를 통해 시장 참가자의 수준이 높아지고, 자동화 방식이 늘어나기 시작했다. 수학적인 접근 방식을 통해 이윤 창출을 추구하게 되었고, 최근에는 머신러닝이 주도하고 있다. 현재의 금융시장 분석은 자체적인 시계열 분석 방법을 사용한다.

리처드 데니스는 알고리즘을 통한 시계열 예측을 하였고, '인공지능'에 대한 생각에도 영향을 주었다.

 

1.1.4 천문학

천문학은 물체, 궤도, 측량 그래프 등을 활용하기 때문에 시계열과 큰 관련이 있다고 볼 수 있다. 시간의 흐름에 따라 우주가 변화하는 방식을 이해할 수 있도록 도와주는 데이터를 수집하기 위해 실시간 스트리밍 형태로 관찰을 함으로써, 도움을 받을 수 있었다. 

 

1.2 시계열 분석의 도약

조지 박스는 실제 세상을 묘사할 수 있는 모델을 만든다는 것은 가능성이 희박한 일이라고 주장하였다. 1970년에 등장한 박스-젠킨스 방법은 시계열 분석에 많은 기여를 했다.

당시, 많은 데이터셋을 모으는 건 가능했지만 R, 파이썬, C++ 등의 도구가 없었기 때문에 많은 데이터를 처리하는 것은 어려웠다. 따라서 시계열 분석과 예측은 컴퓨터의 발전과 동행할 수밖에 없었다. 1970년대 말 초기 개인용 컴퓨터, 컴퓨터 언어의 등장으로 인해 시계열 예측은 혁신을 가져왔다.

지난 수십년간의 하드웨어 기술의 발달로 인해 컴퓨터의 연산 능력은 증가하였고, 덕분에 시계열 분석 및 예측 또한 정확도가 올라갔다.

 

1.3 통계적 시계열 분석의 기원

(저자에 따르면) 통계학은 데이터의 질적인 측면에 의존적인 미성숙한 학문이었으나, 시계열 분석은 하나의 학문의 관점으로 볼 수 있다. 시계열 분석은 자기회귀 모델을 실제 데이터에 적용하였으며, 이는 주기성을 가정하지 않은 모델이다. 초기 시계열 분석의 모델은 전통적인 모델에 의존하였으나 현재는 과학의 발전에 따라 초기 문제들을 해결할 수 있으며, 동시에 다양한 비즈니스 문제를 해결할 수 있다.

 

1.4 머신러닝 시계열 분석의 기원

1969년 발표된 The combination of Forecasts 논문은 예측 성능을 향상시키기 위한 방법으로 '최고의 하나'를 고르는 것보다 여러 예측을 결합하는 방법을 제안했다. 이후 ensemble(앙상블) 방법이 널리 사용되었으며, 이는 월등히 뛰어난 모델이나 완벽한 방안보다는 여러 모델의 특성을 잘 조합을 하는 것이 나을 수 있다는 결론을 내렸다.

이러한 접근 방법은 다양한 시나리오에서 사용되기 시작했으며, 아직까지는 전통적인 통계 방법이나 선형적 방법이 시계열 분석을 지배하고 있다. (저자에 따르면) 시계열 분석과 예측은 황금기를 맞이하지 못했고, 앞으로 미래를 위한 도약을 여전히 기다리고 있다.

Reference :  CS 공부 비서, 티스토리


Q&A

Q. 컴파일러와 인터프리터의 차이가 무엇인가요?

A. 나의 답변

* 컴파일러는 인풋언어(고급어)를 객체어(기계어)로 변환하고, 하드웨어에 종속적이다. 번역 진행 시 전체 코드를 검사한 뒤에 실행한다.
반면 인터프리터는 line by line으로 번역을 진행하고, 하드웨어에 종속되지 않는 특징이 있다. 


Best Answers

 

★ㅇ*님의 답변
컴파일러와 인터프린터는 사람이 작성한 코드(고급언어)를 컴퓨터가 이해할 수 있는 언어(기계어)로 변환하는 작업을 수행해주는 역할을 한다. 컴파일의 경우 고급언어를 한 번에 번역한다.

인터프린터의 경우 고급언어를 한 줄씩 번역을 진행하기 때문에 컴파일 보다 실행시간이 빠르다는 장점이 있다. 그러나 번역을 할 때 실행파일을 생성하지 않기 때문에 매번 실행할 때마다 같은 번역작업을 반복해서 실행해야 되는 단점이 있고, 이러한 문제 때문에 컴파일러를 사용하는 언어보다 실행속도가 느리다.
그럼에도 불구하고 인터프린터를 사용하는 이유는 모든 플랫폼에 종속되지 않는다는 장점을 갖기 때문에 호환문제에서 자유롭다.


★홍*님의 답변
<컴파일러(compiler)>
전체 파일을 스캔하여 한꺼번에 번역한다.
초기 스캔시간이 오래 걸리지만, 한번 실행 파일이 만들어지고 나면 빠르다.
기계어 번역과정에서 더 많은 메모리를 사용한다.
전체 코드를 스캔하는 과정에서 모든 오류를 한꺼번에 출력해주기 때문에 실행 전에 오류를 알 수 있다.
대표적인 언어로 C, C++, JAVA 등이 있다.

<인터프리터(interpreter)>
프로그램 실행시 한 번에 한 문장씩 번역한다.
한번에 한문장씩 번역후 실행 시키기 때문에 실행 시간이 느리다.
컴파일러와 같은 오브젝트 코드 생성과정이 없기 때문에 메모리 효율이 좋다.
프로그램을 실행시키고 나서 오류를 발견하면 바로 실행을 중지 시킨다. 실행 후에 오류를 알 수 있다.
대표적인 언어로 Python, Ruby, Javascript 등이 있다.




★최*님의 답변
컴파일러는 고급 언어로 작성된 프로그램 전체를 일괄적으로 기계어로 번역하는 도구이다. 컴파일 하는 데 시간이 소모되지만, 실행 시에는 필요한 정보들이 모두 미리 계산되어 있기 때문에 인터프리터 방식에 비해 빠르다는 장점이 있다. C, C++, 포트란, 파스칼 등의 언어가 컴파일러를 사용한다.

인터프리터는 실행문을 한 문장씩 번역하면서 실행하는 구조이다. 그에 따라서 바로 실행이 가능하지만, 전체 실행 시간은 컴파일러에 비해서 더 오래 걸린다. 추가적으로 메모리 사용도 컴파일러에 비해서 비효율적인 면이 있다. BASIC, PHP, 펄, 파이썬 등의 언어가 인터프리터를 사용한다.

이밖에도 자바같은 언어는 컴파일러와 인터프리터의 중간 형태의 언어를 사용한다고 볼 수 있다. 이를 혼합형 방식이라고 하는데, 고급 언어를 컴파일해 중간 언어로 번역하고 인터프리터에 의해 번역을 하면서 실행하는 방식을 의미한다. 자바의 경우 자바 가상 머신이 이해할 수 있는 자바 바이트코드를 생성하고, 자바 가상 머신이 이를 실행하는 식으로 구동된다.




★황*님의 답변
작성한 프로그램을 빌드 혹은 실행하는 방법으로는 컴파일러방식과 인터프리터 방식이 있다. 컴파일러와 인터프리터는 고급언어로 작성된 원시 프로그램을 목적 프로그램으로 번역하는 프로그램이며, 프로그램 번역 방식에 따라 구분된다.

"컴파일러"는 고급 언어(C, C++, JAVA)등으로 작성 된 소스 코드를 컴퓨터가 읽을 수 있는 저급 언어(기계어, 어셈블리어)로 번역해주는 프로그램이다. 컴파일러의 경우 크게 4가지 과정(전처리 - 컴파일 - 어셈블리 - 링킹)을 통해 실행 가능한 산출물로 만들어진다.

1. 전처리 
전처리기를 통해 전처리된 소스 코드로 변환하는 과정이다. 주석 제거, 헤더 파일 복사후 삽입, 매크로 치환 및 적용등을 진행합니다.

2. 컴파일
전처리된 소스 코드를 어셈블리어로 변환한다. 언어의 문법검사 정적(Data,BSS)인 영역들의 메모리 할당을 수행한다.

3. 어셈블리
어셈블리어 파일을 오브젝트 파일로 변환하는 과정이다. 오브젝트 파일은 기계어로 쓰여 있으며 보통의 포맷 종류는 PE(Window), ELF(Linux)가 존재한다.

4. 링킹 과정
컴파일러에 존재하는 링커를 통해 오브젝트 파일들을 묶어 실행 파일로 만드는 과정이다. 이 과정에서 오브젝트 파일들과 프로그램에서 사용하는 라이브러리 파일들을 링크하여 하나의 실행 파일을 만든다. 이러한 과정을 거쳐 우리가 작성한 고급언어들을 실행 가능한 파일로 만드는 것이 컴파일러가 수행하는 역할이다.


"인터프리터"는 고급언어로 작성된 프로그램을 한 줄 단위로 받아들여 번역한 뒤 번역과 동시에 프로그램을 한 줄 단위로 즉시 실행시켜 주는 프로그램이다. 줄 단위로 번역, 실행되기 때문에 시분할 시스템에 유용하며 한단계씩 테스트와 수정을 하며 진행시키는데에 적합하다.

1. 소스 코드를 직접 실행한다.
2. 첫번째 줄을 읽는다.
3. 기계어 명령어로 번역한후 CPU에 바로 돌린다.
4. 프로그램 한 줄을 실행한다.

둘의 차이점은
컴파일러 - 전체 단위로 번역함
인터프리터 - 한 줄 단위로 번역함

컴파일러 - 목적 프로그램을 생성함
인터프리터 - 생성하지 않음

컴파일러 - 실행속도의 경우 한번에 번역해서 실행하기 때문에 빠름
인터프리터 - 한 줄씩 읽어내기 때문에 느림

컴파일러 - 번역속도가 느림
인터프리터 - 번역속도가 빠름





★김*님의 답변
컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 
하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다.

인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다.

 




★권*님의 답변
2가지의 차이를 설명하기 이전에 컴퓨터의 시작의 역사를 조금 되짚어보겠다. 흔히 알려진 컴퓨터 OS의 시작은 유닉스이다. 그리고 유닉스가 유료화가 되면서 오픈소스로 만들어진 가장 잘 알려진 리눅스가 된다.

이러한 리눅스에서는 콘솔 창에서 어떤 명령을 수행할지에 대한 명령어 처리 시스템인 셸이 존재한다. 간단하게는 디렉터리 위치 변경, 파일 목록 출력, 문자열 탐색과 같은 명령어들이 있다. 이러한 명령어 집합을 파일로 만들어서 해당 파일을 실행하면 명령어들을 순차적으로 셸에 실행시켜준다. 이를 셸 프로그래밍이라고도 하고, 이는 인터프린터이다.
프로그램 파일의 명령어를 단순히 순차적으로 실행시켜주는 것이다. 잘 알려진 프로그래밍 언어로는 자바스크립트,파이썬,파워쉘, 등이 있을 것이다.


이에 반에 컴파일러는 인터프리터의 문자열 수준의 명령어가 아닌, 기계어 수준의 명령어 집합으로 만드는 것이다. 여기서 기계어란 컴퓨터가 (CPU) 더하기 연산이나 빼기 연산, 레지스터 복사 같은 명령어들을 얘기한다. 컴파일러로 컴파일 할 경우 기계어이다 보니 인터프린터보다 속도가 훨씬 빠르다는 장점이있다. 이런 컴파일러 언어의 예로는 C언어, C++ 가 대표적이다.

참고로 C#이나 Java의 경우, 인터프린터와 컴파일러의 중간에 있다.
Java를 예로 들면, Java 개발사에는 JVM이라는 프로그램을 만들어서 배포한다. 이 JVM은 인터프린터와 같은 명령어 실행기이다. 그리고 Java를 이용하여 프로그램을 만드는 개발자의 경우 프로그래밍을 하고 코드를 실행 시 컵파일이 된다. 컴파일 시 기계어가 아닌 JVM에서 실행시켜줄 수 있는 바이트 코드가 되어 JVM에서 실행된다. 이는 한 코드로 모든 운영체제에서 실행시키려는 자바의 철학이다.
따라서 java 개발사에서는 JVM를 각 운영체제 별로 만들어야 한다. 그리고 프로그램 개발자의 경우 한 코드로 모든 운영체제에서 돌릴 수 있다. 이러한 Java C#은 굳이 따지자면 컴파일러 언어에 더 가깝다.





★박*님의 답변
1. 컴파일러
: 전체 프로그램을 스캔해 한번에 기계어로 번역한다, 코드 분석에 시간이 많이 걸리는 대신 컴파일 후 실행시간이 빠르다. 컴파일러는 기계어와 코드 사이의 중간 코드를 생성하기 때문에 더 많은 메모리가 필요하다.

2.인터프리터
: 한 번에 하나의 프로그램 명령문을 기계어로 번역한다. 소스 코드를 분석하는데 상대적으로 적은 시간이 걸리지만 코드가 실행되는 시간은 더 오래 걸린다. 중간에 기계어와 코드 사이를 연결하는 코드를 생성하지 않아 메모리를 적게 쓴다.

컴파일러는 C, C++ 등에서 쓰이고, 인터프리너틑 JS, Python등에서 대표적으로 쓰인다.





★(*님의 답변
컴파일러는 소스 코드 n줄을 기계 코드로 한 번에 변환한 후 실행 파일로 만들어 해당 실행 파일만 있으면 실행할 수 있게 하는 것이고 인터프리터는 소스 코드 한 줄 한 줄 실행되는 순간 순간에 기계 코드로 변환하여 바로 실행한다는 것이다.

한 번 컴파일 하여 생성된 실행 파일만 있으면 빨리 실행할 수 있다는 장점이 있지만 컴파일 할 때 시간이 걸린다는 단점이 있고 인터프리터는 컴파일을 하지 않기 때문에 바로 바로 코드의 결과를 확인할 수 있다는 장점이 있지만 한줄을 기계 코드로 변환 후 실행하고 다음 한 줄을 기계 코드로 변환 후 실행하기 때문에 컴파일 후 생성된 파일을 실행하는 것보다는 느리다는 단점이 있다.




★서*님의 답변
컴파일러와 인터프리터는 모두 초기 컴퓨터의 서로 다른 cpu의 서로 다른 어셈블리어를 더 나은 방식으로 통합하기 위해 만들어졌다. 즉 서로 같은 명령을 서로 다른 어셈블리어로 번역해 주기 위해 만들어진 것이다.


<컴파일러(compiler)> 

컴파일러는 프로그램 전체를 스캔하여 이를 모두 기계어로 번역한다. 전체를 스캔하기 때문에 대개 컴파일러는 초기 스캔 시간이 오래 걸린다. 하지만 전체 실행 시간만 따지고 보면 인터프리터 보다 빠르다. 왜냐하면 컴파일러는 초기 스캔을 마치면 실행파일을 만들어 놓고 다음에 실행할때 이전에 만들어 놓았던 실행파일을 실행하기 때문이다. 하지만 단점도 있다. 컴파일러는 고급언어로 작성된 소스를 기계어로 번역하고 이 과정에서 오브젝트 코드(Object Code)라는 파일을 만드는데 이 오브젝트 코드를 묶어서 하나의 실행 파일로 다시 만드는 링킹(Linking) 이라는 작업을 해야한다. 설명만 딱 봐도 뚝딱하고 번역을 하는것 같아 보이진 않는다. 이때문에 컴파일러는 통상적으로 인터프리터 보다 많은 메모리를 사용해야 한다. 또한 컴파일러는 오류 메시지를 생성할때 전체 코드를 검사한 후에 오류 메시지를 생성한다. 그래서 실행 전에 오류를 발견 할 수 있다. 대표적인 언어로 C,C++,JAVA 등이 있다.

<인터프리터(interpreter)>

컴파일러와는 반대로 인터프리터는 프로그램 실행시 한 번에 한 문장씩 번역한다. 그렇기 때문에 한번에 전체를 스캔하고 실행파일을 만들어서 실행하는 컴파일러보다 실행시간이 더 걸린다. 그럴 수 밖에 없다고 본다. 한 문장 읽고 번역하여 실행시키는 과정을 반복하는게 만들어 놓은 실행파일을 한번 실행시키는 것보다 빠르긴 힘들어 보인다. 하지만 인터프리터는 메모리 효율이 좋다. 왜냐하면 컴파일러처럼 목적코드를 만들지도 않고, 링킹 과정도 거치지 않기 때문이다. 이 때문에 인터프리터는 메모리 사용에 컴파일러 보다 더 효율적인 모습을 보인다. 인터프리터는 오류 메시지 생성과정이 컴파일러와 다르다. 인터프리터는 한번에 한문장씩 번역하기 때문에 프로그램을 실행시키고 한 문장씩 번역될때 오류를 만나게 되면 바로 프로그램을 중지한다. 그래서 프로그램을 실행해봐야지만 오류 발견이 가능하다. 대표적인 언어로 Python, Ruby, Javascript 등이 있다.





★?*님의 답변
<컴파일러>
- 프로그램 전체를 스캔하여 이를 모두 기계어로 번역
- 전체를 스캔하기 때문에 초기 스캔 시간이 오래 걸리지만 전체 실행 시간만 따지고 보면 인터프리터보다 빠름
- 프로그램 실행 전에 오류를 알 수 있음
- 대표적인 언어로 C, C++, JAVA 등이 있음

<인터프리터>
- 프로그램 실행 시 한 번에 한 문장씩 번역
- 한번에 전체를 스캔하고 실행 파일을 만들어서 실행하는 컴파일러보다 실행 시간이 더 걸림
- 프로그램 실행 후에 오류를 알 수 있음
- 대표적인 언어로 Python, Ruby, Javascript 등이 있음

[last updated Aug 05, 2022]

reference book : 구글 브레인 팀에게 배우는 딥러닝 with TensorFlow.js

 


서문

그동안 대부분의 딥러닝 프레임워크(Tensorflow 등)들은 파이썬으로 쓰여있어서, 파이썬이 익숙치 않은 사람들이 프레임워크를 다루는 것에 어려움이 있었다. 구글 브레인 팀은 자바스크립트와 Tensorflow 를 연결하여 자바스크립트 개발자들도 머신 러닝 모델을 구축하고 배포할 수 있도록 하며, 새로운 종류의 on-device 컴퓨팅을 가능하게 만들었다.

Tensorflow.js는 자바스크립트를 통해 신경망을 다루며 다양한 데이터 형태의 인풋이 가능하도록 하며 사전학습모델(pre-trained model)을 활용한 학습, fine-tuning, 더 나아가 추론(inference) 등이 가능케 하는 API를 제공한다. 

이 책은 Tensorflow.js 의 기능 및 기본적인 머신러닝/딥러닝 이론을 제공하며, <케라스 창시자에게 배우는 딥러닝> 책을 토대로 작성된 책이다. 딥러닝은 수학적 지식을 많이 알아야한다는 조건때문에 허들이 높게 느껴졌던 분들에게 좋은 책이 될 것 같다. 신경망 학습을 통해 활용하거나 확장할 수 있는 서비스가 굉장히 많기 때문에 많은 입문자 혹은 웹 개발자들이 읽기에 적합한 책이다.

책 자체가 프론트엔드 개발이나 Node.js 기반 백엔드 개발 경험을 가진 자바스크립트 실무 경험자를 대상으로 하여 쓰여졌기 때문에 자바스크립트를 경험해 본 사람이라면 이 책을 통해 누구나 쉽게 신경망을 다룰 수 있을 것이다.


환경설정

1) 책을 읽고 실습을 시작하기에 앞서, 도서의 부록 569페이지를 참고하여 실습 환경설정을 해야 한다. 책에 있는 예제를 실행하기 위해서는 node.js 와 npm을 설치해야 한다.

2) Node.js에서 Tensorflow.js GPU 가속 버전을 사용하기 위해서는 CUDA와 CuDNN을 설치해야 하며, CUDA를 지원하는 NVIDIA GPU가 장착되어야 한다. 1이 진행되었다는 가정하에 하기 진행사항을 서술한다.

<리눅스에서 tfs-node-gpu 설치하기>

  1. 리눅스에서 CUDA 툴킷을 설치한 후, sudo 명령으로 파일을 실행한다. 만약 이미 설치된 NVIDIA 드라이버의 버전이 오래됐거나 드라이브가 미설치되었다면 설치 과정에서 NVIDIA 드라이버를 설치 혹은 업데이트 해야한다. 이럴 경우에는 셸 전용 모드로 진입하여 설치하고 시스템을 리부팅해야 한다.
  2. 만약 위 단계가 마무리 되었다면 nvidia-smi 명령이 정상적으로 실행이 되고 GPU의 상태를 확인할 수 있다. 이후 환경 변수에 CUDA 라이브러리 디렉토리를 추가해주면 된다.
  3. 그 다음 CuDNN을 설치해야 하는데, CuDNN은 CUDA를 기반으로 구축한 심층 신경망 연산을 가속하기 위한 NVIDIA 라이브러리이다. 이는 실행 가능한 설치 파일이 아니라 동적 라이브러리 파일과 C/C++ 헤더를 포함하고 있는 압축파일이므로 적절한 폴더에 압축을 풀어 복사해야 한다. 아래 명령어를 통해 진행이 가능하다.
tar xzvf cudnn-10.0-linux-x64-v7.6.4.38.tgz
cp cuda/lib64/* /usr/local/cuda/lib64
cp cuda/include/* /usr/local/cuda/include

   4. 설치가 완료되었다면 node에서 tfjs-node-gpu를 import하여 확인할 수 있다.

npm i @tensorflow/tfjs @tensorflow/tfjs-node-gpu
node

   5. Node.js 명령줄 인터페이스에서 아래와 같이 입력하면 정상 설치가 완료되었을 때 GPU를 찾았다는 메시지와 tfjs-node-gpu를 사용할 준비가 되었다는 로그를 확인할 수 있다.

const tf = require('@tensorflow/tfjs');
require(@tensorflow/tfjs-node-gpu');

  6. 로그가 확인된다면 준비가 다 된것이고 package.json에 사용할 라이브러리 버전을 추가한다. 이후 main.js에서 필요한 라이브러리를 임포트하면 정말 끝이다.


<윈도우에서 tfs-node-gpu 설치하기>

  1. 설치 전 현재 윈도 버전이 CUDA 툴킷 시스템 요구 사항에 맞는지 확인해야 한다. 일부 버전과 32bit 는 지원하지 않는다.
  2. CUDA 툴킷 설치에 필요한 비주얼 스튜디오를 설치한다. (이미 설치되어있다면 패스해도 무방하다.)
  3. CUDA 툴킷을 설치한 후, CuDNN을 설치하는데 이 두 버전이 맞는 버전인지 확인한다.
  4. CuDNN은 zip파일이기 때문에 CUDA 툴킷이 설치된 디렉터리를 찾고 압축 해제한 CuDNN 파일을 동일 이름의 하위 폴더에 복사한다. 이 과정에서 관리자 권한이 필요할 수 있다.
  5. CUDA 툴킷과 CuDNN을 설치한 후 pc를 재부팅한다.
  6. window-build-tools npm 패키지를 설치하고, npm으로 tfjs와 tfjs-node-gpu 패키지를 설치한다.
npm install --add-python-to-path='true' --global windows-build-tools
npm install @tensorflow/tfjs @tensorflow/tfjs-node-gpu

 7. 설치를 확인하기 위해 node 명령줄에서 아래 코드를 실행하고 에러 없이 실행되는지, 로그가 잘 출력되는지 확인한다. 

const tf = require('@tensorflow/tfjs');
require('@tensorflow/tfjs-node-gpu');

본문

전부 적기엔 방대하여 이 책의 주요 포인트와 인상적인 부분만 추려 기록한다.

" 왜 자바스크립트와 머신 러닝을 합쳐야 하나요? "

  • 머신 러닝은 일반적으로 주로 백엔드에 사용되는 언어로 수행되어 웹 브라우저가 아닌 서버나 워크스테이션에서 실행된다. 심층 신경망 모델의 훈련을 위해서는 GPU와 멀티코어가 필요하며, 훈련 데이터는 백엔드에서 입력하는 것이 가장 편리하다. ex) native 파일
  • 머신 러닝이 훈련된 후 배포되지 않는다면 컴퓨터 자원 낭비에 불과하다. 많은 모바일 앱은 웹 뷰로도 전환되는데 그렇기 때문에 웹 브라우저가 딥러닝 모델을 배포하기 위한 합리적인 선택인 것이다.
  • 웹 서비스를 설계하고 확장할 때는 서버 비용이 가장 큰 모델이다. 딥러닝 모델을 위한 GPU를 따로 구축하며 트래픽이 늘어나고 클라우드 비용이 높아지는데, 모델을 클라이언트 측에 배포함으로써 문제를 해결할 수 있다. 모델을 클라이언트 측에 다운로딩하는 오버헤드는 브라우저 캐싱과 로컬 스토리지 기능으로 완화할 수 있다.

그 외에 추론 속도 증대, 데이터 프라이버시, WebGL 가속, 즉각적인 사용 등 자바스크립트를 활용한 다양한 이점이 있다.


후기

파이썬으로만 데이터를 다뤄보고, 자바스크립트는 웹 페이지를 구현하는 데에만 사용해온 나에게 자바스크립트를 활용한 딥러닝이라는 건 상상할 수 없는 조합이었다. 물론 이 책을 보기 전까지는 그랬다.... 두 언어 모두 스크립트 언어라는 공통점을 제외하고는 js로 사용하는 것에 대한 이점을 느낄 수 없었다. 하지만 막상 책을 보고 실습을 진행해보니 사용하는 언어만 바뀌었을 뿐 오히려 자바스크립트라는 언어의 특성을 잘 살려 쉽게 구성된 것 같아 재미있었고 굉장히 신선했다.

그도 그럴것이 목차의 구성을 보면 기본적인 머신러닝, 딥러닝 방법론적인 개념에 대한 설명부터 선형회귀,신경망에 대한 설명도 너무 친절하게 되어 있다. 실습을 통해 실제 딥러닝 workflow를 경험하며 예측모델을 만들어보고, 더 나아가 LSTM, GAN 등을 활용한 딥러닝과 강화학습까지 진행할 수 있다. 

일반적인 딥러닝 책이라면 이 단계까지 진행했겠지만, 모델 테스트 및 최적화, 배포까지 하는 과정까지 소개를 하며 구축부터 배포까지 end-to-end 과정을 친절하게 설명하고 있다. 또한 중간중간 연습문제도 제공하며, 독자가 딥러닝에 대한 지식을 탄탄하게 쌓을 수 있도록 잘 설계된 책이다.  

주변에 데이터를 다루거나 딥러닝을 배우고 싶어하는 웹 개발자분들이 많은데 꼭 추천하고 싶은 책이다. 구글 브레인팀 최고!

Reference :  CS 공부 비서, midas님의 velog


Q&A

Q.  트랜잭션의 각 격리 수준에 대해서 설명하고, 각 수준에서 일어날 수 있는 문제에 대해 설명해주세요

A. 나의 답변

* 트랜잭션은 데이터베이스의 논리적 수행 단위라고 할 수 있는데, 가지고 있는 여러가지 특징 중 격리성에 대한 특징이 있다.
격리성이란 트랜잭션들이 동시에 실행될 때 서로 영향을 미치지 않도록 격리하는 성질을 의미한다.

* 격리 수준은 4가지로 나눌 수 있는데, 하위 단계로 갈수록 격리 수준이 높아지지만 동시처리의 성능은 떨어진다.
1) Read Uncommitted
2) Read Committed
3) Repeatable Read
4) Serializable 


Best Answers

★김*님의 답변
격리성 관련 문제점을 해결하기 위해서 ANSI 표준에서 트랜잭션의 격리성과 동시 처리 성능 사이에 Trade-off 를 두고 4단계 격리수준을 나눴다.

0 - 한 트랜잭션의 변경된 내용을 commit이나 rollback과 상관 없이 다른 트랜잭션에서 읽을 수 있다
문제점 : 더티 리드(Dirty Read) 발생 가능성 존재한다, 데이터 정합성에 문제가 많다

1 - commit이 완료된 데이터만 조회 가능하다
문제점 : Non-repeatable Read 발생 가능성 존재한다, 잠금이 발생하므로 속도나 성능에 있어서 느릴 수 있다, 트랜잭션 간 고립성을 완전히 보장하지 못한다

2 - 트랜잭션이 시작되기 전에 커밋된 내용에 관해서만 조회할 수 있다
문제점 : 다른 사용자는 트랜잭션 영역에 해당되는 데이터에 대한 수정이 불가능하다, 잠금이 적용되는 범위가 넓어져 성능과 속도가 느려진다

3 - 한 트랜잭션을 다른 트랜잭션으로부터 완전히 분리한다
문제점 : 동시처리 능력이 다른 격리수준보다 떨어지며, 성능저하 발생한다


★김*님의 답변
트랜잭션 격리 수준이란 여러 트랜잭션 동시 처리시, 서로 얼마나 고립되었는지를 나타낸 것으로, 한 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할 것인지 결정하는 것이다. ACID와 같은 특성으로 트랜잭션이 독립적인 수행을 하도록 Locking을 통해 다른 트랜잭션 관여 여부를 막는데, 효율적인 Locking을 위해 격리수준을 나눈다.

격리 수준 (Isolatio) 종류
레벨 0. Read Uncommitted
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸리지 않음
- 일관성 유지 불가
- 문제점 : Dirty Read
- user1이 data A 를 B로 변경하는 도중 user2가 data를 B로 읽게되는 현상 (커밋 X)

레벨 1. Read Committed
- Select 문장 수행 중 해당 데이터에 Shared Lock이 걸림
- 트랜잭션 수행 중 다른 트랜잭션이 접근할 수 없어 대기
- 커밋된 트랜잭션만 조회 가능
- Non-Repeatable Read 발생
- A 트랜잭션에서 1번 데이터 조회 : 1
- B 트랜잭션에서 1번 데이터를 2로 바꾸고 커밋
- A 트랜잭션에서 1번 데이터 조회 : 2

레벨 2. Repeatable Read
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 트랜잭션이 범위 내에 조회한 데이터 내용이 항상 동일함을 보장

레벨 3. Serializable
- 트랜잭션 완료 전까지 SELECT 내의 모든 데이터에 Shared Lock
- 완벽한 읽기 일관성 모드 제공



★권*님의 답변
트랜잭션의 각 격리 수준에 대해 얘기하기 이전에 몇 가지 개념을 정리하려 한다. 트랜잭션이란 데이터의 수정/읽기하는 명령을 의미한다.
커밋은 데이터의 영구적인 저장을 의미한다. 
DB의 각 격리수준이 나오는 이유는 DB가 값을 수정하고, 다른 트렌젝션이 값을 읽고 롤백할 경우 데이터의 일관성을 잃는 문제가 있다. 이런 문제들을 갖고 어떤 방법론을 쓸 건지 나눈 것이다.
예를들면 데이터를 수정할 때 데이터를 수정 전의 값 기준으로 한다. 데이터를 수정 후의 기준으로 한다. 데이터를 커밋하기 이전의 기준으로 한다. 이후로 한다. 와 같이 나눠진다.

자세히 살펴보면 다음과 같은 방법이 있다.

READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

READ UNCOMMITTED
커밋하지 않아도 수정한 결과를 계산 값으로 쓴다. 이때 위에 말한 것처럼 롤백을 사용할 경우 데이터의 일관성을 잃는다.


READ COMMITTED
커밋한 결과만으로 값을 쓴다. 그렇다면 데이터의 일관성이 유지되지만 또 다른 문제점이 존재한다. DB가 멀티스레드로 트렌젝션을 동시에 처리할 때이다. 이럴 경우 동기화가 되지않아서 어떤 것은 수정되기 이전 값을 쓰고 이후에 커밋되어 수정된 값을 쓰고 같은 문제가 발생한다.


REPEATABLE READ
트랜잭션이 시작되면 각 트랜잭션이 발생한 시점의 데이터들을 저장한다. 그리고 연산 시 발생한 시점의 데이터만 사용한다. 발생하는 문제로데이터 업데이트할 경우 나중의 트랜잭션만 수행되고, 처음에 시작된 트랜잭션은 무시된다. 또 각 시점별 데이터를 저장하므로 용량 문제가 발생할 수 있다.


SERIALIZABLE
읽기와 수정 모두 동기화를 시켜서 엄격하게 관리한다. 이렇게 할 경우 위의 모든 문제를 해결할 수 있지만 한 작업이 길게 이어지는데 데이터를 오랫동안 사용할 경우 계산낭비가 발생한다.


★.*님의 답변
# 트랜잭션 격리수준(isolation level)이란
- 특정 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것

## 격리수준
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE

### READ UNCOMMITTED
- 어떤 트랜잭션의 변경내용이 COMMIT이나 ROLLBACK과 상관없이 다른 트랜잭션에서 보여진다.
- 데이터 정합성에 문제가 많아, 격리수준으로 인정하지 않음

### READ COMMITTED
- 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있다.

### REPETABLE READ
- 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리수준

### REPEATABLE READ
- UPDATE 부정합: 변경을 수행할 로우에 대해 잠금이 필요하다.
- Phantom READ: 한 트랜잭션 내에서 같은 쿼리를 두 번 실행했는데, 첫 번째 쿼리에서 없던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상을 말한다.

### SERIALIZABLE
- 가장 단순하고 가장 엄격한 격리수준이다.

 



★황*님의 답변
트랜잭션은 데이터의 무모순성을 보장하기 위한 기능입니다. 트랜잭션은 논리적인 작업 셋 자체가 100% 적용되거나(COMMIT) 또는 아무것도 적용되지 않아야 함(ROLLBACK)을 보장해주는 것입니다.
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때, 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것입니다.

격리 수준은 다음과 같이 4가지로 정의할 수 있습니다.
READ UNCOMMITTED(커밋되지 않은 읽기)
READ COMMITTED(커밋된 읽기)
REPEATABLE READ(반복 가능한 읽기)
SERIALIZABLE(직렬화 가능)

1. READ UNCOMMITED
각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.

따라서 트랜잭션 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있는 DIRTY READ현상이 발생합니다.
ex: A트랜잭션에서 값을 바꿨으나 아직 커밋되지 않은 상태에서 B트랜잭션이 해당 바뀐 값을 확인할 수 있는 문제가 발생합니다.

2. READ COMMITTED
실제 테이블 값이 아닌 Undo(잘못되었을 경우 데이터가 변경되기 전의 데이터 보관하는 곳) 영역에 백업된 레코드에서 값을 가져옵니다.

하나의 트랜잭션에서 같은 쿼리를 두 번 실행하였을 때 두 실행 조회 값이 달라질 수 있습니다.

정합성 문제가 해결된 것 같지만 부정합 문제가 발생할 수 있습니다.
ex:)A트랜잭션이 작동 도중 B트랜잭션이 해당 값을 조회 한 결과 "P"라는 결과가 나옴. 그 후 A트랜잭션이 커밋이 되면 B트랜잭션에서 조회한 결과 커밋으로 바뀐 결과가 나타남

하나의 트랜잭션 내에서 똑같은 SELECT를 수행했을 경우 항상 같은 결과를 반환해야 하는 정합성 문제에 어긋납니다.

3. REPETABLE READ
트랜잭션이 시작되기 전 커밋된 내용에 대해서만 조회할 수 있는 격리수준입니다.(트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경된 것만 읽습니다.)

부정합이 발생하지 않습니다.

그러나, PHANTOM READ(한 트랜잭션 안에서 일정범위의 레코드를 두번 이상 읽을 때, 첫 번째 쿼리에서 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상)은 여전히 발생합니다.

고립화 수준을 높여 LOCK을 통해 다른 트랜잭션 시점에 다른 데이터가 추가되는 것을 막을 수 있습니다. 그러나 동시성이 저하됩니다.
(오라클은 Lock을 전혀 사용하지 않은 상태서 서로 다른 쿼리를 SCN 확인 과정을 통해 하나의 시점에 존재했던 대상으로만 집계를 수행하는 방법을 사용합니다. 동시성 저하를 하지 않으면서 일관성 유지)


4. SERIALIZABLE
새로운 트랜잭션이 읽은 데이터를 다른 트랜잭션이 갱신하거나 삭제하지 못하게 하고 중간에 새로운 레코드를 삽입 하는것을 막아줍니다.

이 Level에서는 Insert까지 막아줍니다. 다른 트랜잭션에서 이 레코드 변경을 하지 못하게 되기 때문에 동시처리 능력이 떨어지고, 성능 저하, 속도 저하 등이 발생하게 됩니다.



★정*님의 답변
트랜잭션이란, DB에 이루어지는 작업을 의미합니다. 몇 개의 작업이 한 단위를 이룰 수 있고, 이 작업들의 격리 정도를 트랜잭션의 각 격리 수준이라고 합니다.

트랜잭션의 격리 수준은 아래와 같이 4개의 단계가 있습니다.
1. Read Uncommitted
2. Read Commmitted
3. Repeatable Read
4. Serializable

1. Read Uncommitted
커밋되지 않은 트랜잭션까지 읽을 수 있는 격리 수준입니다. 사실상 격리의 개념이 존재하지 않는다고 볼 수 있습니다.


2. Read Committed
커밋된 트랜잭션을 읽을 수 있습니다. 일부 DB에서는 기본적으로 read committed가 기본 격리 단계로 사용됩니다. 데이터를 수정할 때는 수정이 완료될 때까지 lock이 적용되며, 데이터를 읽을 때는 lock이 해제됩니다. 따라서 데이터를 읽는 도중에 데이터가 변경될 수 있는 위험성이 존재합니다.


3. Repeatable Read
데이터가 수정될 때, 조회될 때 모두 lock을 겁니다. 일부 RDBMS의 기본 격리 수준으로 사용되고 있습니다. Phantom read라는 문제점이 발생할 수 있는데, 반복 조회 시 결과 집합이 달라지는 현상을 phantom read라고 합니다.


4. Serializable
가장 엄격한 단계의 격리 수준으로, 완벽한 격리 수준을 나타냅니다. 데이터를 읽거나 쓸 때, 완료될 때까지 lock을 걸게 됩니다. 하지만 이로 인하여 동시성 처리 성능이 떨어지는 문제점이 존재합니다.


★겨*님의 답변
트랜잭션의 격리 수준은 네개로 나눌 수 있다.
1. READ UNCOMMITTED
2. READ COMMITED
3. REPEATABLE READ
4. SERIALIZABLE


아래로 내려갈수록 트랜잭션 간의 고립 정도가 높아지며 성능이 떨어진다. READ UNCOMMITTED 격리수준에서는 어떤 트랜잭션의 변경내용이 Commit 이나 Rollback 과 상관없이 다른 트랜잭션에서 보여진다. 여기선 한 데이터의 값을 변경 후 커밋을 하지 않았는데 다른 트랜잭션에서 해당 데이터를 조회했을 때 변경된 값이 조회되는 더티리드 현상이 발생할 수있다.

READ COMMITTED는 어떤 트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있는데 이는 현재 오라클 DBMS에서 기본으로사용하고 있다.
해당 격리 수준에서는 하나의 트랜잭션 내에서 똑같은 Select 명령을 수행했을 경우 항상 같은 결과를 반환해야 한다는 Repeatable Read 정합성에 문제가 나타날 수 있다. 이를 Non-Repeatable Read 부정합 문제라고 한다.

REPEATABLE READ는 트랜잭션이 시작되기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리 수준이다. MySQL DBMS에서 기본으로 사용하고 있는데, 이는 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호에서 변경된(커밋된) 데이터만 보게 된다. 해당 격리 수준에서는 Update 부정합과 Phantom Read 라는 문제가 발생할 수 있다.

SERIALIZABLE은 가장 단순하고 엄격한 겨리수준이다. 해당 격리 수준에서는 읽기 작업에도 공유 잠금을 설정하게 되고, 다른 트랜잭션에서 해당 레코드를 변경할 수 없다. 이러한 특성 때문에 동시처리 능력이 다른 격리수준보다 떨어지고 성능저하가 발생하게된다.


★서*님의 답변
트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것으로 네가지로 정의됩니다.


1. READ UNCOMMITTED(커밋되지 않는 읽기)
2. READ COMMITED(커밋된 읽기)
3. REPEATABLE READ (반복 가능한 읽기)
4. SERIALIZABLE(직렬화 가능)


순서대로 1의 수준이 가장 낮고, 4인 직렬화 가능 단계의 수준이 가장 높습니다. 

READ UNCOMMITTED 격리 수준에서는 위 그림처럼 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 하지만 이러한 수준은 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상을 야기하고, 이를 더티 리드(Dirty Read) 라고 합니다.

READ COMMITTED 격리 수준은 오라클 DBMS에서 기본적으로 사용되고 있으며 온라인 서비스에서 가장 많이 선택되는 격리 수준입니다. 이 레벨에서는 위 READ UNCOMMITTED 수준에서 발생할 수 있는 더티 리드(Dirty Read)와 같은 현상은 발생하지 않습니다. 어떠한 트랜잭션에서 데이터를 변경하더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있기 때문입니다. 하만 READ COMMITTED 격리 수준에서도 "NON-REPEATABLE READ"라는 부정합 문제가 존재합니다. 즉, 하나의 트랜잭션내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 "REPEATABLE READ" 정합성에 어긋나게 됩니다.

따라서 세번 째 수준인 REPEATABLE READ는 MySQL의 InnoDB 스토리지 엔진에서 기본적으로 사용되는 격리 수준입니다. 이 격리 수준에서는 READ COMMITTED 격리 수준에서 발생하는 "NON-REPEATABLE READ" 부정합이 발생하지 않습니다. 하지만 이러한 격리수준에서도 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안보였다가 하는 현상인 PHANTOM READ(PHANTOM ROW)이 발생할 수 있습니다. 

이때문에 네번째 격리수준인 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경할 수 없습니다. 즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다. 이는 팬텀리드 현상을 해결합니다.



★김*님의 답변
격리 수준은 READ UNCOMMITTED(커밋되지 않은 읽기), READ COMMITTED(커밋된 읽기), REPEATABLE READ(반복 가능한 읽기), SERIALIZABLE(직렬화 가능) 으로 정의할 수 있습니다. 순서대로 READ UNCOMMITTED의 격리 수준이 가장 낮고 SERIALIZABLE의 격리 수준이 가장 높습니다.

READ UNCOMMITTED 격리 수준에서는 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 보여지게 됩니다. 이를 Dirty Read라고 합니다. READ COMMITTED 격리 수준에서는 어떤 트랜잭션에서 변경한 내용이 커밋되기 전까지는 다른 트랜잭션에서 변경 내역을 조회할 수 없습니다.


REPEATABLE READ는 UNDO 영역에 백업된 이전 데이터를 통해 동일한 트랜잭션 내에서는 동일한 결과를 보여줄 수 있도록 보장합니다. 이에 어긋나는 현상을 NON-REPEATABLE READ라고 합니다. 트랜잭션의 격리 수준이 SERIALIZABLE로 설정되면 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없습니다.

PHANTOM READ는 한 트랜잭션내에서 동일한 쿼리를 두 번 수행했는데, 첫 번째 쿼리에서 존재하지 않던 유령(Phantom) 레코드가 두 번째 쿼리에서 나타나는 현상입니다. 이는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ에서 나타날 수 있습니다.


★용*님의 답변
트랜잭션을 T라고 하고 T1의 단위중 갱신구문이 있을때,


READ UNCOMMITTED는
변경된 레코드를 커밋과 롤백 여부에 상관없이 T2에서 조회할 수 있습니다.
이는 해당 격리수준이 언두로그를 활용하지 않고, 디스크에 바로 반영하기 때문입니다.

READ COMMITTED는
변경된 레코드를 커밋되기 전까지 T2에서 조회할 수 없습니다.
이는 해당 격리수준이 언두로그를 활용해 갱신이전 레코드를 유지하기 때문입니다.

REPEATABLE READ는
트랜잭션마다 ID를 부여하여 현 ID보다 작은 ID에서 갱신한 레코드의 갱신 전 레코드를 조회할 수 있게 합니다.

SERIALIZABLE은
동시에 레코드를 조회함은 가능하지만, 갱신은 불가능하며
T1이 조회하면서 T2가 갱신하는 상황도 불가합니다.

다음은, 문제를 나열하고 어떤 수준에 일어나는지 기술하겠습니다.
DIRTY READ는
T2가 T1의 롤백 이전에 레코드를 조회하는 경우에
재개된 T1의 트랜잭션이 커밋되어 T2의 조회가 온전한 조회일수도
커밋되지 않아 온전한 조회가 아닐 수도 있는 현상입니다.
READ UNCOMMITTED에만 발생합니다.

NON-REPETABLE READ는
T2가 여러번 조회하는 사이 T1이 갱신이후 커밋됬다면 T2의 마지막 조회가 일관되지 않은 현상입니다.
T1의 커밋이전까지는 T2가 언두로그를 바라보지만,
T1의 커밋이후 T2가 디스크를 바라보게 되기때문입니다.
READ UNCOMMITTED와 READ COMMITTED에서 발생합니다.
REPEATABLE READ가 극복할 수 있었던 이유는
현 ID보다 작은 ID에서 갱신한 레코드의 갱신전 레코드는 언두로그에 남아있기 때문입니다.

PHANTOM READ는
T2가 여러번 조회하는 사이 T1이 갱신을 했다면
레코드가 변하지는 않지만 추가되거나 삭제될 수 있는 현상입니다.
SERIALIZABLE을 제외한 모든 격리수준에서 발생합니다.
단, InnoDB엔진의 default 수준인 REPEATABLE READ에는 발생하지 않는데,
Gap lock을 사용해 레코드의 일정 구간 자체에 락이 걸려 T1의 갱신 행위가 이뤄지지 않기 때문입니다.

+ Recent posts