개요

취업을 목표로 하는 기업은 [카카오, 네이버, 라인]과 같은 IT 기업이다.

많은 분야를 두고 고민했으나, 결국 Web 계열 Front-end & Back-end로 결정했다.


SSD 관련해서도 연구실에서 발 담궜으니, 삼성전자 DS에 원서를 쓸 예정이다.

(반도체냐, 웹이냐.............. 서로 이직이 안되므로 고민......)


한달도 안 남은 기간동안 웹 포트폴리오를 만들기 위한 과정을 기록하려고 한다.



웹기술 관련 업계 동향

웹만큼 빠르게 변화하는 업계는 없는 것 같다. 개인적으로 생각하는 업계 동향을 적어본다.



Front-end 초장기에는 순수 JavaScript만이 존재했다. 근데 브라우저끼리 호환도 안되고 해서 소소하게 입력값 검사 정도의 역할만 했다.

이후 AJAX와 jQuery가 등장하였고, 난이도가 낮아지고 기능이 늘어나기 시작한다.


Back-end로는 PHP/ASP/JSP 세 개가 쌈싸먹게 된다.

소규모 사이트는 PHP로, 좀 규모가 있다면 JSP/ASP로 백엔드를 선택하면 되는 편한 상황.


이후 Python(Django), Ruby(Rails) 등등의 Back-end도 나오게 된다.


그런데 Google V8 Engine이 공개되면서 Node.js가 등장했다. JavaScript를 Back-end로 쓰기 시작했다.

단순히 언어만 JavaScript였다면 Django, Rails랑 같은 취급이었을거다. 그런데 장점이 많았다.

Back-end 대세는 Node.js로 흐르기 시작했다. 더불어 JavaScript 언어의 위상도 올라갔다.


Front-end도 장족의 발전을 했다. 프론트는 선택의 여지 없이 JavaScript 언어이다.

jQuery를 밀어내며 Angular(구글), React(페이스북) 등의 프레임워크가 나오기 시작했다.


근데 Angular가 너무 무겁고 규칙이 빡셌나보다. 가벼움을 추구하는 Vue.js, Backbone.js 등이 나오기 시작했다.


그리고 완전 최근 동향은 뭐... GitHub에서 JavaScript언어에 스타 순으로 정렬하면 대충 각 나온다.



정리하자면...


[Front-end] Vanilla JS --> AJAX/jQuery --> Angular/React --> Vue.js

[Back-end] PHP/ASP/JSP --> Django, Rails --> Node.js


너무 빨리 변해서 대체 뭘 공부해야 할 지 초심자 입장에서는 진입장벽이다.

줏어들은 바로는 이미 배운 사람도 문제다. 버전업이 너무 빠르기 때문...



포트폴리오 준비 계획

Kakao, Naver, LINE 채용 페이지에서 과연 어떤 경력직을 모집중인지 조사했다.

그리고 Web 기술이 아닌 것들은 배제했다. (FinTech, Video Streaming, Machine Learning 등)


대체로 요구하는 기술은 아래와 같다.


[공통]

RESTful API 개념, MSA 개념, MVC 패턴

형상관리 (Git)

Single Page Application (SPA) 개념

Linux, Shell Script, MySQL, NoSQL


[JavaScript]

ECMAScript5 (2015), TypeScript

Node.js, MongoDB, Express

jQuery, Backbone.js, React(+Redux), Angular, Vue.js

webpack, Electron

Bootstrap


[PHP]

Laravel


[Java]

Spring, Playframework(Scala)


기간이 한달 남짓이기에 이걸 전부 공부하기에는 시간이 모자라다는 판단이 든다. 선택과 집중을 하자.

우선 PHP는 이미 할 줄 알고, Java는 손절한다. 걍 JavaScript에 집중하기로 했다. 이것도 넘 많아서 일부만 해야한다.


한 달간 공부하고 포트폴리오에 사용할 내용은 다음과 같다:

백엔드는 Node.js(Express, MongoDB, webpack, babel), 프론트는 Vue.js, 디자인은 Bootstrap



웹 관련 개념

RESTful API

HTTP Request의 GET/POST/PUT/DELETE를 이용해서 CRUD(Create, Read, Update, Delete) 기능을 구현하는 것이다.

기능적인 측면만 봤을 때는 위와 같고, 사실 그 뒷면에 이념이나 규칙 등은 조금 더 자세하다. 그 내용은 아래 소스들 참고.

https://meetup.toast.com/posts/92 (REST API 제대로 알고 사용하기)

CRUD를 테스트하는 툴로 Postman을 많이 사용한다. (https://www.getpostman.com)

MSA (Microservice Architecture)

서비스를 작은 단위로 쪼개서 운영하는 구조. 반대말은 Monolithic Architecture이다. (앞으로 Mono와 Micro라고 하겠다.)


Monolithic 아키텍처는 쉽게 말하면 한 웹서버 안에 모든 기능을 다 때려박은 구조이다. 단순하므로 개발이 빠르고 쉽다. 장점들은 많다.


그런데 몇 가지 문제가 있다. (쿠팡 블로그에서 참조함)

1) 일부가 전체에 영향을 미친다. 코드에 메모리 누수가 발생하면 그 서버 전체가 다운되는 수가 있다.

2) 부분적인 Scale-out이 안된다. 일부 서비스에만 오버로드가 발생한다 해도 전체의 스케일을 키워야 한다.

3) 여러 컴포넌트가 강하게 연결되어 있어, 변경이 어렵다. 강결합의 단점은 코드 수정 시 다른 코드에도 영향이 갈 수 있고, 그 정도를 모른다는 점이다.

4) 일부 수정에도 높은 테스트 비용이 든다. 특정 부분만 수정해도 테스트는 전체 서비스에 대해 이뤄지므로 비용이 비싸다.

5) 서비스 규모가 커질 수록 배포 시간이 오래 걸린다.


따라서 서비스를 작은 단위로 쪼개고, 물리적인 서버도 분리하고, 각 서비스끼리는 Message Queue를 두어 통신하게 한다.


이외에 자세한 내용은 아래 소스들 참고.


https://alwayspr.tistory.com/20 (Microservice Architecture 란?)

https://jason-lim.tistory.com/1 (Microservice Architecture에 대한 이야기 - Integration)

https://medium.com/coupang-tech/행복을-찾기-위한-우리의-여정-94678fe9eb61 (쿠팡의 MSA — Part 1)


MVC 패턴

개발할 때 Model-View-Controller 3가지 형태로 역할을 분리하여 개발하는 방법론.


처음에는 '왜 굳이 번거롭게?' 라는 생각이 들 수 있으나, 나중에는 합리적이라는 생각이 든다.

물론 개발 과정이 기존처럼 파일 하나에 다 때려박던 것보다 번거로운건 사실인데, 이렇게 분리함으로써 나중에 관리하기가 편해진다.


[Model] 내부 비즈니스 로직을 맡는 역할. 알고리즘, DB, 데이터 관리 등

[Controller] Model과 View를 연결, 또는 유저와 연결되는 역할. 유저의 명령을 받아 Model에게 일을 넘겨주고 그 결과를 View를 통해 보여줌.

[View] 화면에 무언가 보여주기 위한 역할.


각자 하는 역할이 분리된다. 좀 더 자세히 설명하자면

Model은 데이터 혹은 작업 요청서(?)만 받아서 자기 일을 하고 Controller에게 주면 된다. 사용자랑 무슨 일이 벌어지는지는 관심 없다.

View는 Controller가 요청하면 자신의 모양대로 데이터를 그려내면 된다.

Controller는 Model-View를 중간에서 관리하면서, 유저와 연결되어 있기도 하다.


예)

사용자는 Controller에게 요청을 한다.

Controller는 필요에 따라 Model 에게 작업 혹은 데이터를 주어 처리한다.

그리고 그 결과를 View에게 전달하여 사용자에게 화면을 보여준다.


더 자세한 내용은 아래 소스들 참고.


https://medium.com/@jang.wangsu/디자인패턴-mvc-패턴이란-1d74fac6e256 ([디자인패턴] MVC 패턴이란?)

https://jayzzz.tistory.com/40 (MVC패턴 모델, 뷰, 컨트롤러)


Single Page Application (SPA)

이름 그대로 페이지 하나에 모든 기능을 때려박는(?) 접근 방법이다. 모던 웹의 패러다임이라고 할 수 있다. 페이스북이 이런 식이다.


장점은 페이지 로드 처음에 일단 모든 리소스를 다운받고, 이후에는 변하는 부분만 서버에서 내용을 받아와 표시한다.

따라서 새로고침이 발생하지 않으므로 Native App과 같은 사용자 경험을 줄 수 있다. 트래픽이 줄어들어 모바일 환경에서 좋다.


단점은 최초 1회 로딩에 대하여 많은 양의 리소스를 받아야 하므로 초기로딩속도가 느려지게 된다.

더불어 내용이 상황에 따라 동적으로 변하기 때문에, 검색엔진에서 크롤링이 불가능하다.


이외에 장단점이 더 많이 있다. 역시나 아래 소스들 참고.


https://poiemaweb.com/js-spa (Single Page Application & Routing)

https://medium.com/@bbirec/spa-single-page-application-개발에서-고려할-사항-eedcb7cb618f (SPA 개발에서 고려할 사항)

https://m.mkexdev.net/374?fbclid=IwAR3H9b90QaKAuuNPgJMfoXnWwfsnU4glF4uBp0QSDhAlnBJ8gNb8D5cdeKQ (SPA 단점에 대한 단상)



웹 기술 공부

Node.js (Back-End)

Server-Side에서 동작하며 Network Application을 제작할 수 있는 플랫폼이다. 언어는 JavaScript를 사용한다. (Google V8 엔진 기반)


혼동하지 말 점은, Node.js는 Web Server가 아니라는 점이다. (Apache가 아니다!)

그냥 JavaScript를 실행(Run)할 수 있게 해 주는 런타임(runtime)이다. 마치 Python처럼 말이다.


Node.js가 웹 서버로서 동작하려면 라이브러리(주로 Express)를 이용하여 HTTP 서버 코드를 직접 작성해야 한다.

여기서 직접 작성한다는 말은, Apache가 FTP로 파일을 툭 올렸을 때 폴더 기반으로 파일의 URL을 알아서 처리해 줬던 것과는 달리

Node.js는 URI를 해석하는 것부터, 어떤 파일과 매칭시킬 지 혹은 어떤 코드를 실행시킬 지를 코드로 일일이 라우팅(Routing) 해 주어야 한다.


기존 Apache+PHP 환경에 익숙한 사람은 Node.js가 다소 불편할 수도 있다. 지향하는 바가 조금 다른 것 같다.


Apache는 FTP로 올린 파일의 경로가 URL에도 1:1로 매칭되는 시스템이다. 즉, 파일 위치가 곧 URL이다.

Node.js는 파일의 위치와 URI가 다른 경우가 허다하다. URI와 파일을 직접 매칭 시켜줘야 한다. 그래서 번거로울 수도 있다.


앗, URL과 URI라고 다르게 표기한 것을 눈치챘는가?

URL과 URI의 차이



입문(Tutorial)

Node.js는 공식적인 튜토리얼이 없고, API 문서만 제공한다.

따라서 외부 튜토리얼로 공부해야 한다. 나는 다음 2개의 튜토리얼을 통해 학습하였다.


https://www.w3schools.com/nodejs/ (영문)

https://velopert.com/node-js-tutorials (한글)



설치

학습을 위해 Amazon AWS에 가입하고 프리티어(1년)를 받아 가상서버에서 진행하였다.

Red Hat 리눅스에 설치하였고, 버전은 Node.js 11.10.0 (npm 6.7.0)이다.


엔터프라이즈(RedHat, CentOS, Fedora)는 NodeSource라는 곳에서 바이너리를 배포한다고 한다. (공식 사이트의 안내사항이다.)

아래 링크에서 쉽게 설치하는 쉘스크립트를 제공하고 있다. 명령어 한 줄로 Node.js를 설치할 수 있다.

https://github.com/nodesource/distributions/blob/master/README.md



Hello World 찍어보기

다음 코드를 hello.js에 작성해본다. (vim 이용)


console.log("Hello, World!");


node를 실행하는 명령어는  node 이다. hello.js를 실행하려면  node hello.js 를 입력하면 된다.



아주 간단한 웹서버 만들기

웹서버를 만들기 전에, HTTP 프로토콜에 대한 기반 지식이 필요하다. 특히 헤더의 구조에 대해 알고 있어야 한다.


아래 코드는 http 모듈을 불러오고, 8080 포트에 http 서버를 오픈하는 예제이다.

그 어떤 URI로 접속하던지 동일한 결과를 출력할 것이다. Header에 Response Code: 200(성공)을 보내고, Body는 Hello World.


var http = require("http");


http.createServer(function(request,response) {

    response.writeHead(200, {'Content-Type': 'text/plain'});

    response.end("Hello World\n");

}).listen(8080);


코드를 해석한다. createServer()는 웹서버 객체(Object)를 만든다. 그리고 객체를 만들 때 익명 함수를 작성하여 전달했다.

더불어 웹서버 객체에 대해 8080 포트로 요청을 받아들이도록 listen() 메소드를 호출했다.


이제 해당 웹서버는 8080 포트로 접속이 들어올 때마다, 등록한 익명 함수를 호출할 것이다.


웹서버 예제는 더 복잡한 거 말고 여기까지만 하는 게 좋다. 어차피 Express 모듈을 써서 웹서버를 만들 것이기 때문.



Node Package Manager (NPM)

NPM은 패키지/모듈을 쉽게 설치하고 관리할 수 있도록 해 주는 명령어이다. (RedHat의 yum, Ubuntu의 apt-get과 같은 역할)


Node.js로 사이트(프로젝트)를 만들 때 수많은 모듈을 짜집기해서 만들게 된다. 따라서 필연적으로 다음과 같은 2개의 문제점이 발생한다.


1) 프로젝트마다 필요한 모듈이 다를 것이다.

2) 프로젝트의 개발 시점에 따라서 사용한 모듈의 버전이 달라질 것이다.


따라서 이 프로젝트에 어떤 모듈이 사용됐는지, 모듈의 버전이 무엇인지를 프로젝트 내 package.json 파일에 기록해야 한다.

물론 package.json은 NPM에 의해 자동으로 관리된다. 그런 역할을 NPM이 해 주고 있다.


만약 다른 사람의 프로젝트 파일을 다운받았다고 가정해보자. NPM에서 제공하는 간단한 명령어 2~3줄로

해당 프로젝트의 의존성(Dependency) 패키지들을 한 번에 설치하고, 프로젝트를 바로 실행할 수 있다. 



# 프로젝트 생성

npm init


리눅스에서 적당히 폴더를 하나 만들고, 위 명령어를 치면 이제부터 해당 폴더가 프로젝트 폴더가 된다.

프로젝트의 이름, 버전, 제작자 등의 정보를 기입할 수 있다. 귀찮으면 전부 엔터를 쳐버려도 된다.



# 특정 모듈 설치

npm install [모듈명]


# 현재 프로젝트의 모든 Dependencies 모듈 설치

npm install


위 명령어는 모듈 파일을 다운받아 프로젝트 폴더에 설치해 주지만, package.json에는 기록하지 않는다.


--save 옵션을 주어야 package.json에 "Dependencies" 항목으로 기록된다.

--save-dev 옵션을 주면 "DevDependencies" 항목으로 기록된다. (음... 쉽게 얘기하면 개발용과 배포용을 따로 사용할 수 있다.)

--dev 옵션을 주면 "DevDependencies" 항목의 패키지를 설치한다. 옵션 안주면 일반 Dependencies만 설치된다.

-g 옵션을 주면 글로벌로 설치한다. 기본값은 로컬 설치(현재 프로젝트 폴더에만 설치)이다. 글로벌 설치는 아예 시스템에 파일이 박힌다. (sudo 필요)



이외에도 NPM의 다양한 기능들이 있다.

예를 들어 npm run-script 명령어는 아주 편하고 많이 사용되는 기능이다. script 관련 내용은 아래 package.json에서 익힐 수 있다.



package.json

다음 블로그에서 잘 설명해 주고 있다: https://programmingsummaries.tistory.com/385 (모두 알지만 모두 모르는 package.json)



Callback Function(콜백 함수) 개념

이 개념을 받아들이기 어려워 하는 사람도 있다. 생소하기 때문이다.

자세한 설명은 다른 블로그가 더 잘 해주고 있고, 여기서는 개요만 설명하겠다.



기존 Blocking 코딩에서, get_number() 함수가 처리에 5초 걸린다고 가정해 보겠다.


var a = get_number(); // 5초 걸리는 놈

console.log(a); // get_number()의 결과를 출력


next_function();


프로그램의 실행 흐름은 다음과 같다:

get_number() 호출 --> 5초 대기(blocking) --> a 출력 --> next_function(); 실행


즉, next_function() 입장에서는 앞 코드 실행이 끝날 때까지 기다려야 자기가 실행될 수 있다.



다음 예제는 Node.js가 익명 함수를 사용하여 Blocking을 없애고 있는 모습이다.


get_number(  function(req,res) { console.log(req); }  );

next_function();


get_number() 호출 --> next_function() 호출 --> 5초 후 --> 익명 함수(function)를 호출해서 결과 출력


next_function()은 아무런 대기 시간 없이 즉시 실행될 수 있다.

get_number() 함수가 끝났을 때 무슨 코드를 실행할 지를, 익명 함수를 통해 작성하면 된다. (Non-blocking 구현)

익명 함수는 본 함수의 처리가 끝났을 때 호출될 것이다.



자, 지금까지는 기존 언어(Java 등)에 익숙했기 때문에 '익명 함수' 라고 불렀지만, 사실은 이게 '콜백 함수'이다.

처리가 끝나면 불려지는 함수를 콜백 함수라고 한다.









(공부하면서 계속 내용 추가 중)

(Last Update: 2019/02/21) 

Matched Filter, 정합 필터

원본 신호를 알고 있을 때, 수신된 신호에서 어느 부분이 원본 신호 부분인지 찾아낼 때 사용


Matched Filter는 수신된 신호 중 원본 신호가 위치한 곳에서 최대가 된다.


목적은 두 신호의 유사도를 구하는 게 아니라 원본 신호 지점에서 SNR(Signal-to-Ratio)를 최대로 만드는 것인 듯


Matched Filter의 구현은 한 쪽 신호를 뒤집어서 두 개를 Convolution한다. 그러면 두 신호가 최대로 유사한 지점에서 최대값을 가지게 됨.

(링크에서 Matched Filter 파트의 그림을 참고할 것: http://blog.naver.com/PostView.nhn?blogId=moony6463&logNo=220072038153)


Cross Correlation과 같다고 볼 수 있는데 차이점은 CC가 0을 기준으로 좌우 대칭 모양이 나오는 반면에

Matched Filter는 입력 소스만큼의 길이만 나온다. 즉 CC가 두 배 더 긴 결과를 출력함.


매트랩으로 해 본 결과, Matched Filter와 Cross Correlation은 같은 결과를 내었다.

Cross Correlation은 Correlation이고, Matched Filter는 Reversed Signal을 Convolution 하는 것이라서

수식적으로 풀어보면 같은 효과라고 어디서 줏어들었음

어쩌다보니 연구에 OFDM을 써야하게 되었다. 조사한 내용을 정리해본다.

내 사용 목적은 (1)소리로 데이터를 전송하는 것과, (2)녹음된 소리의 Time Sync를 정확하게 맞추기 위함이다.




OFDM (Orthogonal Frequency Division Multiplexing, 직교 주파수 분할 다중화)

직교하는 부반송파(sub-carrier)를 수십~수천 개씩 사용해서 병렬로 정보를 전송하는 기술

기존 기법들은 Single Carrier로써, 주파수 하나만 잡고(예: FM 라디오 등등)데이터를 전송했으나, 단점이 많이 있었음


(carrier와 channel 용어는 서로 섞여서 쓰인다)




장점

  • Multipath 환경에 강하다.
    • 주변 사물에 부딪혀서 여러 번 겹쳐 녹음될 경우, 신호 분리가 까다로운데 이를 해결할 수 있음.
    • Single Carrier 쓸 때는 데이터를 많이 전송하려면 Higher Rate를 썼어야 했고
      그러면 Multipath 환경에서 신호가 너무 쉽게 겹친다. (목욕탕에서 말을 빨리 하는 것과 같음)
    • OFDM은 여러 Carrier에서 데이터를 나눠서 Lower Rate로 전송한다.
      => 한 비트가 오래 유지되니까 알아듣기 쉽고, 앞 신호랑 조금 겹쳐도 그 부분 걍 잘라내면 된다.
  • 특정 채널의 상태가 좋지 않아도, 병렬 전송이라서 영향이 크지 않다.
    • SIngle Channel 였다면 신호가 아예 죽었을 것
  • 대역폭을 굉장히 효율적으로 사용한다
    • Sub-carrier를 겹치게 배치할 수 있으므로

(더 많은 장점은 위키를 참고: https://ko.wikipedia.org/wiki/직교_주파수_분할_다중_방식)




왜 Orthogonal인가?

병렬 전송에 대한 개념으로 FDM이 먼저 나왔으나 단점이 존재했다. 각 sub-carrier들이 겹치지 않아야 했으므로 Guard Band가 필요했다.

결과적으로 대역폭(Bandwidth)를 많이 차치하여 비효율적인 배치가 된다.


근데 어찌어찌 '직교성' 이라는것을 잘 이용하면 sub-carrier들을 겹치게 배치해도 잘 동작하게 된다. 아래처럼...

FDM과 비교했을 때 훨씬 많은 sub-carrier를 이용할 수 있음을 알 수 있다. Guard Band도 없다.




OFDM 채널 배치 구조

한 Carrier의 Amplitude가 최대일 때, 다른 Carrier들의 Amplitude는 0이 되도록 스펙트럼이 절묘하게 겹쳐져 있다. (직교성)

Theoretical BPSK OFDM spectrum



Guard Interval

위에서 Guard Band라는 용어가 쓰였는데, 채널 사이를 분리해 주는 역할이었다. (Frequency domain)
이번 용어는 Guard Interval로 전혀 다른 개념이며, 전송하는 데이터 사이를 분리해 준다. (Time domain)

예를 들어, 사우나에서 한 단어를 말하고 연달하서 다음 단어를 말하면 Multipath에 의해 첫 단어와 두 번째 단어가 겹쳐서 들린다.
그래서 첫 단어를 말하고 잠깐 쉬어주면(Guard Interval) 첫 단어의 Echo가 완전히 사그라 들게 되고, 이 때 두 번째 단어를 말한다.

즉 Guard Interval은 Echo들이 완전히(혹은 충분히) 사그라 들 때까지 기다리는 시간을 의미한다.

아래 그림은 Signal이 Multipath에 의해 3번 수신된 상황을 예시로 든 것이다. 마지막 Reflection까지를 Guard Interval로 설정했다.
물론 Guard Interval은 환경에 따라 매 번 개발자가 직접 지정해 줘야 하는 부분이다. 동굴 안에서는 충분히 길게 해야 할 것이고...




주로 쓰이는 OFDM 송수신부 구조


위 구조에서 Time Sync와 Cyclic Prefix 등은 빠져있음. 실제 구현하려면 위 구조보다 조금 더 복잡함.



Cyclic Prefix

Cyclic Extension (순환 확장)은 Multipath로 인해 발생하는 ISI(Inter Symbol Interference)를 극복하기 위해 고안된 방법이다.

목적은 Sub-carrier 사이의 직교성(Orthogonality)의 파괴를 방지하기 위함이다.

방식은 Cyclic Prefix의 경우 유효 신호의 마지막 부분 신호를 일정 부분 복사해서 앞에다가 삽입한다.


아래와 같은 데이터를 전송한다고 해보자. 3개의 Symbol이 있다.


이를 전송하면 Multipath로 인해서 Delay를 가진 신호들이 여러 번 들어오게 된다. 아래는 Original과 2개의 Multipath를 예로 들었다.

잘 보면 S2의 앞부분이 S1의 Echo와 겹치기 때문에 Inter Symbol Interference가 발생하여 S2를 추출해 낼 수 없게 된다.

따라서 결과를 보면 S2의 앞부분이 손실되고 뒷 부분만 얻어내게 된다.


그래서 Cyclic Prefix를 두게 된다. 어려운 개념은 아니고 Symbol의 뒷부분 일부를 앞에다가 복사하는 것이다.


그리고 신호를 전송해 보면... Multipath로 겹치는 부분이 발생하더라도 결국은 S2 안에서 일어나는 일이기 때문에

Symbol간의 Inter Symbol Interference는 발생하지 않는다는 것을 알 수 있다.




자주 쓰이는 용어 및 개념

  • FFT (Fast Fourier Transform)
    • 시간 도메인 신호를 주파수 도메인으로 바꿔주는 것
  • IFFT (Inverse Fast Fourier Transform)
    • FFT를 역으로 하는것
  • ISI(Inter Symbol Interference), ICI(Inter Channel Interference)
    • Multipath로 인해 신호가 겹쳐 들리는 현상
  • Modulation
    • 신호를 잘 전달하기 위해 적절히 데이터를 변조하는 것 (전자쪽 용어, 신호처리 분야)
    • QPSK, 16-QAM 등등 주로 사용됨
  • Cyclic Prefix
    • Guard Interval(최대 지연시간)동안의 신호를 복사해서 앞에 갖다붙이는 것
    • Guard Interval을 쓰는 이유? Multipath로 신호가 겹쳐봤자 최대 이 시간까지만 겹칠 것이라고 가정하는 것
    • 쉽게 말하면 뒷쪽 신호를 짤라서 앞에 갖다붙이는 것
    • Inter Symbol Interference를 극복하기 위함 - 신호가 어느정도 겹쳐도 걍 CP를 잘라버림 (어차피 뒤에 또 나올거니까)





[출처]

https://ko.wikipedia.org/wiki/직교_주파수_분할_다중_방식 (OFDM 기본 설명 및 장단점)

http://www.whydsp.org/209 (OFDM과 CP에 대한 이해가 쉬운 설명)

https://www.csie.ntu.edu.tw/~hsinmu/courses/_media/wn_11fall/ofdm_new.pdf (영문)(설명이 그림과 함께 아주 잘 되어있음)

https://dsp.stackexchange.com/questions/20132/ofdm-transmitter-bandwidth (영문)(그림 출처)

https://caesarhks.blog.me/70133244891 (OFDM에 대한 간단한 설명)

http://www.ni.com/white-paper/3370/ko (영문)(OFDM에 대한 간단한 설명)

https://www.radio-electronics.com/info/rf-technology-design/ofdm/ofdm-basics-tutorial.php (영문)(OFDM 설명)


http://www.ktword.co.kr/abbr_view.php?m_temp1=3164 (Cyclic Prefix 용어 설명)

http://www.telecomhall.com/what-is-cp-cyclic-prefix-in-lte.aspx (영문)(Cyclic Prefix 기본 개념 설명)


[좋은 코드 예시들]

http://blog.naver.com/PostView.nhn?blogId=ykryu7&logNo=221256145776 (MATLAB. 예시 코드와 설명)(실수, 허수 구조)

http://www.rfwireless-world.com/source-code/MATLAB/OFDM-matlab-code.html (영문)(MATLAB. 단순하며 직관적인 4-channel 코드 예시)

http://www.skydsp.com/publications/4thyrthesis/code.html (MATLAB. WAV 소리 파일로 생성하는 코드. 논문에 사용된 코드라 다소 복잡함)

http://dspillustrations.com/pages/posts/misc/python-ofdm-example.html (Python. 단계별로 아주 자세히 설명해 주는 코드 예시)

http://wisechoding.tistory.com/41 (MATLAB, 단계별 OFDM 시뮬레이션)

공식 설치 메뉴얼: https://www.tensorflow.org/install/install_windows


TensorFlow 설치 전에 먼저 깔아야 하는 것들(Requirements)

- CUDA Toolkit 8.0

- cuDNN v6.1


주의할 점은 위 requirement들을 최신 버전으로 깔면 TensorFlow가 지원을 안함 ㅡㅡ;;

현재 CUDA 9.1과 cuDNN 7이 최신이라 홈페이지 메인에 떡하니 있는데, 좋다고 넙죽 받아서 설치하면 당연 안되고

꽁꽁 숨어있는 Legacy 다운로드 메뉴로 들어가서 굳이 구버전을 깔아야 함


CUDA Toolkit은 크기가 좀 커서 그렇지(1.5GB) 그냥 깔면 되고

cuDNN은 받아서 압축 풀면 dll이 튀어나오는데, 적절히 원하는 폴더에 넣고 환경 변수에 해당 경로를 박아야 함

예를 들어 C:\Program Files\cudnn 폴더 만들고 그 안에 cudnn64_5.dll를 넣었으면 그 경로를 %PATH%에 박고 재부팅ㄱ





TensorFlow가 잘 깔렸는지 확인하는 파이썬 스크립트:

https://gist.github.com/mrry/ee5dbcfdd045fa48a27d56664411d41c#file-tensorflow_self_check-py

[Sampling]

이 세상의 소리(Sound)라는 것은 아날로그이기에 Linear 하다.

그런데 컴퓨터는 디지털이므로 이 Linear한 소리를 Discrete 한 데이터로 변환해야 한다.


아날로그의 오묘하고 복잡한 특성을 전부 그대로 담기에는 용량의 문제가 있으므로

일부분만 채취(샘플링)하여 최대한 원본과 유사한 디지털 데이터를 만들게 된다.

이러한 과정 또는 행위를 샘플링이라 한다.


용어가 몇 개 있다:

(1) 샘플링 레이트(Sampling Rate) : 1초에 몇 개의 샘플을 추출할 것인지

(2) Bit Depth : 한 개의 샘플이 얼마만큼의 크기를 가지는지


당연하게도 샘플링 레이트가 높을 수록 아날로그와 유사한 디지털 값(고음질)을 얻을 수 있다.

아래 그림은 샘플링 레이트에 따른 디지털 데이터의 모양을 나타낸다. 

잘게 쪼갤 수록 아날로그의 것과 같이 부드러운 곡선이 되는 것(=원본에 가까움)을 확인할 수 있다.


(출처: http://www.morphfx.co.uk/music/edu-sampling.htm)


우리가 일반적으로 구입할 수 있는 음반 CD의 스펙은 44,100hz 16bit 이다.

1초에 44100개의 샘플을 추출하고, 각 샘플의 크기는 16bit (= 2byte short) 라는 것이다.




[나이퀴스트 샘플링 이론(Nyquist–Shannon sampling theorem)]

왜 대부분의 MP3 파일, 혹은 하드웨어들이 44,100hz 스펙을 가지고 있는지에 대해 이 것으로 설명이 가능하다.


이론의 결론만을 요약하면 다음과 같다:

A sufficient sample-rate is therefore 2B samples/second, or anything larger. 

충분한 샘플링 레이트는 대역폭의 두 배, 혹은 그 이상이다.


이론에 대한 간략한 설명


사람이 소리로 들을 수 있는 가청 주파수의 범위는 20~20000 Hz 이다.

즉 데이터의 대역폭이 20 KHz라는 것인데, 이를 왜곡(Aliasing 등) 없이 샘플링 하려면

대역폭의 2배인 40 KHz 샘플링 레이트로 샘플링 해야한다.


여기서 오차 10% 및 영상 업계 표준과의 동기화 문제 등으로 인해

현재는 44,100Hz와 48,000Hz가 범용적으로 가장 많이 사용되게 되었다.


아래는 어디서 줏어들은 것:

44,100hz : 25FPS PAL, 30FPS NTSC

48,000hz : 29.97FPS NTSC




[Sources]

https://en.wikipedia.org/wiki/Sampling_(signal_processing)

https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem

https://en.wikipedia.org/wiki/Aliasing

성균관대학교 대학원 전자전기컴퓨터공학과에서 2017년 3월부터 석사 시작합니다.


이진규 교수님의 지도 하에 랩실에서 근무 예정입니다.

주 연구 분야는 모바일 시스템입니다. 모바일 센싱 중에서도 소리를 이용한 가상 하드웨어를 연구합니다.


Real-Time Computing Laboratory (http://rtcl.skku.edu/)

연구 분야:

- Real-Time Embedded Systems

다양한 코어 시스템에서 실시간 스케줄링을 연구합니다.

멀티 쓰레드 환경에서 실시간 스케줄링을 연구합니다.

하드 리얼타임 환경에서 실행 시간을 보장하는 방법을 연구합니다.

- Cyber-Physical Systems

효율적인 배터리 충전/방전 방법을 연구합니다.

- Mobile Systems

모바일 응용과 서비스를 연구합니다.

모바일 환경에서의 에너지 소비 최적화를 연구합니다.

IoT 관련 분야를 연구합니다.

System 클래스는 Java에서 제일 많이 사용되는 표준 입출력 클래스죠?
System.in(표준 입력), System.err(표준 에러 출력), System.out(표준 출력) 을 포함하죠.

그런데 왜 이 System 클래스가 java.lang 패키지에 속해 있을까요?

이유는 간단합니다.
다시 말하지만 System 클래스는 표준 입출력을 담당하고 있습니다.
그런 만큼 모든 클래스에서 접근이 자유로워야겠죠.

따라서 모든 클래스가 자동으로 import 시키게 되는
Java.lang 패키지에 속해 있는 것입니다.

물론 System 클래스의 필드들은 static으로 선언되어 있지요.

InputStream과 OutputStream은 abstract 클래스입니다.

왜 추상 클래스일까?
크게 두 가지 이유로 나눌 수 있습니다.

첫째,
두 클래스 모두 '바이트의 입, 출력을 담당하는 모든 클래스' 의 수퍼(부모) 클래스이므로
아무런 기능을 가지고 있지 않아야 합니다.

둘째,
사용하고자 하는 클래스에 맞게 read() 나 write() 메소드를
오버라이딩 하여 사용하기 위해
추상 클래스로 선언되어야 합니다.

+ Recent posts