C++에서 C 파일을 컴파일 하려면, 해당 C 파일이 포함된 헤더 파일에 extern "C" 를 선언해주어야 합니다.
이렇게 하면 C++ 컴파일러는 해당 헤더 파일에 있는 함수 및 변수들을 C 스타일로 링크하게 됩니다.
만약 C 파일 자체를 컴파일 하기 위해서는, 해당 C 파일 내에도 extern "C" 를 선언해주어야 합니다.
이렇게 하면 C++ 컴파일러는 해당 C 파일을 C 스타일로 컴파일하게 됩니다.

 

예를 들어, 아래와 같은 C 파일과 헤더 파일이 있다고 가정해보겠습니다.

 

< sample.c 파일 >

 

#include "sample.h"

int add(int a, int b) {
    return a + b;
}

 

< sample.h 파일 >

 

#ifndef SAMPLE_H
#define SAMPLE_H

#ifdef __cplusplus
extern "C" {
#endif

int add(int a, int b);

#ifdef __cplusplus
}
#endif

#endif // SAMPLE_H

 

위의 예제에서 sample.h 파일에서 extern "C" 선언을 사용하여 add 함수가 C 스타일로 링크되도록 설정하였습니다.
이제 이 헤더 파일을 C++ 파일에서 include 하여 사용하면 됩니다.

 

#include "sample.h"

int main() {
    int result = add(1, 2);
    return 0;
}

 

sample.c 파일에서 extern "C"를 선언하지 않아도 되는 이유는, C 파일 자체가 C 스타일로 작성되어 있기 때문입니다.
C 파일은 C++과는 달리 *name mangling 을 하지 않으므로, extern "C" 선언이 필요하지 않습니다.
반면에, C++ 파일에서는 함수나 변수 이름 맹글링이 발생할 수 있으므로, C++ 파일에서 C 함수를 호출하거나 C 변수를 사용할 때는 extern "C" 선언을 해주어야 합니다.
따라서, C++에서 C 함수 또는 변수를 사용할 때는 해당 C 함수 또는 변수가 선언된 헤더 파일에 extern "C" 선언을 추가해주어야 합니다. 그러나 C 파일에서는 해당 선언을 할 필요가 없습니다.

 

 

name mangling 이란?

함수 및 클래스 이름과 같은 식별자(identifier)를 컴파일러가 처리하기 쉬운 내부 표현 형식으로 변환하는 과정을 말합니다.
이는 C++의 오버로딩(overloading) 및 네임스페이스(namespaces)와 같은 기능을 지원하기 위해 필요합니다.
C++ 컴파일러는 linker 가 사용하는 symbol 테이블을 생성하는데, 이 기호 테이블에는 함수와 클래스 이름 및 다른 식별자에 대한 정보가 포함됩니다. 이 정보를 사용하여 링커는 프로그램의 다른 부분에서 해당 함수 또는 클래스를 사용할 수 있습니다.
그러나 C++에서 함수 및 클래스 이름은 여러 매개변수를 가질 수 있습니다.

이를테면, add(int a, int b)와 add(double a, double b)는 동일한 이름의 함수일지라도 서로 다른 매개변수 유형을 가지므로 서로 다른 기호(symbol)로 링크되어야 합니다. 이때, 컴파일러는 이러한 함수 및 클래스 이름을 링커에서 사용할 수 있는 고유한 기호로 변환하기 위해 name mangling을 수행합니다.

즉, Name mangling은 컴파일러에 따라 다를 수 있지만, 일반적으로 함수 및 클래스 이름에 유일한 식별자를 추가하여 고유한 이름을 만듭니다. 이 식별자는 함수의 매개변수 유형 및 반환 유형과 같은 정보를 포함합니다.

예를 들어, add(int, int) 함수의 이름은 _Z3addii와 같은 형식으로 변환될 수 있습니다.

Name mangling은 일반적으로 개발자가 직접적으로 관여하지 않지만, 링커 오류를 해결하거나 디버깅하는 과정에서 체크해야 할 수도 있습니다.

걔가 원래 그렇다고? < You mean he's always like that ?>
몇년 된거 같은데, 사실 많이 나아진거야 <It's been a  few years now, but it's gotten a lot better actually>
예전에는 훨씬 심했어 <It used to be a lot worse >

A: Frank 무슨일 있어?
B: 왜?
A: 애가 항상 좀 날카로운거 같지 않아?
B: Frank 가 좀 그렇지
A: 걔가 원래 그렇다고?
B: 몇년 된거 같은데, 사실 많이 나아진 거야. 예전에는 훨씬 심했어

A: Hey, What's (up) with Frank?
B: Why?
A: Doesn't he seem a bit edgy all the time? 
B: Oh. Yeah, that's Frank
A: You mean he's always like that ? (You mean he's always been like that?)
B: It's been a few years now, but it's(he's) gotten a lot better actually. It used to be a lot worse

 

  • "걔가 원래 그렇다고?"는 사람의 성향 등을 말하는 것이므로, (설계적 특성상) '정상'임을 의미하는 be supposed to 는 안됨 
  • "It's gotten a lot better" 에서 it 은 Frank의 성향을 나타내는 대명사이고, "He's gotten a lot better"에서 he 는 Frank로 둘다 의미상 적절함 

 

~ 했던거(때) 기억나? < Remember when ~>

A: 리모컨 왜이래?
B: 왜?
A: 방향키들 말이야. 너무 끈적해
B: 아 그거? 알아
A: 이것들 왜이런거야?
B: 무슨말이야? 그것들 그런지 좀 됐어
A: 아냐 그러진 않았어. 어제만해도 이러진 않았어
B: 아냐 그랬어. Kyle 이 소다 쏟은거 기억나?
A: 아니
B: 그랬었어. 그게 몇달 전이었고, 그때이후로 쭉 그래

A: What happend to the Remote?
B: Why?
A: The arrow keys. They're so sticky
B: Oh that? Yeah. I know
A: Why are they like this?
B: What do you mean? They've been like that for a while now
A: No, they haven't. They weren't like this yesterday
B: Yes. they were. Remember when Kyle spilled soda on it?
A: No
B: Well he did, that was a few months ago and it's been like that ever since 

 

  • The arrow keys ----> "They are" so sticky, Why "are they" like this?, "They've been like that ~"
  • Oh that? 에서 that은 key가 sticky한 현상(문제)을 지칭
  • Yes. they were : 부정문에 대해 부정하는 대답

정확히 생각은 안나 (정확히 기억나진 않아) < I can't remember exactly >
~ 하려고 생각했어 < I figured I should ~ >
딱히 생각나는데가 없어 : < I couldn't really think of anywhere >

 

A: 너 혹시 거기 이름 생각나? 지난달에 Kim이랑 갔던 그 식당
B: 아 그 시푸드 레스토랑?! 딥 블루 뭐뭐 였는데 정확히 생각은 안나. 왜? 또 가고싶어?
A: 다음 달에 우리 아버지 환갑이라 좋은 데로 가야겠다는 생각이 들었는데, 딱히 생각나는데가 없어서..
     너 혹시 갈만한 데 알아?
B: 응 생각나는데가 몇군데는 있어

A: Do you (happen to/by any chance) remember the name of that place ?
     (Do you remember what that place was called ?)
    The restaurant  that we went to last month with Kim
B: Oh you mean that sea food restaurant ?! I think It was "deep blue someting"
     but I don't(can't) remember exactly.  Why? Do you wanna go there again ?
A: My dad's 60th birthday is next month. So I figured I should take him to a nice place.
    But I couldn't really think of anywhere(anyplace). Do you know some place nice ? (Any recommendations?)
B: Yeah. I can think of a few(several) places 

 

  • the name of that place  : 식당 이름 
    the title of that movie(book) : 영화(책)  제목
  • 혹시 : "happen to" , "by any chance"  
  • "be called" : Do you remember what that place was called?
  • figure : solution 에 대한 생각 (I figured + I should ~ : ~ 해야겠다는 생각이 들었다
    "생각이 들다" 의 다른 표현 : "It occured to me .. " , "It got me thinking" 
  • think of 와 come up with 는 거의 유사하나, come up with  는 좀 더 창의적인 아이디어가 떠올랐을 때 주로 사용함
    ex) He came up with a really great idea
  • really : 문맥상 "딱히"

get to

 

전 누구나 꿈을 갖게 된다고 생각하지 않아요 (전 누구나 꿈을 가질 순 없다고 생각해요)

I don't think everybody gets to have a dream 

 

A: (출장 다녀온 사람에게) "관광도 좀 했어?
B: 시간이 없어서 아쉽게도 관광은 못했어

A: Did you get to do some sightseeing?
B: I didn't have time, so I didn't get to do any sightseeing

 

공부할 게 많아서 20대 때에는 별로 놀지 못했다 

I didn't get to have much fun in my 20's because I had so much studying to do

코로나 때문에 대학 출제를 즐기지 못했다

I didn't get to enjoy the university festivals because of covid

내가 결혼할 때 아내와 나는 가난했기 때문에 멋진 허니문을 못갔다

When I got married, my wife and I didn't get to go on a fancy honeymoon because we were so poor 

모든 사람이 소울메이트를 만나는 건 아니다

Not everybody gets to meet their soulmate
  • 부정형에 some은 어울리지 않음 대신, "much" 나 "any" 사용
  • get to를 추가함으로써 '그부분이 아쉬웠다' 라는 뉘앙스를 추가

give someone a better understanding of
give someone deeper insight into
give someone an idea of

 

그걸 보니까 당시에 상황이 얼마나 심각했는지 더 잘 알 것 같더라

That(It) gave me a (much) better understanding of how serious things were back then 

 

그걸 보니까 일반적인 연쇄살인마가 어떤식으로 형성되는 건지 더 깊이 있게 알게 됐다

This certainly gave me much deeper insight into how a typical serial killer is formed 

 

당시에 제가 살던 집 구조를 좀 알 수 있게 그림을 대충 그려볼게요

To give you an idea of what my house looked like at the time, let me do a quick drawing
(Let me do a quick drawing here just to give you an idea of what my house looked like at the time)
  • 어떻게 생겼었는지에 대한 대략적인 감 - the idea

 


 

"The important things is you know what this means
  you don't have to necessarily have a perfect translation of this sentence as long as you understand what it means"

"I just wanted to give you an example with much more context"

"The reason I came up with a situation like this is in order to give you a better idea of when and how this expression is used.. and you know.. potentially how you might use it.. in a some situation that you might be in" 

A: 다음주부터 Brenda가 널 좀 따라다니도록 할 생각이야
    다 설명할 필욘 없고, 니가 하는걸 그녀가 지켜보게만 해
   그렇게 하면 우리가 여기서 어떻게 일하는지 직관적으로 이해하게 될거같아
   그렇게 하면 더 빨리 배울거라고 생각해. 어떻게 생각해
B: 그런다고(그렇게 한다고 해서) 크게 달라지진 않을 거야.
     그러면 더 지체만 돼
     그래봤자 괜히 일만 더 복잡해져

A: I'm thinking of having Brenda follow you around for the next week or so
    You don't have to explain everything. Just let her watch what you do
    I think that'll give her a much more intuitive understanding of how we work around here.
    I think she'll learn faster that way. What do you think?
B: That wont' make a big difference (make much of a difference)
    That'll only slow things down (That'll only delay the process)
   That'll only complicate things (That'll only make things complicated)

 

  • "follow you around": 누군가가 다른 사람의 움직임을 따라가서 그들과 함께 시간을 보내는 것을 의미
  • "for the next week or so": 앞으로 약 일주일 정도의 시간 동안을 의미
  • "That'll only make things complicated" 보단  "that'll only complicate things" 를 더 많이씀 
    ex) 괜히 일 복잡하게 하지마 : Don't complicate things 

펌웨어(Firmware)

 

펌웨어(Firmware)는 하드웨어 기반 시스템에 내장된 소프트웨어입니다. 이는 기기가 동작하는 데 필요한 제어 코드를 포함하고 있으며, 하드웨어와 소프트웨어 사이에서 인터페이스 역할을 합니다.

펌웨어는 일반적으로 ROM, EPROM, EEPROM, 플래시 메모리 등의 비휘발성 메모리에 저장됩니다. 이러한 비휘발성 메모리는 전원이 꺼져도 데이터가 지워지지 않는 메모리로, 디바이스가 재시작될 때마다 펌웨어가 로드되어 기기를 동작시킵니다.

펌웨어는 하드웨어 제조사에 의해 제공되며, 장치의 제어 및 동작 방식에 영향을 미칩니다. 또한, 펌웨어 업그레이드를 통해 기기의 동작 방식을 변경하거나 버그를 수정할 수 있습니다.

일반적으로, 펌웨어는 임베디드 시스템, 컴퓨터의 마더보드, 그래픽 카드, 무선 라우터, 디지털 카메라 등과 같은 다양한 하드웨어 기반 시스템에서 사용됩니다.

 

 

펌웨어는 임베디드 장치 제조업체가 제공하는 소프트웨어 업그레이드 파일 형태로, 기존 펌웨어와 대체되어 장치의 동작 방식이 변경되는 파일입니다. 펌웨어 파일의 구조와 구성은 장치 및 제조업체에 따라 다를 수 있지만, 일반적으로 다음과 같은 구성 요소로 구성됩니다.

 

헤더 (Header) : 펌웨어 파일의 시작 부분에 위치하며, 파일의 버전 정보, 업그레이드 대상 장치 정보, 파일 크기 및 체크섬 등의 정보를 포함합니다. 이 정보는 펌웨어 파일의 유효성을 검증하는데 사용됩니다.

펌웨어 코드 (Firmware Code) : 펌웨어 파일의 중요한 부분으로, 업그레이드 대상 장치에 로드되어 실행되는 코드입니다. 이 코드는 기존 펌웨어와 대체되어 장치의 동작 방식이 변경됩니다.

설정 파일 (Configuration File) : 장치의 동작에 필요한 설정 정보를 포함하는 파일입니다. 이 파일은 펌웨어 업그레이드를 위해 장치에 대한 초기 설정을 제공합니다.

라이브러리 (Library) : 펌웨어 코드에서 사용되는 함수나 기능을 모아놓은 라이브러리 파일입니다. 이 파일은 펌웨어 코드를 개발할 때 재사용이 가능한 코드를 제공하며, 펌웨어 코드와 함께 업그레이드되어 장치에서 사용됩니다.

도움말 파일 (Help File) : 펌웨어 파일과 함께 제공되는 도움말 파일입니다. 이 파일은 장치에 대한 사용자 설명서, 업그레이드 방법, 문제 해결 방법 등의 정보를 제공합니다.기타 파일 : 펌웨어 파일과 함께 제공되는 기타 파일로, 펌웨어 업그레이드를 위해 필요한 파일이 포함됩니다.

 

펌웨어 업데이트

 

펌웨어 업데이트는 기존의 장치 펌웨어를 새로운 버전으로 업그레이드하는 프로세스입니다. 이 프로세스는 컴퓨터, 스마트폰, 태블릿 등 디지털 장치에서 수행됩니다. 일반적으로 펌웨어 업데이트는 다음과 같은 단계로 수행됩니다.

 

업데이트 파일 다운로드: 펌웨어 업데이트를 위한 새로운 파일을 다운로드합니다. 이 파일은 일반적으로 제조업체 웹사이트에서 제공됩니다.

기기 연결: 디지털 장치를 컴퓨터 또는 기타 호스트 장치에 연결합니다. 이를 위해 USB 케이블 또는 블루투스 등의 연결 방법을 사용할 수 있습니다.

업데이트 모드 진입: 기기를 업데이트 모드로 진입시킵니다. 이 단계는 장치마다 다를 수 있으며, 사용자 매뉴얼 또는 제조업체의 지침을 따라야 합니다.

펌웨어 업데이트 실행: 업데이트 파일을 장치에 업로드하고, 새로운 펌웨어를 설치합니다. 이 과정은 일반적으로 몇 분 이내에 완료됩니다.

재부팅: 펌웨어 업데이트 후에는 장치를 재부팅해야 합니다. 이를 통해 새로운 펌웨어가 적용되며, 장치가 정상적으로 작동하는지 확인할 수 있습니다.

펌웨어 업데이트는 장치의 안정성, 보안 및 성능을 향상시키는 데 중요합니다. 그러나 업데이트를 수행하기 전에는 반드시 백업을 수행해야 합니다. 또한, 업데이트 파일이 기기와 호환되는지 확인하고, 업데이트 모드에서는 다른 프로그램이나 작업을 수행하지 않도록 주의해야 합니다.

 

펌웨어는 보통 디버거를 사용하여 많이 하는데, 그 이유는 다음과 같습니다.

 

효율성: 디버거를 사용하면 펌웨어 업데이트 과정을 자동화할 수 있습니다. 이렇게 하면 업데이트 과정을 수동으로 수행하는 것보다 빠르고 효율적으로 업데이트를 수행할 수 있습니다.

오류 확인: 디버거를 사용하면 펌웨어 업데이트 과정에서 발생하는 오류를 더 쉽게 식별할 수 있습니다. 디버거를 사용하면 업데이트 중에 발생한 오류의 원인을 빠르게 찾아서 수정할 수 있습니다.

안정성: 디버거를 사용하면 펌웨어 업데이트 과정을 안정적으로 수행할 수 있습니다. 업데이트 과정 중에 오류가 발생하면, 디버거를 사용하여 업데이트를 다시 시작할 수 있으며, 이를 통해 장치의 안정성을 유지할 수 있습니다.

기능 추가: 디버거를 사용하여 펌웨어 업데이트를 수행하면, 추가적인 기능을 구현할 수 있습니다. 이를 통해 업데이트 과정을 더욱 효율적으로 수행하고, 새로운 기능을 추가하여 장치의 기능성을 향상시킬 수 있습니다.

물론 디버거를 사용하여 펌웨어 업데이트를 수행할 때에도 주의해야 합니다. 업데이트 파일이 장치와 호환되는지 확인하고, 업데이트 모드에서는 다른 프로그램이나 작업을 수행하지 않도록 주의해야 합니다. 또한, 업데이트 과정에서 발생하는 오류를 적극적으로 확인하고, 오류를 수정하도록 노력해야 합니다.

 

펌웨어 업데이트 과정에서 지정하는 주소값은 업데이트 파일의 위치를 가리킵니다. 일반적으로 이 주소값은 플래시 메모리의 시작 주소를 나타냅니다.

플래시 메모리는 컴퓨터나 기타 디지털 장치에서 비휘발성 저장 장치로 사용됩니다. 이 메모리에는 기기에서 사용되는 소프트웨어 및 데이터가 저장됩니다. 펌웨어 업데이트를 수행하면 새로운 펌웨어 버전이 플래시 메모리에 새롭게 기록되어야 하므로, 업데이트 파일의 위치를 알려주는 것입니다.

이 주소값은 업데이트 파일의 바이너리 형식을 로드하기 위한 시작점을 나타내며, 이 위치부터 파일의 데이터가 플래시 메모리에 기록됩니다. 이렇게 업데이트 파일의 데이터가 플래시 메모리에 정확하게 로드되어야만, 새로운 펌웨어가 정상적으로 작동할 수 있습니다.

 

elf, hex, bin 파일

모두 컴퓨터에서 사용되는 바이너리 파일의 형식을 나타냅니다.

이러한 바이너리 파일 형식은 주로 소프트웨어나 하드웨어를 개발하는 과정에서 사용됩니다.

 

ELF (Executable and Linkable Format): ELF는 리눅스와 유닉스 운영체제에서 사용되는 실행 가능한 형식의 바이너리 파일입니다. ELF 파일은 컴파일된 프로그램의 코드, 데이터 및 기타 정보를 포함하며, 여러 가지 섹션으로 구성됩니다. ELF 파일은 실행 파일 또는 공유 라이브러리 파일로 사용됩니다.

HEX (Hexadecimal): HEX 파일은 16진수 형식으로 표현된 데이터를 담고 있는 파일입니다. 이 파일 형식은 프로그래머가 마이크로컨트롤러나 기타 임베디드 시스템에서 사용하는 프로그램 및 데이터를 포함하는 데 사용됩니다. HEX 파일은 텍스트 파일로 쉽게 열어 볼 수 있습니다.

BIN (Binary): BIN 파일은 이진 형식으로 인코딩된 데이터를 담고 있는 파일입니다. BIN 파일은 주로 하드웨어에서 사용되는 펌웨어나 바이너리 이미지를 포함하는 데 사용됩니다. BIN 파일은 이진 파일 형식으로, 텍스트 에디터로 열기 어려울 수 있습니다.

 

말하자면, ELF 파일은 실행 가능한 형식의 바이너리 파일이고, HEX 파일은 데이터를 16진수 형식으로 인코딩한 파일입니다.

BIN 파일은 이진 형식으로 인코딩된 데이터를 포함하는 파일입니다. 각각의 파일 형식은 사용되는 환경이나 목적에 따라 다르게 사용됩니다

'Computer' 카테고리의 다른 글

하이퍼바이저(hypervisor) 와 도커(docker)  (0) 2023.04.04
메모리 가시성과 메모리 장벽  (0) 2022.11.22

 

RPC 프로토콜

 

RPC (Remote Procedure Call) 프로토콜은 클라이언트 애플리케이션이 서버 애플리케이션에서 함수를 호출하고, 이를 처리한 결과를 반환하는 프로토콜입니다. 이를 통해 클라이언트와 서버 간의 통신이 표준화되고, 보안성과 안정성이 확보됩니다.

RPC 프로토콜은 일반적으로 클라이언트와 서버 간의 통신을 위해 사용되는 네트워크 프로토콜인 TCP/IP, UDP 등을 기반으로 구현됩니다. 클라이언트에서 호출하는 함수의 매개변수는 프로토콜을 통해 서버로 전송되고, 서버에서는 이를 처리한 결과를 클라이언트로 반환합니다.

RPC 프로토콜은 다양한 언어와 운영 체제에서 사용될 수 있으며, 서로 다른 애플리케이션 간의 통신에 사용됩니다. 일반적으로 RPC 프로토콜은 클라이언트와 서버 간의 인터페이스를 정의하는 IDL (Interface Definition Language)을 사용하여 통신을 표준화합니다.

RPC 프로토콜은 분산 시스템 및 마이크로서비스 아키텍처에서 매우 중요한 역할을 합니다. 서로 다른 애플리케이션 간의 통신을 단순화하고, 효율적으로 처리할 수 있는 기능을 제공합니다

 

RPC 서버

RPC (Remote Procedure Call) 서버는 클라이언트 애플리케이션에서 서버 애플리케이션으로 함수를 호출하는 방식입니다. 이 서버를 사용하여 클라이언트 애플리케이션이 서버 측에서 제공하는 함수를 호출하고, 서버에서는 이를 처리하고 결과를 반환합니다.

RPC 서버는 일반적으로 클라이언트와 서버 간의 통신 프로토콜로 RPC를 사용합니다. 이를 통해 클라이언트와 서버 간의 통신이 표준화되고, 보안성과 안정성이 확보됩니다. 또한, 서버 측에서는 여러 클라이언트로부터 요청을 받아 처리할 수 있습니다.

RPC 서버는 다양한 운영 체제와 언어를 지원하며, 이를 사용하여 다른 애플리케이션과 상호작용할 수 있습니다. 이를 통해 다른 애플리케이션과의 연동이 가능해져, 보다 효율적이고 유연한 시스템 구축이 가능해집니다.

 

RPC 서버는 일반적으로 다음과 같은 단계로 작동합니다.

1. 서버는 RPC 호출을 수신할 수 있는 네트워크 포트를 열고 대기합니다.
2. 클라이언트 애플리케이션에서 RPC 요청을 생성하고, 해당 요청을 서버로 전송합니다.
3. 서버는 RPC 요청을 수신하고, 요청에 따른 함수를 호출합니다.
4. 서버에서는 함수 호출 결과를 클라이언트로 반환합니다.
5. 클라이언트는 서버에서 반환된 결과를 수신하고, 이를 처리합니다.

RPC 서버는 분산 시스템 및 마이크로서비스 아키텍처에서 매우 중요한 역할을 합니다.

서로 다른 서버 간의 통신을 단순화하고, 효율적으로 처리할 수 있는 기능을 제공합니다

RPC 프로토콜은 다양한 분야에서 사용되며, 분산 시스템 및 마이크로서비스 아키텍처에서 중요한 역할을 하고 있습니다.

1. Apache Thrift
Facebook에서 개발한 RPC 프레임워크로, 다양한 언어 및 플랫폼에서 사용할 수 있습니다.
Facebook의 분산 시스템에서 사용되며, Hadoop, Cassandra, Elasticsearch 등 여러 대규모 시스템에서 사용됩니다.
2. gRPC
Google에서 개발한 오픈소스 RPC 프레임워크로, Protocol Buffers를 기반으로 구현되어 있습니다. 이를 사용하여 Google의 다양한 서비스에서 사용되며, 대규모 클라우드 기반 시스템에서 효율적인 통신을 지원합니다.
3. CORBA(Common Object Request Broker Architecture)
OMG(Object Management Group)에서 개발한 분산 객체 프레임워크로, 다양한 언어와 플랫폼에서 사용됩니다. 이를 사용하여 대규모 분산 시스템에서 객체 간의 통신을 효율적으로 처리할 수 있습니다.
4. XML-RPC
XML을 기반으로 하는 RPC 프로토콜로, 다양한 언어와 플랫폼에서 사용됩니다. 이를 사용하여 원격으로 데이터를 읽고 쓰는 데 사용됩니다.
5. JSON-RPC
JSON을 기반으로 하는 경량 RPC 프로토콜로, 다양한 언어와 플랫폼에서 사용됩니다. 이를 사용하여 클라이언트와 서버 간의 효율적인 통신을 지원합니다.

 

일반 서버-클라이언트 모델과 차이점

 

RPC 서버는 일반 서버-클라이언트 모델의 서버와는 몇 가지 다른 점이 있습니다.

일반 서버-클라이언트 모델에서는 클라이언트가 서버에 직접 연결하여 요청(request)을 보내고, 서버는 해당 요청을 받아 처리한 후 클라이언트에게 응답(response)을 보내는 방식으로 동작합니다.

반면 RPC 서버는 클라이언트와 서버 간의 통신에서 Remote Procedure Call (RPC) 프로토콜을 사용하기 때문에, 클라이언트가 서버의 메소드(method)를 로컬에서 호출하는 것과 유사한 방식으로 동작하며, 클라이언트는 서버의 메소드를 직접 호출하지 않고, 클라이언트 스텁(client stub)을 통해 서버의 메소드를 호출합니다.

서버는 클라이언트로부터 요청을 받아 해당 메소드를 실행한 후, 결과를 클라이언트에게 응답합니다.즉, RPC 서버는 일반 서버-클라이언트 모델의 서버보다는 높은 수준의 추상화(abstraction)를 제공하며, 클라이언트-서버 간의 통신을 쉽게 처리할 수 있도록 도와줍니다.

이러한 RPC 프로토콜은 대부분의 프로그래밍 언어에서 지원되며, 다양한 RPC 프레임워크가 존재합니다.

 

이러한 RPC 서버의 장점과 단점은 다음과 같습니다.
장점
1. 분산 시스템을 쉽게 구축할 수 있습니다.
RPC 서버는 다수의 클라이언트가 분산된 환경에서 서로 다른 서버의 기능을 사용할 수 있도록 해주기 때문에
분산 시스템을 구축하는 데 있어서 유용합니다.
2. 프로그래밍 언어와 플랫폼에 독립적입니다.
RPC 서버는 다양한 프로그래밍 언어와 플랫폼에서 동작할 수 있도록 설계되어 있습니다.
따라서 서로 다른 언어와 플랫폼에서 개발된 클라이언트가 같은 RPC 서버를 사용할 수 있습니다.
3. 간단한 프로세스 간 통신을 제공합니다.
RPC 서버는 다른 프로세스 간의 통신을 추상화하여 제공합니다.
이를 통해 클라이언트와 서버 간의 통신을 쉽게 처리할 수 있습니다.
4. 유연하고 확장 가능한 시스템을 구축할 수 있습니다.
RPC 서버는 시스템을 유연하고 확장 가능하게 구축할 수 있도록 도와줍니다. 새로운 기능을 추가하거나 기존 기능을 업그레이드할 때 RPC 인터페이스만 수정하면 되기 때문입니다.

단점
1. 성능 문제가 발생할 수 있습니다.
RPC 서버는 다른 프로세스 간의 통신을 추상화하기 때문에, 일반적인 서버-클라이언트 모델보다 더 많은 오버헤드가 발생할 수 있습니다. 이는 서버의 처리량과 응답 속도에 영향을 미칠 수 있습니다.
2. 디버깅이 어려울 수 있습니다.
RPC 서버는 서로 다른 프로세스 간의 통신을 추상화하므로, 디버깅이 어려울 수 있습니다. 클라이언트와 서버 간의 통신 문제를 해결하기 위해서는 네트워크 트래픽을 모니터링하거나, 로그를 수집해야 할 수도 있습니다.보안 문제가 발생할 수 있습니다.
3. RPC 서버는 클라이언트와 서버 간의 통신을 암호화하거나 보안 기능을 제공하지 않습니다.
따라서 보안 요구사항이 높은 시스템에서는 추가적인 보안 조치를 취해야 할 수도 있습니다.

 

 
 
 

아래는 Google에서 개발한 gRPC 프레임워크를 사용하여 RPC 서버 및 클라이언트를 구현한 예제입니다.

 

서버

#include <iostream>
#include <boost/asio.hpp>
#include "rpc.hpp"

int on_add(int x, int y) {
    return x + y;
}

int main() {
    boost::asio::io_service io_service;
    RpcServer server(io_service, 12345);
    server.register_handler("add", on_add);
    server.start();
    std::cout << "Server started." << std::endl;
    io_service.run();
    return 0;
}
on_add 함수 : 클라이언트가 add 메서드를 호출하면, 서버에서 실행되는 함수입니다.
이 함수는 두 개의 정수를 인자로 받아 더한 결과를 반환합니다.
main 함수 : 서버의 메인 함수입니다. io_service 객체를 생성하고, RpcServer 객체를 생성한 뒤 start 메서드를 호출하여 서버를 시작합니다.

클라이언트

#include <iostream>
#include <boost/asio.hpp>
#include "rpc.hpp"

int main() {
    boost::asio::io_service io_service;
    RpcClient client(io_service, "localhost", 12345);
    int result = client.call<int>("add", 1, 2);
    std::cout << "Result: " << result << std::endl;
    return 0;
}
main 함수 : 클라이언트의 메인 함수입니다.
io_service 객체를 생성하고, RpcClient 객체를 생성한 뒤 call 메서드를 호출하여 서버의 add 메서드를 호출합니다.

RPC

#include <string>
#include <functional>
#include <boost/asio.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>

class Message {
public:
    std::string method;
    std::vector<std::string> params;

    Message() {}

    Message(const std::string& method, const std::vector<std::string>& params)
        : method(method), params(params) {}

    std::string to_string() const {
        std::string result = method + "(";
        for (size_t i = 0; i < params.size(); ++i) {
            result += params[i];
            if (i < params.size() - 1) {
                result += ",";
            }
        }
        result += ")";
        return result;
    }

    static Message from_string(const std::string& str) {
        Message msg;
        size_t left_paren = str.find("(");
        size_t right_paren = str.find(")");
        if (left_paren == std::string::npos || right_paren == std::string::npos) {
            return msg;
        }
        msg.method = str.substr(0, left_paren);
        std::string params_str = str.substr(left_paren + 1, right_paren - left_paren - 1);
        size_t pos = 0;
        while (pos < params_str.size()) {
            size_t comma = params_str.find(",", pos);
            if (comma == std::string::npos) {
                comma = params_str.size();
            }
            std::string param = params_str.substr(pos, comma - pos);
            msg.params.push_back(param);
            pos = comma + 1;
        }
        return msg;
    }
};
class RpcServer {
public:
    RpcServer(boost::asio::io_service& io_service, unsigned short port)
        : acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
          socket_(io_service) {}

    void register_handler(const std::string& method, std::function<int(int,int)> handler) {
        handlers_[method] = handler;
    }

    void start() {
        do_accept();
    }

private:
    void do_accept() {
        acceptor_.async_accept(socket_, [this](const boost::system::error_code& error) {
            if (!error) {
                std::make_shared<Session>(std::move(socket_), handlers_)->start();
            }
            do_accept();
        });
    }

private:
    boost::asio::ip::tcp::acceptor acceptor_;
    boost::asio::ip::tcp::socket socket_;
    std::map<std::string, std::function<int(int,int)>> handlers_;
};

class RpcClient {
public:
    RpcClient(boost::asio::io_service& io_service, const std::string& host, unsigned short port)
        : io_service_(io_service), socket_(io_service) {
        boost::asio::ip::tcp::resolver resolver(io_service);
        boost::asio::ip::tcp::resolver::query query(host, boost::lexical_cast<std::string>(port));
        boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
        boost::asio::connect(socket_, endpoint_iterator);
    }

    template<typename Result, typename... Args>
    Result call(const std::string& method, Args... args) {
        Message request(method, { boost::lexical_cast<std::string>(args)... });
        std::string request_str = request.to_string();
        boost::asio::write(socket_, boost::asio::buffer(request_str));
        char response_buf[1024];
        size_t response_len = socket_.read_some(boost::asio::buffer(response_buf, sizeof(response_buf)));
        std::string response_str(response_buf, response_len);
        Message response = Message::from_string(response_str);
        return boost::lexical_cast<Result>(response.params[0]);
    }

private:
    boost::asio::io_service& io_service_;
    boost::asio::ip::tcp::socket socket_;
};

 

Message 클래스
클라이언트와 서버 간에 전송되는 메시지를 나타내는 클래스입니다.
method와 params 멤버 변수를 가지며, to_string 메서드를 통해 문자열 형태로 직렬화할 수 있습니다.
RpcServer 클래스
RPC 서버를 나타내는 클래스입니다. start 메서드를 통해 서버를 시작하며, 클라이언트의 요청이 들어오면 해당 메서드를 실행하고 결과를 반환합니다.
RpcClient 클래스
RPC 클라이언트를 나타내는 클래스입니다. call 메서드를 통해 서버의 메서드를 호출하고 결과를 반환합니다.

하이퍼바이저(hypervisor)

 

하이퍼바이저(Hypervisor)는 가상화 소프트웨어로, 컴퓨터 시스템에서 여러 개의 가상 머신(VM)을 생성하고 관리하는 역할을 합니다.

즉, 가상 머신을 실행하기 위한 소프트웨어입니다

 

하이퍼바이저는 호스트 시스템(컴퓨터)에서 가상 머신을 만들고 호스트의 리소스를 가상 머신들에게 할당하고, 가상 머신들이 호스트 시스템의 하드웨어 자원(CPU, 메모리, 저장소)을 공유하며 동작할 수 있도록 합니다. 이를 통해 여러 개의 운영 체제(OS)나 응용 프로그램을 단일 물리적 시스템에서 실행할 수 있게 됩니다 (단일 시스템 상에서 독립된 운영체제와 애플리케이션 실행 가능)

 

하이퍼바이저는 두 가지 유형이 있습니다.

첫 번째는 Type 1 또는 네이티브 하이퍼바이저이고, 두 번째는 Type 2 또는 호스트 기반 하이퍼바이저입니다.

Type 1 하이퍼바이저는 직접 하드웨어 위에 설치되고, 가상 머신의 하드웨어 리소스를 직접 제어합니다. 이러한 하이퍼바이저는 호스트 시스템과 가상 머신 간의 강력한 격리 기능을 제공하며, 가상 머신에서 실행되는 애플리케이션에 대한 고도의 제어를 제공합니다.

Type 2 하이퍼바이저는 호스트 운영 체제 위에 설치되고, 호스트 시스템의 리소스를 공유합니다. 이러한 하이퍼바이저는 더 쉽게 설치할 수 있으며, 일부 경우에는 Type 1 하이퍼바이저보다 더 빠릅니다. 그러나 Type 2 하이퍼바이저는 호스트 시스템의 보안 취약점을 노출할 수 있으며, 가상 머신 간의 격리 기능도 덜 강력합니다.

 

리소스 관리

하이퍼바이저는 가상 머신의 리소스를 관리하고, 가상 머신 간의 상호작용을 관리합니다. 즉, 각 가상 머신에 할당된 가상 CPU, 메모리, 저장소 등의 리소스를 추적하고, 이 리소스를 가상 머신 간에 균등하게 분배합니다. 또한, 가상 머신 간의 네트워크 연결을 관리하며, 이를 통해 가상 머신 간의 통신을 가능하게 합니다.

 

I/O 작업 관리

가상 머신은 호스트 시스템의 하드웨어 리소스를 사용하므로, 하이퍼바이저는 가상 머신과 호스트 시스템 간의 I/O 작업을 조정합니다. 예를 들어, 가상 머신에서 디스크 작업을 수행하려면, 하이퍼바이저는 호스트 시스템의 디스크 드라이브에 대한 액세스 권한을 부여하고, 가상 머신이 사용할 수 있도록 가상 디스크 드라이브를 제공합니다.

 

가상 머신 보안

하이퍼바이저는 가상 머신의 보안을 유지하기 위해 다양한 보안 기술을 사용합니다. 예를 들어, 하이퍼바이저는 가상 머신 간의 통신을 제어하고, 가상 머신의 메모리에 대한 엄격한 접근 권한을 부여하여 가상 머신에서 실행되는 애플리케이션의 보안을 강화합니다

 

가상 머신의 상태 관리

가상 머신은 일반적으로 운영 체제 및 애플리케이션과 같은 복잡한 시스템을 실행하므로, 하이퍼바이저는 가상 머신의 상태를 모니터링하고, 문제가 발생할 경우에는 가상 머신을 재부팅하거나 복구하는 등의 조치를 취합니다.

 

이처럼, 하이퍼바이저는 가상 머신을 실행하는 데 필요한 모든 기능을 제공합니다. 가상 머신은 하이퍼바이저 위에 생성되므로, 각 가상 머신은 독립적으로 실행될 수 있습니다. 이러한 구성은 클라우드 컴퓨팅, 서버 가상화, 테스트 및 개발 등 다양한 용도로 사용됩니다.

 

하이퍼바이저는 가상화 기술의 핵심 기술로, 다양하게 사용되고 있습니다.

1. 서버 가상화
기업에서는 하이퍼바이저를 사용하여 하나의 서버를 여러 개의 가상 서버로 분할하여 사용합니다. 이를 통해 기업은 서버의 사용률을 높이고, 물리적 서버의 수를 줄이면서 IT 인프라의 비용을 절감할 수 있습니다.
2. 클라우드 컴퓨팅
클라우드 컴퓨팅은 인터넷을 통해 IT 리소스를 제공하는 서비스입니다. 하이퍼바이저를 사용하여 클라우드 컴퓨팅 환경을 구축하면, 여러 사용자가 동시에 클라우드 인프라를 공유할 수 있습니다. 이를 통해 기업은 더 많은 고객에게 서비스를 제공하면서 인프라 비용을 절감할 수 있습니다.
3. 테스트 및 개발
하이퍼바이저를 사용하여 테스트 및 개발 환경을 구축하면, 여러 개의 테스트 환경을 동시에 실행할 수 있습니다. 이를 통해 애플리케이션을 더 빠르게 개발하고, 오류를 더 쉽게 수정할 수 있습니다.
4. 보안
하이퍼바이저를 사용하여 가상 머신을 분리하면, 서로 다른 보안 수준을 필요로 하는 애플리케이션을 실행할 수 있습니다. 이를 통해 기업은 보안을 강화하고, 서로 다른 애플리케이션 간의 상호 간섭을 방지할 수 있습니다.
5. 모바일 기술
하이퍼바이저는 모바일 기술에서도 널리 사용됩니다. 예를 들어, BYOD(Bring Your Own Device) 환경에서는 하이퍼바이저를 사용하여 기업 데이터와 개인 데이터를 분리할 수 있습니다. 이를 통해 기업은 보안을 유지하면서도 직원이 자신의 디바이스를 사용할 수 있도록 합니다.
VMware
가상화 기술을 기반으로 한 서버 가상화 솔루션을 제공합니다.
이를 통해 서버의 하드웨어 리소스를 효율적으로 활용하고, 서버의 가용성과 안정성을 높일 수 있습니다.
Microsoft Hyper-V
윈도우 서버 가상화 기술을 제공합니다. 서버 가상화 및 서버 운영 관리를 효율적으로 수행할 수 있습니다.
Citrix XenServer
오픈소스 가상화 플랫폼으로, 클라우드 컴퓨팅 및 가상 데스크톱 인프라를 제공합니다.
이를 통해 클라우드 인프라 및 가상 데스크톱 인프라를 효율적으로 관리하고, 자원의 활용도를 높일 수 있습니다.
Oracle VM VirtualBox
데스크톱 가상화 플랫폼으로, 다양한 운영체제를 호스팅하는 가상 머신을 만들 수 있습니다.
테스트 및 개발 환경 구축을 용이하게 할 수 있습니다.
IBM z/VM
메인프레임 가상화 플랫폼으로, 메인프레임의 자원을 효율적으로 관리하고, 가상 서버를 만들어서 다양한 운영체제 및 어플리케이션을 호스팅할 수 있습니다. 이를 통해 메인프레임의 가용성과 안정성을 높일 수 있습니다

 

도커(docker)

Docker는 컨테이너 기반의 가상화 기술을 사용하여 응용 프로그램을 패키징하고 실행하는 플랫폼입니다.

컨테이너는 가상화된 환경에서 응용 프로그램을 실행할 수 있도록 격리된 공간을 제공합니다. 이러한 격리된 공간에서는 응용 프로그램이 필요로 하는 라이브러리, 파일 시스템 등의 환경을 포함한 모든 것이 패키징되어 있습니다.

Docker는 이러한 컨테이너 기반의 가상화 기술을 사용하여 응용 프로그램을 패키징하고 배포할 수 있도록 도와주는 플랫폼입니다. Docker는 호스트 운영 체제와 컨테이너 간의 직접적인 상호작용을 통해 응용 프로그램을 실행합니다.

이처럼 Docker는 하이퍼바이저(가상 머신 기반의 가상화)와는 다른 방식으로 응용 프로그램을 가상화합니다

 

Docker는 컨테이너라는 가상화 기술을 사용하여 응용 프로그램을 패키징하고 실행하는 것을 지원합니다.
Docker는 다음과 같은 원리로 동작합니다.

1. 이미지 작성
Docker 이미지는 응용 프로그램과 그 실행 환경을 포함하는 것입니다. Dockerfile이라는 특별한 파일 형식을 사용하여 Docker 이미지를 작성합니다. Dockerfile은 응용 프로그램 실행에 필요한 파일, 라이브러리, 환경 변수, 포트 등을 정의합니다.
2. 이미지 빌드
Dockerfile을 사용하여 Docker 이미지를 빌드합니다. Docker는 Dockerfile에 정의된 내용에 따라 이미지를 빌드하고, 필요한 파일과 라이브러리 등을 다운로드합니다. 이미지를 빌드한 후에는 해당 이미지를 Docker 레지스트리에 업로드하거나 다른 사용자와 공유할 수 있습니다.
3. 컨테이너 실행
Docker 이미지를 사용하여 컨테이너를 실행합니다. 이때 컨테이너는 호스트 운영 체제의 자원을 사용합니다. Docker는 컨테이너 실행에 필요한 모든 자원을 미리 준비하여 컨테이너가 실행될 때 즉시 사용할 수 있도록 합니다.
4. 컨테이너 관리
Docker는 컨테이너를 관리하기 위한 명령어를 제공합니다. 이를 사용하여 컨테이너를 시작, 중지, 재시작하고, 로그를 볼 수 있습니다. Docker는 또한 컨테이너 간의 통신을 지원합니다.
5. 네트워크
Docker는 기본적으로 호스트 운영 체제와 동일한 네트워크에 컨테이너를 배치합니다. 이는 컨테이너 간의 통신을 간편하게 만들어 줍니다. Docker는 또한 다른 네트워크와의 연결을 지원합니다.
6. 데이터 관리
Docker는 컨테이너에서 생성되는 데이터를 관리하기 위해 볼륨이라는 개념을 제공합니다. 볼륨은 컨테이너와 호스트 운영 체제 사이의 데이터 공유를 가능하게 합니다.
Docker는 이러한 방식으로 컨테이너화된 응용 프로그램을 실행하고 관리합니다. 이는 가볍고 빠른 실행 속도, 쉬운 배포, 높은 이식성 등의 장점을 제공합니다.

 

Docker는 다양한 용도로 사용될 수 있습니다. 일부 일반적인 사용 사례는 다음과 같습니다.

애플리케이션 배포

Docker는 애플리케이션을 가상 컨테이너로 패키징하여 배포하는 데 이상적입니다. 이렇게 하면 애플리케이션을 호스트 운영 체제에 영향을 주지 않고 실행할 수 있으며, 호스트 운영 체제에 설치된 의존성 라이브러리의 충돌 문제를 해결할 수 있습니다.

서비스 분리
Docker는 서비스를 분리하여 실행하고, 서비스 간의 의존성을 관리하는 데도 유용합니다. 예를 들어, 웹 애플리케이션의 프론트엔드와 백엔드를 분리하여 각각 Docker 컨테이너로 실행하면, 서로 다른 호스트에서도 실행할 수 있고, 확장성과 격리성이 개선됩니다.

개발 환경 구성
Docker는 개발 환경 구성을 간편하게 만들어 줍니다. Docker를 사용하면 개발자는 개발에 필요한 환경을 Docker 이미지로 빌드하여 다른 개발자와 공유할 수 있습니다. 이렇게 하면 개발자는 개발 환경을 쉽게 설정하고, 이식성이 개선됩니다.

테스트 환경 구성
Docker를 사용하면 테스트 환경 구성도 간편해집니다. 개발자는 테스트를 위한 Docker 이미지를 빌드하여 테스트 서버에서 실행할 수 있습니다. 이렇게 하면 테스트 서버에 일시적인 의존성을 설치하지 않아도 되므로, 서버 관리가 더욱 용이해집니다.

마이그레이션
Docker를 사용하면 더 나은 성능을 제공하는 새로운 운영 체제나 호스트로 마이그레이션하는 것이 용이해집니다. 애플리케이션과 의존성을 Docker 이미지로 패키징하면, 이미지를 다른 호스트로 이동하여 쉽게 배포할 수 있습니다.
위와 같은 방식으로 Docker는 여러 분야에서 사용되고 있습니다. Docker는 컨테이너 기술을 통해 애플리케이션 실행 및 관리를 간편하게 해주므로, 인기 있는 기술 중 하나입니다.

 

  • Airbnb
    Airbnb는 도커를 사용하여 마이크로서비스 아키텍처를 구현하고 서비스를 컨테이너화하여 배포하고 있습니다.
    이를 통해 서비스의 가용성과 안정성을 높였으며, 인프라 관리 및 개발과 배포 과정을 효율화했습니다.
  • Spotify
    Spotify는 도커를 사용하여 서버 인프라를 관리하고 있습니다. 이를 통해 개발과 배포 과정을 효율화하고,
    서비스를 더 빠르게 출시하고, 확장성과 안정성을 높였습니다.
  • Uber
    Uber는 도커를 사용하여 개발 및 배포를 자동화하고, 서버 인프라를 관리하고 있습니다.
    이를 통해 개발 및 배포 과정을 효율화하고, 서비스의 안정성과 가용성을 높였습니다.
  • NASA
    NASA는 도커를 사용하여 우주선과 로봇 운영을 위한 소프트웨어를 개발하고 있습니다.
    이를 통해 소프트웨어를 더 안정적으로 운영할 수 있으며, 운영 비용을 줄일 수 있습니다.
  • eBay
    eBay는 도커를 사용하여 마이크로서비스 아키텍처를 구현하고, 서비스를 컨테이너화하여 배포하고 있습니다.
    이를 통해 개발과 배포 과정을 효율화하고, 서비스의 안정성과 가용성을 높였습니다.

 

하이퍼바이저와 도커

 

Docker와 하이퍼바이저는 모두 가상화 기술을 사용하여 응용 프로그램을 실행하는 기술입니다.

하지만, Docker와 하이퍼바이저는 큰 차이점이 있습니다.

 

가상화 방식
하이퍼바이저는 가상 머신을 생성하고, 각 가상 머신에 운영 체제를 설치하여 실행합니다. 따라서 가상 머신마다 자원과 운영 체제가 필요합니다. 이는 가상 머신을 사용하는 데 있어서 상대적으로 더 많은 자원이 필요하다는 것을 의미합니다.
반면 Docker는 호스트 운영 체제 위에서 동작합니다. Docker는 컨테이너라는 가벼운 가상화 기술을 사용하여 응용 프로그램을 패키징하고 실행합니다. 따라서 Docker는 가상 머신처럼 각각의 운영 체제를 설치하는 것이 아니라, 호스트 운영 체제의 커널을 공유하여 실행합니다. 이는 매우 가볍고 빠르게 실행할 수 있다는 것을 의미합니다.

성능
하이퍼바이저는 각 가상 머신이 독립적인 운영 체제를 가지므로 자원이 더 많이 필요합니다. 또한 가상 머신 사이에 자원을 분할하고 조정하는 작업이 필요합니다. 이는 상대적으로 느린 실행 속도를 가져올 수 있습니다.
한편, Docker는 호스트 운영 체제에서 실행되므로 가상 머신과는 달리 호스트와 컨테이너 간의 자원 분할과 조정이 필요하지 않습니다. 또한 컨테이너는 각각의 운영 체제를 가지지 않으므로, 가상 머신보다 상대적으로 더 빠르게 실행할 수 있습니다.

이미지 관리 방식
하이퍼바이저는 가상 머신 이미지를 사용하여 가상 머신을 생성합니다. 이는 대부분의 경우 ISO 파일로 제공됩니다. 새로운 가상 머신을 만들 때마다 이미지를 다운로드하고 설치해야 합니다. 이는 이미지 관리가 번거롭고 불편할 수 있다는 것을 의미합니다.
그런데 Docker는 컨테이너 이미지를 사용하여 응용 프로그램을 패키징하고 배포합니다. 이러한 이미지는 Docker Hub와 같은 저장소에서 공유되어 사용할 수 있습니다

 

'Computer' 카테고리의 다른 글

Firmware(펌웨어)와 elf, bin, hex 파일  (0) 2023.04.04
메모리 가시성과 메모리 장벽  (0) 2022.11.22

라이브러리(library)란?

 

라이브러리(library)란 다른 프로그램에서 사용할 수 있는 코드의 모음을 의미합니다.

 

라이브러리를 만들기 위해서는 헤더 파일과 라이브러리를 구성하는 코드가 필요합니다. 헤더 파일은 사용자가 라이브러리를 사용하기 위해 호출할 함수와 변수의 프로토타입을 선언하며, 라이브러리 코드는 실제로 함수와 변수를 구현하는 코드입니다.

 

헤더 파일과 라이브러리 코드를 함께 컴파일하여 정적 라이브러리 또는 동적 라이브러리를 생성할 수 있습니다. 이때, 라이브러리 코드는 오브젝트 파일 형태로 제공되며, 라이브러리를 사용하는 프로그램은 이 오브젝트 파일을 링크하여 라이브러리를 사용할 수 있습니다. 

 

헤더 파일은 라이브러리를 사용하는 사용자가 라이브러리를 쉽게 사용할 수 있도록 인터페이스를 제공합니다. 이를 통해 라이브러리를 사용하는 사용자는 라이브러리를 사용하는데 필요한 함수와 변수의 이름, 매개변수, 반환값 등을 알 수 있습니다. 또한, 헤더 파일은 라이브러리를 구현하는 소스 코드와 사용자 코드 간의 인터페이스를 명확히 하여 코드의 가독성과 유지보수성을 높이는 역할도 합니다.

따라서, 헤더 파일은 라이브러리를 사용하는 사용자가 라이브러리를 사용하기 위한 필수적인 정보를 제공하는 역할을 하기 때문에 따로 구분하여 사용합니다. 라이브러리를 만드는 개발자는 헤더 파일을 작성하여 라이브러리의 인터페이스를 제공하고, 라이브러리를 사용하는 사용자는 해당 헤더 파일을 include하여 라이브러리를 사용할 수 있습니다. 이를 통해 라이브러리를 쉽게 사용할 수 있으며, 라이브러리를 수정하더라도 헤더 파일만 수정하면 라이브러리를 사용하는 모든 코드에 영향을 주지 않습니다.

 

이렇게 만들어진 라이브러리는 여러 프로그램에서 재사용되어 코드의 중복을 막고 개발 시간을 단축시키는 등의 이점을 제공합니다.

라이브러리는 크게 static library와 dynamic library로 나눌 수 있습니다.

 

1. static library
Static 라이브러리는 컴파일 시에 라이브러리의 코드가 사용자의 프로그램에 복사되어 실행 파일에 포함됩니다.
이 때, 실행 파일은 라이브러리를 사용할 때마다 그 라이브러리의 모든 코드를 메모리에 로드합니다.
따라서, 여러 프로그램에서 같은 라이브러리를 사용하는 경우, 메모리를 많이 차지할 수 있습니다.
Static 라이브러리는 사용자가 컴파일러에게 직접 링크하도록 지정하는 방법으로 사용할 수 있습니다.
이 경우, 사용자의 소스 코드와 함께 실행 파일에 라이브러리 코드가 포함됩니다.
이러한 방식은 실행 파일의 크기가 크다는 단점이 있지만, 실행 파일이 라이브러리 파일에 의존하지 않으므로 이식성이 높습니다.

2. dynamic library

Dynamic 라이브러리는 실행 파일과 별도로 존재하며, 프로그램이 실행될 때 메모리에 로드됩니다.
따라서, 라이브러리의 코드는 여러 프로그램에서 공유될 수 있습니다.
이렇게 공유된 라이브러리는 메모리를 적게 사용할 수 있습니다.
Dynamic 라이브러리는 사용자가 라이브러리를 호출할 때마다 동적으로 로드됩니다.
이를 위해 프로그래밍 언어에 따라서는 로딩에 대한 명시적인 호출이 필요할 수 있습니다.
이 방식은 실행 파일의 크기를 줄일 수 있지만, 실행 파일이 라이브러리 파일에 의존한다는 단점이 있습니다.
또한, Dynamic 라이브러리는 라이브러리 코드가 변경될 경우, 실행 파일을 다시 빌드하지 않아도 되므로, 유지보수가 용이합니다. 그러나, 라이브러리 파일이 필요하므로 이식성이 낮을 수 있습니다.

 

shared object
UNIX 및 유닉스 계열 운영 체제에서 자주 등장하는 용어인 "shard object" 또한 동적 라이브러리(dynamic library)의 일종입니다
즉, Windows 운영 체제에서 사용되는 DLL(Dynamic Link Library)이 유닉스 운영체제에서는 SO(shared object)인 것입니다.
Shared objec 역시 실행 파일과 별도로 존재하는 라이브러리 파일이며, 런타임에 메모리에 로드되어 프로그램에서 사용됩니다.
따라서 여러 프로그램에서 공유될 수 있으므로 메모리를 절약할 수 있습니다. (동적 링크 통해 실행 파일 크기 줄일수 있음)
Shared object는 보통 .so (shared object) 확장자를 갖습니다. 사용자가 컴파일러에게 직접 링크하거나, 런타임에 로드하기 위해 명시적인 호출이 필요합니다. 
Shared object는 다양한 용도로 사용될 수 있습니다.
예를 들어, 시스템 라이브러리와 같은 기본적인 함수를 포함하여, user-defined 함수, 플러그인, 응용 프로그램의 모듈 등을 구현 등에 사용될 수 있습니다. 또한, Shared object는 유지보수 및 업그레이드 작업을 용이하게 하므로, 대규모 프로젝트에서 매우 유용합니다.

 

링킹(linking) 

 

링킹(Linking)은 프로그래밍에서 컴파일된 객체 파일(Object File)을 실행 파일(Executable File)로 결합하는 과정을 말합니다.

일반적으로 컴파일러가 소스 코드를 컴파일하여 오브젝트 파일(Object File)을 생성하면, 이러한 오브젝트 파일은 실행 파일을 만들기 위해 링커(Linker)에 의해 결합됩니다.

링킹은 크게 두 가지 유형이 있습니다.

 

1. 정적 링킹(Static Linking)
정적 링킹은 컴파일된 오브젝트 파일(Object File)과 라이브러리(Library)를 결합하여 실행 파일(Executable File)을 생성하는 과정입니다. 이 때, 실행 파일은 모든 함수와 라이브러리를 포함하므로, 런타임에 추가적인 라이브러리 로딩이 필요하지 않습니다.
정적 링킹의 장점은 실행 파일이 의존성 문제를 일으키지 않으며, 이식성이 높아진다는 것입니다. 그러나 단점은 실행 파일의 크기가 커질 수 있으며, 여러 프로그램에서 동일한 라이브러리를 사용할 때, 메모리 낭비가 발생할 수 있다는 것입니다.

 

예를 들어, C 프로그램에서 "math" 라이브러리를 사용하여 삼각함수를 계산한다고 가정해봅시다.

이 경우, 다음과 같은 과정으로 링킹이 수행됩니다.

1. 컴파일러는 소스 코드를 컴파일하여 오브젝트 파일을 생성합니다.
   이때, "math.h" 헤더 파일을 포함하여 "sin", "cos", "tan" 함수 등을 호출하면,
   컴파일러는 오브젝트 파일에 함수를 호출하는 코드를 생성합니다.
2. 링커는 "math" 라이브러리를 포함하여 실행 파일을 생성합니다.
    이때, "math" 라이브러리의 함수가 필요하면, 링커는 "math" 라이브러리에서 해당 함수를 찾아 오브젝트 파일에 결합합니다.
    이때, 정적 링킹을 사용한다면, 링커는 "math" 라이브러리에서 해당 함수를 직접 찾아서 실행 파일에 포함시킵니다.
3. 실행 파일이 실행될 때, 필요한 라이브러리와 함수가 이미 실행 파일 내에 포함되어 있으므로,
     런타임에 추가적인 라이브러리 로딩이 필요하지 않습니다.

따라서, 정적 라이브러리를 사용하는 경우, 모든 함수와 라이브러리를 실행 파일에 포함시켜 런타임에 추가적인 라이브러리 로딩을 방지하고, 실행 파일의 이식성을 높일 수 있습니다.


2. 동적 링킹(Dynamic Linking)
동적 링킹은 런타임에 필요한 라이브러리를 로드하여 실행 파일(Executable File)을 생성하는 과정입니다. 이 때, 실행 파일은 필요한 라이브러리만 포함하므로, 실행 파일의 크기가 줄어들고, 여러 프로그램에서 공유할 수 있습니다.
동적 링킹의 장점은 실행 파일의 크기가 작고, 메모리 절약 효과가 있다는 것입니다. 그러나 단점은 런타임에 추가적인 라이브러리 로딩이 필요하므로, 실행 시간이 더 오래 걸릴 수 있다는 것입니다.

동적 라이브러리는 실행 파일과 별도로 존재하는 라이브러리로, 실행 파일이 라이브러리를 필요로 할 때에만 로딩되며, 메모리에 올라가서 사용됩니다. 이러한 동적 라이브러리는 링커에 의해 실행 파일에 포함되는 것이 아니라, 실행 파일이 로딩될 때 동적으로 링킹됩니다.

동적 라이브러리 링킹 과정은 크게 두 단계로 나눌 수 있습니다.
첫 번째 단계는 라이브러리를 로딩하는 과정이며, 두 번째 단계는 라이브러리를 실행 파일과 링킹하는 과정입니다.

첫 번째 단계에서는 운영 체제가 라이브러리를 찾아서 메모리에 로딩합니다.
예를 들어, "math" 라이브러리를 동적 라이브러리로 만들어서 사용한다고 가정해봅시다. 이때, 컴파일러가 소스 코드를 컴파일하여 오브젝트 파일을 생성하는 단계에서, "math" 라이브러리의 함수를 호출하는 코드가 생성됩니다. 하지만, 링커는 "math" 라이브러리를 실행 파일에 포함시키지 않습니다.
대신, 실행 파일이 로딩될 때, "math" 라이브러리가 필요한 경우, 운영 체제는 "math" 라이브러리를 로딩하여 해당 함수들을 실행 파일과 링킹합니다. (이 단계에서는 운영 체제가 라이브러리를 찾아서 메모리에 로딩합니다. 이때, 라이브러리는 운영 체제가 지정한 경로에서 찾을 수도 있고, 실행 파일이나 다른 라이브러리에 의해 이미 로딩된 경우에는 해당 라이브러리를 공유하여 사용할 수도 있습니다.)

두 번째 단계에서는 실행 파일과 라이브러리를 링킹합니다.
이때, 실행 파일은 라이브러리가 제공하는 함수와 변수를 사용할 수 있습니다. 이 과정에서는 라이브러리가 제공하는 함수와 변수의 이름과 주소를 실행 파일의 심볼 테이블에 등록합니다. 이후 실행 파일에서 라이브러리의 함수를 호출하면, 실행 파일은 등록된 주소를 참조하여 해당 함수를 실행합니다.

동적 라이브러리를 사용하면, 라이브러리를 로딩하는 시점에 메모리 사용량이 증가하며, 실행 파일과 동적 라이브러리가 모두 필요한 경우 초기 로딩 시간도 더 걸리지만, 실행 파일의 크기를 줄일 수 있으며, 여러 개의 실행 파일에서 동일한 라이브러리를 사용할 경우, 해당 라이브러리의 코드와 데이터가 메모리에 한 번만 로딩되므로 디스크 공간의 낭비를 줄일 수 있습니다.(실행파일과 라이브러리의 호환성 문제가 발생 할 수 있음) 또한, 라이브러리를 업데이트하면, 모든 실행 파일을 다시 컴파일하지 않아도 되며, 새로운 버전의 라이브러리를 로딩하는 실행 파일만 수정하면 됩니다.


링킹은 컴파일러와 링커에 의해 자동으로 수행되지만, 경우에 따라 명시적으로 링커를 호출하여 링킹을 수행할 수도 있습니다. 링킹 과정에서는 중복된 기능을 가진 오브젝트 파일과 라이브러리를 제거하고, 링크 주소를 결정하여 실행 파일을 생성합니다

 

 

1. Take your time : 여유를 가져, 천천히 해

 

밥 먼저 먹고, 상대한테 천천히 먹으라고 할때 

Take your time, I can wait

 

식당에서 메뉴판을 좀 오래 보고 있을 때 웨이터가 

Take your time, I'll be back

 

밖에서 그렇게 여유 부릴 순 없어요. 돌아오셔야 해요

You can't just take your time out there, you need to get back

 


 2. Never mind : 신경 쓰지마, 아무것도 아니야

*뉘앙스를 잘 살려야햠 : 차가운 어투로 말하면 '신경 꺼'가 될 수 있음. (부드러운 어투로 말할 것)

*비지니스 영어로는 사용하지 않는 것을 권장

 

A: 뭐하세요?

B: 아... 신경쓰지마세요 이 비디오는..

 

A: What are you doing?

B: Ahh.. never mind this video is..

 

 


3. I'll be right back : 금방(짧은 시간) 돌아올게

 

A: Microwave's the way

B: I'll be right back

 

1시간 안에 올게

I'll be back in an hour

 

30분 안에 올게

I'll be back in 30 minutes


4. Are you ready to ~ ? : ~ 할 준비 됐어요?

 

식사가 끝나고 상대방도 접시가 빈 것을 확인 한 후 일어나자고 제안할 때

 Are you ready to go ?

 

(웨이터가) 식당에서 손님들에게

Are you ready to order ?

 


5. I can tell : 보니까 알거 같아 / 보니까 그런거 같아

 

보다시피 잘 하진 못해.

네 그런것 같네요. 그거나 좀 주실래요?

 

Not good at this apparently

Yeah. I can tell. Can we have it though?

 

달라진거 알거 같아?

Can you tell the difference ?

응 너 머리잘랐네

Yeah, I can tell. you cut your hair

 

네 잡아보니까 차이를 알거같아요

Yeah. I can tell the difference holding it


6. go ahead : 먼저 하세요/ 그렇게 하세요 

 

A: 이거 버리려고

B: 그래 그렇게 해. 어차피 당신 그거 안쓰잖아

 

A: I was gonna thow it away

B: Go ahead. You never used it anyway

 


7. Here you go : 여기요

잔돈 건낼 때

 

*Here we go : 자 이제 가봅시다. 시작해 봅시다

 

   

 


8. Have a good one : 좋은하루 보내세요

말할 때보다 듣는 경우가 많으므로, 대답으로 "you too"(그쪽도요) 라고 하면 됨

 

A: Have a good one

B: You too

 


9. I'm down : 좋아요. 동의해요

 

A: 우리 그냥 이것들 크리스마스 때까지 24시간 걸어둘까?

B: 그래 난 찬성이야

 

A: Is it okay if we just have this hang in out for 24/7 until Christmas?

B: Yeah, I'm down 

 

피자먹으러 갈래?

I'm down

 

그거에 대해서는 확실히 동의해요

I'm down for that for sure

 


10. What's that ? : 뭐라고요? 뭐라고 하셨죠?  (+ Can you say that again?)

 

A: Sorry, what's that ?

B: Didn't you want me to keep talking?

 

 

*sorry? 잘못들었습니다 (끝을 올려줘야함)

 


 

11.  Sounds good :  좋은 생각이야

 

Sound : ~ 처럼 들린다

Sounds good I'm down.

 

오늘 커피한잔 하러 갈까? : Do you wanna go get some coffee today ? --> Sounds good


12. My bad : 아이고 미안합니다 (작은 실수에 대해 사과)

 

I'm sorry 보다 약한 표현

 

(문 밀고 당기는 상황에서 부딪칠뻔한 상황이나, 스마트폰 보다가 살짝 부딪치거다 부딪칠 뻔한 상황)

 

A: Oh, My bad

B: That's fine

 


13. It's(that's) fine : 괜찮아요

 

사소한 실수에 대해 괜찮다고 대답할 때 (식당에서 음식이 늦게 나와서 미안하다고 할때) ---> It's fine.

옷을 샀는데 어떠냐고 물어보면, 그럭저럭 괜찮다고 표현할 때 --> That's fine. That's OK

 


14. See you around : 나중에 보자. 또보자

 

그래 이제 가볼께 나중에 또보자: Alright I gotta get going we'll see you around


15. have fun : 재밌게 해 , 즐겨

 

상대방이 놀러간다고 했을때, "재밌게 하세요~"

 

Go have fun : 재밌게 노세요~


16. What do you mean ? : 무슨 뜻이야? 무슨 말이야?

 

A: It's not rocket science 

B: What do you mean (by that) ?

A: I mean it's not that much difficult

 

What do you mean by 'accidental'? : 우연이었다는게 무슨 말씀인가요?


17. I'm not sure : 확실하진 않아

 

영화 언제 개봉하는지 알아?

확실하겐 모르겠는데, 화요일인거 같아

 

A: Do you know when the movie is released ?

B: I'm not sure. but I think it's tuesday

 

뭔지는 모르겠는데, 이쁘네요

I'm not sure what that is, but it looks good 


18. please let me know : 알려주세요

 

If you ever need anything just let me know : 필요한거 있으시면 알려주세요

you guys got any questions just let us know : 질문있으시면 말씀하세요


19. No way : 말도 안돼? 진짜? 헐 대박

 

(약간) 놀랐을 때, 신기한 얘기 들었을 때


20. Take care : 잘 지내, 조심히 가, 몸 조심해

 

좋은하루 보내시구여 들어가요 : Have a wonderful day. Take care

 

 

 

 

 

 

 

 

 

 

 

 

출처: 유튜브 채널 '하루영어회화'

https://www.youtube.com/watch?v=puwNbyv5CmQ 

 

 

+ Recent posts