Why

만약 당신이 독학 엔지니어나 부트캠프 졸업생이라면 컴퓨터 과학을 배우는 것도 놓쳐서는 안됩니다

세상에는 두 부류의 소프트웨어 엔지니어가 있습니다. 첫 번째 부류는 컴퓨터 과학을 깊이 이해하고 도전적이고 혁신적인 일을 수행하는 엔지니어들입니다. 이들은 시간이 지나면서 중요한 상업 프로젝트나 오픈소스 프로젝트에서 성취감을 느끼고, 기술적 리더십을 쌓으며, 더 높은 보수를 받습니다.

두 번째 부류는 특정 툴이나 기술에만 집중하며, 기초를 깊이 이해하지 못한 채 표면적으로만 기술을 익힙니다. 시간이 지나면서 이들에 대한 고용 기회는 감소하고, 중요한 일에서 배제될 가능성이 큽니다. 고용 안정을 원하거나 첫 번째 부류의 엔지니어가 되고 싶다면, 컴퓨터 과학을 깊이 배우는 것이 중요합니다.

Teach Yourself CS 내용 발췌

그런데 이 말이 진짜일까? 

위 책내용에 대해서 본격적으로 들어가기 전에 간단히 Typescript 에서 소개해주는 내용도 봤습니다 (이것도 스터디로 진행)

  • 프로그래밍 언어
  • 새로운 타입스크립트 고유 구문이 포함 됨
  • 타입 검사기
  • 파일에서 생성된 변수 함수를 이해하고 잘못된 부분을 알려 주는 프로그램
  • 컴파일러
  • 자바스크립트 코드를 생성 해주는 프로그램
  • 언어 서비스VS code 와 같은 편집기에 유용한 유틸리티 제공법을 알려주는 프로그램

3개의 프로그램과 타입스크립트 고유 구문으로 이루어져 있습니다

https://www.huy.rocks/everyday/04-01-2022-typescript-how-the-compiler-compiles

타입스크립트 컴파일러가 동작하는 방식, 즉 tsc 명령어를 눌렀을 때 일어나는 작업은 크게 아래와 같이 나눠볼 수 있습니다

  1. tsconfig 읽기: 타입스크립트 프로젝트라면, root에 tsconifg.json을 읽는 작업부터 시작할 것이다.
  2. preprocess: 파일의 root 부터 시작해서 imports로 연결된 가능한 모든 파일을 찾는다.
  3. tokenize & parse: .ts로 작성된 파일을 신택스 트리로 변경한다.
  4. binder: 3번에서 변경한 신택스 트리를 기준으로, 해당 트리에 있는 symbol (const 등) 을 identifier로 변경한다.
  5. 타입체크: binder와 신택스 트리를 기준으로 타입을 체크한다.
  6. transform: 신택스트리를 1번에서 읽었던 옵션에 맞게 변경한다.
  7. emit: 신택스 트리를 .js .d.ts파일 등으로 변경한다.
  • 3번까지의 과정이 소스코드를 읽어 데이터로 만드는 과정
  • 4, 5가 타입체킹 과정
  • 6, 7 을 파일을 만드는 과정

조금 더 디테일한 내용을 알려고 하면 자세하게 정리한 내용을 참고해 봐도 좋습니다 

 

tsc 명령어로 ts 파일을 js 파일로 바꿉니다

얘기하고 싶은 부분은 jdk 를 설치하면 javac로 .java 파일을 해석하듯 typescript를 설치하면 tsc 로 .ts 파일을 해석할 수 있었습니다

다른 컴파일러를 구현한다면? 아래와 비슷하겠네요

loadModuleFromFile(.. , .. , .. , .. )

 

 

밑 바닥부터 만드는 컴퓨팅 시스템의 목차는 아래와 같습니다. 

1.불 논리
2.불 연산(중요)
3.순차 논리
4.기계어
5.컴퓨터 아키텍처

6.어셈블러(기초 적인 번역)
7.가상머신 1: 스택산술 (중간급 번역기)
8.가상머신 2: 프로그램 제어
9.고수준 언어
10.컴파일러 1: 구문분석 (아주 복잡한 번역기)
11.컴파일러 2: 코드생성
12.운영체제 (해당 항목은 따로 깊게)
이걸 어떻게 이해할 수 있을까?

저는 Chip 그림의 명세만 보고는 도저히 내부를 상상할 수가 없었습니다 (어떠한 가설조차 불가능) 그래서 관련 내용을 설명해주는 영상을 보고 역으로 답지를 먼저 보고 문제를 마지막에 보았습니다 

그리고 그림을 직접 손으로 따라 그려봤습니다

영상 1

영상 2

직접 한번 그려 보쟈!

아주 간단히 얘기하면 아래를 하기 위해서 

X + Y = ?

Bit 반전이 되는 6개의 Input 값이 있고 1개의 중요한 Output 값과 2개의 부가적인 OutPut 값이 나오게 되는 것 (책 속의 ALU 에서는.. 이게 표준? )

ALU 내부 방식에 대한 설계는 어떻게 가능할 수 있는가? 이걸로 스터디 원들과 메신저로 얘기도 해봤습니다 (너무 막연하더군요)

여기까지가 HW 이야기 입니다

저만의 결론은 단지 사칙연산이라기보다는 그렇다고 논리회로라기 보다는 그저 겉 핧기식 판단이라도 해보자면 입력과 출력이었습니다

뭔가 아직 이야기(코드)의 흐름은 연결이 되지 않았지만 철저하게 기계화된 약속과 그 약속을 가지고 Chip 이라는 것이 만들어졌습니다 

Chip 은 단순하지만 Chip 을 활용하면 메모리나 CPU 를 조합할 수 있습니다 객체지향적 컨셉이라기보다는 천재의 영역같은 조합이 이루어지면 저희는 이걸 컴퓨터 아키텍처라고 부른다는 생각이 드는군요 

 

  • i 와 sum 두 개의 변수와 loop, end 두개의 label 
  • 번역된 코드는 주소 0부터 시작하는 메모리에 저장하고 변수들은 1024부터 할당
  • 다음으로 소스코드에 새로운 기호가 나타날 때마다 테이블에 추가하는 방식으로 기호테이블에 추가하는 방식
  • 다 만들어지면 이 테이블을 이용하게 됩니다

기계어 프로그램은 명령어를 코드화 한 것

2진 코드는 연상기호를 사용하게 되어 있어서 1010 0001 0001 0001(16bit) 으로 된 코드는

1010 → ADD

0010 → R2

0001 → R1

0001 → R3 

이 기호를 좀 더 추상화하면 2진 명령어 대신에 기호를 텍스트로 입력해서 프로그램을 작성가능 이런 기호 표기법을 어셈블리 언어, 어셈블러라고 합니다 

스터디원의 Question? 왜 VM 이라는 중간자를 거쳐서 해석(컴파일)같은 과정을 거쳐야 할까?

여기서 중요한 기반은 스택산술머신을 구현하는 것

명세

산술 명령: 스택에서 산술 및 논리 연산을 수행함

메모리 접근 명령: 스택과 가상 메모리 세그먼트 사이에 데이터를 주고 받는 명령

프로그램 흐름 명령: 조건 및 무조건 분기 연산을 가능하게 함

함수 호출 명령: 함수를 호출하고 결과를 반환 함

명세에 따라 아래와 같은 어셈블러 코드를 이해하는 부분을 구현할 수 있습니다 

명세에 따라 스택에 연산을 어떻게 할지 분기 작성을 구현할 수 있습니다

메인함수에서는 스택과 서브루틴을 사용해서 넣고 빼고 하면서 흐름을 진행합니다 

이것이 가능한 이유는 스택기반 산술머신이 구현이 되어 있기 때문입니다 즉, 메모리에 넣고 뺴고 하면서 논리를 해석할 수 있는 구조를 만들었습니다 

왜 이런 세부사항을 다 살펴봐야 하는지 의아해하는 사람들에게

이 책에서 가장 좋았던 부분

더 나은 고수준 프로그래머가 될 수 있는 희망을 준 책

만약 복잡하고 어려운 문제를 만난다면(워딩을 재해석)

  • 재귀(반복적인 부분 → 아키텍처로 누구나 따라할 수 있는 공식화가 가능할 수 있는 부분)

피호출자를 위한 인수, 함수프레임, 지역변수, 작업스택으로 구성된 메모리 블록을 스택에 추가

  • 모듈을 분리하고 관심사로 나누어 복잡도를 단순화 한다

효율성을 고려해서 재귀코드를 순차 코드로 다시 표현하려 한다

  • 정규화/반정규화 혹은 성능이나 비즈니스 요구사항을 고려해서 최적의 기능과 성능을 도출

고수준 프로그래머가 가당키나 한 말인가…

100번 1000번 다시 태어나도 그렇게 될 확률이나 자신이 없음… ㅎㅎㅎ… ㅜㅠㅡㅠㅜ

그렇다면 보편적으로 고수준(좋은) 프로그래머는 어떤 역량을 갖춘걸까?

단지 실력이라는 부분으로 모든 것을 치환하기는 힘들것으로 생각됩니다

ALU나 어셈블러, VM번역기 그리고 컴파일러 또는 운영체제 마저도 복잡하고 어려운 내부 시스템을 갖추고 있는 것으로 보입니다

그럼에도 불구하고 매우 높은 안정성과 성능을 보여주고 있는데

공통적으로 모듈이 되어 있고 관심사 별로 처리 방법이 잘 포장되어 있는 것으로 보입니다

그러면 이런 규칙들을 잘 설계하고 명세하는 것이 일단 시작이지 않을까?

즉 모든 구현에 대한 인터페이스 설계가 정말 중요한 것이지 않을까?

틈틈히 비즈니스에서 기술을 사용하는 부분에 대해서 인터페이스에 대해 문서화를 해보고 있습니다

과거에는 팀장이나 선임이 만든 인터페이스 문서로만 봤던 부분을 직접 작성해보니 작은 부분도 고민이되고 어려운 부분이 많은 것 같습니다 

특히 혼자 정하기 어려운 부분도 많고 꾸준히 생각해봐야 하는 부분들도 있습니다 하지만 기능은 추가되어야 하고 코드는 늘어나야 하며 일정은 준수해야 합니다 그리고 생산성이 뛰어나서 시간이 더 생겨서 문서를 쓸 수 있는 것이 아니라 어느정도 본인 희생적인 부분도 필요해 보입니다

즉, 내부구조를 설계하고 왜 이렇게 해야 하는지 공감이되고 품질과 성능과 그리고 생산성 좋은 인터페이스도 고려해야 합니다

절대적으로 시간에 쫓기면 더 많은 상상을 하기가 어려운 것 같습니다

시간에 쫓기더라도 시간을 고민하기 전에 단 한번이라도 한번 더 좋은 방법에 대해 More Thinking 을 항상 해보는 것은 어떨지..

독학 엔지니어라는 워딩이 있는지 몰랐는데 ㅎㅎ 어느정도 지식이 쌓이기 전까지는 계속 수많은 상상과 가설로 문제에 접근한 적도 많았습니다. 이처럼 Thinking 은 비용이 아니라고 생각되는 부분이라서 꾸준히 공부하고 검증해야 한다고 생각되네요

이번 스터디를 통해서 그동안 너무나 막연했던 컴퓨터 세상에 대해 조금 접근해 볼 수 있었고 무엇보다 아무런 준비나 부담없이 그냥 모여서 자유롭게 토론하고 얘기하고 상상하고 그런 부분이 좋았던 것 같습니다

아무말로 막 시작하지면 그래도 항상 결론은 책과 비슷하게 도출했던 부분이 가장 좋은 기억으로 남습니다

스터디를 정리하면서 과거에 제가 까막눈일때 코드를 알기 위해 모든 디버깅 포인트를 찍고 무작정 시작부터 한땀한땀 따라갔던 기억이 납니다

똑똑한 컴파일러의 도움이 없었다면 아마 저는 지금 여기에 없을지도 모르겠네요

마지막으로 코틀린으로 컴퓨터언어(책에서는 핵언어)를 해석하는 파서 부터 구현을 해보려고 도전했던 부분으로 마무리합니다

컴퓨터는 항상 어려우니 언제나 more thinking 을 하다보면 좀 더 고수준 개발자에 가까워지지 않을까 미래를 예측해 봅니다  

 

'My Reading > IT' 카테고리의 다른 글

2019 NDC 후기  (0) 2019.06.22
블록체인이란? (사내세미나)  (0) 2018.02.17

+ Recent posts