brunch

You can make anything
by writing

C.S.Lewis

by 정주홍 Aug 09. 2017

컴퓨터공학과를 다니면서 배운 것

4년가량의 시간 동안 무엇을 배웠을까

최근 학교에서 그동안 공부했던 것을 다시 훑어볼 일이 있었다. 공부하는 김에 각 강의에서 어떤 것들을 배웠나 정리해두면 도움이 되지 않을까 싶어서 여러 대학교에서 공통적으로 배울만한 강의명 아래 우리 학교에서는 무엇을 배웠는지 큰 분류상으로 정리해봤다. 세부 내용을 다 정리하자면 너무 복잡해질 것 같아서... 대충 이 강의에서는 저런 내용을 배우는구나 하고 참고할만한 정도로만 썼다. 좀 더 자세히 쓴 부분도 있는데, 그동안의 경험상 해당 부분을 왜 배우는지 잘 모르는 경우가 많은 것으로 보였던 것에 대해서 약간의 부연 설명을 추가한 것이다. 나름대로 분류를 해서 정리하긴 했는데, 충분히 잘 분류했는지 모르겠다. 소프트웨어 공학 같이 중요하지만 내가 수강하지 않았기 때문에 리스트에 없는 것도 있다.


- 수학에 대해

    - 이산수학

        - 이산 수학에 대해 배움

        - 명제, 증명, 집합, 정수론 기초에 대해 배우고

        - 알고리즘과 시간 복잡도 개념, 재귀 개념에 대해 배우고

        - 순열과 조합에 대해 배우고

        - 이진 관계 속성들에 대해 배우고

        - 부분 순서에 대해 배우고

        - 그래프에 대해 배우고

        - 트리에 대해 배우고

        - 탐색에 대해 배우고

        - 부울 대수에 대해 배움

    - 선형대수

        - 기하학적인 관점에서 문제를 접근하는 방법에 대해 배움

        - 일차 연립방정식을 행렬로 계산하는 법을 배우고

        - 부분 공간을 배우고

        - 가우스 소거법을 배우고

        - LU 분해를 배우고

        - 벡터 공간을 배우고

        - 행렬식을 배우고

        - 정규 직교화를 배우고

        - 고윳값과 고유 벡터를 배우고

    - 오토마타

        - 형식 언어와 계산 이론에 대해 배움

        - 형식 언어에 대해 배우고

        - finite automaton인 DFA, NFA로 regular grammar를 처리할 수 있음을 배우고

        - pumping lemma를 통해 어떤 언어가 regular language에 속하는지 판단할 수 있음을 배우고

        - pushdown automaton로 context free grammar를 처리할 수 있음을 배우고

        - 문법 간소화를 위한 촘스키 노말 폼에 대해 배우고

        - context free grammar를 기반으로 언어를 파싱 하여 parse tree를 만드는 방법에 대해 배우고

        - turing machine의 원리와 계산 가능성에 대해 배우고

        - 계산 복잡도에 대해 배움

- 프로그램 실행 과정에 대해

    - 논리회로

        - 0, 1로만 구분되는 전기 신호를 이용하여 복잡한 실행을 위해 논리 게이트들을 어떻게 구성하는지 배움

    - 컴퓨터 구조

        - 논리 회로로 만들어진 CPU, 메모리와 같은 하드웨어에서 어셈블리 명령어 실행을 위해 알아야 할 것들을 배움

        - 산술 연산, 논리 연산, 메모리 접근, 실행 제어 명령어를 CPU 구조에서 어떻게 실행하는지 배우고

        - 그 명령어들을 더 빠르게 실행하기 위한 파이프라이닝 기법과 그 기법의 문제 해결 방법에 대해 배우고

        - 메모리 구조와 속도 향상을 위한 캐시, 논리 메모리를 물리 메모리로 맵핑하는 방법에 대해 배우고

        - IO 장치에서 IO가 어떻게 일어나는지 배우고

        - 인터럽트 처리 방법에 대해 배움

    - 시스템 프로그래밍

        - 간단한 명령어 집합을 가진 기계를 가정하고, 어셈블리 언어를 CPU에서 실행 가능한 목적 코드로 변환하는 어셈블러를 만들기 위해 알아야 할 것들을 배움

        - 어셈블리 언어를 파싱 하여 각 명령어 별로 인코딩하는 법을 배우고

        - 명령어 별로 주소가 설정되고, 특정 명령어에 설정된 레이블을 이용하여 명령어 주소로 변환하는 법을 배우고

        - 변수에 메모리 할당을 위해 목적 코드를 어떻게 구성해야 하는지 배우고

        - 만들어진 목적 코드를 읽어서 실행하는 시뮬레이터를 만듦으로써 프로그램이 CPU에서 어떻게 실행되는지 간접적으로 배움

    - 프로그래밍 언어

        - 어셈블리보다 더 고수준 언어, 예를 들면 C언어를 만들기 위해 고려해야 할 것들에 대해 프로그래밍 언어의 평가 기준인 readability, writability, reliability, cost 관점에서 살펴봄

        - 더욱 자연어에 가까워진 언어를 프로그램에서 읽어 들이기 위한 문법 구조에 대해 배우고

        - 우리에게 익숙한 Expression들을 문법 구조와 LL, LR 파싱 방법에 따라 Syntax Tree를 만드는 법을 배우고

        - 이름, 바인딩, 영역에 대해 배우고

        - 여러 가지 Type들을 지원하기 위해 고려해야 할 것들에 대해 배우고

        - 기본적인 expression statements 지원을 위해 고려해야 할 것들에 대해 배우고

        - selection statements(if, else, switch 등), iterative statements(for, while 등) 지원을 위해 고려해야 할 것들에 대해 배우고

        - 서브 프로그램 기능 구현을 위해 알아야 할 것들을 배움

    - 컴파일러

        - 프로그래밍 언어를 통해 알게 된 것들을 어셈블리로 변환하기 위한 컴파일러를 만드는 방법에 대해 배우며, 보통 교재로 많이 쓰는 책에서는 TINY라는 좀 더 간단한 언어에 대한 컴파일러를 만들어보는 식으로 배움

        - Lex를 이용한 Lexical Analysis 하는 법을 배우고

        - 하향식 파싱에 대해 좀 더 자세히 배우고

        - 상향식 파싱에 대해 좀 더 자세히 배우고

        - Yacc을 이용한 Syntax Analysis 후 Syntax Tree 만드는 법을 배우고

        - 만들어진 Syntax Tree를 Traverse 하면서 Semantic Analysis 하는 법을 배우고

        - 분석이 끝난 Syntax Tree를 미리 가정한 스택 머신의 명령어 집합의 어셈블리로 변환하는 법을 배우고

        - 만들어진 어셈블리를 실행할 수 있는 시뮬레이터로 실행해 봄

- 프로그래밍에 대해

    - 자료구조

        - 프로그램에서 자료를 다루기 위해 필요한 여러 가지 자료구조에 대해 배움

        - 스택과 큐

        - 연결 리스트, 환형 연결 리스트, 이중 연결 리스트

        - 트리, 트리 순회 방법, 이진트리, 이진 탐색 트리, AVL 트리, 힙, 우선순위 큐

        - 그래프, 무방향 그래프, 방향 그래프, 최소 신장 트리, 작업 네트워크

        - 위상 정렬

    - 알고리즘

        - 문제 해결을 하기 위한 알고리즘을 프로그래밍 언어로 구현하는 방법에 대해 배움

        - 여러 가지 복잡도와 계산 방법을 배우고

        - 분할 정복 방법을 배우고

        - 다이나믹 프로그래밍 방법을 배우고

        - 그리디 접근 방법을 배우고

        - 백 트랙킹 방법을 배우고

        - 몬테 카를로 방법을 배우고

        - 분기 한정 방법을 배움

    - 문제 해결

        - 더 어려운 알고리즘들을 배움

        - 간단한 코딩 워밍업

        - 다이나믹 프로그래밍 - 0/1 Knapsack 문제, Longest Common Subsequence, Longest Increase Subsequence, Edit Distance

        - 기하 문제 - Area Formula, Convex Hull, Triangulation

        - 그래프 문제 - 위상 정렬, Strongly Connected Component, Maximum Flow 문제와 Ford-Fulkerson method, Bipartite Matching 문제와 Hungarian method, Kuhn-munkres algorithm

    - 객체 지향 프로그래밍

        - Swing으로 코딩하면서 객체 지향적으로 프로그래밍하는 방법에 대해 배움

        - Swing을 이용한 코딩을 하면서 객체 지향 프로그래밍의 몇 가지 특징들을 배우고

        - 팀 프로젝트로 프로그램 개발

    - 사용자 인터페이스

        - 안드로이드 개발을 하면서 객체 지향 프로그래밍을 좀 더 심화하여 배움

        - 안드로이드 개발을 전반적으로 배우고

        - 팀 프로젝트로 안드로이드 앱 개발

- 네트워킹에 대해

    - 컴퓨터 통신과 네트워크

        - OSI 5 계층의 각 계층, 특히 transport, network 계층에서 일어나는 일들을 자세히 배움

        - transport 계층의 TCP 프로토콜에서 어떻게 신뢰성 있는 통신을 하는지와 UDP 통신이 어떻게 되는지 배우고

        - network 계층에서 목적지까지 라우팅 하는 방법을 배우고

        - network access 계층에서 이웃 노드에게 데이터를 전달하는 방법을 배우고

        - physical 계층에서 비트를 전송하는 방법을 배움

    - 네트워크 프로그래밍

        - 리눅스에서 소켓 API를 이용하여 네트워킹하는 방법을 자세히 배움

        - 고수준, 저수준 소켓 API들을 배우고

        - 운영체제에서 소켓을 어떻게 관리하고 연결하는지 배우고

        - 서버/클라이언트 구조를 배우고

        - 다중 소켓 처리를 위한 방법인 멀티프로세스, 멀티플렉싱, 멀티쓰레드 방법을 배우고

        - 유명한 프로토콜인 HTTP, FTP을 배워서 구현해봄

- 인공 지능과 기계 학습에 대해

    - 지능형 시스템

        - 지능형 시스템이 무엇이고 어떻게 작동될 수 있는지 기본적인 부분에 대해 배움

        - 지식 표현 방식에 대해 배우고

        - reasoning에 대해 배우고

        - 널리 알려진 지능형 시스템들의 작동 방식에 대해 배움

    - 인공지능

        - 지적 행위를 할 수 있는, 인공 지능 프로그램을 만들기 위한 방법에 대해 배움

        - 에이전트와 환경의 개념에 대해 배우고

        - 문제 해결을 위한 탐색 방법에 대해 배우고

        - 제약 만족 문제에 대해 배우고

        - 명제 논리와 1차 논리를 이용하여 문제를 해결하는 논리적 에이전트에 대해 배움

    - 데이터 마이닝

        - 여러 가지 감독 기계 학습 모델로 회귀, 분류를 하는 방법에 대해 배움

        - 통계적 학습이 무엇인지 배우고

        - 편향-분산 딜레마에 대해 배우고

        - 선형 회귀 방법을 이용한 회귀에 대해 배우고

        - 로지스틱 회귀, LDA, QDA 방법을 이용한 분류에 대해 배우고

        - resampling 방법에 대해 배우고

        - 선형 모델 선정과 정규화에 대해 배우고

        - 트리 기반 방법에 대해 배우고

        - Support Vector Machine에 대해 배움

- 운영체제에 대해

    - 운영 체제가 하는 일들과 그 일을 하기 위해 어떤 자료구조와 알고리즘을 사용하는지 배움

    - 프로세스 관리에 대해 배우고

    - 메모리 관리에 대해 배우고

    - 스토리지 관리에 대해 배우고

    - 보호와 보안에 대해 배우고

- 데이터베이스에 대해

    - 사용에 대해

        - 데이터베이스를 사용하는 것에 대해 배움

        - 관계형 데이터 모델에 대해 배우고

        - SQL으로 질의하는 법에 대해 배우고

        - 상용 RDBMS가 제공하는 추가적인 기능들에 대해 배우고

        - ER 데이터 모델과 어떻게 RDB 디자인에 대해 배움

    - 개발에 대해

        - 데이터베이스를 만든다면 고려해야 할 것들에 대해 배움

        - 트랜잭션이 무엇인지와 트랜잭션을 어떻게 관리하는지에 대해 배우고

        - 여러 트랜잭션을 동시에 실행하기 위한 방법을 배우고

        - 복구 기능과 안정적인 스토리지 운영 및 버퍼 관리 방법에 대해 배우고

        - 빠른 질의 처리를 위한 인덱스의 종류에 대해 배우고

        - 질의 처리를 위한 과정과 JOIN이나 정렬과 같은 몇 가지 주요 연산을 어떻게 처리하는지 배우고

        - ORDB 개념에 대해 배우고

        - 데이터 웨어하우스 및 마이닝과 관련된 부분을 조금 배우지만 의미는 크게 없는 듯


정리하고 나니까 양이 꽤 된다. 그래도 시간을 아예 날린 것은 아닌 건지...


몇 개 강의는 굳이 학교에서 들을 필요 없었다 싶은 것들도 있다. 위 리스트에서는 객체 지향 프로그래밍이나 사용자 인터페이스 같은 강의인데, 혼자 공부할 일이 있는 류가 대체로 굳이 학교에서 들을 필요가 없었던 것들에 많이 포함된다. (수강했던 강의들 중 굳이 학교에서 배울 필요 없었다 싶은 강의들은 리스트에 추가하지 않았다.) 예를 들어 컴퓨터 구조, 프로그래밍 언어, 컴파일러 같은 것들은 앞으로 따로 찾아서 공부할 일이 잘 없을 것이라 생각한다. 찾아본다 하더라도 그때 닥친 문제를 해결하기 위한 아주 지엽적인 부분만 조금 찾아보는 수준일 것이다. 전체를 다 공부하기엔 시간이 너무 많이 드니까. 그러나 전체적인 흐름을 이해하고 있는 것과 각각 작은 부분만을 알고 넘어가는 것은 그 분야의 이해도에 있어 큰 차이를 보일 것이라 생각한다. 

아직 초보 수준인 내가 이렇게 말하는 게 설득력은 별로 없겠지만... 대학교에서 공부하기 전부터 코딩을 해왔지만 근 4년 간 컴퓨터 과학 내에서 다양한 전공들을 공부하고 난 지금, 과거의 나와 지금의 나를 비교해보면 문제를 어떻게 해결할지 생각할 때 좀 더 풍부하게 생각할 수 있게 된 것 같다. 이런 점에서 학교에서 실무를 많이 가르쳐야 한다는 주장에 대해서는 딱히 공감하지 않는 편이다. 예를 들어 학교에서 React를 이용한 웹 개발이나 게임 엔진을 이용한 게임 개발 같은 것을 굳이 배울 필요가 없다고 생각하는 게, 그건 그냥 혼자 알아서 공부하면 되는 것이라고 생각하기 때문이다. 학교에서 배워야 할 것은 좀 더 근본적인 것, 그리고 그것을 바탕으로 새로운 지식을 만들어낼 수 있는 능력이라고 생각한다. 새로운 지식들도 결국 그 지식을 만들기 위해 그 이전의 이론을 활용한 것인 경우가 많으니까 말이다. 아예 새로운 개념조차도 그 개념을 생각해내는 것 자체는 이전의 지식 없이 불가능하지 않나 싶다.

마지막으로 대학 생활이 4년 정도를 그냥 일을 하는 것에 비해 더 나은 경험이었는지, 등록금만 따졌을 때 도합 3천만 원에 달하는 수업료를 낼만한 가치가 있는 경험이었는지는 섣불리 판단 못 하겠다. 어쨌든 이제 거의 끝이다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari