출처 : LLVM for Grad Students (Adrian Sampson) (일어번역판) 大学院生のためのLLVM

LLVM에 대해 개괄적으로 설명한 문서 중에 입문용으로 가장 적합한 것 같아서 번역합니다.

영어 원문과 일어 번역판을 동시에 참고해가면서 번역합니다.

 

본업이 따로 있기 때문에 주말에 틈틈히, 천천히 번역합니다. 원문에 있는 하이퍼링크들은 번역이 완료되면 여기에도 최대한 구현합니다.

 

 

-------------------------

 

 

이 글은 LLVM 컴파일러를 기반으로 리서치를 하고자 하는 사람을 위한 입문서입니다. 컴파일러에 대해 전혀 관심이 없는 사람도 LLVM을 즐겁게 사용하면서 좋은 성과를 낼 수 있을 것 입니다.

 

LLVM이란 무엇인가.

LLVM은 매우 훌륭하고, 해킹하기 쉬우며, 시대를 앞서가고 있는 C/C++과 같은 네이티브 언어를 위한 컴파일러입니다.

물론 LLVM이 훌륭하기 때문에 더 많은 기능에 대해 들을 수 있을 것 입니다.(JIT이 될 수도 있고 C계열이 아닌 언어에서 대응 가능하다든가, APP Store에서 새로운 배포 형태 라든가 등등...) 물론 전부 사실입니다만 이 글의 목표를 위해서는 위에 기술한 정의가 가장 중요합니다.

 

LLVM이 이 외의 컴파일러와 차별화되는 이유에는 몇개의 중요한 특징이 있습니다.

 

- LLVM의 중간표현(IR)은 훌륭한 혁신기술입니다. LLVM은 어셈블리 언어를 읽을 수 있다면 실제로 읽을 수 있는 프로그램 표현으로서 기능합니다. 이것이 대단하게 느껴지지 않을지도 모릅니다만 실제로는 대단한 것입니다. 다른 컴파일러들의 IR은 in-memory구조를 가지고 있어서 너무나 복잡하기 때문에 글로 쓰기 힘듭니다. 이것이 다른 컴파일러가 이해가기 어렵고 이식하는 것이 복잡한 이유입니다.

- LLVM은 잘 쓰여있습니다. 이것의 아키텍쳐는 다른 컴파일러보다 훨씬 더 모듈화 되어있습니다. 이런 장점이 가능했던 이유는 우리 중의 한명이기도 한 첫 개발자 덕분입니다.

- LLVM은 우리같이 이리저리 옮겨다니는 학문적인 hacker들의 리서치용 툴로 사용 될 뿐만 아니라 지구상에 가장 큰 기업에 의해 서포트되고 있는 산업적으로도 강한 컴파일러입니다. 이것은 자바에서 HotSpot까 Jikes사이에서 고민하듯이 훌륭한 컴파일러와 해킹가능한 컴파일러 사이에서 고민하지 않아도 된다는 것을 뜻합니다.

 

대학원생이 왜 LLVM을 신경써야 하는가

 LLVM은 좋은 컴파일러입니다. 하지만 컴파일러에 대한 공부가 아니라면 왜 이것을 신경써야 할까요?

 

컴파일러 인프라는 여러분이 프로그램에 관련된 무언가를 할 때마다 유용합니다. 내 경험에서 이런 경우는 매우 많죠. 당신은 프로그램이 얼마나 무언가를 자주 행하는지 분석하거나, 당신의 시스템에 맞춰서 더 효율적으로 일하도록 변경하거나, 당신의 새로운 아키텍쳐나 OS를 실제로 새로 칩을 찍어보거나 커널 모듈을 쓰지 않고도 마치 사용하고 있는 것 처럼 만들 수 있습니다. 대학원생에게 있어서 컴파일러 인프라는 사람들이 보증하는 것보다 더 적합한 수단입니다. 당신이 다음 툴들을 사용해야할 더 나은 이유가 있기 전까지는 LLVM을 기본적으로 사용해보길 바랍니다.

- 아키텍쳐 시뮬레이터

- Pin과 같은 dynamic binary instrumentation tool

- source-level transformation (sed와 같은 간단한 것에서부터 AST 파싱과 직렬화와 같은 것을 행하는 복잡한 툴들까지)

- system call들을 중간에 가로채기 위한 커널 해킹

- hypervisor 비슷한 무언가들

당신의 작업에 완벽하게 알맞지 않는 것처럼 보이더라도 source-to-source변환에 비하면 90%는 더 빨리 원하는 지점에 도달할 수 있습니다.

 

컴파일러와 깊은 관계까지는 아닌 연구 프로젝트에 LLVM을 적용해 효과적이었던 예는 다음과 같습니다.

- UIUC의 Virtual Ghost는 오류가 있는 OS kernel로부터 프로세스들을 보호하기 위해 컴파일러 패스를 사용할 수 있다는 것을 보여주었습니다.

- UW의 CoreDet는 멀티스레드 프로그램이 deterministic한 결과를 내도록 했습니다.

- 우리의 approximate computing 연구에서는 LLVM 패스를 프로그램에 에러를 내기 쉬운 하드웨어를 시뮬레이션 하는데 사용합니다.

 

다시 한번 강조하건대 LLVM은 단순히 새로운 컴파일러 최적화를 적용하기 위한 것이 아닙니다.

 

구성요소

여기에 그린 것은 LLVM 아키텍쳐의 주요 구성요소입니다. (모던 컴파일러 아키텍쳐이기도 합니다.)

Front End, Passes, Back End

여기에는

- 프론트 엔드 : 소스 코드를 중간 언어 혹은 IR로 불리는 언어로 변환시킵니다. 이 변환은 컴파일러의 나머지 부분이 해야 하는 일을 단순화 시킵니다. C++소스 코드의 복잡함을 더이상 고려하지 않아도 되기 때문이죠. 과감한 대학생인 여러분은 Clang을 수정하지 않고 사용함으로써 이부분은 해킹할 필요가 없을 것입니다.

- pass들 : IR에서 IR로 변환합니다. 일반적인 상황에서 패스들은 코드를 최적화합니다 - 즉, IR을 입력으로 받아 더 빠른 IR을 산출물로 내놓습니다. 이것이 여러분이 해킹해야하는 부분입니다. 여러분의 research용 도구는 컴파일 과정에 따라 IR을 따라가거나 바꾸게 됩니다.

- 백 엔드 : 실제 기계어 코드를 만들어내는 부분입니다. 이 부분은 건드릴 필요가 없습니다.

 

비록 이것이 근대의 대부분의 컴파일러의 구조라고 하더라도 LLVM만의 특별한 점은 봐 둘 필요가 있습니다. 프로그램들은 이 과정에서 동일한 IR을 사용합니다. 다른 컴파일러들에서 각 pass는 고유의 형태로 된 코드를 생성합니다. LLVM은 정 반대의 접근을 했고 이것은 해커들에게 매우 유용했습니다 : 우리는 우리의 코드가 어떤 환경에서 돌아가는 신경 쓸 필요가 사라졌습니다. 프론트엔드와 백엔드 사이의 어디쯤에서 돌아갈 것이란 것만 알면 됩니다.

 

 

시작하기

그럼 해킹을 시작해보도록 합시다.

 

LLVM 받기

LLVM을 설치해야 합니다. Linux 디스트리뷰션 중에는 LLVM와 Clang을 제공하는 것들이 있습니다. 하지만 당신이 해킹할 모든 헤더파일들을 가지고 있는 버젼인지 확인해야 합니다. Xcode에 따라오는 OS X빌드 같은 경우는 충분하지 않습니다. 다행스럽게도 CMake를 이용해 LLVM을 빌드하는 것은 ㅡ그다지 어렵지 않습니다. 일반적으로 LLVM자체를 빌드하기만 하면 됩니다 : 버젼이 맞는 한 시스템이 제공한 Clang이 잘 작동 할 것입니다. (물론 Clang을 빌드하기 위한 절차도 있습니다.)

OS X에 한해서는 Brandon Holt씨가 빌드를 잘 하기 위한 과정을 올려주었습니다. Homebrew formula또한 존재합니다.

 

레퍼런스를 읽읍시다.

문서들을 가까이 할 필요가 있습니다. 다음 링크들은 반복해서 참고할 만 합니다.

● 자동으로 만들어진 Doxygen 페이지는 매우 중요합니다. 여러분은 LLVM을 해킹하는 동안 조금이라도 나아가기 위해선 이 API 페이지들을 계속 파야 합니다. 이 페이지들은 검색이 힘드니 구글을 통해 들어가는 것을 추천합니다. 아무 함수나 클래스 이름에 'LLVM'을 붙여서 검색하면 Google은 보통 Doxygen 페이지를 찾아줍니다. (여러분이 조금만 부지런하다면 LLVM을 칠 필요도 없이 LLVM 결과를 맨 처음 가져오도록 만들 수도 있습니다!) 이것이 이상하게 들릴 수도 있습니다만, 살아남기 위해서는 LLVM의 API 문서 여기저기를 찾아다녀야 합니다 - 그리고 API를 찾아다니는 더 나은 방법을 저는 찾지 못했습니다.

● Language reference manual은 LLVM IR의 덤프를 보는데 문법이 헷깔린다면 참고하기 편합니다.

● programmer's manual은 LLVM 특유의 자료 구조의 toolchest를 설명하고 있습니다. 이는 효과적인 string, map이나 vector를 위한 STL의 대체재 등을 포함합니다. 또한 시시각각 마주치게 될 fast type introspection 툴들(isa, cast 그리고 dyn_cast)에 대한 설명도 있습니다.

● 여러분의 pass가 어떤 일을 할 수 있는지 궁금할 때마다 Wriring an LLVM Pass 튜토리얼을 읽는 것이 좋습니다. 여러분은 어디까지나 연구자이지 매일매일 컴파일러를 해킹하는 사람은 아니기 때문에 이 글의 몇몇 디테일에 관한 부분은 중요하지 않다고 봅니다. (가장 크게는 Makefile을 기반으로 한 빌드 시스템 명령을 스킵하고 바로 CMake를 기반으로 한 'out-of-source' 명령을 바로 보는 것이 좋습니다.) 하지만 그럼에도 불구하고 일반적인 pass에 관해서는 가장 고전적인 자료입니다.

● GitHub 미러는 온라인에서 LLVM소스를 보는데 편리합니다.

 

Pass를 만들어봅시다.

LLVM을 사용하여 생산적인 연구를 하기 위해서는 일반적으로 pass를 수정 할 필요가 있습니다. 이 섹션에서는 그때그때 프로그램을 변경할 수 있는 간단한 pass를 빌드하고 실행하는 과정을 설명합니다.

 

Skeleton

실용적이지 않은 LLVM pass가 있는 템플렛용 레포지터리를 만들어 놓았으므로 여기서부터 시작하겠습니다. 처음부터 시작하려면 build configuration의 설정이 어려울 수 있습니다.

GitHub에서 llvm-pass-skeleton 레포지터리를 clone합니다.

 

  1. $ git clone https://github.com/sampsyo/llvm-pass-skeleton.git

실제 작업은 skeleton/Skeleton.cpp파일에서 이루어집니다. 따라서 이 파일을 열어줍니다. 실제 작업이 진행되는 공간은 아래와 같습니다.

 

  1. virtual bool runOnFunction(Function &F) {
  2. errs() << "I saw a function called " << F.getName() << "!\n";
  3. return false;
  4. }

LLVM pass에는 여러 종류가 있습니다만, 우리는 function pass라는 pass를 사용합니다. (처음 시작하기에 좋은 pass입니다.) 여러분이 생각하는 바와 같이 LLVM은 우리가 컴파일하려는 프로그램에서 함수를 만날때마다 위 함수를 실행합니다. 지금은 단순히 이름을 프린트하기만 합니다.

 

추가 설명:

● err()라고 되어있는 것은 LLVM이 제공하는 C++ output stream으로 console창에 출력하는데 사용할 수 있습니다.

● 함수 F를 수정하지 않았기 때문에 false를 리턴합니다. 이후로 프로그램을 변형하는 경우에는 true로 리턴해야 합니다.

 

빌드하기

CMake를 이용해 pass를 빌드합니다.

 

  1. $ cd llvm-pass-skeleton
  2. $ mkdir build
  3. $ cd build
  4. $ cmake .. # Generate the Makefile.
  5. $ make # Actually build the pass.

LLVM이 전역으로 설치되어있지 않다면 CMake에게 어디에서 찾아야 하는지 지정해줘야 합니다. LLVM_DIR 환경변수 안에 LLVM이 있는 share/llvm/cmake/ 디렉터리 중 하나를 경로로 지정합니다. Homebrew의 경로의 예는 다음과 같습니다.

 

  1. $ LLVM_DIR=/usr/local/opt/llvm/share/llvm/cmake cmake ..

pass를 빌드하면 공유 라이브러리를 생성하게 됩니다. build/skeleton/libSkeletonPass.so나 플랫폼에 따라서는 그와 비슷한 이름에서 이를 찾아볼 수 있습니다. 다음 단계에서는 이 라이브러리를 불러와서 실제 코드 위에서 실행시켜 보겠습니다.

 

실행하기

새로운 Pass를 실행시키기 위해선 C 프로그램에서 clang을 불러와 방금 컴파일 한 공유 라이브러리를 가리키는 특수한 플래그를 사용합니다.

 

  1. $ clang -Xclang -load -Xclang build/skeleton/libSkeletonPass.* something.c
  2. I saw a function called main!

이 -Xclang -load -Xclang path/to/lib.so를 사용하면 Clang 상에서 여러분의 pass를 읽어와 활성화 시킬 수 있습니다. 보다 큰 프로젝트를 처리 할 필요가 있다면 Makefile의 CFLAGS나 사용 중인 빌드 시스템 상의 CFLAGS의 동등한 것에 이 argument를 더해주면 됩니다.

(clang에서 불러들이지 않고 pass를 한번에 실행하는 방법도 있습니다. 이는 LLVM의 opt 커맨드를 쓰는 것인데, 공식 문서에도 기술되어있는 것이지만 이 글에서는 다루지 않습니다.)

축하합니다. 컴파일러의 해킹이 완료되었습니다! 앞으로는 이 hello-world pass이 프로그램에 재미있는 동작을 하도록 확장시켜보겠습니다.

 

LLVM IR 이해하기

LLVM을 가지고 프로그램들을 다루기 위해서는 IR의 구조를 조금 알아야 합니다.

 
  • 모듈은 함수를 포함하고 이 함수들은 BasicBlock들을 가지고 있고 BasicBlock들은 명령들을 가지고 있습니다. 모듈을 제외한 것들은 Value에서 파생된 것들입니다.

 

컨테이너

LLVM 프로그램에서 가장 요소들의 개요는 다음과 같습니다.

● 모듈은 크게 봤을 때는 소스 파일, 전문적인 용어로는 translation unit을 의미합니다. 다른 모든 것은 모듈 안에 포함되게 됩니다.

● 가장 특징적인 것으로 모듈은 함수를 가지고 있습니다. 함수는 이름 그대로 실행 가능한 코드의 묶음입니다. (C++에서는 함수와 미소드 둘 다 LLVM 함수를 가리킵니다.)

● 함수명이나 인수의 선언 등은 제외하고, 함수는 주로 BasicBlocks들을 가지고 있습니다. Basic block은 컴파일러에서는 유명한 개념입니다만 우리의 목적을 위해서는 명령의 집합이라고만 알아둡시다.

● 그리고 이 명령은 단일 코드 연산자입니다. 추상화의 정도는 크게 RISC 계열의 기계언어와 같습니다. 명령의 예로는 정수의 덧셈, 실수의 나눗셈, 혹은 메모리에의 저장 등이 있습니다.

 

LLVM에서 대부분의 것-함수, BasicBlock, 그리고 명령 등을 포함하여-은 다방면에서 쓰이는 Value라는 클래스를 상속받습니다. Value는 숫자나 코드의 주소 등 계산에 사용될 수 있는 값들 모든 것을 포함합니다. 글로벌 변수나 정수('5'와 같은 리터럴들)도 Value 입니다.

 

명령

LLVM IR에서 사람이 읽을 수 있는 형식의 명령의 예는 다음과 같습니다.

 

  1. %5 = add i32 %4, 2

이 명렁은 (i32라는 타입에서 알 수 있는)32비트 정수 값 두개를 더합니다. %4가 가리키는 4번 레지스터 안의 숫자와 2가 가르키는 정수 2를 더합니다. 그리고 그 결과값을 5번 레지스터 안에 저장합니다. 이것이 제가 LLVM IR이 이상적인 RISC 기계어 코드처럼 보인다고 하는 이유입니다. 레지스터와 같은 동일한 용어를 사용합니다. 하지만 무한개의 레지스터가 존재합니다.

 

이 명령은 컴파일러 안에서 C++ 클래스인 명령의 인스턴스로서 나타납니다. 객체에는 명령 코드(opcode)가 있고 opcode는 덧셈, 타입, 그리고 다른 Value 객체의 포인터인 operand들의 리스트들을 가지고 있습니다. 위 명령의 경우, 이는 상수 객체인 숫자 '2'를 가리키고 다른 명령은 레지스터 %4를 가리킵니다. (LLVM IR이 static single assignment 형식을 가지고 있기 때문에, 레지스터와 명령들은 사실상 하나 뿐이고 같습니다. 레지스터 숫자는 텍스트로 표현하기 위해 인공적으로 만들어집니다.)

 

만약 당신이 만든 프로그램의 LLVM IR을 보고 싶다면 Clang을 이용해 이를 만들어낼 수 있습니다.

 

  1. $ clang -emit-llvm -S -o - something.c

 

Pass 안에서 IR 살펴보기

작업하고 있던 LLVM IR로 되돌아 가 봅시다. 우리는 dump()라는 일반적이면서 편리한 메소드를 통해 중요한 IR 객체들을 모두 살펴볼 수 있습니다. 이것은 사람이 읽을 수 있는 형태로 IR객체들을 출력해줍니다. 우리들의 Pass가 함수 단위를 가져오기 때문에 dump를 각 함수의 BasicBlocks, 그리고 각 BasicBlock들의 명령어들에 대해 반복하게 만드는데 사용 해 봅시다.

 

다음은 이 작업을 하기 위한 코드입니다. llvm-pass-skeleton의 git repository에서 체크아웃 하면 됩니다.

 

  1. errs() << "Function body:\n";
  2. F.dump();
  3.  
  4. for (auto& B : F) {
  5. errs() << "Basic block:\n";
  6. B.dump();
  7.  
  8. for (auto& I : B) {
  9. errs() << "Instruction: ";
  10. I.dump();
  11. }
  12. }

C++11의 멋진 자동 type과 foreach 문법을 사용하면 LLVM IR의 계층 구조를 더 간단하게 탐색할 수 있습니다.

 

pass를 다시 한번 빌드하고 이를 통해 프로그램을 실행한다면 여러 부분의 IR들이 우리가 직접 traverse하는 것처럼 분기하는 것을 볼 수 있습니다.

 

Pass를 이용해 좀 더 재밌는 것 하기.

 여러분이 프로그램에서 패턴을 찾아내고 이 패턴을 찾을 때 코드를 바꾸게 만들면 마법같은 일이 일어나게 됩니다. 간단한 예는 다음과 같습니다 : 우리가 모든 함수 안의 첫번째 binary operator(+, - 등)를 *로 바꿔본다고 합시다. 왠지 쓸모있을 것 같지 않나요?

그것을 하게 만드는 코드는 다음과 같습니다. 이 버젼은 실제로 실험해볼 수 있는 프로그램과 함께 llvm-pass-skeleton의 the mutate branch에서 가져올 수 있습니다.

 

  1. for (auto& B : F) {
  2. for (auto& I : B) {
  3. if (auto* op = dyn_cast<BinaryOperator>(&I)) {
  4. // Insert at the point where the instruction `op` appears.
  5. IRBuilder<> builder(op);
  6.  
  7. // Make a multiply with the same operands as `op`.
  8. Value* lhs = op->getOperand(0);
  9. Value* rhs = op->getOperand(1);
  10. Value* mul = builder.CreateMul(lhs, rhs);
  11.  
  12. // Everywhere the old instruction was used as an operand, use our
  13. // new multiply instruction instead.
  14. for (auto& U : op->uses()) {
  15. User* user = U.getUser(); // A User is anything with operands.
  16. user->setOperand(U.getOperandNo(), mul);
  17. }
  18.  
  19. // We modified the code.
  20. return true;
  21. }
  22. }
  23. }

 

해설:

● dyn_cast<T>(p)는 LLVM 고유의 introspection utility입니다. 동적 타입 테스트를 효율적으로 하기 위해 LLVM codebase에 있는 몇개의 convention 들을 사용합니다. 컴파일러들은 이런 convention들을 항상 지켜야만 합니다. 이 construct(dyn_Cast를 가리킴)는 이것이 Binary Operator가 아니라면 null pointer를 리턴합니다. 따라서 이런 경우에 사용하지 매우 좋습니다.

● IR Builder는 코드를 만들기 위해 사용합니다. 여기에는 여러분이 만드려는 코드들을 만들기 위한 수많은 방법들이 있습니다.

 

 

 

출처 : http://www.atmarkit.co.jp/ait/articles/1507/10/news028.html

 

이 기사에서는 MS가 제공하는 Cross Platform의 고기능 에디터 'Visual Studio Code'(이하 VSCode)에서 가능한 것, 조작의 기본에 대해 정리해 본다.

 

VS Code란 무엇인가.

VS Code는 Electron이라고 불리는 Web기술을 사용하여 '크로스 플랫폼 데스크탑 어플리케이션을 개발하기 위한 프레임워크'위에 구축되어 있다. VSCode의 특징으로서는 다음과 같은 것을 들 수 있다. 이에 더하여 버젼 1.0이후로는 일본어로의 로컬라이즈모 되어 있다.[각주:1]

 

Cross Platform / 경량 & 소속 / 디버그 기능 내장 / 표준으로서 다양한 언어 서포트 / IntelliSense 지원 / Git기능 지원 / Extension을 이용한 기능 확장 / Task 기능

 

VSCode의 큰 특징 중 하나는 여러 프로그래밍 언어(그리고 마크업)을 지원한다는 것이다.(표준으로 지원하고 있는 언어에 대해서는 공식 사이트의 'Languages'페이지를 참고) 즉 많은 언어에서 구문에 표시를 해 주거나 Intellisense에 의한 자동완성을 사용하여 쾌적한 코드 입력이 가능하다.

 

표준으로 지원되지 않는 언어더라도 Visual Studio Marketplace에서 검색하면 그 언어용 Extension을 발견할 수도 있다.(단, 지원 정도는 언어에 따라 다르다. 표준에서는 구문 하이라이트만 지원하는 언어가 많다. 이 경우 보다 좊은 기능을 제공하는 Extension을 Marketplace에서 찾아보면 좋다.)

또한, VSCode는 어디까지나 에디터이고 IDE는 아니다. 하지만 디버그 기능이나 Git 지원, Task(빈번히 사용하는 작업의 자동화)등의 기능이 포함되어 있기 때문에 코드의 편집 -> 어떠한 형태로의 컴파일/빌드 처리 -> 디버그 실행 -> 코드 편집 ->...->Git레포지터리로의 커밋/푸쉬까지의, 프로그래머가 일상적으로 행하는 작업을 1개의 에디터 내에서 완결시킬 수 있다.(실제로는 커맨트 프롬프트나 터미널과 조합하는 경우가 많겠지만.) (VSCode는)본가인 VS정도로 다양한 기능을 제공하고 있지는 않으나, 가벼운 환경에서 쾌적하게 개발작업을 행하는 것을 목표로 하고 있다고 할 수 있다.

 

이제부터는 Windows판의 VSCode를 기본으로, 필요하다면 MAC OS X(이하 OSX)/리눅스판(이 원고에서는 Ubuntu 15.10을 사용)의 VS Code에 대해 기술하도록 한다. (*다른 버젼에서는 이 기사와 설정이 다르기 때문에 유의할 점이 있을 수 있다.)

 

VSCode의 설치

VSCode의 바이너리는 Visual Studio Code 다운로드 페이지에서 다운로드 할 수 있다. 윈도우판, OSX판, Linux판(데비안, 우분투, 레드햇, 페도라, CentOS)가 있다. 이들에 대해 Stable판과 Insider판 두 종류가 제공되고 있다. 후자는 신기능이나 버그를 먼저 잡은 버젼이나 Stable판에 비해 동작이 불안정하거나 시험적으로 탑재된 기능이 최종적으로 변경될 수 있다. 두 버젼을 동시에 설치할 수도 있다고 하나 필자는 해본 적이 없다. 최신기능을 하루라도 빨리 체험해보고 싶은 사람이라면 Insider판을, 그렇지 않다면 월 1회정도의 페이스로 공개되는 Stable판을 이용하는 것이 좋을 것이다. 본 기사에서는 Stable판을 설치했다.

 

Window판은 설치파일을 다운로드 하면 그걸 실행 하면 끝난다. 실행하려면 시작 메뉴나 바탕화면에서 아이콘을 선택한다. 인스톨러의 옵션에서 path에 VSCode를 추가한 경우에는 커맨드 프롬프트에 code를 입력해도 VSCode가 실행된다.

 

(OSX, 리눅스 설명 생략)

 

 

 VSCode의 화면구성

그러면 다음으로 VSCode의 화면 구성과 기본적인 조작에 대해 알아보자. VSCOde에 이 기사를 편집하고 있는 화면은 다음과 같다.

VS Codeの画面構成

간단하게 설명하자면 뷰바(1)는 사이드바(2)에 표시할 요소를 선택하거나, 사이드바의 표시/비표시를 바꿀 수 있다. 에디터(3)은 프로그래머가 작업을 하는 중요한 영역이다. 최대 3개의 에디터를 동시에 표시할 수 있다. 스테이터스바(4)에는 여러 정보가 표시된다. 아래에서는 각각에 대해 조금 자세히 알아본다.

 

 

뷰바와 사이드바

VSCode의 윈도우 왼쪽 끝에는 뷰바가 있다. 여기서 바로 옆 사이드바에 표시될 정보를 선택한다. 대부분의 경우 익스플로러를 사이드바에 표시하게 될 것이다. 이 외에는 검색을 위한 '검색', Git관련 작업을 하는 'GIT', 디버그 관련 정보가 표시되는 '디버그'를 표시할 수 있다.

ビューバーとサイドバー

사이드바의 '익스플로러'에서는 파일이나 폴더를 연거나 닫고 하위 폴더를 보는 것이 가능하기 따문에 이 만으로도 파일의 조작이 가능하도록 되어있다. 또한 사이드바의 표시/비표시 여부도 뷰바에서 바꿀 수 있다. (예를들면 '익스플로러'가 '사이드바'에 표시하고 있는 상태로 이에 대응하는 아이콘을 뷰바에서 클릭하면 사이드바가 접힌다.)

 

위 화면에서는 '익스플로러'에 '작업 파일'과 'VSCODE'라고 하는 2개의 항목이 표시되어 있는데, 전자는 유저가 현재 작업하고 있는 파일이 폴더 계층구조와 무관하게 표시된다. (양쪽 모두에 표시되어 있는 vscode.txt는 같은 파일을 나타낸다) 이에 반해 VSCODE라고 하는 항목은 VSCode가 연 폴더 VSCode를 표현하는 것으로 이 아래에서는 VSCode폴더에 있는 파일(hogehoge.txt, vscode.txt, vsctest.cs, vsctest.js)가 표시되어 있다. VS Code에서 아직 폴더를 열고 있지 않은 경우에는 아래 화면처럼 '폴더를 열기'버튼이 있는데 이를 클릭하면 폴더를 열기 위한 다이얼로그가 생성된다.

[フォルダーを開く]ボタン

 

에디터

에디터는 동시에 3개까지 화면을 표시할 수 있다. 분할표시를 위해서는 에디터 오른쪽 위의 '에디터 분할' 버튼을 클릭하거나 '익스플로러'에서 표시하고 싶은 파일을 오른쪽 클릭 하여 context메뉴에서 '나란히 열기'를 선택한다.

エディターを3つ表示したところ

자동적으로 에디터가 분할표시되는 경우도 있다. (키보드 쇼트컷을 커스터마이즈 해 실행시킨다든가...) 이 경우에는 기존에 정해져있는 유저 설정대로 에디터가 표시된다.

또한 VSCode 1.1.0판부터는 사이드바나 에디터의 스크롤바가 경계부분을 더블클릭하면 사이드바 또는 분할표시되어 있는 에디터의 사이즈가 자동적으로 조정되게 되었다.

사이드바에 '익스플로러'가 표시되어 있을 때 이 작업을 하면 파일명이 생략되지 않도록 사이즈가 조정된다.

한편 사이드바에 검색이나 GIT, 디버그가 표시되어 있을 경우 이 작업을 하면 사이드바가 최소 사이즈가 된다. 에디터를 자동으로 사이즈 조정을 하면 분할되어 있는 파일에서 에디터 부분을 균등하게 나누도록 사이즈가 조정된다.

 

스테이터스바

스테이터스바의 왼쪽은 확장기능, GIT관련 정보, 디버그 실행시의 에러나 경고 등이 표시된다. 우측에는 편집중인 파일에 대한 커서의 위치, 그 문자 코드와 개행 문자[각주:2]의 종류, 파일의 종류, VSCode에 관련된 응답을 입력하는 화면을 여는 마크가 표시된다.

ステータスバー(左側)

<왼쪽 

ステータスバー(右側)

<오른쪽

 위의 그림의 스테이터스 바 왼쪽에는 확장기능 버튼, GIT의 브랜치 인디케이터, 리모트 레포지터리로의 푸쉬 버튼, 에러/경고의 수(여기서는 둘 다 0)가 표시되어 있다. 오른쪽에는 현재 커서의 위치, 인덴트를 탭으로 할지 공백문자로 할지와 인덴트 폭, 문자코드, 개행문자의 종류, 프로그래밍 언어, 힌트, 피드백용 아이콘이 표시되어 있다.

VSCode의 윈도우에는 이 외에도 필요에 따라 여러 영역이 표시된다. 이후로는 이에 대해 간단하게 소개하도록 한다.

 

커맨드 팔레트

먼저 키보드에서 CTRL+P(OSX에서는 command+P)를 누르면 VSCode 윗부분에 커맨드 팔레트가 표시된다. VSCode에서 실행 가능한 각종 커맨드에는 이름이 붙어있기 때문에 그 이름을 이 커맨드 팔레트에 입력하는 것으로 이를 실행시킬 수 있다.

예를 들어 커맨드 팔레트에 '>find'라고 입력하면 그와 관련된 각종 커맨드가 표시된다. 거기에서 커서 키를 사용해 하이라이트되어 있는 항목을 변경해 엔터 키를 누르면 커맨드를 실행할 수 있다. (마수를 사용해 선택해되 되지만 커맨드 팔레트는 키보드로부터 손을 떼고싶지 않은 사람들을 위한 기능이기 때문에 마우스 사용은 추천하지 않는다.)

コマンドパレットコマンドパレットに入力をしたところ

VSCode 1.1.0에서는 커맨드 파레트에 입력함에 따라 입력된 글자에 맞는 커멘드가 일본어와 영어로 표시되어 보기 좋게 되어있다. 두 언어 모두 검사하기 때문에 '>검색'이라고 입혁하든 '>find'라고 입력하든 상관 없다. (단, 매치되는 커맨드는 그 내용에 따라 달라진다. 흥미가 있는 분은 실제로 실험해보자.) 코딩시에는 반각영문자를 입력하는 경우가 대부분이므로 평소에는 영단어를 입력하는 것이 가장 추천할 만하다.

 

커맨드 팔레트는 거기에 입력하는 최초의 문자에 따라 동작아 바뀐다. 위에서 기술한 '>find'의 경우의 '>'가 그러하다. 이 경우 일반적인 에디터에서 지원하는 각종 커멘드의 실행이 가능하다. 선두문자로는 '>'가 아닌 'Q'.':'등도 사용할 수 있다. 이를 입력했을 때 커맨드 팔레트가 어떻게 동작하는지는 '?'를 입력하면 헬프가 표시되므로 참고하면 된다.

 

예를 들어 위 화면에서 커맨드 팔레트에 ':'를 입력하고 이어서 '1'을 입력하면 파일의 첫번째 줄이 표시된다. 그대로 엔터키를 누르면 '행1로 이동'커맨드가 확정되어 커서가 첫번째 줄로 이동한다.

 

한편 키보드의 CTRL+SHIFT+P키(OSX에서는 command+shift+p)를 누르면 >가 붙어서 커맨드 팔레트가 열린다. 에디터 커맨드를 입력하고 싶은 경우에는 한단계 빨리 실행시킬 수 있다. 또한 CTRL+G키로 ':'가 붙은 커맨드 파레트를 열 수 있다. G는 'Go'의 약자다.

 

문자 코드, 개행 문자, 파일 종류의 선택

스테이터스바의 오하단에는 현재 편집중인 파일의 문자코드가 표시된다. 여기를 마우스로 클릭하면 위 커맨드 팔레트와 같은 위치에 '액션 선택'이라고 쓰여있는 박스가 나온다. 선택할 수 있는 것은 'Reopen with Encoding'과 'Save with Encoding'이다. 커서 키를 사용해서 어느쪽을 선택하거나 영어 표기와 맞도록 문자를 입력해 엔터를 누른다. 어느쪽을 선택하든 이어서 문자 코드를 선택하는 드롭다운이 나오므로 문자코드를 선택하면 지정한 문자 코드로 파일을 재오픈하거나 파일을 보전할 수 있다.

 

文字コード部分(ここでは「Shift JIS」)をクリックする

 여기서 문자 코드 부분을 클릭

[エンコード付きで再度開く]を選択するか、「r」「reopen」などと入力してから[Enter]キーを押す

둘 중에 하나 선택

設定したい文字コードを選択する

설정하고 싶은 문자 코드를 선택

같은 방법으로 오른쪽 아래에 있는 개행문자를 클릭하면 이를 설정하든가, 그 오른쪽에 있는 파일의 종류를 표시(위 화면의 플레인 텍스트)를 클릭하여 현재 편집중인 파일의 종류를 지정하든지 할 수 있다.

 

이 기사 편집 시점에는 파일을 오픈할 때 문자코드를 해석/추측해주지는 않는다. 또한 VSCode의 디폴트 문자 코드는 UTF-8이다. SHIFT JIS파일이 다수 존재하는 현재 상황에서는 파일을 열면 글자가 깨져있는 경우도 많으리라 생각된다. 문자코드를 선택하는 방법은 처음에 알아두자. 또한 디폴트 문자 코드도 설정 가능하다(후술).

 

여기까지 VSCode의 화면 구성의 기본에 대해 알아보았다. 앞으로는 VSCode의 기본적인 조작방법에 대해 간단히 알아보기로 한다.

 

VSCode조작 가이드

여기서부터는 VSCode를 사용해가면서 기억해 두어야 할 기본 조작을 정리한다. 키보드 쇼트컷의 설정을 변경 가능한 항목에 대해서는 어느 항목을 설정하는 것이 좋은지도 기재하도록 한다.

 

VSCode의 실행과 종료

VSCode의 실행방법에 대해서는 위에서 설명했다. GUI로부터도 터미널이나 커맨드 프롬프트 등의 CUI로부터도 실행할 수 있다. CUI에서 실행 할 때에는 인수로 파일명이나 폴더명을 지정할 수 있다. 이 경우 지정한 파일 또는 폴더가 오픈된 상태로 VSCode가 실행된다. 인수로 여러개의 파일/폴더를 지정하는 것도 가능하다. 

 

VSCode의 종료 방법은 다른 응용 프로그램들과 동일하다. Windows/Linux판에서는 커맨드 팔레트에서 'Close Window'커맨드를 실행 해 최후의 윈도우가 닫힌 시점에서 VSCode가 종료된다.

 

(중략)

 

파일 / 폴더의 열기/닫기

VSCode 내의 파일/폴더를 열고 닫기 위한 커맨드의 종류를 아래에 정리한다. 'Files:'등의 Prefix를 입력하지 않고 바로 close등을 입력하면 커맨드 팔레트에 적당한 후보군이 표시되는 점은 기억해 두도록 한다.타자수를 줄일 수 있다. 파일 관계 커맨드에 무엇이 있었는지 궁금할 때 File등을 입력해보면 좋다.

또한 이하 표의 Ctrl+L -> Ctrl+W등의 동작은 Ctrl을 누르고 있으면서 K키와 W키를 누르는 것을 의미한다. 한편, Ctrl+K -> W등의 동작은 Ctrl키와 K키를 동시에 누른 후 W키를 단독적으로 누르는 것을 뜻한다. 커맨드 팔레트나 'command'지정에 커맨드가 2종류 써져 있는 경우는 앞이 Windows/Linux, 후자가 OSX다.

 

 
操作 コマンドパレット Win/Linux OS X "command"指定
파일 열기 Files: Open File/Files: Open [Ctrl]+[O] [Command]+[O] "workbench.action.files.openFile"/
"workbench.action.files.openFileFolder"

파일 닫기

Files: Close File [Ctrl]+[K]→[W] [Command]+[K]→[W] "workbench.files.action.closeFile"

모든 파일 닫기

Files: Close All Files [Ctrl]+[K]→[Ctrl]+[W] [Command]+[K]→[Command]+[W] "workbench.files.action.closeAllFiles"
폴더 열기 Files: Open Folder/Files: Open [Command]+[O] "workbench.action.files.openFolder"/
"workbench.action.files.openFileFolder"
폴더 닫기 File: Close Folder [Ctrl]+[K]→[F] [Command]+[K]→[F] "workbench.action.closeFolder"
 

(중략)

'폴더 닫기'만은 커맨드 팔레트의 영어 커멘드의 Prefix가 Files:가 아닌 File:이 되어 있음에 유의하자.

 

또한 사이드바의 익스플로러에서도 마우스 등을 사용해 파일/폴더의 열기, 닫기, 생성, 보존 등을 할 수 있다. 개별 파일이나 폴더를 우클릭하면 표시되는 컨텍스트 메뉴에도 많은 기능이 있으므로 파일 관련 작업을 터미널, 커맨드 프롬프트, 익스플로러, Finder등의 윈도우들을 바꾸지 않고 할 수 있다는 점은 편리하다.

 

커서의 이동

커서의 이동은 Windows/Linux판과 OSX판이 크게 다르다 필자의 환경에서는 OSX에서는 Ctrl+P,N,F,B키로 커서가 상하좌우로 이동한다. 이에 반해 Windows/Linux판에서는 커서의 상하좌우는 커서키를 사용하도록 되어있다(디폴트 상태). 아래에 주요 커서 이동 키를 표시한다. (중략)

 
操作 Win/Linux OS X "command"指定
1행 위로 [↑] [Ctrl]+[P]/[↑] "cursorUp"
1행 아래로 [↓] [Ctrl]+[N]/[↓] "cursorDown"
1글자 왼쪽으로 [←] [Ctrl]+[B]/[←] "cursorLeft"

1글자 오른쪽으로

[→] [Ctrl]+[F]/[→] "cursorRight"

커서가 위치한 단어의 맨 왼쪽으로

[Ctrl]+[←] [Option]+[←] "cursorWordStartLeft"
커서가 위치한 단어의 끝으로 [Ctrl]+[→] [Option]+[→] "cursorWordEndRight"

커서를 줄의 맨 앞으로

[Home] [Ctrl]+[A]/[Command]+[←]/[Home] "cursorHome"

커서를 줄의 맨 끝으로

[End] [Ctrl]+[E]/[Command]+[→]/[End] "cursorEnd"

커서를 파일의 맨 앞으로

[Ctrl]+[Home] [Command]+[↑] "cursorTop"
커서를 파일의 맨 끝으로 [Ctrl]+[End] [Command]+[↓] "cursorBottom"
カーソル移動キー

Shift키를 누른 상태로 위의 키 조작을 하면 이동한 범위가 선택상태가 된다. 이 외에 커맨드로서 존재하지만 단축키는 존재하지 않는 것으로 cursorWordLeft/cursorWordRight등이 있다. 잘 사용한다면 단축키로 설정하는 것이 좋다.

 

문자/행의 삽입과 삭제

VSCode는 Vim계통의 에디터가 아니기 때문에 키보드를 치면 평범하게 커서 위치에 그 문자기 입력된다. 아래에서는 문자의 삭재, 행의 삽입에 관련된 것을 정리한다. 커맨드 팔레트에서 실행하게되는 것도 있다.

操作 Win/Linux OS X "command"指定
커서 오른쪽의 1글자 삭제 [Delete] [Ctrl]+[D] "deleteRight"

커서 왼쪽의 1글자 삭제

[Backspace] [Delete]/[Ctrl]+[H] "deleteLeft"

커서의 오른쪽을 전부 삭제

[Ctrl]+[K]/[Command]+[Fn]+[Delete] "deleteAllRight"

커서의 왼쪽을 전부 삭제

[Command]+[Delete] "deleteAllLeft"

커서가 있는 줄을 전부 삭제

[Shift]+[Ctrl]+[K] [Shift]+[Command]+[K] "editor.action.deleteLines"

커서의 윗 행에 삽입

[Shift]+[Ctrl]+[Enter] [Shift]+[Command]+[Enter] "editor.action.insertLineBefore"

커서의 윗행에 삽입

[Ctrl]+[O] "lineBreakInsert"
커서의 아래 행에 삽입 [Ctrl]+[Enter] [Command]+[Enter] "editor.action.insertLineAfter"

(중략)

 

멀티 커서

멀티커서란 이름 그대로 1개의 에디터 내에서 복수개의 커서가 표시되는 기능이다. (2개째 이후의 커서는 선이 얇아진다.) 커서를 복수개 표시하는 방법은 몇가지 있다.

- Ctrl+Alt+↑/↓의 각 키로 현재 커스의 위(혹은 아래)의 행에 커서를 삽입한다.

- 현재 커서 위치에 있는 단어와 같은 단어 전부를 Ctrl+F2키로 동시에 선택한다. 그 단어를 한번에 바꿀 수 있다.

처음의 방법으로는 복수개의 커서가 컨텍스트에 맞춰 동작한다. 즉, 커서를 여러개 표시한 후 어느 동작을 할 것인가에 대해 생각하지 않아도 된다.

 

[Shift]+[→]キーを4回押す
[Shift]+[→]キーを4回押す
それだと「phone」の「e」が選択できない
それだと「phone」の「e」が選択できない
[Shift]+[Ctrl]+[→]キーを使うと「e」まで選択できる
[Shift]+[Ctrl]+[→]キーを使うと「e」まで選択できる

マルチカーソルの使い方(1)
最初の画像では、「name: name」の右側の「name」の先頭にカーソルを置き、[Ctrl]+[Alt]+[↓]キーを2回押して、合計3つのカーソルを表示している。
次の画像では[Shift]+[→]キーを4回押して、カーソルを4文字右に移動して、選択状態にしている。パラメータ名の文字数が違うので、このままではうまく全てのパラメータ名を選択できない。

そうではなく、3番目の画像のように、[Shift]+[Ctrl]+[→]キーを押すことで、カーソルを1語右に移動して、単語全体を選択する。「1語右」という操作により、全ての識別子を選択できた。 

이 예와 같이, 문자단위의 이동이 아닌 단어단위의 이동을 함으로써 문자수가 다른 식별자를 자연스럽게 선택할 수 있다. 어떤 이동 커맨드를 사용하면 좋을지에 따라 사용하는 것이 달라지기 때문에 처음에는 고민을 많이 하게 될 것이다.

 

「phone」にカーソルを合わせて、[Ctrl]+[F2]キーを押す
「phone」にカーソルを合わせて、[Ctrl]+[F2]キーを押す「tel」と入力すると全てが書き換えられる「tel」と入力すると全てが書き換えられるマルチカーソルの使い方(2)

 

이 그림에서 알 수 있는 것처럼, 해당하는 단어를 한번 입력함으로써 한번에 변경할 수 있다. 단, 같은 것을 'addr'에 대응해서 하게되면 인수나 프로퍼티명 뿐이 아니라 함수명에 포함되는 'Addr'까지 대상이 되어버린다. 예상 밖의 부분까지 변경될 수 있기 때문에 주의가 필요하다.

 

이와 같이 처음엔 멀티커서를 사용하는 것이 어려울지도 모르지만 손에 익숙해져 빠르게 사용할 수 있도록 하자.

 

커스터마이즈, 기초 중의 기초

본 원고에서는 마지막으로 VSCode의 커스터마이즈의 기본에 대해 알아보자. VSCode에서는 다음의 5가지 방법으로 커스터마이즈를 할 수 있다.

1.유저 설정 2.워크스페이스 설정 3.키보드 쇼트컷 4.snippet 5.확장기능

 

유저설정/워크스페이스 설정

유저설정은 유저별로 개별 설정을 해 VSCode에서 공통적으로 사용된다. 이에 대해 워크스페이스 설정은 열고있는 폴더별로 고유의 설정을 하게 된다. 이들은 메뉴의 파일 - 기본 설정 - 유저설정 혹은 워크 스페이스 설정을 선택 해 설정할 수 있다.

유저설정은 그 유저 단독의 VSCode 기본설정이다. 워크스페이스 설정은 현재 열고있는 폴더(프로젝트, 워크스페이스)에 관한 설정을 한다. 워크 스페이스 설정에서 유저 설정을 덮어쓰는 것도 가능하다. 이 프로젝트에서는 개별적으로 이런 설정을 하고싶다-같은 경우 워크스페이스 설정을 하도록 하자. 메뉴에서 위에 기술한 유저설정 혹은 워크스페이스 설정을 선택하면 대부분 아래와 같은 화면이 나올 것이다. 이것은 유저설정을 하고 있는 부분이다. 왼쪽의 에디터 그룹에는 디폴트 설정을, 왼쪽의 에디터 그룹에서는 유저 설정을 표시한다.

 

여기에서는 80글자에서 자동 줄바꿈을 하는 기능("editor.wrappingColumn": 80)과 디폴트 문자 코드를 SHIFT JIS로 하도록 설정("files.encoding": "shiftjis")하고 있다. 이와 같이 설정은 JSON형식으로 기술한다.

디폴트 설정이 표시되고 있는 에디터에서 검색바를 표시해(Ctrl+F) 설정하고 싶은 항목과 관계 있는 문자열을 입력해 검색한다. 발견했다면 그 위에 있는 커맨드를 참고 해 유저 설정(혹은 워크 스페이스 설정) 파일에 커스터마이즈 내용을 기술하도록 한다.

위에서 본 자동 줄바꿈 위치와 디폴트 문자 코드 외에는 다음과 같은 요소들을 기억하면 좋을 수 있다. 또한 자바스크립트나 CSS와 같은 개별 언어나 기술용의 설정들에 대해서는 Prefix가 붙어 있으므로 이들을 키워드로 삼아 디폴트 설정을 검색해가도 좋을 것이다.

 
設定内容 対応する設定項目
フォントファミリー "editor.fontFamily" "editor.fontFamily": "メイリオ"
フォントサイズ "editor.fontSize" "editor.fontSize": 14
行番号表示 "editor.lineNumbers" "editor.lineNumbers": false
タブ幅 "editor.tabSize" "editor.tabSize": 4
ユーザー設定/ワークスペース設定でカスタマイズ可能な要素(ほんの一部)

키보드 쇼트컷

키보드 쇼트컷은 유저 고유의 설정이다. 여기에서는 입력한 키스트로크/실행하는 커맨드/그 커맨드를 실행하는 조건에 대해 설정한다. 여기에서는 키스트로크를 실행하는 커맨드를 중심으로 살펴본다.

또한, 조건이라고 하는 것은 어떤 키스트로크에

 

 

(이후 추가 예정)

  1. 한국어로도 되어 있음. [본문으로]
  2. https://ko.wikipedia.org/wiki/%EC%83%88%EC%A4%84_%EB%AC%B8%EC%9E%90 [본문으로]

+ Recent posts