[컴][웹] StackOverflow 의 architecture

stack overflow architecture / programming stack / 스택오버플로우 구조 / 구성 /  하드웨어 구성


2018년 기준, StackOverflow 의 architecture


자세한 내용은 위 link 를 참고하자. 여기는 대략적인 내용만 적어놓는다.

H/W 구성

  • 9 Web server : ram 64GB
  • 4 Sql server : 2개의 cluster
    • Stack Overflow 용 : RAM 1.5GB / DB size 2.8TB
    • Stack Exchange, Careers, Meta 용: RAM 768GB, DB size 3.9TB
  • 2 Redis server : 
    • RAM 256GB
    • master-slave
  • 3 Tag engine servers
  • 3 ElasticSearch Server : 
    • RAM 196GB
    • load balanced
  • 2 HAProxy Servers
    • 1 live / 1 failover
  • 최고 초당 15,000 의 connection 처리

Programming Stack

  • C#
  • ASP.NET MVC
  • Dapper ORM
  • StackExchange.Redis
  • DotNetOpenAuth
  • MiniProfiler
  • Jil

[컴] 외국회사 Mock Interview

구글 인터뷰 예 / 구글 인터뷰 동영상 녹화


외국회사 Mock Interview

이 인터뷰는 mock interview 라고 한다. 아마 실제처럼 인터뷰를 진행하고 녹화한듯 하다. 그래서 정확히 그 회사의 인터뷰라고 할 수는 없겠지만, 어떤 식으로 인터뷰를 진행하는지에 대해 느껴볼 수 있을 것이다.


[웹][컴] Firefox Gecko View

겍코뷰 / gecko view 사용법 /

Gecko View

Firefox Focus 라는 모바일 app 이 있다. 처음에 Firefox 라는 이름에 Firefox app 에서 처럼 Gecko engine 을 사용하고 옵션만 바꿔 놓은줄 알았는데, WebView 를 사용했다고 한다.[ref. 1]

그런데 이번 release (2018. 10. 2) 에서는 Gecko 를 사용할것이라 한다.

WebView 의 한계

WebView 는 우리가 pc에서 쓰는 브라우저의 모든 기능을 제공하고 있지 않다. Web standard 의 일부만 지원한다. 그래서 실제로 완전한 browser 를 만들기에는 한계가 있다고 한다.
Foremost, it isn’t designed for building browsers. Despite being based on Chromium, WebView only supports a subset of web standards, as Google expects app developers to use native Android APIs, and not the Web, for advanced functionality.[ref. 1]
이런 이유로 Gecko engine 을 사용하려고 한다고 한다.

Gecko View

그런데 Gecko 는 WebView 처럼 다른 app 에서 사용할 수 있는 형태가 아니다. 그래서 이것을 WebView 처럼 여러곳에서 재사용할 수 있게 만들었는 데 이것이 Gecko View 이다.

현재 용량이 WebView(4MB) 보다 훨씬 큰 38MB(Gecko View) 정도라고 한다. 물론 계속 용량을 줄이고 있다고 한다. (참고: GeckoView in Firefox Focus)

Gecko View 의 사용법은 ref. 1에 일부 언급이 있다. 참고하자.



References


  1. Firefox Focus with GeckoView - Mozilla Hacks - the Web developer blog

[컴][웹] Medium Editor 사용해 보기



medium editor

medium site 에서 사용하는 editor 와 같은 기능을 제공한다.

장점

  • 화면에서 버튼을 이용해서 바로 추가적인 tag 를 넣을 수 있다. (underline, bold 등)
    • 버튼bar 가 아닌 bubble tip 버튼을 이용해서 편집을 하기에 좀 더 직관적인다.
  • 다양하게 확장이 가능하다.(extension)[ref. 1]

image insert

image 는 그냥 끌어다 놓으면 된다. 다만 이경우에 data:image/png 등의 모습으로 insert 된다. 이녀석은 server 단에서 image 로 변환하면 된다. 자세한 것은 아래 글을 참고하자.



local 에서 사용해보기

아래 4개의 파일을 경로에 맞춰서 local 에 넣자. 그리고 absoulte-container.html 을 실행하면 medium editor 를 사용해 볼 수 있다. 직접 demo 를 확인하고 싶다면 여기로 가자
<medium-editor>/dist/css/medium-editor.css
<medium-editor>/dist/css/themes/default.css
<medium-editor>/dist/js/medium-editor.js
<medium-editor>/demo/absolute-container.html


버튼 기능 확장

medium editor 의 버튼을 확장할 수 있다. 즉, 버튼을 추가하고, 원하는 기능을 넣을 수 있다. 자세한 사항은 아래 글에서 확인하자.

예제

아래처럼 editor의 toolbar 에 highlighter 를 추가할 수 있다.
var editor = new MediumEditor('.editable', {
    toolbar: {
        buttons: ['bold', 'italic', 'underline', 'highlighter']
    },
    extensions: {
        'highlighter': new HighlighterButton(),
        ...
    }
});

HighlighterButton class 는 위 글에서 code 를 옮겨왔다. 아래 처럼 자신이 원하는 버튼 기능을 만들면 된다.(자세한 것은 위링크를 확인하자)

rangy.init();
var HighlighterButton = MediumEditor.Extension.extend({
  name: 'highlighter',

  init: function () {
    this.classApplier = rangy.createClassApplier('highlight', {
        elementTagName: 'mark',
        normalize: true
    });

    this.button = this.document.createElement('button');
    this.button.classList.add('medium-editor-action');
    this.button.innerHTML = '<b>H</b>';
    this.button.title = 'Highlight';

    this.on(this.button, 'click', this.handleClick.bind(this));
  },

  getButton: function () {
    return this.button;
  },

  handleClick: function (event) {
    this.classApplier.toggleSelection();

    // Ensure the editor knows about an html change so watchers are notified
    // ie: <textarea> elements depend on the editableInput event to stay synchronized
    this.base.checkContentChanged();
  },

  // 파란색 함수는 이미 효과가 적용된 text 를 select 했을 때 
  // 버튼이 눌러진 모습을 표현하기 위한 것이다.
  isAlreadyApplied: function (node) {
    return node.nodeName.toLowerCase() === 'mark';
  },

  isActive: function () {
    return this.button.classList.contains('medium-editor-button-active');
  },

  setInactive: function () {
    this.button.classList.remove('medium-editor-button-active');
  },

  setActive: function () {
    this.button.classList.add('medium-editor-button-active');
  }
});



References

  1. medium-editor/src/js/extensions at master · yabwe/medium-editor · GitHub
  2. GitHub - yabwe/medium-editor-tables: Tables extension for MediumEditor

[컴][웹] jquery 를 사용하지 않는 markdown editor

마크다운 에디터 / js editor

jquery 를 사용하지 않는 markdown editor





See Also


[컴][웹] Server-Side Event(SSE)

서버 사이드 이벤트 / 폴링 / 푸쉬 메시지



Server-Side Event(SSE)

여기서는 ref. 2 에 있는 이야기의 일부를 다룬다. 되도록 ref. 2 내용 전체를 보는 것이 더 도움이 될 듯 하다.

대략적으로 이야기하면, 이녀석은 기본적으로 ajax 로 했던 polling 을 browser 가 대신해준다고 생각하면 된다. 즉, polling 을 사용했어야 하는 모든 경우에 사용할 수 있다. 그리고 polling 이 끊겼을때등에 대한 처리에 관한 설정(id 같은, ref. 2를 참고) 도 가능하기 때문에 훨씬 편리하고 좋다.

그리고 ref.2 에 보면 SSE 는 http protocol 로 만들어졌다고 한다. 그래서 이것을 실행하는 주체는 browser 안에서 layer 가 좀 다를 수는 있지만, js script 내에서 polling 을 구현한 것이랑 거의 다를 바가 없을 듯 하다. 여하튼 ref. 2 에서는 이것을 event streaming 이라고 부른다.


event streaming 을 close 하는 법


이렇게 주기적으로 browser 가 server로 부터 event 를 받아오는데, 이것을 close 하는 방법이 2가지 있다.
  • 서버에서 close 하는 법 : 
    • Content-Type 이 text/event-stream 가 아닌 response 를 보내거나
    • 200 이외의 HTTP status 를 보낸다.
  • client 에서 close 하는 법
    • source.close();
다만 이런 방법으로 Event streaming 을 끝내지 않고, 만약 network 가 끊어진 상황, 즉 browser 가 아예통신을 못하거나 한 상황에 의해 event streaming 이 끊긴 경우라면, browser 가 알아서 주기적으로 연결을 위해 시도를 한다.


message event

기본적으로 발생시키는 event 는 message event 이다. 하지만, server 의 응답에 "event" 를 정의해서 browser 로 하여금 새로운 event 를 발생시키도록 할 수 있다.
event: servertime
data: The server time...

source.addEventListener('servertime', function(event) {
    document.getElementById("result").innerHTML += event.data + "<br>";
});



Response

header 조건

  1. Content-Type: text/event-stream
  2. Cache-Control: no-cache

body

  • data: data_you_want_to_put
reponse body 이 딱 data 만 있으면 된다. 다른 option 들도 존재한다.(ref. 2 참고)
data: The server time...




Security 

보안상의 이슈로 client 에서 event handler 를 구현할 때 event 의 origin 을 check 하라고 한다.[ref. 2]
source.addEventListener('message', function(e) {
  if (e.origin != 'http://example.com') {
    alert('Origin was not http://example.com');
    return;
  }
  ...
}, false);


References

  1. HTML5 Server-Sent Events
  2. Stream Updates with Server-Sent Events - HTML5 Rocks