2019-11-27 작성

[Book] 프로그래밍 언어도감(3) C 언어

목차: C 계열 언어

  • C
  • C++
  • C#
  • D
  • Objective-C  
  • Swift
  • Rust
  • Go

C

  • 탄생 : 1972년
  • 주요 용도 : 게임, 임베디드, 교육
  • 분류 : 절차형/컴파일러

고속 : OS나 디바이스 등 메모리나, CPU 등을 직접 이용하는 시스템 개발에 사용되는 경우가 많다. 게임이나 임베디드 기기와 같이 빠른 처리속도가 필요한 경우에도 사용된다.

 컴파일러 : 많은 프로그래밍 언어의 컴파일러가 C로 개발되어 있다.

사용 방법을 틀리면 위험 : Buffer overrun 같은 취약점이나, 메모리 누수(memory leak) 등 개발자가 제대로 이해하고 사용해야 한다.

이식성 : 특정 플랫폼에 의존한 부분을 언어에서 분리해서 개발하고 있기 때문에 프로그램의 이식이 비교적 쉽다. 다만 이식할 때는 재컴파일이 필요하다.

임베디드 : 가전제품이나 자동차의 제어장치에 사용되고 있는 임베디드 기기처럼, CPU나 메모리 같은 리소스에 여유가 적은 환경에서 실행되는 것에 사용된다.

포인터 : 변수나 함수의 주소를 가리키는 값을 보존하는 변수이다. 함수 호출의 인자로 포인터를 전달하기 때문에, 큰 사이즈의 변수나 복잡한 구조를 가진 구조체라도 확보하는 메모리는 포인터의 사이즈만으로 충분하다.

C++

  • 탄생 : 1983년
  • 주요 용도 : 게임, 임베디드, 교육
  • 분류 : 절차형 객체지향형/컴파일러

 C언어에 객체지향 추가 : C언어에 대해 상위 호환성이 있고, C언어처럼 절차형 프로그래밍도 할 수 있다. 객체지향형이라서 대규모 프로그램의 개발에도 적합하다. C++는 대규모 소프트웨어에서 빠른 속도로 요구되는 게임 개발에 필수적이다.

GC가 없다 : Java, C#에서는 자동 메모리 관리 기능이 있지만, C++ 에는 존재하지 않기 때문에 메모리 누수가 발생할 수 있다.

다중 상속 가능 : Java, C#에서는 단일 상속만 가능하지만, C++에서는 여러 개의 클래스를 상속할 수 있다. 

make 빌드 툴 : C언어나 C++을 이용해서 프로그램을 작성한 경우, 컴파일을 할 때 필요한 파일로 소스코드, 헤더 파일, 링크하는 라이브러리 등을 지정할 필요가 있다. 규모가 커지면 매번 지정하는 것이 힘들어지기 때문에 빌드 툴이 사용된다. make는 현재 많은 프로그램에서 사용되는 빌드 툴이다.

 STL : Standard Template Library. C++의 표준 라이브러리. 컨테이너, 이터레이터, 알고리즘이 포함되어 있다.

Boost : 차기 C++ 표준으로 불리는 오픈소스 라이브러리. 벡터, 행렬, 문자열 처리 등 다양한 기능을 갖추고 있다. 무료 사용 가능하고 GPL처럼 소스코드의 공개 의무도 없다.

Qt : X Window System이나 Windows, macOS 등의 다양한 환경에서 실행할 수 있는 GUI를 갖춘 애플리케이션을 같은 소스코드로 개발할 수 있는 프레임워크

C#

  • 탄생 : 2000년 (Microsoft)
  • 주요 용도 : Windows, 웹, 모바일 앱 개발
  • 분류 : 절차형 함수형 객체지향형/컴파일러

좋은 점만 취하기 : Java, Delphi, C++, Visual Basic 등 언어에서 좋은 점만 잘 조합해서 만들어졌다. Windows에서 사용되고 있는 .NET의 표준 언어로, 언어 사양이 공개/표준화되어 있다.
 사용하기 쉬운 개발 환경 : Visual Studio 같은 통합 개발 환경이 있어서 초보자도 쉽게 개발할 수 있다.

폭넓은 환경에 대응 : Windows 앱, ASP, .NET의 웹 앱, 스마트폰의 앱까지 폭넓게 개발할 수 있다.

 .NET Framework : Microsoft가 개발한 애플리케이션 개발 및 실행 환경. .NET Framework에 대응한 언어로 작성한 소스코드는 공통 중간 언어(CIL)로 컴파일되어 공통 언어 기반(CLI)으로 실행된다.

Xamarin : Android, iOS의 앱 개발에 사용할 수 있는 라이브러리 개발 환경. 일반적으로 Android의 앱은 Java, iOS의 앱은 Objective-C, Swift를 사용하는데, 이 언어들을 따로 배우지 않고 C#만으로 어느 쪽 앱이든 만들 수 있다.

Unity : Windows, macOS로 동작하는 통합형 게임 개발 환경에서 C#으로 코딩한다. 앱(Android/iOS) 혹은 데스크톱 앱(Windows, macOS) 혹은 게임기(Wii U/Play Station/Xbox 360)에서도 동작하는 3D 애플리케이션을 작성할 수 있다.

D

  • 탄생 : 2001년
  • 주요 용도 : 데스크톱 앱, 게임, 웹앱
  • 분류 : 절차형 함수형 객체지향형/컴파일러

C, C++에서 더 향상됨D는 외적으로는 C, C++와 비슷하지만, 서로 간의 소스코드 호환성은 없다. C++ 문제점을 해결할 수 있도록 설계되어 있고(메모리 누수 같은), C언어처럼 OS의 API나 하드웨어에 직접 접근하는 기능도 제공한다. 객체지향형이나 함수형도 지원하고 있다.

 별명을 붙일 수 있다 : 변수, 함수, this 키워드 등에 별명을 붙일 수 있는 'Alias' 기능이 있다.

유닛 테스트 지원 : unittest 키워드가 붙은 구문을 쓰면, 컴파일 시 유닛 테스트의 실행을 지정할 수 있다.

 DUB : D언어 개발 툴, 패키지 관리 툴. 의존 관계를 자동적으로 취득하고, 쉽게 커스터마이즈 할 수 있도록 설계되어 있다. 다양한 패키지를 간단하게 도입, 업데이트할 수 있다.

 계약 프로그래밍 : 프로그램이 충족해야 할 사항을 소스코드 안에 기술해서, 만약 사양을 위반하면 예외를 생성하는 것으로 설계의 안정성을 높인다.

SafeD : C언어의 미정의 동작이나 포인터 같은 안전성을 위협하는 부분을 배제하고, 개발자가 쉽게 학습할 수 있도록 작성된 D언어의 부분 집합이다.

Objective-C 

  • 탄생 : 1983년
  • 주요 용도 : iOS/macOS의 앱
  • 분류 : 절차형 객체지향형/컴파일러

Apple이 선택한 iOS/macOS의 개발 언어 : C언어에다가 객채지향형을 '특수한 처리'로 확장하고 있다. 따라서 소스코드에 특별한 표기가 등장하지만 C언어를 그대로 사용할 수도 있다. 멤버 함수의 주소가 실행 시에 결정되고, 클래스가 확장하는 등 스크립트 언어와 같은 유연성이 있다. 다만, 현재는 'Swift'로 바뀌고 있다.

클래스 메서드 & 인스턴스 메서드 : 메서드명 앞에 '-'을 추가하면 인스턴스를 생성해서 사용하는 인스턴스 메서드가 디고, '+'을 추가하면 인스턴스 생성이 불필요한 클래스 메서드가 된다.

@으로 시작하는 컴파일러 디렉티브 : 클래스 선언이나 접근 제어자에 컴파일러 지시문을 사용한다. 예를 들어 '@ interface' '@ end'와 같이 @마크로 시작한다.

Smalltalk와의 융합 : Smalltalk에서 유래된 '메시지 송신'을 사용해서 객체를 조작한다. '프로토콜'로 불리는 방법을 정의할 수 있고, Java 등의 인터페이스에 해당한다.

 Xcode : macOS 상의 통합 개발 환경. Mac App Store에서 무료 다운로드 할 수 있고 Objective-C, Swift, Java, AppleScript 등도 컴파일이 가능하다.

NS : 1980~1990년대에 사용된 NeXT 라는 컴퓨터의 개발에 사용된 OS 인 'NeXTSTEP'의 약어. Next Computer는 Apple을 퇴사한 스티브 잡스가 창업했던 회사로 지금도 macOS는 이 흐름을 이어받고 있고, 많은 클래스의 슈퍼 클래스인 NSObject 인 것처럼 'NS'라는 문자가 자주 등장한다. 

Cocoa : macOS 용인 애플리케이션을 개발할 때에 사용되는 프레임워크. iOS용인 앱 개발에 사용되는 'Cocoa Touch'도 있고 모두 Xcode를 사용해서 개발을 한다.

Swift 🔥

  • 탄생 : 2014년
  • 주요 용도 : iOS/macOS의 앱
  • 분류 : 절차형 함수형 객체지향형/컴파일러

Apple이 밀고 있는 최신 언어 : iOS, macOS를 위해 개발된 언어로, Objective-C에 비해 학습 비용이 낮다. 또한 Objective-C로 작성된 클래스를 Swift에서 호출하는 등, 기존 코드와 공존할 수 있기 때문에 과거의 자산도 활용할 수 있다. 메모리 자동 관리나 변수의 초기화 등으로 Objective-C에 비해 안전성도 향상되고 있다.

안전성 중시 : 개발자의 의도치 않은 작동을 방지하기 위해, 정적인 자료형 체크나 변수의 초기화 강제, 수치형 오버플로우 검사, 자동 참조 횟수에 따른 메모리 관리 등이 있다.

현대적인 기능 : 최근 등장한 언어이기 때문에 다른 언어에 비해 클로저, 튜플, 제네릭 프로그래밍, Optional 타입 같은 현대적인 기능이 있다.

대화형으로 사용 가능 : REPL(Read-Eval-Print Loop)을 통해 콘솔에서 대화형으로 처리되는 값을 확인하는 것도 가능하다. 따라서 디버깅도 쉽게 되어 있다.

 오픈소스화 : Swift 소스코드가 공개되었다. Apple 제품뿐만 아니라 Linux 환경이나 웹 애플리케이션의 개발에도 사용할 수 있게 되었다. Apache 2.0 오픈소스 라이선스로 제공되어 있기 때문에, Swift를 자신의 소프트웨어에 통합할 수도 있다.

Swift Playgrounds : iPad용 앱으로 제공되는 실행 환경. Xcode의 Playground처럼 사용할 수 있다. Swift의 동작이나 로직의 확인이 가능할 뿐만 아니라, 어린이를 위한 학습 환경으로 사용할 수 있도록 배려되어 있다.

LLVM : 모든 프로그래밍 언어에 대응 가능한 컴파일러 모듈. 컴파일 및 실행 등을 할 때 빠르게 실행할 수 있도록 최적화 되어 있다. Swift와 Objective-C는 LLVM에서 동작한다.

Rust

  • 탄생 : 2010년 (Mozila)
  • 주요 용도 : 시스템 프로그래밍 영역
  • 분류 : 절차형 함수형 객체지향형/컴파일러

OS 개발 : 안정성, 고속, 병렬실행 등의 특징이 있으며 OS 개발에 사용되고 있다. 하트웨어에 가까운 시스템 개발과 네트워크를 이용하는 서버-클라이언트 프로그램을 작성하는 데 유용하다. Firefox의 일부에는 Rust 코드가 포함되어 있다.

변수에 소유권이 있다 : Rust는 자원에 대한 속박이 하나만 존재하는 것을 방지하기 위해, 다른 변수로 속박하면 원래의 변수는 사용할 수 없게 된다. (컴파일 에러). 함수의 인수로서 무언가를 전달 후에도 그것을 사용하려고 하면 에러가 발생한다.

설정에 사용되는 TOML : 컴파일러에 지시 등을 설정 파일에 저장하는 프로그래밍 언어가 많다. 언어에 따라서 XML, YAML INI, JSON 등 파일의 종류가 다양하다. Rust는 설정에 INI 파일과 유사한 'TOML'를 사용한다. 

trait : 자료형에 대한 메서드의 집합. 특정 자료형에 대한 메서드가 아니라, 모든 자료형에 적응하는 메서드의 집합을 정의할 수 있고 자료형에 대해서 trait을 구현할 수 있다.

Iron, nickel, Rustful : Rust로 만들어진 웹 프레임워크. 라우팅 기능을 중심으로 플러그인이 준비되어 있다. 모두 "Hyper"라는 HTTP 라이브러리를 사용하고 있다.

Cargo : Rust에서 빌드 및 패키지를 관리하는 소프트웨어. Cargo 커맨드로 패키지 작성, 빌드, 인스톨, 의존관계 검사 등을 실행할 수 있다.

Go

  • 탄생 : 2009년
  • 주요 용도 : 웹앱
  • 분류 : 절차형 객체지향형/컴파일러

코드 스타일 통일 : if문에서 중괄호를 새로운 행에 쓰면 문법 오류로 취급된다. 삼항 연산자를 사용할 수 없다. 이처럼 스타일을 통합하기 쉽다. 'go fmt' 커맨드를 사용하면 표준 스타일로 수정할 수 있다. "불필요한 것은 피하고 간단하게 만드는 것이 품질이 좋은 코드를 만든다"는 철학이 있다.

유닛 테스트를 표준으로 갖추고 있다 : 소스코드안의 모든 경로를 테스트했는지 코드 커버리지를 조사하는 것도 가능하다.

쉬운 크로스 컴파일 : Linux에서 Windows의 바이너리를 만들 수 있고, Mac에서 Linux의 바이너리를 만들 수 있는 등 컴파일 시의 실행 환경을 지정할 수 있다. 이 때문에 프로그램의 배포가 쉬워진다.

 특수한 객체지향 : Go에는 클래스라는 개념은 없다. interface를 사용하지만 어떤 구조로 인터페이스를 사용할지는 정의하지 않았다. 어떤 인터페이스로 정의된 메서드를 가진 자료형은 그 인터페이스를 구현하고 있는 것으로 간주된다.

Docker : 컨테이너형 가상화 소프트웨어. 고속으로 기동해 다양한 환경에 운반할 수 있어서 많은 상황에서 사용된다. Docker의 개발에도 Go가 사용되고 있다.

 Go 루틴 : 경량 스레드에 의한 병행처리를 위해 한 개의 프로세스 안에 대량으로 생성할 수 있다. 함수 호출 전에 'go'를 붙이는 것만으로 해당 함수를 비동기로 실행할 수 있다. 이것에 의해서 CPU에 맞춘 복수의 스레드에 할당되어 멀티 코어를 활용할 수 있다.

Go 커맨드 : Go로 사용할 수 있는 패키지 다운로드나 인스톨, 소스코드의 빌드나 테스트 등을 실행할 수 있는 커맨드, 의존관계 조사 등도 자동으로 실행할 수 있다.