├── .github └── workflows │ └── action.yml ├── .mergify.yml ├── Android └── application fundamentals.md ├── Browser ├── BrowserXY.md ├── Cookie.md ├── Cookie_Store.md ├── FOUC.md ├── HTTP2_Websocket.md ├── IndexedDB_WebSQL.md ├── Layer_Model.md ├── WebWorker.md ├── Worklet.md ├── 웹 브라우저의 작동 원리.md └── 최신_브라우저의_내부_살펴보기.md ├── CS ├── Binding.md ├── Bomb-Lab(1).md ├── Call-By-Sharing.md ├── Counting-sort.md ├── Graph.md ├── Memory.md ├── Radix-sort.md ├── aspect-oriented-programming.md ├── cohension&coupling.md ├── compression.md ├── dependency-inversion-principle.md ├── grasp.md ├── information_theory.md ├── integer_representation.md ├── interface-segregation-principle.md ├── liskov_substitution_principle.md ├── methods_in_IPC.md ├── non-blocking.md ├── non-linear-search.md ├── open-closed-principle.md ├── soc.md ├── srp.md ├── union-find.md ├── 페이징과 세그먼테이션.md └── 플로이드-와샬-알고리즘.md ├── CSS ├── CJK.md ├── WebToMobile.md └── safe-area.md ├── Database ├── DB Connection Pool.md ├── Query Builder ( Knex.js).md └── Types of Databases.md ├── Deprecated ├── AMD와 CommonJS.md ├── Async-Await.md ├── B_EventLoop.md ├── B_Module.md ├── CORS(Cross-Origin Resource Sharing).md ├── CSS 애니메이션 vs JS 애니메이션.md ├── CallByReference.md ├── EventLoop.md ├── EventLoop_Advanced.md ├── Funtional.md ├── Higher_Order_Functions.md ├── Javascript_BuildTool.md ├── Module.md ├── Promise1.md ├── Promise2.md ├── Reactive.md ├── Repaint와 Reflow.md ├── WebWorker.md ├── animation.md ├── setState.md ├── 기본적인 렌더링 최적화 방법.md ├── 웹 브라우저의 작동 원리.md └── 점진적향상_우아한하향.md ├── Design_Pattern ├── Composite.md ├── JSP model.md ├── MSA.md ├── MVC1, MVC2.md ├── MVC_MVP_MVVM.md ├── Memoization.md ├── RxJS.md ├── Singleton.md └── Throttle and Debounce.md ├── ECMAScript ├── ArrowFunction.md ├── Destructuring_Assignment.md ├── ECMA2019.md ├── ES6-module-in-Browser.md ├── Generator와 async-await.md ├── Includes_IndexOf.md ├── Iteration_Protocol.md ├── ModulePattern_class.md ├── Number_isNaN.md ├── Spread_Operator.md └── Tagged_Template_Literals.md ├── Git └── gitBy_.git.md ├── HTML ├── ARIA.md ├── DOM API.md ├── DOM.md ├── HTML-Templating.md ├── Head_Meta.md ├── Standard&QuirksMode.md ├── WebM&WebP.md ├── input태그의_value바꾸기(input태그의_dirty flag).md ├── preload&prefetch.md └── 웹 컴포넌트(Web Component).md ├── Java ├── ArrayList vs LinkedList 그리고 Vector.md ├── Comparable vs Comparator.md ├── Dependency Injection(DI).md ├── JSP와 Servlet처리.md ├── JVM(Java Virtual Machine).md ├── Java Garbage Collection(GC).md ├── Mybatis.md ├── Set.md ├── String, StringBuilder, StringBuffer.md ├── String,StringBuilder, StringBuffer차이.md ├── Upcasting과 Downcasting.md ├── WAS.md ├── copy-object.md ├── date-api-in-java.md └── junit-setup.md ├── Javascript ├── Ajax.md ├── Animation.md ├── B_Async.md ├── B_Call_Apply_Bind.md ├── B_Callback.md ├── B_Class.md ├── B_Function.md ├── B_Type.md ├── Build Tool.md ├── CallStack.md ├── Closure.md ├── Control_CSSOM.md ├── DocumentFragment.md ├── Event Delegation.md ├── InsertAdjacentHTML.md ├── JavaScript의 this.md ├── Javascript_Engine.md ├── Javascript_메모리관리.md ├── Javascript의_동작원리-변수객체(VariableObject).md ├── Javascript의_동작원리-실행컨텍스트(Execution Contexts).md ├── Jest.md ├── Learning_more_about_this.md ├── Module.md ├── MouseEvent.md ├── Object.create&Object.assign.md ├── Observer.md ├── Optional_Chaining.md ├── PromisePattern.md ├── Prototype_Chain.md ├── Proxy.md ├── Reduce.md ├── Redux State 정규화.md ├── Regular_Expressions.md ├── Scope.md ├── Some_Every.md ├── Storybook.md ├── Sync&Async_Multi&Single_Thread.md ├── TimeInJS.md ├── Variable.md ├── WebRTC.md ├── Web_Storage_API.md ├── ajax(2).md ├── bind.md ├── object.md ├── object_create_pattern-constructor.md ├── object_생성패턴.md ├── prototype(2).md ├── prototype.md ├── scope_this.md ├── throttling과 rAF.md ├── tricks_of_js.md ├── underscore와 lodash그리고 Native.md ├── window.history.md ├── 논리연산자.md ├── 렉시컬_속이기(eval).md ├── 배열 내장함수.md ├── 상태관리 라이브러리.md ├── 이벤트 루프(Event Loop).md ├── 클래스(class).md ├── 클로저.md └── 함수 선언.md ├── LICENSE ├── Language ├── Currying.md ├── Lamda.md ├── Reactive.md ├── XML_JSON.md ├── 고차함수(High Order Function).md └── 함수형 프로그래밍.md ├── ML └── 머신러닝이란.md ├── Network ├── 3-way handshaking & 4-way handshaking.md ├── CORS.md ├── DHCP&DNS.md ├── Flow control.md ├── HTTP3.md ├── IP.md ├── JSend.md ├── OSI7 Layer.md ├── REST API.md ├── REST.md ├── SOAP API.md ├── Subnetmask.md ├── Switch.md ├── TCP & UDP.md ├── TypesOfIP.md ├── comet.md ├── congestion control.md ├── get&post.md ├── http-caching.md ├── 로드밸런싱 & 클러스터링.md └── 사용자 인증 방식(Cookie, Session & oAuth 2.0 & JWT).md ├── Node.js ├── make_meta_file.md └── nodejs의_특징.md ├── OpenCV └── 이미지전처리.md ├── Performance ├── DeadLock(교착상태).md ├── HTTP2.0의 필요성.md ├── Reflow Repaint.md ├── Throttling vs Debouncing.md ├── requestAnimationFram(rAF).md ├── 기본적인 렌더링 최적화 방법.md ├── 서버 사이드 렌더링(SSR).md └── 점진적향상_우아한하향.md ├── README.md ├── React ├── Component, Props, State.md ├── Composition.md ├── Element와 Component.md ├── ImmutableState.md ├── React Server Components.md ├── React.memo.md ├── React의 Lifecycle Event.md ├── SWR.md ├── Virtual DOM.md └── props와 state.md ├── Rules ├── Commit.md └── Markdown.md ├── Security ├── HTTPS와 SSL.md ├── Response_Header_Security.md ├── SQL_Injection.md └── 리만가설과 소수정리.md ├── Tool ├── Chrome_80_DevTool.md ├── Framework vs Library.md └── Package Manager.md ├── Typescript ├── 인터페이스(Interface).md ├── 정적 타이핑.md ├── 제네릭(Generic).md └── 클래스(class).md ├── Vue └── Vue_LifeCycle.md ├── WPF └── wpf.md └── assets ├── IndexDB ├── TodoList │ ├── index.html │ ├── js │ │ ├── indexDB.js │ │ └── todo.js │ └── todoStyle.css └── index2.html ├── TEST ├── bigfile.html ├── img_css_image_sprites.png └── window.history.demo.html ├── gif ├── MobileCSS.gif ├── MobileDock.gif └── MobileLayout.gif └── images ├── CallByValue.png ├── Collection_Hierarchies.png ├── EventLoop.png ├── Functional_Programming_Main.png ├── Gecko.jpg ├── Graph-그래프.png ├── Graph-리스트_무향.png ├── Graph-리스트_유향.png ├── Graph-보행.png ├── Graph-종류.png ├── Graph-쾨니헤스베르크_다리.png ├── Graph-크기.png ├── Graph-행렬.png ├── HTML-Templating1.png ├── HTML-Templating2.png ├── HTML-Templating3.png ├── HTMLCollection.png ├── HashTable.png ├── LongPolling.png ├── Parent_Child_workflow.png ├── SQL_Injection_1.png ├── SQL_Injection_2.png ├── ScopeChain.png ├── ServletClass.png ├── Sync&Async_Multi&Single_Thread_1.jpg ├── Vue-lifecycle.png ├── Webkit.png ├── ajax.png ├── array_list.png ├── bucket-sort.png ├── call-by-sharing01.png ├── coalescing.png ├── compaction.png ├── compilerDesign.jpg ├── copy-object01.png ├── event_delegation.png ├── event_loop.jpeg ├── event_loop_gif.gif ├── flux_architecture.png ├── get&post.png ├── gitBy_.git_gitlifecycle.png ├── gitBy_.git_gitobjects.png ├── https_asymmetric_key.png ├── hystrix.png ├── insertAdjacentHTML_1.PNG ├── insertAdjacentHTML_2.PNG ├── insertAdjacentHTML_3.PNG ├── java_Runtime_Data_Areas.jpg ├── java_gc_heap.png ├── java_gc_object.png ├── java_runtime_data_area.png ├── javascript의_동작원리-실행컨텍스트(ExecutionContexts)-1.png ├── javascript의_동작원리-실행컨텍스트(ExecutionContexts)-2.png ├── linked_list.png ├── memoryHier.png ├── memorymodel.png ├── non-blocking.png ├── non-linear-search-bfs.png ├── non-linear-search-dfs.png ├── non-linear-search.gif ├── page_pageframe.png ├── polling.png ├── preflight-process.png ├── primitiveCasting.png ├── prototype1.png ├── prototype2.png ├── react_lifecylce.png ├── rendering.png ├── segmentation.png ├── server_side.png ├── servletArchitecture.png ├── streaming.png ├── typescript_access_modifier.png ├── typescript_type.png ├── was1.png ├── was2.png ├── was3.png └── was4.png /.github/workflows/action.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Request Action" 2 | on: 3 | pull_request: 4 | types: [opened] 5 | 6 | jobs: 7 | test: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Create link 11 | uses: Im-D/Im-Bot/packages/pr-supporter@master 12 | with: 13 | myToken: ${{ secrets.GITHUB_TOKEN }} 14 | - name: Create reviewRequest 15 | uses: Im-D/Im-Bot/packages/pr-reviewer@master 16 | with: 17 | myToken: ${{ secrets.GITHUB_TOKEN }} 18 | - name: Create Link at README file 19 | uses: Im-D/Im-Bot/packages/update-readme@master 20 | with: 21 | myToken: ${{ secrets.GITHUB_TOKEN}} 22 | linkLocTarget: '### 📅 History' -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: Automatic merge on review 3 | # https://doc.mergify.io/examples.html#require-all-requested-reviews-to-be-approved 4 | conditions: 5 | - "#approved-reviews-by>=4" 6 | - "#changes-requested-reviews-by=0" 7 | - base=master 8 | - label=approval + 3 9 | actions: 10 | merge: 11 | method: merge 12 | delete_head_branch: {} 13 | 14 | - name: Add Label needs author response 15 | conditions: 16 | - "#changes-requested-reviews-by>=1" 17 | actions: 18 | label: 19 | add: ["needs author response"] 20 | remove: ["needs review"] 21 | 22 | - name: Remove Label needs author response 23 | conditions: 24 | - "#changes-requested-reviews-by=0" 25 | actions: 26 | label: 27 | add: ["needs review"] 28 | remove: ["needs author response"] 29 | 30 | - name: Add Label approval + 1 31 | conditions: 32 | - "#approved-reviews-by=1" 33 | actions: 34 | label: 35 | add: ["approval + 1"] 36 | 37 | - name: Add Label approval + 2 38 | conditions: 39 | - "#approved-reviews-by=2" 40 | actions: 41 | label: 42 | add: ["approval + 2"] 43 | remove: ["approval + 1"] 44 | - name: Add Label approval + 3 45 | conditions: 46 | - "#approved-reviews-by=3" 47 | actions: 48 | label: 49 | add: ["approval + 3"] 50 | remove: ["approval + 2"] 51 | -------------------------------------------------------------------------------- /Browser/FOUC.md: -------------------------------------------------------------------------------- 1 | # FOUC(Flash of Unstyled Content) 2 | 3 | `FOUC(Flash of Unstyled Content)`란 브라우저에서 웹 페이지에 접근했을 때, 미처 스타일이 적용되지 못한 상태로 화면이 나타나는 현상을 말한다. 4 | 5 | 스타일이 적용되기 전의 상태가 먼저 화면에 렌더링된 후 그 상태에서 스타일이 적용되기 때문에 스타일이 적용되는 과정이 사용자에게 그대로 노출되는 현상이다. 이러한 현상은 사용자의 경험(UX)를 떨어트리게 된다는 문제가 있다. 6 | 7 | `FOUC`는 특히 `IE(Internet Explorer)` 브라우저에서 주로 발생되며 `IE11`에서도 여전히 발생되고 있는 문제다. 8 | 9 | ## FOUC의 발생 원인 10 | 11 | `FOUC`의 발생 원인은 다양하지만 몇 가지만 우선적으로 살펴보면 다음과 같다. 12 | 13 | ### CRP(Critical Rendering Path) 14 | 15 | ![Webkit](https://user-images.githubusercontent.com/24724691/62412567-bf49f200-b63f-11e9-9ed4-ec8215d04a7d.png) 16 | 17 | 위처럼 브라우저에서 화면이 그려지기까지의 주요한 과정을 `CRP(Critical Rendering Path)`라고 한다. 18 | 19 | 1. HTML 마크업을 처리하고 DOM 트리를 빌드한다. 20 | 2. CSS 마크업을 처리하고 CSSOM 트리를 빌드한다. 21 | 3. DOM 및 CSSOM을 결합하여 Rendering 트리를 형성한다. 22 | 4. Rendering 트리에서 레이아웃을 실행하여 각 노드의 기하학적 형태(화면의 위치)를 계산한다. 23 | 5. 개별 노드를 화면에 paint한다. 24 | 25 | `Render Tree`가 노출된 후 CSS와 JS 파일등으로 변경되면 이 변경 사항들이 화면에 노출될 수 있다. 이 현상이 `FOUC`다. 26 | 27 | 웹 브라우저의 작동 원리에 대해 좀 더 자세히 알고 싶다면 [다음](https://github.com/im-d-team/Dev-Docs/blob/master/Browser/%EC%9B%B9%20%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98%20%EC%9E%91%EB%8F%99%20%EC%9B%90%EB%A6%AC.md)을 참고하길 바란다. 28 | 29 | 최근의 웹 페이지들은 여러 개의 CSS 파일을 참조하거나 웹 폰트를 사용함으로써 DOM 구조를 변경하기 때문에 더욱 자주 발생할 수 있는 환경이다. 30 | 31 | ### `@import`를 사용한 CSS 32 | 33 | IE(Internet Explorer)를 제외한 브라우저의 경우, 참조(`@import`)되는 스타일이 적용될때까지 화면에 표시하지 않는다. 하지만, IE의 경우 화면에 노출된 상태로 스타일이 적용되어 FOUC를 유발한다. 34 | 35 | ### 웹 폰트의 사용 36 | 37 | 이또한 `@import`를 사용하여 스타일링을 할 때와 같은 원리로 `FOUC`가 발생하게 된다. IE는 웹 폰트를 사용할 경우 기본 폰트를 불러들이고 이를 사용된 웹 폰트로 다시 재변경되게 되는데 이 과정을 그대로 화면에 노출시키게 된다. 38 | 39 | ## FOUC 해결 40 | 41 | ### JS import 위치 변경 42 | 43 | 일반적으로 자바스크립트를 선언할 때는 성능을 위해 `` 태그 바로 위에 위치시키곤 한다. 44 | 하지만 이를 ``태그 안으로 위치시킴으로써 `FOUC`를 개선할 수 있다. 하지만 이 방법으로는 웹 폰트나 `@import`를 사용한 CSS로 인한 `FOUC` 발생을 막을 수는 없다. 45 | 46 | ### FOUC 발생 위치의 컴포넌트 숨기기 47 | 48 | `@import` 사용으로 인한, 웹 폰트로 인한 `FOUC`발생을 막기 위해서는 `FOUC`가 발생하는 위치의 컴포넌트를 숨겼다가 웹 폰트 혹은 참조(`@import`) CSS의 로딩이 완료되면 보여주는 방법이 있다. 물론, 숨기는 것은 한 예시일 뿐이고 로딩바를 보여준다거나 스켈레톤 UI를 보여준다거나 할 수 있다. 49 | 50 | ```html 51 | 52 | 53 | 58 | 63 | 64 | 65 | 66 |
67 | FOUC 발생 지점 68 |
69 | 72 | 73 | 74 | ``` 75 | [소스 출처 - webdir.tistory.com](https://webdir.tistory.com/416) 76 | 77 | 위 소스에 대해 간단히 설명하면 자바스크립트와 CSS 스타일이 모두 로딩되었을 경우, `fouc` ID를 가진 컴포넌트를 렌더링시켜준다. 78 | 79 | `FOUC`의 발생은 최근에는 대부분 `IE`에서 발생하기 때문에 `IE`에 대해서만 분기 처리를 한 후 `FOUC`에 대한 처리를 하는 것도 좋은 방법이 될 수 있다. 80 | 81 | --- 82 | 83 | #### Reference 84 | 85 | - [화면 깜빡임(FOUC) 문제해결](https://webdir.tistory.com/416) 86 | - [UZULAB - #3 FOUC, 화면 깜박임 문제](https://uzulab.tistory.com/4) 87 | -------------------------------------------------------------------------------- /Browser/HTTP2_Websocket.md: -------------------------------------------------------------------------------- 1 | # HTTP2.0과 Web Socket 2 | 3 | ## HTTP란 4 | 5 | HTTP는 HyperText Transfer Protocol의 약자다. Request와 Response로 이루어진 통신 규약이다. 6 | 7 | 이 HTTP의 단점 중 하나는 Request가 있어야만 Response가 존재한다는 점이다. 이 요청은 URL로 이루어져 새로운 요청을 보내려면 새로운 페이지가 필요하다. 예를들어 회원가입시 ID 중복확인을 하려면 새 페이지로 넘어가야 한다. 8 | 9 | 또한 페이스북처럼 정보를 거의 실시간으로 확인 할 수 있는 SNS의 경우, 정보의 갱신이 매우 빠르게 일어나는데 이를 업데이트 하려면 항상 클라이언트의 Request가 필요하다. 만약 이 경우 서버의 정보가 갱신되지 않았다면 통신의 낭비가 일어나기도 한다. 10 | 11 | HTTP의 대표적인 단점으로는 12 | 13 | - 1개의 커넥션에 1개의 리퀘스트만 가능하다. 14 | - Request는 클라이언트 사이드에서만 시작할 수 있다. 15 | - 헤더가 압축되지 않는다. 16 | - 우선순위가 없다. 17 | 18 | 등 다양하다. 19 | 20 | ## 문제해결 21 | 22 | 이러한 문제들중 몇가지를 해결하기 위해 등장한 것이 AJAX와 COMET방식이다. 23 | 24 | ### AJAX 25 | 26 | --- 27 | 28 | 구글의 AJAX는 HTTP 통신을 사용은 하지만 HttpRequst가 아닌 XMLHttpRequest를 사용하여 새로운 HTML을 사용하지 않고 페이지의 일부만 수정할 수 있게 된다. 29 | 30 | ### COMET 31 | 32 | --- 33 | 34 | Comet은 서버측의 데이터 갱신이 있을때 Request를 기다리지 않고 Response를 보내기 위한 방법이다. Comet의 경우 Request에 따른 Response를 반환하지 않고 보류해둔다. 그 뒤 서버의 데이터가 갱신되면 Response를 반환하는 방식이다. 롱폴링(long polling)방식이라고도 한다. 35 | 36 | 위의 두가지 방법은 모두 프로토콜 레벨의 방법은 아니며 HTTP가 가진 근본적인 단점을 해결해 줄 수는 없다. 37 | 38 | ## SPDY 39 | 40 | 느린 HTTP를 해결하기 위해 나온 것이 SPDY다. 구글이 시도했던 실험 프로토콜이다. Page Load Time을 50%로 줄이기 위함이 목표였다. 41 | 42 | 핵심적인 변화는 이러하다. 기존의 데이터는 플레인 텍스트로 통신을 하였는데 이를 바이너리로 인코딩하여 **프레임** 이라는 단위로 변경하여 전송한다. 즉 하나의 chunk에서 frame이라는 단위로 쪼개기가 가능해진다. 이를 통해 요청/응답 다중화, 우선순위 지정 및 헤더 압축이 목표였다. 43 | 44 | 이게 2012년의 이야기이며 이를 본 HTTP-WG(HTTP Working Group)이 HTTP2.0을 만든다. 45 | 46 | 이 HTTP2.0은 SPDY의 사양을 채택해 출발하게 되고 2015년 SPDY는 지원을 중단하며 HTTP2.0으로 사실상 통합되게 된다. 47 | 48 | ## Web Socket 49 | 50 | 2014년 HTML5의 등장과 함께 Web Socket이 등장한다. 51 | 52 | HTTP와 같이 Web Socket은 프로토콜이며 양방향 소통을 지원하는 프로토콜이다. HTTP가 가진 근본적인 문제 중 하나인 **Request는 클라이언트 사이드에서만 시작할 수 있다.** 를 완전히 해결할 수 있는 프로토콜이다. 53 | 54 | 시작점은 클라이언트에게 있지만 처음 HTTP로 연결한 뒤 그 뒤로는 WebSocket 프로토콜을 이용하여 양쪽 모두 송신이 가능하게 된다. 55 | 56 | 또한 처음 HTTP 통신 이후에는 헤더의 사이즈를 감소시켜 통신량을 줄이게 된다. 57 | 58 | ## HTTP 2.0 59 | 60 | HTTP 2.0의 도입배경은 SPDY를 통해 소개를 했다. 61 | 62 | 핵심적인 변화로는 Binary Framing부터 시작한다. 새로운 메커니즘으로 아래와 같은 구조를 가진다. 63 | 64 | - 스트림(바이트의 흐름) 65 | - 메시지(전체 시퀀스며 Request / Response의 단위다.) 66 | - 프레임(통신의 최소단위) 67 | 68 | 프레임이 모여 메시지가 되고 메시지가 모여 스트림이 된다. 69 | 70 | 장점을 알아보자 71 | 72 | ### 요청 및 응답 다중화 73 | 74 | --- 75 | 76 | 프레임은 헤더나 메시지 페이로드 등을 전송하며 **인터리빙**이 가능하다. 즉 데이터를 읽을 때 순서대로가 아니게 읽는 것이 가능하며 대역폭 증가의 효과를 가진다. 77 | 78 | 인터리빙으로 병렬처리가 가능해지면서 통신 단위의 변경이 가능해집니다. 79 | 80 | HTTP 1.0은 기존의 메시지가 단위였다면 2.0부터는 스트림이 단위가 된다. 따라서 동시에 여러 메시지를 처리할 수 있게 되고 Request의 순서와 상관없이 Response를 보낼 수 있게 되었다. 81 | 82 | HTML 파싱 시 여러 Request가 필요한데 이것의 순서가 없어져 Response를 기다려야하는 통신의 낭비가 사라진다. 83 | 84 | ### 우선순위 지정 85 | 86 | --- 87 | 88 | 인터리빙에 따른 병렬처리로 서버와 클라이언트측에 각각 요청이 전달되는 순서가 성능 이슈로 떠오릅니다. 따라서 가중치를 통해 우선순위를 줄 수 있게 됩니다. 89 | 90 | ### 서버푸쉬 91 | 92 | --- 93 | 94 | 서버푸쉬는 웹소켓과는 다른 개념이다. 95 | 96 | 예를들어 초기 페이지에 index.html만이 아니라 많은 css, js, image파일과 같은 추가적인 리소스가 필요하다면 이를 클라이언트가 요청하지 않아도 서버가 푸쉬할 수 있는 방식이다. 97 | 98 | ### 헤더압축 99 | 100 | --- 101 | 102 | 기존의 HTTP는 헤더를 항상 일반텍스트로 보냈다. 103 | 이를 HTTP 2.0에서는 HPACK 압축방식을 이용하여 보내게끔 되어있다. 104 | -------------------------------------------------------------------------------- /CS/Memory.md: -------------------------------------------------------------------------------- 1 | # Memory 2 | 3 | 메모리는 말그대로 저장소다. 뭔가를 하려면 어떤 데이터를 어떻게 처리하라고 한다. 즉 데이터와 처리명령 두가지가 필요하다. 4 | 5 | 그래서 메모리도 두 영역으로 나뉘어 있다. Program / Data 부분이 나뉜다. 6 | 7 | ## 메모리 계층구조 8 | 9 | 메모리는 당연히 빠를수록 비싸다. 그래서 빠르고 비싼 메모리는 용량이 작다. 반대로 느리면서도 싼 메모리는 용량이 크다. 아주 쉽게 생각할 것은 HDD와 SSD의 차이를 생각해보면 된다. 10 | 11 | ![memoryHierachy](/assets/images/memoryHier.png) 12 | 13 | 그래서 위와 같은 그림이 나온다. 레지스터와 캐시는 CPU 내부에 존재한다. 그만큼 작고 빠르다. Cache는 SRam과 같다. Memory는 Dram이다. 흔히 RAM 이라고 부른다. 8GB DDR4 램 사면 이거다. Disk는 하드디스크 그거다. 14 | 15 | 보통 레지스터, 캐시, 메모리를 주 기억장치, 디스크를 보조 기억장치라고 부른다. 주 기억장치는 보조보다는 빠르나 전원을 끄면 데이터가 날아간다.(휘발성) 16 | 17 | ## 메모리 구조 18 | 19 | 메모리는 다음 그림과 같이 공간을 나누어 관리한다. 20 | 21 | ![memoryModel](/assets/images/memorymodel.png) 22 | 23 | 그림에 따라 low address와 high address가 반대가 되어 스택이 쌓이는 구조로 보이기도 한다. 그러나 중요한 점은 메모리는 사용용도에 따라 구역을 나누어 관리하고 순서가 있다는 점이다. 24 | 25 | ### TEXT 26 | 27 | 프로그램 코드가 저장되는 영역이다. 따라서 코드영역이라고도 불린다. 물론 개발자가 작성한 소스코드는 아니고 기계어로 저장된다. 28 | 29 | Read-Only Data다. CPU가 이 영역의 데이터를 fetch해서 실행한다. 30 | 31 | ### DATA(GVAR + BSS) 32 | 33 | 전역변수, static 변수가 저장되는 공간이다. 34 | 35 | 초기화된 데이터는 data 영역에 저장되고, 초기화 되지 않은 데이터는 BSS(Block Stated Symbol)영역에 저장된다. 36 | 37 | js의 var let const의 호이스팅 시 선언, 초기화, 할당에 관한 내용 중 초기화와 관련한 내용이지 않을까 싶다. 38 | let과 const는 선언만 되며 초기화가 되지않아 메모리에 없다. 39 | 그런데 js는 전역 스코프 역시 객체다. 그럼 참조타입이라 heap에 저장될 것 같다. 40 | 실행 컨텍스트와 관련된 내용같은데 자세히 좀 더 알아보자 41 | 42 | 프로그램이 실행될 때만 생성되고 종료시 반환하는 영역이다. 43 | 44 | ### HEAP 45 | 46 | 흔히 참조타입이 저장된다. 이 영역에 저장하기 위해 `new` 키워드를 사용한다. 47 | 48 | 개발자가 임의로 만들 수 있는 영역이라 동적 할당영역이라고 부른다. 49 | 50 | HEAP을 참조하는 영역이 없으면 GC가 돌면서 마킹을 통해 제거하는 영역이다. 51 | 52 | ### STACK 53 | 54 | 지역변수, parameter, 리턴 값 등이 임시로 저장되었다가 사라지는 영역입니다. 55 | 56 | 원시 값 타입이 저장되는 공간입니다. 57 | 58 | stack은 함수 호출 시 할당되며 함수 종료(return)시 제거됩니다. 59 | 60 | 엄격하게 LIFO가 지켜집니다. 이렇게 스택에 저장되는 호출정보를 stack frame이라고 합니다. 흔히 우리가 부르는 call stack은 stack frame과 연관이 있습니다. 61 | 62 | ### 흐름 63 | 64 | 1. 개발자가 소스코드를 완성하여 컴파일 => 실행단계가 되면 코드는 TEXT에 올라간다. 65 | 2. 프로그램이 실행되면 프로그램은 프로세스가 된다.(프로세스 == 실행중인 프로그램) 66 | 3. 프로세스의 흐름에 따라 DATA영역에 전역과 static변수를 만든다. 67 | 4. 코드의 흐름에따라 HEAP과 STACK영역을 움직이며 메모리를 사용한다. 68 | 5. 프로그램이 종료되면 DATA영역을 반환한다. 69 | 70 | ### 문제 71 | 72 | 너무 자주 봐왔고, 참조변수와 포인터에 관한 이야기다. 73 | 74 | ```js 75 | const arr = [1, 2, 3]; 76 | 77 | const foo = arr => { 78 | arr[1] = 100; 79 | arr = [4, 5, 6]; 80 | 81 | console.log(arr); 82 | }; 83 | 84 | foo(arr); 85 | 86 | console.log(arr); 87 | ``` 88 | 89 | 어떻게 나올지는 항상 언제 물어봐도 메모리 그림을 그려 대답할 수 있도록 하자. 90 | 91 | ### 참고자료 92 | 93 | - [메모리 저장구조 이해하기](https://m.blog.naver.com/PostView.nhn?blogId=itperson&logNo=220821884483&proxyReferer=https%3A%2F%2Fwww.google.com%2F) 94 | - [TCP school 메모리의 구조](http://tcpschool.com/c/c_memory_structure) 95 | -------------------------------------------------------------------------------- /CS/Radix-sort.md: -------------------------------------------------------------------------------- 1 | # 기수 정렬(Radix Sort) 2 | 3 | 비교(comparison) 기반 정렬 알고리즘의 가장 낮은 복합도는 `O(nlogn)` 이다. 4 | 5 | 반면 계수 정렬(counting sort)은 선형 시간 정렬 알고리즘이다. 검색 대상의 범위가 1부터 k까지라고 할 때 `O(n+k)` 의 복합도를 가진다. 6 | 7 | > [선형 시간(lineart time)](https://ko.wikipedia.org/wiki/%EC%84%A0%ED%98%95_%EC%8B%9C%EA%B0%84) : 계산 복잡도 이론에서 입력된 길이 n에 대하여 실행시간이 `O(n)` 이 되는 것 8 | > 9 | > 참고 : [계수 정렬](https://github.com/Im-D/Dev-Docs/blob/master/CS/Counting-sort.md) 10 | 11 | 하지만 대상의 범위 k가 n^2 보다 커질 경우 `O(n^2)` 이상의 복잡도를 가지게 된다. 이는 비교 기반 정렬 알고리즘보다 성능이 좋지 않다. 12 | 13 | 이런 경우 기수 정렬을 통해 선형 시간을 갖는 정렬을 할 수 있다. 14 | 15 | ## 수행과정 16 | 17 | 기수 정렬은 각 자릿수마다 순차적으로 정렬하는 방식이다. 18 | 19 | 10진수를 사용한다면 각 자릿수는 최소 0에서 최대 9까지의 값만 나올 수 있다. 20 | 21 | 따라서 각 자릿수 마다 계수 정렬을 실행한다면, 계수 정렬 대상의 수는 항상 10 이하로 정해진다. 22 | 23 | > 계수 정렬을 사용하기 때문에 부동 소수점은 정렬이 불가능하다. 24 | 25 | 수행과정은 다음과 같다. 26 | 27 | ```java 28 | // 정렬 대상 29 | int arr[] = {170, 45, 75, 90, 802, 24, 2, 66}; 30 | int max = 정렬 대상의 최대값 31 | 32 | for (자릿수 = 1; max/자릿수 > 0; 자릿수 *= 10) { 33 | 계수정렬 실행 34 | } 35 | ``` 36 | 37 | > 참고 : [수행과정 - Radix Sort | GeeksforGeeks](https://youtu.be/nu4gDuFabIM?t=18) 38 | 39 | 40 | 41 | 자릿수의 개수만큼 반복해야하기 때문에 최고 자릿수가 `d` 일 때 기수 정렬의 시간 복잡도는 `O(dn)` 이다. 예를 들어, 가장 큰 수가 10000이라면, 최고 자릿수가 5이기 때문에 `O(5n)` 이 된다. 42 | 43 | 따라서 특정 조건을 만족하면 아주 빠른 알고리즘이지만, 자릿수 만큼의 저장 공간이 추가로 발생하기 때문에 공간 복잡도가 좋지 않다. 44 | 45 | ## 기수 정렬의 다른 방법 46 | 47 | 위에서 알아본 계수 정렬 방법은 일반적인 방법으로 가장 오른쪽 부터 시작하는 LSD radix sort이다. 반대로 가장 왼쪽 부터 시작하는 경우는 MSD라고 한다. 48 | 49 | > LSD(Least Significant Digit; 최하위 자릿수) 50 | > 51 | > MSD(Most Significant Digit; 최대 자릿수) 52 | 53 | LSD의 경우 stable하지만, MSD는 stable 하지 않다. 따라서 기수 정렬의 서브루틴으로 계수 정렬을 사용하기 위해서는 LSD를 사용해야한다. 54 | 55 | LSD는 모든 자릿수를 정렬해야 정렬된 결과를 얻을 수 있지만, MSD의 경우 중간에 정렬이 완료될 수 있다. 하지만 이를 위해 추가적인 연산과정과 메모리가 필요하다. 자세한 사항은 다음을 참고하자. 56 | 57 | > 참고 : [In-place MSD radix sort implementations - wikipedia](https://en.wikipedia.org/wiki/Radix_sort#In-place_MSD_radix_sort_implementations) 58 | 59 | ### 버킷 정렬(bucket sort) 60 | 61 | 이외에도 큐 혹은 버킷을 이용하여 기수 정렬을 구현하는 경우가 있다. 이는 버킷 정렬을 사용한다. 62 | 63 | ![bucketsort](../assets/images/bucket-sort.png) 64 | 65 | 버킷 정렬은 정렬 대상의 값들이 일정하게 분포되어 있을 때 효과적인 방법이다. 66 | 67 | 값의 분포에 따라 특정 범위를 지정한다. 이 때, 지정한 범위가 버킷이다. 68 | 69 | 범위에 해당되는 값들을 각 버킷에 담고 버킷 내의 값들을 정렬하는 방법이다. 70 | 71 | 이 때, 버킷 내의 값들은 버킷 정렬을 반복하여 적용시키거나, 다른 알고리즘을 사용하여 정렬한다. 72 | 73 | 이러한 원리를 이용하여 기수 정렬을 병렬 컴퓨팅에 적용하는 경우도 있는데 이는 다음을 참고하자 74 | 75 | > 참고 76 | > 77 | > - [Application to parallel computing - wikipedia](https://en.wikipedia.org/wiki/Radix_sort#Application_to_parallel_computing) 78 | > - [Fastest sorting algorithm for distributed systems (Parallel Radix Sort) [Difficulty: Medium]](https://summerofhpc.prace-ri.eu/fastest-sorting-algorithm-for-distributed-systems-parallel-radix-sort-difficulty-medium/) 79 | 80 | --- 81 | 82 | References 83 | 84 | - [Bucket Sort - GeeksforGeeks](https://www.geeksforgeeks.org/bucket-sort-2/) 85 | - [What are the differences between radix sort and bucket sort? - Quora](https://www.quora.com/What-are-the-differences-between-radix-sort-and-bucket-sort) 86 | - [Radix Sort - BRILLIANT](https://brilliant.org/wiki/radix-sort/) 87 | - [Radix sort - wikipedia](https://en.wikipedia.org/wiki/Radix_sort) 88 | - [기수 정렬(Radix Sort) - tubuk.tistory.com](https://tubuk.tistory.com/16) 89 | -------------------------------------------------------------------------------- /CS/cohension&coupling.md: -------------------------------------------------------------------------------- 1 | # 응집도(Cohension)와 결합도(Coupling) 2 | 3 | 좋은 프로그램은 높은 응집도와 낮은 결합도를 가진다. 4 | 5 | ## 응집도 6 | 7 | 응집도는 모듈 내부의 기능적인 응집 정도를 뜻한다. 이상적인 응집도는 모듈 내부의 모든 기능이 단일한 목적을 위해 수행되는 것이다. 응집도는 클 수록 좋다. 8 | 9 | * 기능적 응집도(Functional Cohesion) 10 | * 모듈 내부의 모든 기능이 단일한 목적을 위해 수행되는 경우 11 | * 순차적 응집도(Sequential Cohesion) 12 | * 모듈 내에서 한 활동으로 부터 나온 출력값을 다른 활동이 사용할 경우 13 | * 교환적 응집도(Communication Cohesion) 14 | * 동일한 입력과 출력을 사용하여 다른 기능을 수행하는 활동들이 모여있을 경우 15 | * 절차적 응집도(Procedural Cohesion) 16 | * 모듈이 다수의 관련 기능을 가질 때 모듈 안의 구성요소들이 그 기능을 순차적으로 수행할 경우 17 | * 시간적 응집도(Temporal Cohesion) 18 | * 연관된 기능이라기 보단 특정 시간에 처리되어야 하는 활동들을 한 모듈에서 처리할 경우 19 | * 논리적 응집도(Logical Cohesion) 20 | * 유사한 성격을 갖거나 특정 형태로 분류되는 처리 요소들이 한 모듈에서 처리되는 경우 21 | * 우연적 응집도(Coincidental Cohesion) 22 | * 모듈 내부의 각 구성요소들이 연관이 없을 경우 23 | 24 | > 우연적 응집도 < 논리적 응집도 < 시간적 응집도 < 절차적 응집도 < 교환적 응집도 < 순차적 응집도 < 기능적 응집도 25 | 26 | 위에서 아래로 내려올 수록 응집도가 낮아진다(나빠진다)고 할 수 있다. 기능적 응집도가 이상적인 응집정도이다. 27 | 28 | ## 결합도 29 | 30 | 결합도는 의존성 정도이다. 이상적인 결합도는 인터페이스의 파라미터를 통해서만 상호 작용이 일어나며, 파라미터는 값으로 이루어져야 한다. 결합도는 낮을 수록 좋다. 31 | 32 | * 자료 결합도(Data Coupling) 33 | * 모듈간의 인터페이스 전달되는 파라미터를 통해서만 모듈간의 상호 작용이 일어나는 경우 34 | * 깔끔한 Call by value 35 | * 스탬프 결합도(Stamp Coupling) 36 | * 모듈간의 인터페이스로 배열이나 오브젝트, 스트럭쳐등이 전달되는 경우 37 | * 제어 결합도(Control Coupling) 38 | * 단순히 처리를 해야할 대상인 값만 전달되는게 아니라 어떻게 처리를 해야 한다는 제어 요소(명령어, Flag등)이 전달되는 경우. 39 | * 외부 결합도(External Coupling) 40 | * 어떤 모듈에서 반환한 값을 다른 모듈에서 참조해서 사용하는 경우 41 | * 공통 결합도(Common Coupling) 42 | * 파라미터가 아닌 모듈 밖에 선언되어 있는 전역 변수를 참조하고 전역변수를 갱신하는 식으로 상호작용하는 경우 43 | * 내용 결합도(Content Coupling) 44 | * 다른 모듈 내부에 있는 변수나 기능을 다른 모듈에서 사용 하는 경우 45 | 46 | > 자료 결합도 < 스탬프 결합도 < 제어 결합도 < 외부 결합도 < 공통 결합도 < 내용 결합도 47 | 48 | 위에서 아래로 내려올 수록 결합도가 커진다(나빠진다)고 할 수있다. 자료 결합도가 가장 이상적인 결합정도이다. 49 | 50 | --- 51 | 52 | #### References 53 | 54 | - [응집도(Cohension)](http://itwiki.kr/w/%EC%9D%91%EC%A7%91%EB%8F%84) 55 | - [결합도(Coupling)](http://itwiki.kr/w/%EA%B2%B0%ED%95%A9%EB%8F%84) 56 | 57 | -------------------------------------------------------------------------------- /CS/information_theory.md: -------------------------------------------------------------------------------- 1 | # 정보이론 2 | 3 | ## 소통 4 | 5 | 소통에는 늘 잡음이 낀다. 6 | 7 | 이웃이 주식으로 돈을 좀 많이 벌었다라는 사실이 있다면 정보는 왜곡되고 과장이 되기 마련이다. 8 | 그 이웃은 돈을 벌어 집도 사고 차도 새로 뽑는다. 친구의 뒷통수를 쳐 돈을 벌었으며 곧 해외로 도망간단다. 9 | 10 | 꼭 소문만이 아니다. 실제로 정보의 통신에는 잡음이 낀다. 무전기로 통신을 할 때 잡음이 생기는걸 생각해보면 된다. 11 | 12 | 신호는 전송 도중 에너지를 빼앗겨 그 신호가 약해진다. 봉화에 불을 붙이면 가까이선 잘 보이지만 멀리선 당연히 잘 안 보인다. 13 | 14 | 0과 1로 이루어진 신호 역시 통신시에는 잡음이 생긴다. 15 | 16 | ## 통신과 잡음 17 | 18 | 우리가 컴퓨터로 통신할 때 잡음이 생긴다면 어떨까? 내가 1000만원을 송금했는데 잡음이 생겨 0이 하나 빠져 100만원이 송금된다면? 끔찍하다. 19 | 20 | 그럼 어떻게 메시지를 온전하게 전달할 수 있을까? 정보를 온전히 전달하는 기술은 정보이론에 기초한다. 정보이론은 1948년 클로드 섀년이 그의 나이 32세에 탄생시킨다. 21 | 22 | ### 잡음에 대한 다른 시각 23 | 24 | 통신에는 잡음이 생긴다고 했다. 1948년에는 잡음은 물리적인 현상이며 이를 물리(하드웨어, 아날로그)적인 방식으로 어떻게 극복할 수 있을까 고민했다. 25 | 26 | 메시지 전달속도를 높이려면 주파수를 높이거나, 잡음이 생긴다면 신호를 강하게 만들면 된다거나 하는 방법으로 말이다. 27 | 28 | 하지만 섀년은 달랐다. 하드웨어가 아니라 소프트웨어(보내려는 메시지)적인 방법으로 해결하고자 했다. 29 | 30 | ## 정보량 31 | 32 | 소프트웨어인 메시지에 주목하고자 먼저 한 일은 정보량에 대해 정리하는 일이었다. 33 | 34 | 정보의 양은 뭘까? 섀넌은 확률을 기준으로 정보량을 정리했다. 35 | 36 | 예를들어 '하겠습니' 다음에는 '다'가 나올 확률이 '까'가 나올 확률보다 훨씬 높다. '하겠습니다'는 '하겠습니까'보다 자주 나오므로 예측하기 쉽다. 예측하기 쉬우면 정보의 양이 적다. 37 | 38 | 왜 예측하기 쉬우면 정보의 양이 적을까? 쉽게 장마철을 생각해보자. 장마철에 비가오는건 당연하다. 확률이 높다. 장마철에 내일도 비가 올 것입니다 라는 정보는 그다지 중요하지 않다. 39 | 40 | 반대로 가뭄에 비가 올 확률은 매우 적다. 한 달 동안 가뭄인 상태에서 내일은 드디어 비가 올 것 같습니다 라는 정보는 훨씬 더 중요하다. 즉 훨씬 더 중요하며 정보량이 많다. 41 | 42 | 위의 논리라면 알파고의 78수가 나올 확률은 0.007%이며 이는 매우 중요한 정보라는 것이 증명된다. 43 | 44 | ### 엔트로피 45 | 46 | 이는 엔트로피의 개념과 같다. 나는 문과 출신이라 엔트로피에 대해 잘 모른다. 쉽게 무질서의 정도라고 한다. 47 | 48 | 예를들어 문서에 a, b, c, d만 등장하며, 각각의 문자가 등장할 확률이 모두 25%로 같다고 하자. 그렇다면 이 문서의 정보량은 엔트로피의 공식에 의해 2라고 한다. 49 | 50 | 확률이 모두 같다면 가장 정돈된 상태다. 가장 정돈된 상태가 네 글자로 만들 수 있는 최대 정보량이다. 확률이 달라진다면 어떤 글자가 나올지 예측하기가 쉬워지며 정보의 양이 줄어든다. 51 | '하겠습니' 뒤에는 '다'가 나올 확률이 높으니 정보가 줄어드는 것처럼 영어에는 e가 제일 많이 나와 정보의 양이 줄어든다. 52 | 53 | 즉 확률이 서로 다르면 무질서한 상태가 된다. 무질서할수록 정보의 양은 줄어든다. 54 | 55 | ### 정보량과 잡음 56 | 57 | 아까도 말했듯 통신에는 잡음이 생긴다. 이를 물리적인 방법으로 해결하는 데에는 한계가 있다. 메시지의 강도를 높이면 잡음도 심해지기 때문이다. 58 | 59 | 섀넌은 통신의 한계는 물리적인 것에 있다고 보지 않았다. 통신의 한계점은 정보량에 기준한다는 새로운 패러다임을 제시한다. 60 | 61 | 정보량은 초당 H이며 온전히 전달할 수 있는 채널 용량이 초당 C라고 가정하자. 62 | H <= C 라면 정보에 비해 용량이 크므로 온전하게 전달 할 수 있다. 63 | H > C 라면 잡음은 H-C미만으로 줄일 수 없다. 64 | 65 | 섀넌은 위와 같은 정의를 내린다. 66 | 67 | 이에 C를 키우기 위해 신호의 전력을 키우면 잡음도 증가한다를 수식적으로 증명한다. 68 | 69 | 기존의 개념은 채널의 용량인 C를 키워 통신을 온전하게 만들자는 것이었다. 하지만 섀넌은 잡음을 더 줄일 수 없으니 H를 줄이자라는 길을 제시했다. 70 | 71 | H는 정보의 양이며 정보량을 줄이는 방법은 엔트로피를 조정하면 된다. 이 개념에서 시작된 것이 압축이다. 72 | 73 | --- 74 | 75 | 참고자료 76 | 77 | - [정보이론 1편](https://brunch.co.kr/@chris-song/68) 78 | - 컴퓨터과학이 여는 세계, 이광근, 인사이트 79 | - 성공과 실패를 결정하는 1%의 네트워크 원리, Tsutomu Tone, 이도희 역, BM성안당 80 | -------------------------------------------------------------------------------- /CS/non-blocking.md: -------------------------------------------------------------------------------- 1 | # non-blocking 2 | 3 | Non-blocking은 os와 알고리즘에 대한 것이다. 공유자원을 안전하게 동시 사용할 수 있도록 하는 방법론이다. 4 | 5 | Non-blocking은 하나의 작업이 실패하거나 정지하더라도 다른 스레드에 영향을 주지 않도록 한다. 이를 위해 Non-blocking 알고리즘은 [lock-free](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Lock-freedom) 특성과 [wait-free](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom) 특성을 포함한다. lock-free는 wait-free를 포함하는 개념이다. 이로인해 non-blocking은 동시성(concurrency)을 갖는다. 6 | 7 | > 동시성 : 프로그램을 실행할 때 단 하나의 실행 순서를 갖도록 하는 제약을 없애고 각 부프로그램이 다른 부프로그램과 병렬적으로 동시에 실행되는 것 8 | 9 | lock-free 알고리즘이라는 것은 하나의 작업이 시작되어도, 시스템 전체의 진행이 보장되는 것이다.(A non-blocking algorithm is lock-free if there is guaranteed system-wide progress)
10 | wait-free 알고리즘은 각 스레드의 진행이 각각 보장되는 것(A non-blocking algorithm is wait-free if there is also guaranteed per-thread progress)이다.
11 | ![non-blocking i/o](/assets/images/non-blocking.png) 12 | blocking 모델은 요청이 동작 가능할때까지 스레드가 블록된다. 반면, non-blocking 모델은 요청이 동작 불가능하다는 것을 알려주어 블록상태 없이 계속해서 진행가능하다. 즉, 다른 스레드의 작업을 기다리지 않는다. 이를 통해 대기 상태 없이 공유 자원에 접근할 수 있다. 13 | 14 | > Java의 멀티 스레드 어플리케이션에서 Synchronized를 시키는 것은 BlockingQueue Interface를 구현하는 것이라고 생각하면 된다. 당연히 non-blocking은 이와 반대다. 15 | 16 |
17 | 18 | ## Non-blocking I /O 19 | 20 | Non-blocking I/O 는 I/O와 관계없이 프로세스가 계속해서 진행되는 것을 뜻한다. 기존 방식(blocking 혹은 synchronous한 I/O모델)에서는 I/O처리를 시작하면 작업이 끝날 때 까지 기다려야한다. 즉 프로그램이 block된다. 반면, Non-blocking I/O 모델에서는 입,출력을 외부에 맡겨 I/O의 진행 상황과 관계없이 프로그램이 진행된다. 21 | 22 |
23 | 24 | ## Asynchronous Programming과 Non-blocking I/O 25 | 26 | 프로그램의 주 실행흐름을 멈추거나, 대기 상태 없이 즉시 다음 작업을 수행할 수 있도록 하는 것이 asynchronous 방식이다. 27 | 28 | Ansynchronous programming은 언어 차원에서 지원하거나, 함수 전달을 통해 처리하는 방식을 통해 구현한다.
언어차원에서 지원하는 방식은 future, promise와 같이 객체 형태의 결과를 돌려받거나 특정 문법을 이용하여 구현할 수 있다.
함수 전달을 통해 처리하기 위해서는 함수를 값처럼 사용(일급 함수)를 지원하는 언어에서 Callback을 전달하여 결과를 처리할 수 있다. 29 | 30 | non-blocking 알고리즘과, non-blocking I/O 모델의 관점이 다른 것 처럼, Asnychronous programming은 Asynchronous I/O 와 다르다. 따라서 Asnychronous programming과 Non-blocking I/O는 서로 바라보는 관점이 다르다. Event-loop를 사용하여 동시성을 확보하였어도 I/O 작업이 blocking될 수 있기 때문이다. 31 | 32 |
33 | 34 | 만약 I/O 모델들의 조합을 알아보고 싶다면 다음을 참고하길 바란다. - [Asynchronous IO 개념 정리 - Uno's Blog](https://djkeh.github.io/articles/Boost-application-performance-using-asynchronous-IO-kor/) 35 | 36 | --- 37 | 38 | #### Refereces 39 | 40 | - [Non-blocking Algorithms - jenkov.com](http://tutorials.jenkov.com/java-concurrency/non-blocking-algorithms.html) 41 | - [Blocking and Non-Blocking Algorithms - modernescpp](https://www.modernescpp.com/index.php/blocking-and-non-blocking) 42 | - [Non-Blocking Algorithms in Java - netjs.blogspot.com](https://netjs.blogspot.com/2016/06/non-blocking-algorithms-in-java.html) 43 | - [Non-blocking algorithm - wikipedia](https://en.wikipedia.org/wiki/Non-blocking_algorithm) 44 | - [멈추지 않고 기다리기(Non-blocking)와 비동기(Asynchronous) 그리고 동시성(Concurrency) - Peoplefund Tech](https://tech.peoplefund.co.kr/2017/08/02/non-blocking-asynchronous-concurrency.html) 45 | -------------------------------------------------------------------------------- /CS/non-linear-search.md: -------------------------------------------------------------------------------- 1 | # 비선형(Non-Linear) 구조의 탐색 2 | 3 | ## 선형 구조 4 | 5 | 선형 구조를 간단히 설명하면, 말 그대로 진행하는 방향이 직선으로(일자로) 되어있는 구조이다. 알고리즘에서는 데이터가 연속적으로 연결되어있는 모양으로 구성이 된 것을 선형 구조라 한다. 선형 구조는 연결리스트, 스택, 큐, 덱 등이 있다. 6 | 7 | > 선형 구조를 탐색하는 일반적인 방법론에는 순차검색과 이진검색이 있다. 8 | 9 |
10 | 11 | ## 비선형 구조 12 | 13 | 비선형 구조는 선형이 아닌 구조이다. 어떤 원소를 탐색했을 때 다음에 탐색할 수 있는 원소가 여러 개 존재하는 구조가 비선형 구조이다. 비선형 구조는 트리나 그래프 형태로 표현할 수 있다. 14 | 15 | > 트리는 순환(cycle)이 없는 그래프이다. 16 | 17 |
18 | 19 | ## 비선형 구조 탐색 20 | 21 | 비선형 구조는 탐색해야 할 데이터가 순차적이지 않다. 따라서 단순한 반복만으로 탐색할 수 없다. 이 때문에 스택이나 큐와 같은 자료구조를 활용하여 탐색할 방법과 순서를 만들어 탐색한다. 일반적으로 깊이우선탐색(depth first search; DFS)과 너비우선탐색(breadth first search; BFS)을 이용한다. 만약 탐색 대상이 그래프일 경우 탐색이 완료되면 [신장트리(spanning tree)](http://59.23.150.58/30stair/spanning_tree/spanning_tree.php?pname=spanning_tree#spanning)가 만들어진다. 22 | 23 | ![search](../assets/images/non-linear-search.gif) 24 | 25 | > DFS와 BFS는 완전 탐색을 위한 방법이며, 가중치가 있는 그래프의 최단 거리를 찾기 위해서는 다익스트라와 플로이드-워셜 알고리즘이 주로 사용된다. 26 | 27 |
28 | 29 | ### 깊이우선탐색(DFS) 30 | 31 | 시작점에서 더는 이동할 수 없는 지점까지 탐색한 뒤, 인접한 정점이 있었던 곳으로 돌아가 같은 방법으로 차례로 탐색하는 방법이다. 이때 시작점(부모노드)으로 되돌아오는 과정을 백트래킹이라고 한다. 32 | 33 | 이러한 탐색 과정은 스택을 이용하는 것과 동일하기 때문에 스택을 사용하거나 재귀호출을 이용하여 구현한다. 34 | 35 | ![dfs](../assets/images/non-linear-search-dfs.png) 36 | 37 | 현 경로상의 노드만 기억하면 되기 때문에 저장공간이 비교적 적게 필요하다. 또한, 목표 노드가 깊을 경우 유리하다. 38 | 39 | 반면, 해가 없는 너무 깊은 곳까지 탐색하게 되거나 목표에 이르는 경로가 많을 경우 비효율적이다. 또한, 찾은 경로가 최단 거리가 아닐 수 있다. 40 | 41 | > 재귀호출을 하면 스택을 사용하는 것과 같은 효과를 낼 수 있다. 42 | 43 |
44 | 45 | ### 너비우선탐색(BFS) 46 | 47 | 시작 정점을 방문한 후 시작정점에 인접한 모든 정점을 방문한 뒤, 해당 정점들과 인접한 정점을 탐색하는 방법이다. 이는 큐와 동일하다. 48 | 49 | ![bfs](../assets/images/non-linear-search-bfs.png) 50 | 51 | 하나의 레벨에서 보행 가능한 정점을 모두 찾아보기 때문에 목표 노드까지의 최단 길이가 결과로 나오는 것이 보장된다. 52 | 53 | 반면, 경로가 길 경우(깊을 경우) 많은 기억 공간이 필요하다. 또한, 무한그래프의 경우 탐색이 불가능하다. 54 | > 무한 그래프는 정점이 무한한 그래프를 뜻한다. 55 | > - DFS의 경우 하나의 정점의 결과값을 찾아 들어가기 때문에 무한한 정점 중에서 하나의 해를 구할 수 있으면 된다. 56 | > - 반면 BFS의 경우, 정점이 무한하다면 다음 수준으로 나아가는 것 자체가 불가능해진다. 57 | 58 | --- 59 | 60 | #### References 61 | 62 | - [[알고리즘] 비선형구조의 탐색, 그래프의 구현 - https://12bme.tistory.com](https://12bme.tistory.com/123) 63 | - [깊이*우선*탐색 - 위키백과](https://ko.wikipedia.org/wiki/%EA%B9%8A%EC%9D%B4_%EC%9A%B0%EC%84%A0_%ED%83%90%EC%83%89) 64 | - [너비*우선*탐색 - 위키백과](https://ko.wikipedia.org/wiki/%EB%84%88%EB%B9%84_%EC%9A%B0%EC%84%A0_%ED%83%90%EC%83%89) 65 | - [[그래프] DFS와 BFS 구현하기 :: 마이구미 - https://mygumi.tistory.com](https://mygumi.tistory.com/102) 66 | - [[DFS][BFS] DFS 와 BFS - https://cru6548.tistory.com](https://cru6548.tistory.com/10) 67 | -------------------------------------------------------------------------------- /CS/soc.md: -------------------------------------------------------------------------------- 1 | # 관심사 분리(Separation of Concerns; SoC) 2 | 3 | 관심사 분리는 프로그램의 각 부분이 자신의 관심사만을 다루도록 분리되어야 한다는 것이다. 여기서 `관심사`란 프로그램 코드에 영향을 주는 일련의 정보를 의미한다. 4 | 5 | > **예시** 6 | > 자동차 창문을 여는 장치가 망가져 수리를 한다. 간단한 고장이기 때문에 금방 수리를 했다. 7 | > 하지만 창문은 잘 고쳤는데 갑자기 시동이 걸리지 않는다. 원인은 자동차를 자동차를 제어하는 배선이 너무 복잡해 창문을 제어하는 배선을 만지면 차량의 시동을 거는 배선에도 영향을 주기 때문이었다. 8 | > 만약 창문을 제어하는 배선과 시동을 거는 배선이 잘 분리되어 있다면 이런 일은 발생하지 않았을 것이다. 9 | 10 | 만약 위의 예시를 프로그램화 했다면 창문을 제어하는 기능과 시동을 거는 기능을 분리하는 것으로 생각해볼 수 있다. 이처럼 각 기능들이 서로 얽히지 않고 각각의 역할만 하도록 하는 것을 관심사 분리라고 한다. 각각의 모듈은 각자의 기능만을 해결해야 한다. 11 | 12 | 관심사 분리는 추상화의 한 형태이다. 때문에 관심사 분리를 위해서 캡슐화가 잘 되어야 한다. 기능의 구현은 내부적으로 숨겨놓고 해당 모듈을 실행시켰을 때 정확한 기능이 동작하도록 보장되어야 한다. 인터페이스 뒤에 모듈의 구현 세부사항을 숨기면 다른 부분의 세부사항을 알 필요 없이 해당 코드를 개선하거나 수정할 수 있다. 이렇게 되면 다른 기능에 영향을 주지 않고 유지 보수가 가능하다. 13 | 14 | 계층화(layered) 된 설계는 관심사 분리의 좋은 예시이다. 예를들어 MVC패턴의 각 계층(layer)은 각각의 관심사만을 수행하도록 구성된다. 이외에도 객체 지향 언어에서는 관심사를 객체로 분리할 수 있으며 절차 지향 언어에서는 관심사를 메소드 혹은 프로시저로 분리할 수 있다. 15 | 16 | 웹 프로그램을 개발할 때 JSP 파일 안에 SQL을 작성하지 않는다. 결과를 계산하는 모듈에서 HTML 파일을 생성하지 않는다. 또한 비즈니스 규칙은 데이터베이스 스키마와 독립적으로 이루어져야한다. 만약 그렇게 작성한다면 하나의 기능에 대한 수정때문에 모든 기능이 중단될 수 있다. 이는 관심사 분리를 해야하는 이유이다. 17 | 18 | --- 19 | 20 | #### References 21 | 22 | - [The Single Responsibility Principle](https://blog.cleancoder.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html) 23 | -------------------------------------------------------------------------------- /CS/페이징과 세그먼테이션.md: -------------------------------------------------------------------------------- 1 | # 페이징 기법과 세그먼트 기법 2 | 3 | ## 가상기억장치 4 | 5 | 가상기억장치는 **주기억장치의 용량이 부족할 때 하드디스크의 일부 공간을 마치 주기억장치처럼 사용하는 기억장치**를 말한다. 6 | 가상기억장치에 프로그램을 저장할 때는 불필요한 메모리 낭비를 줄이기 위해 프로그램을 여러 개의 블록 단위로 나눠 보관한다. 각각의 블록은 **mapping** 과정을 통해 주기억장치에 적재된다. 7 | 주기억장치와 가상기억장치 간 프로세스를 무슨 단위로 load하고 store할지 정하는 방법에는 페이징 기법과 세그먼테이션 기법이 있다. 8 | 9 |
10 | 11 | ## 페이징 기법 12 | 13 | ### Page와 Page frame, Swapping 14 | 15 | ![Page Pageframe](../assets/images/page_pageframe.png) 16 | 17 | 우선 페이징 기법은 위 그림과 같이 가상기억장치의 블록을 **고정 크기**로 나눈다. 이 블록을 **Page** 라고 부르며, 프로그램 실행시 요구되는 블록만 주기억장치에 적재된다. 주기억장치의 메모리 역시 Page와 같은 단위의 블록으로 나뉘는데, 이 명칭을 **Page frame** 이라고 한다. 18 | 주기억장치에 모든 작업이 상주하지 않기 때문에 프로그램 실행 중 필요한 부분만 교체할 수 있다. 이를 **Swapping** 이라고 한다. 19 | 20 |
21 | 22 | ### Page mapping - Page fault 23 | 24 | Page mapping 과정을 위해서는 주기억장치에 **Page table** 이 생성된다.(때문에 Page의 크기가 작을수록 더 많은 주기억장치의 메모리가 낭비된다.) Page table은 Page의 번호, Page Frame의 시작주소 등이 저장되어있다. 25 | Page frame에 적재되는 Page가 교체되거나 Page fault가 발생할 때마다 Page Table은 갱신된다. 26 | 27 | **Page fault** 는 프로그램에서 필요로 하는 Page가 주기억장치에 있지 않는 경우에 발생하는 현상이다. Page fault가 발생하면 Page를 찾아 mapping하고 Page Table이 갱신되는 일이 발생된다. 이러한 현상을 줄이기 위해서 Page frame의 크기를 늘릴 수 있다. 28 | 29 |
30 | 31 | ### Thrashing 32 | 33 | 너무 많은 Page fault 현상으로 페이지 교체 시간이 프로세스 수행 시간보다 많은 경우를 말한다. Thrashing이 발생하면 CPU 이용률이 급격히 감소하므로 이를 방지하기 위해 다중 프로그래밍의 정도를 낮추거나 Page frame의 크기를 늘려야 한다. 34 | 35 |
36 | 37 | ### 내부단편화 38 | 39 | 프로그램의 크기가 30k이고, 각 page의 고정 크기가 4k라고 한다면 마지막 page의 실질적 크기는 2k가 될 것이다. 따라서 마지막 page가 주기억장치에 적재될 때 2k만큼의 **내부단편화**가 발생된다. 즉 필요한 공간보다 더 큰 메모리가 할당되어 불필요하게 메모리가 낭비되는 현상을 내부단편화라고 한다. 이를 해결하기 위해 page를 작게 만들 수도 있지만 위에서 언급했듯이 page를 무조건 작게 만드는 것이 능사는 아니다. 40 | 41 |
42 | 43 | ## 세그먼테이션 기법 44 | 45 | 세그먼테이션 기법은 페이징 기법과 달리 프로그램을 기능별로 분할하는 것을 말한다. 또한 주기억장치는 구분하지 않고, 전체를 비연속적으로 할당받는다. 따라서, 페이징 기법이 프로그램을 물리적으로 분할한 개념이라면 세그먼테이션은 논리적으로 분할한 개념이다. 46 | 47 | ![segmentation](../assets/images/segmentation.png) 48 | 49 | ### Seg fault, 외부 단편화 50 | 51 | 세그먼테이션 기법에서는 세그먼트 길이에 맞는 주기억장치의 영역을 할당받지 못한 경우 해당 프로그램이 다른 프로그램의 영역을 침범하는 **Seg fault**가 발생할 수 있다. 52 | 53 | 또한 고질적인 문제로 **외부단편화**가 발생할 수 있다. 위 그림에서 `B-1`의 크기가 6K,남은 공간이 3K라고 가정해보자. `B-1`의 프로세스가 끝나고 메모리를 해제하면 주기억장치에는 `A-1 / 빈공간(6k) / B-3 / 빈공간(3k)`가 있을 것이다. 여기에 7k 크기의 프로세스가 들어오려고 한다면, 총 공간은 9k지만 각 공간이 7k보다 작기 때문에 적재될 수 없다. 이런 현상을 외부 단편화라고 한다. 이를 해결하기 위해 `통합` 또는 `압축`을 할 수 있다. 54 | 55 | 다음의 그림과 같이, 통합은 빈 공간의 주소가 인접한 경우 하나로 합치는 방법이고 압축은 프로세스의 재배치를 통해 모든 빈 공간을 하나로 합치는 방법이다. 56 | 57 | ![coalescing](/assets/images/coalescing.png) 58 | ![compaction](/assets/images/compaction.png) 59 | 60 | 61 | 62 | #### Reference 63 | [특수기억장치 및 기억장치의 분류](http://junhojohn.blogspot.com/2018/11/blog-post_12.html) -------------------------------------------------------------------------------- /Deprecated/AMD와 CommonJS.md: -------------------------------------------------------------------------------- 1 | # AMD와 CommonJS 2 | 3 | ## 배경 4 | 5 | 자바스크립트(ES5 기준)는 파이썬, 루비, 다른 스크립트 언어 계열과 차이점이 존재한다. 6 | 7 | 바로 **모듈 사용의 표준이 존재하지 않는다는 것**이다. 8 | 9 | Node.js를 사용하고 있는 개발자들은 `module.exports`를 통해 모듈을 정의하고 `require()` 함수를 통해 정의한 모듈을 불러와 사용하고 있다. 10 | 11 | 이러한 방식을 **CommonJS**라고 한다. 12 | 13 | 프론트엔드에서는 위와 같은 모듈 제공 방식이 없었다. 14 | 15 | 이에 따라 `window`객체를 이용하여 모듈의 리소스를 전달하는 방식을 이용했었다. 16 | 17 | ```js 18 | //math.js 19 | var sum = function() { 20 | var total = 0; 21 | for (var idx in arguments) { 22 | total += arguments[idx]; 23 | } 24 | return total; 25 | }; 26 | 27 | window.Math = { 28 | sum: sum 29 | }; 30 | ``` 31 | 32 | ```js 33 | //main.js 34 | if (typeof Math !== 'undefined') { 35 | if (typeof Math.sum === 'function') { 36 | console.log(Math.sum(1, 2)); 37 | } else { 38 | throw new Error('Math.sum function is not defined.'); 39 | } 40 | } else { 41 | throw new Error('A module `Math` is undefined.'); 42 | } 43 | ``` 44 | 45 | 위 소스를 보면 **전역 오브젝트인 `window` 객체를 통해 다른 자바스크립트 파일에 리소스를 전달** 하고 있다. 46 | 47 | 하지만 이것도 사용하는 HTML에서 불러오는 모듈 파일을 먼저 로드해야한다. 48 | 49 | 즉, **대상 모듈이 존재할수도, 존재하지 않을 수도 있는 상태**가 된다. 50 | 51 | 이후 점차 프로젝트 규모가 커지게 되면서 프론트엔드에서 좀 더 효율적인 모듈화를 제공하기 위헤 `AMD`와 `CommonJS` 방식이 생겨나게 됐다. 52 | 53 |
54 | 55 | ## AMD(Asynchronous Module Definition) 56 | 57 | AMD에서는 `define`을 사용한다. 58 | 59 | ```js 60 | //math.js 61 | define([], function() { 62 | return { 63 | sum: function() { 64 | var total = 0; 65 | for (var idx in arguments) { 66 | total += arguments[idx]; 67 | } 68 | return total; 69 | } 70 | }; 71 | }); 72 | ``` 73 | 74 | ```js 75 | //main.js 76 | requirejs.config({ 77 | baseUrl: './' 78 | }); 79 | 80 | require(['math'], function(Math) { 81 | console.log(Math.sum(1, 2)); 82 | }); 83 | ``` 84 | 85 | 원래 AMD의 규칙을 따르는 도구를 사용해 모듈을 정의하고 불러와야하지만 위의 코드에선 ReuireJS를 사용했다. 86 | 87 |
88 | 89 | ## CommonJS 90 | 91 | CommonJS 방식은 위에서도 말했듯이 **Node.js에서 사용하고 있는 모듈 방식**이다. 이것이 CommonJS 방식의 제공이 중요한 이유다. 92 | 93 | ```js 94 | module.exports = { 95 | sum: function() { 96 | var total = 0; 97 | for (var idx in arguments) { 98 | total += arguments[idx]; 99 | } 100 | return total; 101 | } 102 | }; 103 | ``` 104 | 105 | ```js 106 | var math = require('./math'); 107 | 108 | console.log(math.sum(1, 2)); 109 | ``` 110 | 111 | ### CommonJS 방식으로 제공되어야 하는 경우 112 | 113 | --- 114 | 115 | * 프론트엔드 라이브러리일지라도 Node.js 코드를 통해 유닛 테스팅을 하는 경우 116 | 117 | * `moment.js`, `underscore.js`처럼 Node.js에서도 사용 가능해야하는 라이브러리 일 경우 118 | 119 |
120 | 121 | ## 모듈 제공의 방향과 ES6 122 | 123 | 이전 Module 제공 방식의 추세가 AMD vs CommonJS였다면, CommonJS와 ES6 타입으로 축약되는 것으로 보인다. 124 | 125 | 즉, **AMD 방식은 사양되는 분위기**다. 126 | 127 | 하지만 여전히 일부 라이브러리가 AMD방식을 사용하고 있어 지금도 번들링은 UMD로 하고 있다. 128 | 129 | 위의 내용까지는 ES5기준으로 본 모듈 방식의 정의고 ES6기준으로 보면 또 다른 모듈 방식이 존재한다. 130 | 131 | **ES6 모듈은 import를 제공하여 모듈을 불러오는 방식**이다. 132 | 133 | require.js와 import를 사용하여 모듈을 불러올 때 각각의 차이 중 하나는 **Tree-Shaking**을 할 때 알 수 있다. 134 | 135 | **`import`를 사용한 방식은 라이브러리의 특정 모듈만을 가져와 번들링할 수 있지만, `require` 방식으로 가져온 라이브러리는 모듈 전체를 번들링**해야한다. 136 | 137 | 즉, **`require` 방식으로 가져온 모듈에 대해서는 Tree-shaking을 진행할 수 없다.** 138 | 139 |
140 | 141 | --- 142 | 143 | #### Reference 144 | 145 | - [자바스크립트 모듈 제공을 위한 AMD, CommonJS 그리고 RequireJS 소개](https://blog.pigno.se/post/157992405313/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%AA%A8%EB%93%88-%EC%A0%9C%EA%B3%B5%EC%9D%84-%EC%9C%84%ED%95%9C-amd-commonjs-%EA%B7%B8%EB%A6%AC%EA%B3%A0-requirejs-%EC%86%8C%EA%B0%9C) 146 | - [JavaScript 표준을 위한 움직임: CommonJS와 AMD](https://d2.naver.com/helloworld/12864) -------------------------------------------------------------------------------- /Deprecated/EventLoop.md: -------------------------------------------------------------------------------- 1 | # 자바스크립트의 이벤트루프와 콜백함수 2 | 3 | ## 이벤트루프와 싱글 쓰레드 4 | 5 | 자바스크립트와 콜백은 뗄레야 뗄 수 없는 관계라고 생각한다. 흔히들 자바스크립트는 싱글쓰레드 기반이라고 얘기합니다. 그게 바로 이벤트루프가 싱글 쓰레드기 때문에 하는 얘기다. 그럼 이 이벤트 루프는 무엇일까? 6 | 7 | ## 자료구조 8 | 9 | 스택은 밑이 비어있는 컵 모양에 넣고 빼는 것이며 큐는 양쪽이 뚫려있는 튜브라고 말한다. 스택은 LIFO이며 큐는 FIFO다. 10 | 11 | 이 자료구조는 자바스크립트 엔진에서 사용됩니다. 바로 호출 '스택'과 태스크 '큐'입니다. 12 | 13 | 호출 스택은 어느 언어에서도 존재한다. 쉽게 생각하자면 [main(), a(), b()] 구조로 호출되면 b -> a -> main 순으로 빠져 나간다. 자 그러면 이제 `setTimeout()`을 생각해보자. 14 | 15 | ```js 16 | function foo() { 17 | console.log('b'); 18 | } 19 | console.log('a'); 20 | setTimeout(foo, 0); 21 | console.log('c'); 22 | ``` 23 | 24 | 이러면 출력결과는 당연히 a -> c -> b가 된다.. 의사코드로 소스를 분석해봅시다. 25 | 26 | 1. a를 출력해라 27 | 2. 0초 뒤에 foo를 실행해라 28 | 3. c를 출력해라 29 | 30 | 그렇다면 a -> b -> c가 되어야 하는것 아닐까 할 수 있다. 이는 호출스택에서는 당연히 맞지만 자바스크립트에서는 그렇지 않다. 자바스크립트는 호출 스택만 사용하지 않기 때문이다. 자바스크립트는 호출스택, 백그라운드, 태스크 큐(es6+부터는 큐 관리방식이 변화되어 태스크 큐 이외도 존재)라는 개념이 존재한다. 31 | [자바스크립트 비동기 작업 3가지](./EventLoop_Advanced.md) 32 | 33 | ![eventLoop](/assets/images/EventLoop.png) 34 | 35 | 이런 구조입니다. 자 이제 코드대로 생각을 해보자. 36 | 37 | 1. main() 스택에 들어감 38 | 2. log("a") 도 스택에 들어간 뒤 실행 39 | 3. setTimeout()이 스택에 들어간 뒤 실행 - 백그라운드에서 0초뒤에 foo를 "실행"시키라고 명령 40 | 4. 0초가 지나 "태스크큐"에 foo()들어감 41 | 5. log("c") 가 스택에 들어간 뒤 실행 42 | 6. main() 종료 43 | 7. 태스크 큐에 있던 foo()를 호출스택에 밀어넣음 (이벤트 루프가 전역 컨텍스트의 main이 종료되면 큐 실행) 44 | 8. foo()가 호출스택에 들어간 뒤 실행 45 | 46 | 이래서 결과가 위와 같았다. 47 | 48 | ## 콜백함수 49 | 50 | 이런 자바스크립트의 싱글 쓰레드 구조에서 비동기성의 이벤트 기반 실행이나 ajax요청이 필요하다면, 콜백 함수를 이용해 백그라운드로 보내고 큐를 통해 호출 스택으로 보내 해결하게 된다. 51 | 52 | 자바스크립트에서는 쓰레드를 통해 병렬처리가 안되기 때문에 콜백함수의 사용은 뗄 수가 없게 되는 것이다. 53 | 54 | ## 큐와 콜백 55 | 56 | 이러한 이벤트 루프의 가장 중요한 점은 바로 위 과정의 3번과 4번 그리고 7번이다. 흔히 setTimeout(foo, 3)이라는 함수를 말할 때 foo 함수를 3초 뒤에 실행시켜라 라고 생각한다. 그러나 4번에 보듯 foo는 일정시간 뒤에 실행되는게 아니라 큐에 들어가게 된다. 57 | 58 | 3번에 `백그라운드에서 0초뒤에 foo를 "실행"시키라고 명령`이라고는 적었지만 정확히 말하자면 `foo를 "큐"에 집어넣어라` 가 맞는 것이다. 큐에 아무것도 없다면 3초뒤에 바로 실행이 되겠지만 만일 다른 콜백으로 인해 다른 작업들이 존재한다면 어떻게 될까?? 59 | 60 | 맞다. 3초가 넘어가서 실행되게 됩니다. setTimeout()이라는 함수는 n초 뒤에 콜백을 단순히 큐에 집어넣는게 끝이다. 이 큐에 들어간 콜백은 이벤트 루프가 스택으로 밀어넣어 실행된다다. 코드를 간단히 보자면 아래와 같다. 61 | 62 | ```js 63 | var eventLoop = []; 64 | var event; 65 | 66 | while (true) { 67 | // 틱! 68 | if (eventLoop.length > 0) { 69 | event = eventLoop.shift(); 70 | } 71 | 72 | try { 73 | event(); // 호출스택으로 밀어넣는다 74 | } catch (err) { 75 | //... 76 | } 77 | } 78 | ``` 79 | 80 | 이 큐에 이미 대기번호가 100개가 있다면 foo는 101번째 대기표를 받게 될 것이다. 따라서 setTimeout()은 지정한 시간동안은 실행되지 않는 것은 보장할 수 있지만 지정한 시간에 실행되는것은 보장할 수 없다! 81 | 82 | ## 현재 이벤트 루프 83 | 84 | es6+부터는 잡큐와 같은 새로운 개념이 등장하고 promise를 이용해 콜백을 처리하게 되는데 이는 나중에 더 다루도록 하겠습니다. 85 | [자바스크립트 비동기 작업 3가지](./EventLoop_Advanced.md) 86 | -------------------------------------------------------------------------------- /Deprecated/Javascript_BuildTool.md: -------------------------------------------------------------------------------- 1 | # Webpack과 Gulp 그리고 Grunt 2 | 3 | 현재 Build Tool의 대세는 당연코 Webpack이다. 그런데 이 이전에는 Gulp와 Grunt가 있었다. 나는 자바스크립트 빌드의 개념을 배울 때 이미 웹팩이 대중화되는 시기였다. 그래서 그냥 웹팩을 사용했다. 그런데 모든 새로운 기술에는 등장이유가 있으며 장점과 단점이 존재한다. 웹팩이 다른 기술들과는 어떤 차이점을 가지는지 간단하게 알아보자. 4 | 5 | ## Webpack과 Gulp&Grunt는 태생부터 다르다 6 | 7 | ### Gulp와 Grunt 8 | 9 | --- 10 | 11 | webpack과 gulp, grunt는 사실 아예 다르다. Gulp와 Grunt(이하 걸프로 통일하겠음)는 Task Runner라고 한다. 12 | 용어로 얘기하면 되게 생소해 보이지만 별건 없다. 간단한 Task를 실행해주는 것이다. uglify나 압축등의 반복 가능한 간단한 작업을 자동화해주는 툴이다. 13 | 14 | ### 서로의 차이점 15 | 16 | --- 17 | 18 | gulp와 grunt의 하는일은 같지만 만들어내는 방식이 다르다. grunt는 package.json처럼 json형식으로 설정을 선언하여 사용한다. 이와 다르게 gulp는 nodeJS의 스트림 기능을 이용하여 자바스크립트 코드를 사용한다. 이건 현재 유행하는 기술도 아니고 크게 중요한 점도 아니니 넘어가도록 하자. 19 | 20 | ## Webpack 21 | 22 | 이전 툴들이 Task Runner인 것과 다르게 웹팩은 이름부터 다르다. `Module Bundler` 혹은 `Package Bundler` 라고 불린다. 모듈 개념은 이미 한 번 정리 했었다. [Module](./Module.md) 23 | 24 | ### 모듈번들러 25 | 26 | --- 27 | 28 | 모듈 번들러가 뭐냐면 이 각각의 모듈들의 의존성을 파악하여 번들(묶는다)해주는 것이다. 모듈과 의존성이라는 단어가 낯설다. 이 단어들에 대해서 다시 생각해보자. 29 | 30 | ### 모듈과 의존성 31 | 32 | --- 33 | 34 | 자바스크립트는 큰 소스를 나눠 편하게 개발하고 유지보수하기 위해 모듈이라는 추상적인 개념을 사용한다. 마치 클래스와 비슷하다 이렇게 모듈 방식으로 코딩을하고 거기에 모듈별로 파일까지 나누어 개발하면 참 좋다. 모듈과 파일이 분기된 개념은 보통은 노드JS에서 많이 사용한다. 35 | 36 | 모듈화 된 각각의 파일들은 서로의 의존성을 가진다. 의존성이란 쉽게 말해 `import * from './index'` 이 구문이다. 현재 파일에서 다른 파일을 이용하게되면 서로 의존성이 생긴다. 37 | 38 | 그런데 브라우저 상에서는 이러한 의존성을 표현하기가 어렵다. 특히 HTTP/1.1을 사용해야 하는 환경이라면 더욱 힘들다. HTTP/2.0의 경우 한 번의 요청에 여러 파일을 받아올 수 있지만 1.1의 경우는 의존성을 통해 여러 파일이 필요하게 된다면 너무 많은 네트워크 자원을 소모하게 된다. 39 | 40 | 그러면 많은 의존성으로 엮인 JS파일들을 그냥 하나의 JS파일로 압축해서 만들면 어떨까?? 요청 한 번에 그 압축파일 하나만 주면 땡! 하게 말이다. 그게 웹팩이다. 꼭 하나는 아니다. 라이브러리 / 핵심 소스를 나누어 파일을 두개로 분기할 수도 있다. 요점은 다양한 파일들을 번들(bundle)해서 네트워크 비용을 최소화하여 파일을 번들한다! 라는 것이다. 41 | 42 | Gulp나 Grunt처럼 필요한 자동화 기능까지 더해 빌드 해주는 것이 바로 모듈 번들러다. 43 | 44 | ### 더 나아가 45 | 46 | --- 47 | 48 | 웹팩은 위에서 말한 자바스크립트의 의존성을 파악하여 번들하는 것만이 아니다. 모든 리소스(javascript, css, image, font, 심지어 typescript, coffeescript, less, sass 등)에 대한 dependancy graph를 생성하여 빌드 시켜준다. 요즘처럼 SPA를 구현하게 되면 이러한 의존성은 꼬리에 꼬리를 물고 Graph(Tree) 형태로 만들어지게 되는데 이걸 번들링하여 하나의 js 파일로 딱 만들어주는게 모듈 번들러의 역할이다. 49 | 50 | ## 결론 51 | 52 | 두 종류의 빌드 툴 모두 리소스들을 압축한다는 공통점이 있다. 53 | 54 | Gulp나 Grunt는 단순 자동화 작업으로 파일을 압축하는 작업을 많이 하게 된다. 그러나 웹팩의 경우 자바스크립트의 각 모듈 혹은 파일, 심지어는 다양한 리소스들까지 의존성을 파악하여 묶어주기 때문에 엄청나게 큰 차이점을 보인다. 55 | 56 | 따라서 현재 코드가 모듈화 된 코드가 아니거나, 다양한 의존성을 다루어야 하는 작업이 아니라면 Gulp나 Grunt도 충분히 좋은 빌드 툴이 될 수 있다. 그러나 꽤 준수한 프로젝트 규모를 가지거나, 자바스크립트를 모듈화하여 코딩하거나, 무거워질 수 밖에 없는 프레임워크를 사용하는 프로젝트 등에는 웹팩이 훨씬 더 좋은 툴이 될 것이다. 57 | -------------------------------------------------------------------------------- /Deprecated/Module.md: -------------------------------------------------------------------------------- 1 | # javascript의 module 2 | 3 | Java나 Python과 같은 OOP 언어들에서는 Class라는 이름으로 객체지향 프로그래밍을 구현해왔다. OOP의 보통 특징으로는 널리 알려져있듯 encapsulation, inheritance, polymorphism이 있다. 그 중 자바스크립트의 scope를 공부하고 있었는데 encapsulation과 관련이 있었으며, 자연스레 class와 비슷한 기능을 하는 자바스크립트의 module을 공부해봤다. 4 | 5 | javascript에서는 이 scope를 기준으로 캡슐화를 한다. 그래서 자연스레 이 scope를 이용하여 외부로부터 보호하려는 노력이 있어왔다. ES5에서는 함수가 scope의 기준이기 때문에 당연히도 함수의 scope를 이용해 encapsulation을 시도했다. 또한 자신의 스코프의 참조를 가진다는 클로저를 이용해 내부 속성들을 사용할 수 있게 했다. 6 | 7 | ## ES 5의 모듈화 8 | 9 | 크게 세가지가 있었다. IIFE(즉시실행함수표현식), 노출식 모듈 패턴, AMD다. 여기서 AMD는 크게 중요하지 않다고 생각되어 define을 사용한다고만 하고 넘어가겠다. 10 | 11 | ### IIFE 12 | 13 | --- 14 | 15 | 함수를 즉시 호출시켜 스코프를 오염시키지 않는 방식이다. 16 | 17 | ```js 18 | function moduleFunction() { 19 | 20 | var a = 3; 21 | 22 | function helloWorld(){ 23 | console.log('Hello'); 24 | } 25 | 26 | return { 27 | a : a, 28 | sayHello: helloWorld 29 | } 30 | }() 31 | 32 | moduleFunction.sayHello(); 33 | doSomething(moduleFunction.a); 34 | ``` 35 | 36 | 함수를 바로 실행시킨 뒤 object를 반환하여 전역 네임을 한번만 사용하여 스코프를 오염시키지 않는다. 또한 외부에서 내부 코드로의 접근을 차단하여 보호한다. 모듈의 개념을 잘 이행하고 있다. 다만 의존성관리가 되지 않는다. 코드를 재 작성하지 않으면 다른 파일에서 재사용이 불가능하다. 37 | 38 | ### 노출식 모듈패턴 39 | 40 | --- 41 | 42 | IIFE와 크게 다르는 않다. 반환값을 변수에 담으면 되는데 singleton 의 패턴이다. 43 | 44 | ```js 45 | var singleton = (function moduleFunction() { 46 | var a = 3; 47 | 48 | function helloWorld() { 49 | console.log('Hello'); 50 | } 51 | 52 | return { 53 | a: a, 54 | sayHello: helloWorld 55 | }; 56 | })(); 57 | 58 | singleton.sayHello(); 59 | doSomething(singleton.a); 60 | ``` 61 | 62 | 비슷하다. 이 역시 문제는 의존성관리가 안된다. 63 | 64 | ## Node JS의 모듈화 65 | 66 | 의존성 관리 문제 때문에 ES5에서는 AMD, UMD, CommonJS 와 같은 모듈 포맷을 사용했는데 여기서는 가장 흔히 알려진 CommonJS방식에 대해 알아보자 67 | 68 | ```js 69 | var dep1 = require('./dep1'); 70 | var dep2 = require('./dep2'); 71 | 72 | module.exports = function() { 73 | // ... 74 | }; 75 | ``` 76 | 77 | 와 같은 구조다. 흔히 구글링한 코드에서 찾아볼 수 있는 `require`, `module.exports` 구조다. 외부의 dep1.js를 `module.exports`로 내보내고 `require()`로 불러와 사용하는 방식이다. 사실 내부적으로는 IIFE와 크게 다르지 않다. 내보낼 module을 파라미터로하여 IIFE를 실행시키고 반환하는 방식이다. 78 | 하지만 파일 외부에서 작성하고 불러온다는 점에서 많이 나아진 방식이다. 79 | 80 | ## ES 6 모듈 81 | 82 | ES 6에서는 모듈을 사용하기 위한 내장 문법을 지원한다. 바로 `export`다. 83 | 84 | ```js 85 | // some.js 86 | export function helloWorld() { 87 | console.log('Hello'); 88 | } 89 | 90 | function somePrivateFunction() { 91 | // ... 92 | } 93 | 94 | // =========== 95 | // =========== 96 | 97 | // something.js 98 | import { helloWorld as hello } from './some'; 99 | // import * from './some' 도 가능합니다. 100 | 101 | hello(); 102 | ``` 103 | 104 | 이렇게 하면 파일을 분리하고 그 파일에서 필요한 부분만 반환하여 사용할 수 있게 된다. 또한 재사용성이 극대화되어 의존성 관리도 가능하게 된다. 105 | 106 | 현재 예제 코드에서는 함수만 반환했지만 당연히 object도 가능하다. 107 | 108 | 또한 단일 값을 반환할 경우 default 형식을 지원한다. 이 경우 {} 를 사용하지 않아도 된다. 109 | 110 | ```js 111 | // lib.js 112 | 113 | // Export default function 114 | export default function sayHello(){ 115 | console.log('Hello'); 116 | } 117 | 118 | 119 | // Export non-default function 120 | function sayGoodbye(){ 121 | console.log('Goodbye'); 122 | } 123 | 124 | // Export simple value 125 | const apiUrl = '...'; 126 | 127 | returnObject = { 128 | goodbye : sayGoodbye, 129 | apiUrl : apiUrl 130 | } 131 | export returnObject; 132 | 133 | // Export object 134 | export const settings = { 135 | debug: true 136 | } 137 | 138 | // app.js 139 | import sayHello, { returnObject, settings } from './lib'; 140 | 141 | sayHello(); 142 | returnObject.sayGoodBye(); 143 | ``` 144 | 145 | 하지만 현재 이러한 모듈 포맷은 모든 브라우저에서 지원하지 않는다. 따라서 Babel과 같은 변환기를 통해 ES5에서 사용하던 방식인 AMD나 CommonJS 형식으로 코드를 변환한 뒤 사용한다. 146 | -------------------------------------------------------------------------------- /Deprecated/Promise1.md: -------------------------------------------------------------------------------- 1 | # Promise1 2 | 3 | ## 콜백을 구하라 4 | 5 | 프로미스를 몇번 사용은 해봤다. 그러나 사실 이게 왜 대단한지 크게 알 수 가 없었다. 체이닝이 되서 추적이 쉽다는것? async / wait 을 이용해서 비동기/동기를 이동할 수 있다는 것? 정도만 알고 있었다. 6 | 7 | 하지만 이번에 공부하면서 이게 왜 등장했으며 어떤 장점이 있는지 조금은 알게 되었다. 8 | 9 | ## 제어의 역전 10 | 11 | 콜백 지옥의 문제점은 제어의 역전이다. 믿음직하지 못한 어떤 비동기 프로그램에게 우리 프로그램의 호출 제어권을 넘겨주어 어떤 일이 발생할 수 있다는 것이다. 12 | 13 | 이전 시리즈의 예를 다시 들어보자.[Callback](./Callback.md) 14 | 15 | ```js 16 | solutionUtil.trackPurchase(purchaseData, function CBF() { 17 | // 결제데이터를 넘긴 뒤 18 | // 비동기적인 처리가 완료되면 콜백실행 19 | assignCredit(); // 결제 20 | goThanksPage(); // 페이지 이동 21 | }); 22 | ``` 23 | 24 | 저 유틸의 trackPurchase 라는 함수는 25 | 26 | - purchaseData 와 콜백함수 두가지 인자를 받는다. 27 | - 우리는 알 수 없는 어떤 로직 진행 후 완료가되면 콜백함수를 실행한다. 28 | 29 | 이 과정의 문제점은 콜백의 실행 제어권이 저 함수에게 넘어간다는 점이다. 저 함수안에서 어떤 일이 잘못되어 콜백함수가 5 번 실행될 수 있다는 게 가장 큰 문제였다. 30 | 31 | ## 제어의 재역전 32 | 33 | 자 이제 저 제어권을 돌려받자. 콜백을 저 함수가 아니라 우리가 실행할 수 있게 만들자는 개념이 promise 다. 34 | 먼저 예시를 들어보자. 35 | 36 | 1. 어떤 작업을 하려고 foo()라는 함수를 부른다. 37 | 2. foo()의 내용은 관심이 없지만 foo()가 끝나길 기다린다. 38 | 3. foo()가 끝나면 어떤 작업을 실행한다. 39 | 40 | 콜백 베이스의 코드라면 foo()를 실행할 때 콜백을 넘겨준다. 41 | 42 | ```js 43 | foo(someData, bar(), barErr()); 44 | ``` 45 | 46 | 이렇게 하면 foo 가 자신이 끝나면 bar()를 **백그라운드**에서 실행한다. 하지만 자바스크립트에는 이벤트 방식도 존재한다. 47 | 48 | ```js 49 | function foo(x) { 50 | // 어떤 일을 실행하고 이벤트를 반환 51 | return listner; 52 | } 53 | 54 | var evt = foo(42); 55 | 56 | evt.on('completion', bar()); 57 | evt.on('failure', barErr()); 58 | ``` 59 | 60 | 이거다 바로. 이게 사실 프로미스가 실행되는 방식이다. 61 | 위의 코드를 잘 생각해보자. foo 가 비동기적으로 실행되고 그 결과를 받아 evt 에 저장한다.foo(42)가 완료되어 evt 에 할당되면 그걸 우리가 읽고 다음 단계를 실행한다. 62 | 63 | 콜백 패턴을 뒤집었다. 정확히 정반대이다. 64 | 즉 제어권을 다시 역전시킨 것이다. 65 | 66 | 조금 더 간단하게는 67 | 68 | ```js 69 | var evt = foo(42); 70 | 71 | bar(evt); 72 | barErr(evt); 73 | ``` 74 | 75 | 이렇게 바뀐다. 76 | 77 | 위의 예시와 아래의 예시를 잘 보면 크게 다른것 같지 않은데? 그냥 코딩스타일 차이 아닌가? 라고 생각할 수 도 있다. 그렇지만 제어권을 기준으로 보자. foo라는 함수가 끝나면 콜스택의 제어권을 누가 가지고 있는지가 중요하다 78 | 79 | ## 리스너를 프로미스로 80 | 81 | 이벤트 리스너가 아니라 프로미스로 조금만 바꿔보자. 82 | 83 | ```js 84 | function foo(x) { 85 | // 어떤 일을 실행하고 프로미스를 반환 86 | 87 | return new Promise(function(resolve, reject) {}); 88 | } 89 | 90 | var p = foo(42); 91 | 92 | bar(p); 93 | ``` 94 | 95 | 여기서 bar 의 내부를 보자면 96 | 97 | ```js 98 | function bar(fooPromise) { 99 | fooPromise.then( 100 | function() {}, // resolve 시 작업 101 | function() {} // reject 시 작업 102 | ); 103 | } 104 | ``` 105 | 106 | 이렇게 되어있을 것이다. 현대의 코드는 then()과 catch()를 많이 사용하지만 기본은 resolve 와 reject 다. 107 | 108 | 이러한 프로미스는 단 한번만 결과값이 귀결된다. 이 값은 불변성을 가져 변하지 않는다. 믿음을 준다. (믿음성) 109 | 110 | 단 한번만 결과값이 도출되기에 여러번 호출하지 않고, 값이 변하지 않기 때문에 그 결과로 다른 로직에 이용되도 같은 결과가 도출된다. 또한 에러가 발생하더라도 프로그램의 흐름은 멈추지 않는다. 그냥 예외가 되었기에 버림콜백(reject)로 진행한다. 111 | 112 | 그렇다면 프로미스가 과연 믿음직스러운건가?? 아직 조금 부족하다. 113 | -------------------------------------------------------------------------------- /Deprecated/Promise2.md: -------------------------------------------------------------------------------- 1 | # Promise2 2 | 3 | ## Promise.resolve() 4 | 5 | 프로미스는 사실 별게 아니다. 콜백을 넘겨주는 위치를 달리했을 뿐이다. foo()에 콜백을 넘기는 것이 아닌 foo()에서 프로미스를 받은 뒤 이 프로미스에 콜백을 준 것이다. 6 | 7 | 프로미스가 나오게 된 가장 중요한 점은 믿음이다. 8 | 근데 중요한 것은 이 받은 프로미스가 진짜 프로미스가 아니라면? 단지 .then()을 쓸 수 있는 object 라면 어떨까? 9 | 10 | 이를 책 *You Don't Know JS*에서는 Thenable 이라고 한다. 11 | 12 | ```js 13 | var p = { 14 | then: function(foo, err) { 15 | foo(42); 16 | err('하이'); 17 | } 18 | }; 19 | 20 | p.then( 21 | function resolve(val) { 22 | console.log(val); 23 | }, 24 | function rejected(err) { 25 | console.log(err); 26 | } 27 | ); 28 | ``` 29 | 30 | 이 Object p처럼 then()이 있는 thenable은 모두 프로미스처럼 보이게 동작할 수 있다. 31 | 32 | 이 경우 Promise.resolve()로 해결이 가능하다. Promise.resolve()를 거치면 이 값으로 이루어진 프라미스 객체가 반환된다. 33 | 34 | 이게 굉장히 중요하다. 프로미스가 등장한 이유가 믿음성인데 이 믿음성을 해결해준다. 35 | 36 | ```js 37 | var p1 = new Promise(function(resolve, reject) { 38 | resolve(42); 39 | }); 40 | var p2 = Promise.resolve(42); 41 | 42 | p1 === p2; // true 43 | ``` 44 | 45 | 자 이제 Thenable 한 값을 Promise.resolve()에 들어가면 정규화시켜보자. 46 | 47 | ```js 48 | Promise.resolve(p).then( 49 | function resolve(val) { 50 | console.log(val); 51 | }, 52 | function rejected(err) { 53 | console.log(err); // 실행 안됌 54 | } 55 | ); 56 | ``` 57 | 58 | 자 그럼 이제 할 일은 아래와 같다. 만일 foo()가 어떤 비동기 행위이며 반환값이 프로미스인지 확신하게끔 만들자. 59 | 60 | ```js 61 | foo(42).then(function(v) { 62 | console.log(v); // 멍청 63 | }); 64 | 65 | Promise.resolve(foo(42)).then(function(v) { 66 | console.log(v); // 현명 67 | }); 68 | ``` 69 | 70 | 이러면 어떠한 경우에도 무리가 없다. 믿음이 확실해진다. 71 | 72 | ## 익숙한 ajax 73 | 74 | 그럼 자주 사용하는 ajax 에 응용해보자. 75 | 76 | 가장 중요하게 기억해야 할 것은 기존의 콜백은 백그라운드에서 호출, 프로미스는 호출스택에서 호출한다는 점이다. 77 | 78 | ```js 79 | function request(url) { 80 | return new Promise(function(resolve, reject) { 81 | // ajax의 콜백함수가 일반 함수가 아니라 방금 생성한 promise의 resolve가 된다. 82 | ajax(url, resolve); 83 | }); 84 | } 85 | 86 | request('https://...') 87 | .then(function(response1) { 88 | return request('https://.../?q=' + response1); 89 | }) 90 | .then(function(response2) { 91 | console.log(response2); 92 | }); 93 | ``` 94 | 95 | 자주 사용되는 AJAX 공통 코드를 Promise를 이용해서 더욱 믿음을 가지고 사용할 수 있게 될 것이다. 96 | -------------------------------------------------------------------------------- /Deprecated/Repaint와 Reflow.md: -------------------------------------------------------------------------------- 1 | # Repaint와 Reflow 2 | 3 |
4 | 5 | ## 브라우저의 rendering 과정 6 | 7 | ![rendering](/assets/images/rendering.png) 8 | 9 | 위의 그림과 같이 브라우저는 화면을 rendering하는 과정에서 **배치\(flow\)** 와 **그리기\(paint\)** 의 과정을 거친다. 10 | 11 |
12 | 13 | ## Reflow의 발생 14 | 15 | 생성된 DOM 노드의 레이아웃이 변경될 떄, 변경 후 영향을 받는 모든 노드를 다시 계산하고 렌더 트리를 재생성 한다. 16 | 17 | 이러한 과정을 `reflow`라 하고 `reflow`가 일어난 후, `repaint`가 일어난다. 18 | 19 | ```javascript 20 | function reFlow() { 21 | var container = document.getElementById('container'); 22 | 23 | container.style.padding = '20px'; 24 | container.style.border = '20px'; 25 | container.appendChild(document.createTextNode('hello')); 26 | } 27 | 28 | ``` 29 | 30 |
31 | 32 | ## Repaint의 발생 33 | 34 | 생성된 DOM 노드에 대하여 style을 변경시켰을 때, **무조건 `reflow`가 발생하진 않는다.** 35 | **레이아웃 수치에 대한 변경이 일어나지 않는다면, `reflow`가 일어나지 않고, `repaint`만 일어난다.** 36 | 이러한 경우에는, 색상변경과 같이 레이아웃의 변경이 없는 경우가 있다. 37 | 38 | ```javascript 39 | function repaint() { 40 | var container = document.getElementById('container'); 41 | 42 | container.style.backgroundColor = 'black'; 43 | container.style.color = 'white'; 44 | } 45 | 46 | ``` 47 | 48 |
49 | 50 | ## Repaint와 Reflow의 최적화 51 | 52 | `Repaint`와 `Reflow`가 많아질수록 애플리케이션의 렌더링 성능은 느려지게 된다. 53 | 즉, 이를 줄일수록 성능을 높일 수 있다. 54 | 55 | ### DOM객체의 캐싱 56 | 57 | --- 58 | 59 | ```javascript 60 | //Before 61 | for(var i=0; i<100; i++) { 62 | document.getElementById('container').style.padding = i + 'px'; 63 | } 64 | 65 | //After 66 | var container = document.getElementById('container'); 67 | 68 | for(var i=0; i<100; i++) { 69 | container.style.padding = i + 'px'; 70 | } 71 | ``` 72 | 73 | ### class명과 cssText사용 74 | 75 | --- 76 | 77 | ```javascript 78 | //Before 79 | var container = document.getElementById('container'); 80 | 81 | container.style.padding = "20px"; 82 | container.style.border = "10px solid red"; 83 | container.style.color = "blue"; 84 | 85 | //After cssText 86 | container.style.cssText = 'padding:20px;border:10px solid red;color:blue;'; 87 | 88 | //After class 89 | container.className = 'test'; 90 | ``` 91 | 92 | ### 애니메이션이 들어간 노드는 가급적 position:fixed 또는 position:absolute로 지정 93 | 94 | --- 95 | 96 | ``` javascript 97 |
98 | ``` 99 | 100 | 프레임에 따라 reflow비용이 많은 애니메이션 효과의 경우엔 노드의 `position`을 `absolute`나 `fixed`로 주면 전체 노드에서 분리된다. 101 | 이 경우엔, **전체 노드에 걸쳐 Reflow 비용이 들지 않으며 해당 노드의 Repaint 비용만 들어가게 된다.** 102 | 103 | ### 테이블 레이아웃을 피한다. 104 | 테이블로 구성된 페이지 레이아웃의 경우, 점진적 페이지 렌더링이 일어나지 않고 모든 계산이 완료된 후, 화면에 렌더링이 되기 때문에 피하는게 좋다. 105 | 106 |
107 | 108 | ## Virtual DOM 109 | 110 | **Virtual DOM**은 React나 Angular와 같은 UI/UX기반의 라이브러리 혹은 프레임워크에서의 컨셈이 되는 개념이다. 111 | 112 | 기존에 javascript나 jQuery에서 사용되던 DOM 직접접근 방식의 문제는 reflow와 repaint의 연관성도 빼놓을 수 없다. 113 | 114 | **DOM은 정적이다.** 115 | DOM 요소에 접근하여 동적으로 이벤트를 주어 layout을 바꾸게 되면 reflow와 repaint가 일어나게 된다. 116 | 117 | 이 과정에서 규모가 큰 애플리케이션일수록 recalculate할 양이 늘어나고 이는 성능에 큰 영향을 미친다. 118 | 119 | ### Virtual DOM의 사용 120 | 121 | > 1. 데이터가 업데이트되면, 전체 UI 를 Virtual DOM 에 리렌더링. 122 | > 2. 이전 Virtual DOM 에 있던 내용과 현재의 내용을 비교. 123 | > 3. 바뀐 부분만 실제 DOM 에 적용. 124 | 125 | 즉, **Virtual DOM을 사용함으로써 바뀐 부분(Component)만 rerendering하기 때문에 컴포넌트가 업데이트 될 때, 레이아웃 계산이 한 번만 일어나게 된다.** 126 | 127 |
128 | 129 | --- 130 | 131 | #### Reference 132 | 133 | - [Reflow or Repaint(or ReDraw)과정 설명 및 최적화 방법](http://webclub.tistory.com/346) 134 | - [DOM의 문제점과 Virtual DOM](https://velopert.com/775) 135 | 136 | -------------------------------------------------------------------------------- /Deprecated/WebWorker.md: -------------------------------------------------------------------------------- 1 | # Web Worker 2 | 3 | `WebWorker`는 `script` 실행을 메인 쓰레드가 아니라 백그라운드 쓰레드에서 실행할 수 있도록 해주는 기술이다. 4 |
5 | 6 | 이 기술을 통해 무거운 작업을 분리된 쓰레드에서 처리할 수 있으며, 이를 통해 메인 쓰레드(일반적으로 UI 쓰레드)는 멈춤, 속도저하 없이 동작할 수 있다. 7 |
8 | 9 | ## WebWorker의 개념과 활용 10 | 11 | `Worker` 는 `Worker()` 생성자를 통해 생성되며 지정된 `Javascript` 파일에 포함된 코드를 `Worker` 쓰레드에서 실행하며, (`Worker`는 현재 `Window` 와 분리된 `DuplicatedWorkerGlobalScope` 라는 별도의 `Global context` 에서 동작) `Worker` 쓰레드에서 어떠한 코드도 실행할 수 있지만, 몇가지 예외가 있다. 12 |
13 | 14 | 예를들어 `Worker` 내에서는 `DOM` 을 직접 다룰 수 없다. 또한 `Window` 의 기본 메서드와 속성을 사용할 수 없다. 15 |
16 | 17 | `Message System` 을 통해 `Worker` 와 메인 쓰레드 간에 데이터를 교환할 수 있다. 18 |
19 | 20 | `Worker.postMessage()` 메서드를 통해 데이터를 전송할 수 있으며, `Worker.onmessage` 이벤트 핸들러 `Attribute` 를 통해 응답할 수 있다. (전송되는 메세지는 `MessageEvent.data` 에 포함). 전송되는 데이터는 공유되지 않으며 복제를 통해 전달되게 된다. 21 |
22 | 23 | 부모페이지와 동일한 `Origin` 내에서 `Worker` 는 새로운 `Worker` 를 생성할 수 있다. `Worker` 들은 `XMLHttpRequest` 를 통해 네트워크 통신을 할 수 있지만 `XMLHttpRequest` 의 `responseXML` 과 `channel attribute` 는 항상 `null` 을 반환한다. 24 |
25 | 26 | 지금까지 알아본 `Dedicated Worker` 와 다른 유형의 `Worker`들도 존재한다. 27 |
28 | 29 | - `Shared worker` 는 `Worker` 가 동일한 도메인 내에 존재하는 여러 `script` 에 의해 사용될 수 있다. `Shared Worker` 는 `Dedicated worker` 보다 좀더 복잡성을 가지고 있다. 예를들어 `Script` 들은 반드시 활성화된 `Port` 를 통해 통신해야 한다. 30 | - `ServiceWorker` 는 웹 어플리케이션 사이의 `Proxy Server`와 브라우저로서 역할을 하며 (만약 가능하다면)통신을 구축한다. 이를 통해 효율적인 오프라인 경험을 구축하고, 네트워크 요청을 가로채어 통신이 가능한지 여부에 따라 적절한 동작을 수행하며, 서버에 존재하는 자원들을 갱신할 수 있다. 또한 푸시 알림이나 백그라운드 동기화 API에 접근을 허용한다. 31 | - `Chrome Worker` 는 `Firefox` 에서만 사용 가능한 `worker` 유형으로 Add-on을 제작할 때나 확장기능에서 `Worker` 를 사용하고 싶을 때 사용할 수 있으며, `Worker` 에서 `js-ctypes` 에 접근할 수 있다. 32 | - `Audio Workers` 는 스크립트를 통한 직접적인 오디오 처리를 `Web Worker` 에서 처리할 수 있도록 해준다. 33 | 34 |
35 | 36 | --- 37 | 38 | #### Reference 39 | 40 | - [MDN-WebWorker](https://developer.mozilla.org/ko/docs/Web/API/Web_Workers_API) 41 | - [MDN 예제]( 42 | https://github.com/mdn/simple-web-worker) 43 | 44 | 45 | -------------------------------------------------------------------------------- /Deprecated/웹 브라우저의 작동 원리.md: -------------------------------------------------------------------------------- 1 | # 웹 브라우저의 작동 원리 2 | 3 |
4 | 5 | ## Rendering Engine 6 | 7 | * Webkit Engine : Chrome, Safari 8 |
9 | 10 | ![Webkit](/assets/images/Webkit.png) 11 | 12 | * Gecko Engine : Firefox 13 |
14 | 15 | ![Gecko](/assets/images/Gecko.jpg) 16 | 17 |
18 | 19 | ## Critical Rendering Path 20 | 21 | 웹 브라우저가 화면을 그리는데(Rendering) 거치는 주요한 과정 22 | 23 | 1. HTML데이터를 파싱하고 DOM Tree를 빌드. 24 | 2. 파싱 중 CSS링크를 만나면, CSSOM(CSS Object Model) Tree를 빌드. 25 | 3. DOM Tree와 CSSOM Tree를 이용해 Render Tree 생성. 26 | 4. Render Tree의 노드들의 위치를 계산(Layout) 27 | 5. 화면에 웹 페이지를 그린다. 28 | 29 |
30 | 31 | ### 1. HTML 데이터 파싱 / DOM Tree 빌드 32 | 33 | --- 34 | 35 | 브라우저는 HTML 데이터를 파싱해 DOM Tree를 만든다. 36 | 모든 HTML 태그에는 노드가 있고 각각의 노드는 Tree형태로 구현된다. 37 | 이를 DOM Tree라 한다. 38 | 39 | ```javascript 40 | 41 | 42 | BKJang 43 | 44 | 45 |
46 | 47 | middle 48 | 49 |
50 | 51 | 52 | ``` 53 | 54 | ### 2. CSSOM Tree 빌드 55 | 56 | --- 57 | 58 | HTML 파싱 중 CSS 링크를 만나면 리소스를 받아온다. 59 | 받아온 파일은 파싱되고 CSSOM Tree를 빌드한다. 60 | CSSOM이 구성되어야 다음 과정이 진행된다.(Rendering의 Blocking 요소) 61 | 62 | 63 | ### 3. Render Tree 생성 64 | 65 | --- 66 | 67 | DOM Tree와 CSSOM Tree를 결합, Render Tree를 빌드. 68 | Render Tree는 DOM Tree에 있는 것들 중에 실제 보이는 것들로만 구성. 69 | **ex) style='display : none;'은 Render Tree에서 제외. 메타태그 역시 제외.** 70 | 71 | 72 | Render Tree에는 Render Object Tree, Render Layer Tree, Render Style Tree, InlineBox Tree등이 포함. 73 | 74 | Render Object의 필요에 따라 **Render Layer**가 만들어지고 GPU 처리 여부에 따라 **Graphic Layer** 생성.(하드웨어 가속) 75 | 76 | 기본적으로 Layer는 하나고 CPU가 렌더링에 주요한 역할. 77 | 78 | * CSS 3D Transform(translate3d, preserve-3d 등)이나 perspective 속성이 적용된 경우 79 | 80 | * CSS 애니메이션함수나 필터함수를 사용하는 경우 81 | 82 | * video나 canvas 요소를 사용하는 경우 83 | 84 | * 자식 요소가 레이어로 구성된 경우 85 | 86 | * z-index가 낮은 형제 요소가 레이어로 구성된 경우 87 | 88 | 89 | ### 4. Layout 90 | 91 | --- 92 | 93 | Render Tree가 만들어지고, 각각의 노드들의 위치를 계산하는 과정. 94 | 위치 관련된 속성 계산(position, width, height 등). 95 | 96 | **ex) width:100%인 상태에서 브라우저를 리사이즈하면, Render Tree는 변경되지 않고 Layout 이후 과정만 다시 거치게 된다.** 97 | 98 | #### 5. Paint 99 | 100 | 실제 웹페이지를 화면에 그리는 작업. 101 | 102 | **색이 바뀐다거나 노드의 스타일이 바뀌는 걸로는 Layout 과정을 거치지 않고 Paint만 일어난다.** 103 | 104 | 105 |
106 | 107 | ## CSS와 JavaScript의 위치 108 | 109 | 브라우저의 렌더링 과정에서 DOM Tree를 빌드한 후, 스타일 규칙이 없으면 Rendering이 불가. 110 | 111 | 인터프리터은 HTML을 위에서 아래로 읽기 때문에 CSS를 ``태그 사이에 두면 CSS 리소스를 최대한 빨리 받을 수 있다. 112 | 113 | 반면, JavaScript는 DOM객체를 컨트롤하기 때문에 CSS처럼 위에 두게 되면 파싱을 멈추고 스크립트 파일을 읽기 때문에 성능이 저하된다. 따라서, JavaScript 소스는 주로 ``태그 위에 모아두는게 좋다. 114 | 115 | 단, 이런 경우 JS 애니메이션이 나중에 적용되어 사용자 입장에서 깜빡임 현상이 생길 수 있기 때문에 애니메이션 부분만 ``사이에 두는 것도 방법이다. 116 | 117 |
118 | 119 | --- 120 | 121 | #### Reference 122 | 123 | - [Naver D2 - 브라우저의 작동 원리](http://d2.naver.com/helloworld/59361) 124 | - [브라우저가 웹페이지를 그리는 법](https://isme2n.github.io/devlog/2017/07/06/browser-rendering/) 125 | - [웹브라우저에서 HTML문서 렌더링 과정](http://jeong-pro.tistory.com/90) 126 | 127 | -------------------------------------------------------------------------------- /Deprecated/점진적향상_우아한하향.md: -------------------------------------------------------------------------------- 1 | # 점진적 향상, 우아한 하향 2 | 3 | 2가지 개발접근법이 있다. 우아한 낮춤과 점진적인 향상.
4 | 간단히 정리하자면 다음과 같이 정의할 수 있다. 5 |
6 | 7 | ## 우아한 낮춤(Graceful degradation) 8 | 9 | - 원하는 기능을 갖는 또다른 버전을 제공하거나, 사용자가 제품의 결점이 사용성을 보장하기 위한 안전 조치때문이라는 것을 인지하도록 만드는 것이다. 10 | - 최신 기술 기반 또는 기기에서 동작하는 기능을 만들고 나서 오래된 기술 기반 혹은 기기에서도 유사한 성능으로 동작하도록 조치하는 것이다. 11 | - 사용자들의 기기를 위해 별도의 버전을 만들어 놓는 것이다. 12 | 13 |
14 | 15 | ex) 사용자의 브라우저가 javascript를 지원하지 않을 때 16 | 17 | - js를 지원하지 않는 기기를 위해