├── .eslintrc.js ├── 00-hello-world ├── .gitignore ├── README.md ├── index.html ├── main.js └── package.json ├── 01-create-react-app ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ └── logo.svg ├── 02-simple-contacts ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── components │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── ContactItem.css │ │ ├── ContactItem.js │ │ └── ContactList.js │ ├── index.css │ └── index.js └── yarn.lock ├── 03-oh-my-youtube ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── components │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── SearchBar.css │ │ ├── SearchBar.js │ │ ├── VideoDetail.css │ │ ├── VideoDetail.js │ │ ├── VideoList.css │ │ ├── VideoList.js │ │ ├── VideoListItem.css │ │ └── VideoListItem.js │ ├── index.css │ ├── index.js │ └── logo.svg └── yarn.lock ├── 90-web-basics └── README.md ├── 91-component-based-design └── README.md ├── 93-be-nerd-of-vim └── README.md ├── 94-be-nerd-of-zsh └── README.md ├── 95-be-nerd-of-tmux └── README.md ├── 99-github-pages-and-cloudflare └── README.md ├── LICENSE └── README.md /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // So parent files don't get applied 3 | root: true, 4 | env: { 5 | es6: true, 6 | browser: true, 7 | node: true, 8 | }, 9 | extends: 'eslint:recommended', 10 | parser: 'babel-eslint', 11 | parserOptions: { 12 | ecmaVersion: 7, 13 | sourceType: 'module', 14 | ecmaFeatures: { 15 | jsx: true, 16 | experimentalObjectRestSpread: true, 17 | } 18 | }, 19 | plugins: [ 20 | 'babel', 21 | 'react', 22 | 'mocha', 23 | 'material-ui', 24 | "import", 25 | "flowtype" 26 | ], 27 | rules: { 28 | 'array-bracket-spacing': ['error', 'never'], 29 | 'arrow-spacing': 'error', 30 | 'arrow-parens': 'error', 31 | 'block-spacing': ['error', 'always'], 32 | 'brace-style': 'error', 33 | 'comma-dangle': ['error', 'always-multiline'], 34 | 'comma-spacing': ['error', {before: false, after: true}], 35 | 'comma-style': ['error', 'last'], 36 | 'computed-property-spacing': ['error', 'never'], 37 | 'consistent-this': ['error', 'self'], 38 | 'consistent-return': 'off', // Wishlist, one day 39 | 'dot-notation': 'error', 40 | 'dot-location': ['error', 'property'], 41 | 'eqeqeq': ['error', 'smart'], 42 | 'eol-last': 'error', 43 | 'indent': ['error', 2, {SwitchCase: 1}], 44 | 'id-blacklist': ['error', 'e'], 45 | 'jsx-quotes': ['error', 'prefer-double'], 46 | 'keyword-spacing': 'error', 47 | 'key-spacing': 'error', 48 | 'max-len': ['error', 120, 4], 49 | 'new-cap': ['off', {capIsNew: true, newIsCap: true}], // Wishlist, one day 50 | 'no-unused-expressions': 'error', 51 | 'no-unused-vars': 'error', 52 | 'no-shadow': 'off', // Wishlist, one day 53 | 'no-spaced-func': 'error', 54 | 'no-multiple-empty-lines': 'error', 55 | 'no-multi-spaces': 'error', 56 | 'no-undef': 'error', 57 | 'no-empty-pattern': 'error', 58 | 'no-dupe-keys': 'error', 59 | 'no-dupe-args': 'error', 60 | 'no-duplicate-case': 'error', 61 | 'no-cond-assign': 'error', 62 | 'no-extra-semi': 'error', 63 | 'no-extra-boolean-cast': 'error', 64 | 'no-trailing-spaces': 'error', 65 | 'no-underscore-dangle': 'error', 66 | 'no-unneeded-ternary': 'error', 67 | 'no-unreachable': 'error', 68 | 'no-var': 'error', 69 | 'one-var': ['error', 'never'], 70 | 'operator-linebreak': ['error', 'after'], 71 | 'padded-blocks': ['error', 'never'], 72 | 'prefer-arrow-callback': 'off', // Wishlist, one day 73 | 'prefer-const': 'error', 74 | 'prefer-template': 'error', 75 | 'quotes': ['error', 'single', 'avoid-escape'], 76 | 'semi': ['error', 'always'], 77 | 'space-before-blocks': ['error', 'always'], 78 | 'space-before-function-paren': ['error', 'never'], 79 | 'space-infix-ops': 'error', 80 | 'space-unary-ops': ['error', { words: true, nonwords: false }], 81 | 'spaced-comment': 'error', 82 | 'yoda': 'error', 83 | 'babel/object-curly-spacing': ['error', 'never'], 84 | 'generator-star-spacing': 'error', 85 | 'babel/no-await-in-loop': 'error', 86 | 'flowtype/object-type-delimiter': 'error', 87 | 'react/display-name': 'error', 88 | 'react/jsx-boolean-value': ['error', 'always'], 89 | 'react/jsx-closing-bracket-location': 'error', 90 | 'react/jsx-curly-spacing': 'error', 91 | 'react/jsx-equals-spacing': 'error', 92 | 'react/jsx-filename-extension': ['error', {extensions: ['.js']}], 93 | 'react/jsx-first-prop-new-line': ['error', 'multiline'], 94 | 'react/jsx-handler-names': 'error', 95 | 'react/jsx-indent': ['error', 2], 96 | 'react/jsx-indent-props': ['error', 2], 97 | 'react/jsx-max-props-per-line': ['error', {maximum: 3}], 98 | 'react/jsx-no-comment-textnodes': 'error', 99 | 'react/jsx-no-duplicate-props': 'error', 100 | 'react/jsx-no-undef': 'error', 101 | 'react/jsx-pascal-case': 'error', 102 | 'react/jsx-space-before-closing': 'error', 103 | 'react/jsx-uses-react': 'error', 104 | 'react/jsx-uses-vars': 'error', 105 | 'react/jsx-wrap-multilines': 'error', 106 | 'react/no-danger': 'error', 107 | 'react/no-deprecated': 'error', 108 | 'react/no-did-mount-set-state': 'error', 109 | 'react/no-did-update-set-state': 'error', 110 | 'react/no-direct-mutation-state': 'error', 111 | 'react/no-multi-comp': 'off', // Wishlist, one day 112 | 'react/no-render-return-value': 'error', 113 | 'react/no-is-mounted': 'error', 114 | 'react/no-unknown-property': 'error', 115 | 'react/prefer-arrow-callback': 'off', // Wishlist, one day 116 | 'react/prefer-es6-class': 'error', 117 | 'react/prop-types': 'error', 118 | 'react/react-in-jsx-scope': 'error', 119 | 'import/extensions': 'error', 120 | 'react/require-render-return': 'error', 121 | 'react/self-closing-comp': 'error', 122 | 'react/sort-comp': 'error', 123 | 'react/sort-prop-types': 'error', 124 | 'material-ui/docgen-ignore-before-comment': 'error', 125 | 'mocha/handle-done-callback': 'error', 126 | 'mocha/no-exclusive-tests': 'error', 127 | 'mocha/no-global-tests': 'error', 128 | 'mocha/no-pending-tests': 'error', 129 | 'mocha/no-skipped-tests': 'error', 130 | 131 | 'react/no-string-refs': 'warn', // Wishlist, one day. 132 | 133 | 'strict': 'off', 134 | 'no-case-declarations': 'off', 135 | 'react/jsx-key': 'off', 136 | 'react/jsx-no-bind': 'off', 137 | 'react/jsx-no-literals': 'off', 138 | 'react/jsx-no-target-blank': 'off', 139 | 'react/jsx-sort-props': 'off', 140 | 'react/no-set-state': 'off', 141 | 'react/forbid-prop-types': 'off', 142 | 'react/prefer-stateless-function': 'off', 143 | 'react/require-optimization': 'off', 144 | 'mocha/no-synchronous-tests': 'off', 145 | 'mocha/valid-suite-description': 'off', 146 | 'mocha/valid-test-description': 'off', 147 | 'babel/object-shorthand': 'off', 148 | 'babel/new-cap': 'off', 149 | }, 150 | }; 151 | -------------------------------------------------------------------------------- /00-hello-world/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (http://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | 65 | # End of https://www.gitignore.io/api/node 66 | -------------------------------------------------------------------------------- /00-hello-world/README.md: -------------------------------------------------------------------------------- 1 | # Hello React! 2 | 3 | ## Introduction 4 | 5 | React는 브라우저 상에서 자바스크립트로 실행되지만, 개발 프로세스는 편의를 위해 Node로 진행된 후 트랜스파일링(Transpiling) 과정을 거치어 배포됩니다. Node와 Javascript의 차이가 무엇인지, 여러 언급되는 ES6, ES7 등의 용어가 무엇을 의미하는지 알아보도록 합시다. NPM을 사용하여 Node 프로젝트를 새로 만들고, "Hello, World!"를 띄우는 간단한 React 어플리케이션을 만들어 봅니다. 6 | 7 | 8 | ## Topics 9 | 10 | - Node는 왜 만들어졌는가? 11 | - ECMAScript는 무엇인가? 12 | - ES6, ES7 스펙의 주요 변경사항은 무엇인가? 13 | - NPM 사용법 14 | - `package.json` 작성법 15 | - Python의 `SimpleHTTPServer` 활용법 16 | - JSX 소개 17 | 18 | 19 | ## Resources 20 | 21 | 22 | ## Checklist 23 | 24 | - Node와 Javascript의 관계에 대해 설명하시오. 25 | - ECMAScript는 무엇인가? 26 | - ES6, ES7, ES2015, ES2016이 무엇을 의미하는지 설명하시오. 27 | - JSX가 무엇인지 설명하시오. 28 | - NPM의 역할은 무엇인가? 29 | - `package.json`은 왜 작성하는 것인가? 30 | - Python의 `SimpleHTTPServer` 모듈을 사용하여 웹 서버를 외부에 오픈할 수 있다. 31 | - `package.json`의 `scripts` 섹션에 명령어를 추가하여 `npm run`을 통해 실행할 수 있다. -------------------------------------------------------------------------------- /00-hello-world/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello World - React Tutorial 00 6 | 7 | 8 | 15 |
16 | 17 | 26 | 27 | 28 | 29 | 30 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /00-hello-world/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * The simplest React component ever. 3 | * 4 | * It jsut renders an H1 tag into the body of the page. Since 5 | * JSX is basically just HTML, you can use any valid tag you want. 6 | */ 7 | 8 | ReactDOM.render( 9 |

Hello, World!

, 10 | document.getElementById('root') 11 | ); -------------------------------------------------------------------------------- /00-hello-world/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "00-hello-world", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "python -mSimpleHTTPServer 3333", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "author": "Claud D. Park (http://www.posquit0.com)", 11 | "license": "MIT", 12 | "dependencies": { 13 | "react": "^15.4.2", 14 | "react-dom": "^15.4.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /01-create-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | -------------------------------------------------------------------------------- /01-create-react-app/README.md: -------------------------------------------------------------------------------- 1 | # Create React App 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - `create-react-app`를 사용하는 이유 9 | - **ECMAScript 2015(ES6)**의 모듈 의존성 문법인 `import`, `export` 이해 10 | - **트랜스파일러(Transpiler)** 이해 및 바벨(Babel) 간략 소개 11 | 12 | 13 | ## Resources 14 | 15 | - [create-react-app](https://github.com/facebookincubator/create-react-app) 16 | - [ES6: import](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/import) 17 | - [ES6: export](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Statements/export) 18 | - [Babel Transpiler](https://babeljs.io/) 19 | 20 | 21 | ## Quest 22 | 23 | - `create-react-app`을 이용하여 리액트 프로젝트를 만들어 본다. 24 | - `package.json`에 미리 정의된 명령어를 사용해 본다. 25 | 26 | 27 | ## Checklist 28 | 29 | - `create-react-app`을 사용하는 이유를 설명할 수 있다. 30 | - 개발버전과 배포버전의 분리 방식을 이해할 수 있다. 31 | - ES6에 소개된 `from`과 `import` 문법을 통해 외부 모듈을 사용할 수 있다. 32 | - ES6에 소개된 `export` 문법을 통해 모듈을 만들 수 있다. 33 | - 트랜스파일러가 무엇인지 설명할 수 있다. 34 | - 모던 웹 개발에 트랜스파일러를 쓰는 이유를 설명할 수 있다. -------------------------------------------------------------------------------- /01-create-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "01-create-react-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^15.4.2", 7 | "react-dom": "^15.4.2" 8 | }, 9 | "devDependencies": { 10 | "react-scripts": "0.9.5" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | } 18 | } -------------------------------------------------------------------------------- /01-create-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/posquit0/react-tutorial/c7c2ba8def83894823351afe14204facd4206a79/01-create-react-app/public/favicon.ico -------------------------------------------------------------------------------- /01-create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /01-create-react-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /01-create-react-app/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | class App extends Component { 6 | render() { 7 | return ( 8 |
9 |
10 | logo 11 |

Welcome to React

12 |
13 |

14 | To get started, edit src/App.js and save to reload. 15 |

16 |
17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /01-create-react-app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /01-create-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /01-create-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('root') 9 | ); 10 | -------------------------------------------------------------------------------- /01-create-react-app/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /02-simple-contacts/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | -------------------------------------------------------------------------------- /02-simple-contacts/README.md: -------------------------------------------------------------------------------- 1 | # Simple Contacts 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - **함수 기반 컴포넌트(Functional Component)**와 **클래스 기반 컴포넌트(Class Component)** 이해 9 | - 리액트 컴포넌트의 프로퍼티 **Props** 이해 10 | 11 | 12 | ## Resources 13 | 14 | - [Components and Props](https://facebook.github.io/react/docs/components-and-props.html) 15 | 16 | 17 | ## Quest 18 | 19 | - **Simple Contacts**를 따라 만들어 본다. 20 | 21 | 22 | ## Checklist 23 | 24 | - 리액트 컴포넌트를 함수 혹은 클래스에 기반하여 제작할 수 있다. 25 | - 리액트 컴포넌트의 프로퍼티를 전달/이용할 수 있다. -------------------------------------------------------------------------------- /02-simple-contacts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "02-simple-contacts", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^15.5.4", 7 | "react-dom": "^15.5.4" 8 | }, 9 | "devDependencies": { 10 | "react-scripts": "0.9.5" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | } 18 | } -------------------------------------------------------------------------------- /02-simple-contacts/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/posquit0/react-tutorial/c7c2ba8def83894823351afe14204facd4206a79/02-simple-contacts/public/favicon.ico -------------------------------------------------------------------------------- /02-simple-contacts/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ContactList from './ContactList'; 3 | import './App.css'; 4 | 5 | 6 | const contacts = [{ 7 | id: 1, 8 | name: '박병진', 9 | img: 'https://avatars0.githubusercontent.com/u/1484002?v=3&s=460', 10 | tel: '010-9999-1411', 11 | email: 'posquit0.bj@gmail.com' 12 | }, { 13 | id: 2, 14 | name: '홍길동', 15 | tel: '010-1234-2345', 16 | email: 'mr.hong@gmail.com' 17 | }, { 18 | id: 3, 19 | name: '김세정', 20 | img: 'http://file2.instiz.net/data/file2/2016/01/30/5/b/9/5b96fd93fa523311bde471939f550f7c.jpg', 21 | tel: '010-9876-2345', 22 | email: 'love.sj@gmail.com' 23 | }]; 24 | 25 | class App extends Component { 26 | render() { 27 | return ( 28 |
29 |
30 |

Simple Contacts

31 |
32 | 33 |
34 | ); 35 | } 36 | } 37 | 38 | export default App; 39 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/ContactItem.css: -------------------------------------------------------------------------------- 1 | .contact-item { 2 | list-style: none; 3 | } 4 | 5 | .contact-img { 6 | width: 180px; 7 | height: 180px; 8 | } 9 | 10 | .contact-name { 11 | font-weight: bold; 12 | font-size: 1.3em; 13 | } 14 | 15 | .contact-email a { 16 | text-decoration: none; 17 | color: red; 18 | } 19 | 20 | .contact-email a:hover { 21 | color: grey; 22 | } 23 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/ContactItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './ContactItem.css' 3 | 4 | 5 | const CONTACT_IMAGE_DEFAULT = 'http://bcdcog.com/wp-content/uploads/2016/05/profile-default-02.png'; 6 | 7 | const ContactItem = (props) => { 8 | const img = props.contact.img || CONTACT_IMAGE_DEFAULT; 9 | 10 | return ( 11 |
  • 12 | { 13 |
    { props.contact.name }
    14 |
    { props.contact.tel }
    15 |
    16 | Send E-Mail 17 |
    18 |
  • 19 | ); 20 | }; 21 | 22 | export default ContactItem; 23 | -------------------------------------------------------------------------------- /02-simple-contacts/src/components/ContactList.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ContactItem from './ContactItem'; 3 | 4 | 5 | class ContactList extends React.Component { 6 | renderContactItem(contact) { 7 | return 8 | } 9 | 10 | render() { 11 | const contacts = this.props.contacts; 12 | 13 | return ( 14 |
      15 | { contacts.map(this.renderContactItem) } 16 |
    17 | ); 18 | } 19 | } 20 | 21 | export default ContactList; 22 | -------------------------------------------------------------------------------- /02-simple-contacts/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /02-simple-contacts/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('root') 9 | ); 10 | -------------------------------------------------------------------------------- /03-oh-my-youtube/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | 19 | -------------------------------------------------------------------------------- /03-oh-my-youtube/README.md: -------------------------------------------------------------------------------- 1 | # Oh My Youtube 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - 리액트 컴포넌트의 **속성(Props)**과 **상태(State)** 이해 9 | - 리액트 컴포넌트의 이벤트 핸들러 이해 10 | - [**Google Developer Console**](https://console.developers.google.com)에서 Youtube API KEY 발급 11 | 12 | 13 | ## Resources 14 | 15 | - [State and Lifecycle](https://facebook.github.io/react/docs/state-and-lifecycle.html) 16 | - [Handling Events](https://facebook.github.io/react/docs/handling-events.html) 17 | - [Forms](https://facebook.github.io/react/docs/forms.html) 18 | - [Google Developer Console](https://console.developers.google.com) 19 | 20 | 21 | ## Quest 22 | 23 | - **Oh My Youtube**를 따라 만들어 본다. 24 | 25 | 26 | ## Checklist 27 | 28 | - 리액트 컴포넌트의 속성과 상태의 차이를 설명할 수 있다. 29 | - 리액트 컴포넌트의 프로퍼티를 전달/이용할 수 있다. -------------------------------------------------------------------------------- /03-oh-my-youtube/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03-oh-my-youtube", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "prop-types": "^15.5.10", 7 | "react": "^15.5.4", 8 | "react-dom": "^15.5.4", 9 | "youtube-api-search": "^0.0.5" 10 | }, 11 | "devDependencies": { 12 | "react-scripts": "0.9.5" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test --env=jsdom", 18 | "eject": "react-scripts eject" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /03-oh-my-youtube/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/posquit0/react-tutorial/c7c2ba8def83894823351afe14204facd4206a79/03-oh-my-youtube/public/favicon.ico -------------------------------------------------------------------------------- /03-oh-my-youtube/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 |
    20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/App.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | min-height: 100%; 5 | margin: 0; 6 | padding: 0; 7 | } 8 | 9 | body { 10 | background: #f1f1f1; 11 | } 12 | 13 | .app-logo { 14 | animation: App-logo-spin infinite 20s linear; 15 | height: 80px; 16 | } 17 | 18 | .app-header { 19 | background-color: #222; 20 | padding: 20px; 21 | text-align: center; 22 | color: white; 23 | } 24 | 25 | .app-intro { 26 | font-size: large; 27 | } 28 | 29 | @keyframes app-logo-spin { 30 | from { transform: rotate(0deg); } 31 | to { transform: rotate(360deg); } 32 | } 33 | 34 | .app-content { 35 | height: 100%; 36 | padding: 10px; 37 | display: -webkit-box; 38 | display: -moz-box; 39 | display: -ms-flexbox; 40 | display: -moz-flex; 41 | display: -webkit-flex; 42 | display: flex; 43 | } 44 | 45 | .app-content .video-detail { 46 | -webkit-box-flex: 1; 47 | -moz-box-flex: 1; 48 | -webkit-flex: 1; 49 | -ms-flex: 1; 50 | flex: 1; 51 | } 52 | 53 | .app .video-detail { 54 | width: 100%; 55 | margin-right: 10px; 56 | background: white; 57 | border: 1px solid #e8e8e8; 58 | } 59 | 60 | .app .video-list { 61 | width: 320px; 62 | margin: 0; 63 | background: white; 64 | border: 1px solid #e8e8e8; 65 | } 66 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import searchYoutube from 'youtube-api-search'; 3 | import SearchBar from './SearchBar'; 4 | import VideoDetail from './VideoDetail'; 5 | import VideoList from './VideoList'; 6 | import logo from '../logo.svg'; 7 | import './App.css'; 8 | 9 | 10 | const YOUTUBE_API_KEY = 'AIzaSyAXAgSCHclQLTB7ZfzAPyrIH1a8A4lT8-I'; 11 | 12 | class App extends Component { 13 | constructor(props) { 14 | super(props); 15 | 16 | this.state = { 17 | videos: [], 18 | selectedVideo: null 19 | }; 20 | 21 | this.searchVideos('charlie puth'); 22 | } 23 | 24 | searchVideos(query) { 25 | const options = { key: YOUTUBE_API_KEY, term: query }; 26 | searchYoutube(options, (videos) => { 27 | this.setState({ 28 | videos, 29 | selectedVideo: videos[0] 30 | }); 31 | }); 32 | } 33 | 34 | render() { 35 | return ( 36 |
    37 |
    38 | logo 39 |

    Oh My YouTube

    40 | this.searchVideos(query) } /> 41 |
    42 |
    43 | 44 | this.setState({ selectedVideo }) } /> 47 |
    48 |
    49 | ); 50 | } 51 | } 52 | 53 | export default App; 54 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/SearchBar.css: -------------------------------------------------------------------------------- 1 | .search-bar input { 2 | width: 320px; 3 | height: 32px; 4 | font-size: 1.2em; 5 | } 6 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/SearchBar.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './SearchBar.css'; 3 | 4 | 5 | class SearchBar extends Component { 6 | constructor(props) { 7 | super(props); 8 | 9 | this.state = { query: '' }; 10 | } 11 | 12 | onInputChange(query) { 13 | this.setState({ query }); 14 | 15 | if (this.props.onQueryChange) 16 | this.props.onQueryChange(query); 17 | } 18 | 19 | render() { 20 | return ( 21 |
    22 | this.onInputChange(event.target.value) } /> 26 |
    27 | ); 28 | } 29 | } 30 | 31 | export default SearchBar; 32 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoDetail.css: -------------------------------------------------------------------------------- 1 | .video-detail { 2 | 3 | } 4 | 5 | .video-detail .video-player { 6 | width: 100%; 7 | height: 400px; 8 | min-height: 400px; 9 | overflow: hidden; 10 | } 11 | 12 | .video-player iframe { 13 | width: 100%; 14 | height: 100%; 15 | border: none; 16 | } 17 | 18 | .video-detail .video-information { 19 | padding: 10px; 20 | } 21 | 22 | .video-information .video-description { 23 | font-size: 0.7em; 24 | } 25 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoDetail.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './VideoDetail.css'; 3 | 4 | 5 | class VideoDetail extends Component { 6 | renderNotFound() { 7 | return ( 8 |
    No Videos
    9 | ); 10 | } 11 | 12 | render() { 13 | const video = this.props.video; 14 | 15 | if (!video) 16 | return this.renderNotFound(); 17 | 18 | const { videoId } = video.id; 19 | const { title, description } = video.snippet; 20 | const url = `https://www.youtube.com/embed/${videoId}`; 21 | 22 | return ( 23 |
    24 |
    25 | 26 |
    27 |
    28 |

    { title }

    29 |

    { description }

    30 |
    31 |
    32 | ); 33 | } 34 | } 35 | 36 | export default VideoDetail; 37 | 38 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoList.css: -------------------------------------------------------------------------------- 1 | .video-list { 2 | list-style: none; 3 | padding: 0; 4 | } 5 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoList.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import VideoListItem from './VideoListItem'; 3 | import './VideoList.css'; 4 | 5 | 6 | class VideoList extends Component { 7 | renderVideoListItem(video) { 8 | console.log(video); 9 | return ( 10 | 14 | ); 15 | } 16 | 17 | render() { 18 | const videos = this.props.videos; 19 | 20 | return ( 21 |
      22 | { videos.map((video) => this.renderVideoListItem(video)) } 23 |
    24 | ); 25 | } 26 | } 27 | 28 | export default VideoList; 29 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoListItem.css: -------------------------------------------------------------------------------- 1 | .video-list-item { 2 | display: -webkit-box; 3 | display: -moz-box; 4 | display: -ms-flexbox; 5 | display: -moz-flex; 6 | display: -webkit-flex; 7 | display: flex; 8 | padding: 10px; 9 | border-bottom: 1px solid #e8e8e8; 10 | } 11 | 12 | .video-list-item:last-child { 13 | margin-bottom: 0; 14 | border: none; 15 | } 16 | 17 | .video-list-item:hover { 18 | cursor: pointer; 19 | background: #fca13d; 20 | } 21 | 22 | .video-list-item .information { 23 | -webkit-box-flex: 1; 24 | -moz-box-flex: 1; 25 | -webkit-flex: 1; 26 | -ms-flex: 1; 27 | flex: 1; 28 | } 29 | 30 | .video-list-item .thumbnail { 31 | width: 120px; 32 | height: 90px; 33 | } 34 | 35 | .video-list-item .information { 36 | margin: 0 10px; 37 | } 38 | 39 | .information .title { 40 | margin: 0; 41 | font-size: 0.7em; 42 | } 43 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/components/VideoListItem.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import './VideoListItem.css' 4 | 5 | 6 | class VideoListItem extends Component { 7 | render() { 8 | const { video, onVideoSelect } = this.props; 9 | const { title } = video.snippet; 10 | const thumbnail = video.snippet.thumbnails.default.url; 11 | 12 | return ( 13 |
  • onVideoSelect(video) }> 14 | 15 | { 16 | 17 |
    18 |

    { title }

    19 |
    20 |
  • 21 | ); 22 | } 23 | } 24 | 25 | VideoListItem.propTypes = { 26 | video: PropTypes.object.isRequired, 27 | onVideoSelect: PropTypes.func 28 | }; 29 | 30 | export default VideoListItem; 31 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './components/App'; 4 | import './index.css'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('root') 9 | ); 10 | -------------------------------------------------------------------------------- /03-oh-my-youtube/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /90-web-basics/README.md: -------------------------------------------------------------------------------- 1 | # Web Basics 2 | 3 | ## Introduction 4 | 5 | 기초를 몰라도 웹 개발은 가능합니다. 하지만, 기초가 튼튼하고 웹이라는 시스템이 어떻게 돌아가는지 전체적인 그림을 볼 수 있다면 디테일이 더욱 살아있는 개발을 할 수 있습니다. 6 | 7 | 8 | ## Topics 9 | 10 | - 소켓이란 무엇인가? 11 | - IP와 PORT란 무엇인가? 12 | - 네트워크 기초 프로토콜: TCP/UDP, 그리고 HTTP 13 | - HTTP 메소드(GET/POST/PUT/PATCH/DELETE/HEAD) 14 | - HTTP 요청/응답 15 | - HTTP와 HTTPS의 차이 16 | - 웹 브라우저의 동작 방식 17 | - 웹 발전 역사 18 | - 쿠키(Cookie), 그리고 세션(Session) 19 | - 사용자의 패스워드는 어떻게 저장될까? 20 | - 포스트맨(Postman)을 활용한 HTTP 통신 테스트 21 | 22 | 23 | ## Resources 24 | 25 | - [IPv4와 IPv6의 차이점, 그리고 IPv6의 장점](http://enter.tistory.com/140) 26 | - [HTTP 상태 코드](https://ko.wikipedia.org/wiki/HTTP_상태_코드) 27 | - [HTTP 요청/응답 스펙 간략히 이해하기](https://blog.outsider.ne.kr/888) 28 | - [HTTP 프로토콜](http://webmastertool.naver.com/guide/basic_http.naver) 29 | - [안전한 패스워드 저장](http://d2.naver.com/helloworld/318732) 30 | - [REST 아키텍처를 훌륭하게 적용하기 위한 몇 가지 디자인 팁](https://spoqa.github.io/2012/02/27/rest-introduction.html) 31 | - [Postman](https://www.getpostman.com/) 32 | 33 | 34 | ## Checklist 35 | 36 | - CRUD가 무엇인지 설명하시오. 37 | - CRUD 개념과 연관지어 각 HTTP 메소드들의 역할을 설명하시오. 38 | - GET 요청과 POST 요청의 차이를 설명하시오. 39 | - HTTP의 요청/응답의 스펙을 설명하시오. 40 | - HTTP Query Parameter가 무엇인가? 41 | - HTTP Response Status Code가 무엇인지, 그리고 1XX, 2XX, 3XX, 4XX, 5XX, 각 번호 대역이 의미하는 바를 설명하시오. 42 | - HTTP와 HTTPS 프로토콜이 사용하는 기본 포트는 무엇인가? 43 | - HTTPS를 사용해야 하는 이유는 무엇인가? 44 | - TCP와 UDP의 차이점을 설명하시오. 45 | - IP V4와 V6의 차이점을 설명하시오. 46 | - URI의 구조를 설명하시오. 47 | - 웹 브라우저와 웹 서버가 어떻게 통신하는지 설명하시오. 48 | - 정적 파일(Static File)이 무엇인지 설명하시오. 49 | - Apache, Nginx, Tomcat과 같은 웹 서버의 역할이 무엇인지 설명하시오. 50 | - AMP가 무어인지 설명하시오. 51 | - 웹, 안드로이드, iOS를 모두 지원하는 서비스의 기본적인 아키텍처를 설계해보자. 52 | - 쿠키에 저장할 수 있는 데이터는 무엇이 있는가? 53 | - 세션에 저장할 수 있는 데이터는 무엇이 있는가? 54 | - API 서버의 역할은 무엇인가? 55 | - 모던 웹 어플리케이션에서는 API 토큰 등의 데이터를 어디에 저장하는가? 56 | - 해시 함수는 무엇인가? 57 | - 패스워드 저장에 많이 사용되는 해시 함수의 예를 들어보시오. 58 | -------------------------------------------------------------------------------- /91-component-based-design/README.md: -------------------------------------------------------------------------------- 1 | # Component based Design 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | 9 | ## Resources 10 | 11 | - [How We're Using Component Based Design](https://medium.com/@lewisplushumphreys/how-were-using-component-based-design-5f9e3176babb) 12 | 13 | 14 | ## Quest 15 | 16 | 17 | ## Checklist -------------------------------------------------------------------------------- /93-be-nerd-of-vim/README.md: -------------------------------------------------------------------------------- 1 | # Be Nerd of Vim 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - **설정파일(dotfiles)**란 무엇인가? 9 | - [**Vim Plug**](https://github.com/junegunn/vim-plug)을 이용한 Vim 플러그인 관리 10 | - Git 저장소로 Vim 설정파일 관리하는 법 11 | - Vim vs Emacs 12 | - Programmable Editor란 무엇인가? 13 | - Editor vs IDE, 판단의 기준 14 | - 프로그래밍 효율성을 위하여 에디터/IDE가 갖추어야 할 주요 기능 소개 15 | - 문법 강조(Syntax Hilighting) 16 | - 문법 검사(Syntax Check, Lint) 17 | - 자동완성(Auto-complete) 18 | - 코드 스니핏(Code Snippet) 19 | - 파일 탐색(File Explorer) 20 | - NeoVim에 대하여 21 | 22 | 23 | ## Resources 24 | 25 | ### Vim Plugins 26 | 27 | - [Vim Plug: 비동기 Vim 플러그인 관리자](https://github.com/junegunn/vim-plug) 28 | - [NERD Tree: 파일탐색기](https://github.com/scrooloose/nerdtree) 29 | - [Tagbar: 코드구조 탐색기](https://github.com/majutsushi/tagbar) 30 | - [CtrlP: Fuzzy 파일탐색기](https://github.com/kien/ctrlp.vim) 31 | - [Airline: 가볍고 훌륭한 상태표시줄](https://github.com/vim-airline/vim-airline) 32 | - [Multiple Cursors: SublimeText의 멀티커서 기능](https://github.com/terryma/vim-multiple-cursors) 33 | - [EditorConfig: 협업을 위한 프로젝트별 에디터 설정](https://github.com/editorconfig/editorconfig-vim) 34 | - [AutoPairs: 자동 괄호완성](https://github.com/jiangmiao/auto-pairs) 35 | - [Polyglot: 최신 언어팩](https://github.com/sheerun/vim-polyglot) 36 | - [ALE: Asynchronous Lint Engine](https://github.com/w0rp/ale) 37 | - [Syntastic: Synchronous Line Engine](https://github.com/vim-syntastic/syntastic) 38 | - [Deoplete: Asynchronous 자동완성 프레임워크](https://github.com/Shougo/deoplete.nvim) 39 | - [Deoplete TernJS: 자바스크립트 자동완성 모듈](https://github.com/carlitux/deoplete-ternjs) 40 | - [Tern for Vim: 자바스크립트 자동완성 프레임워크 Tern의 Vim 모듈](https://github.com/ternjs/tern_for_vim) 41 | - [UltiSnips: Code Snippet 프레임워크](https://github.com/SirVer/ultisnips) 42 | - [NERD Commenter: 쉬운 주석 기능](https://github.com/scrooloose/nerdcommenter) 43 | - [Vim Node: Node.js 개발 효율성을 위한 도구 제공](https://github.com/moll/vim-node) 44 | - [Emmet: 빠른 웹 개발을 위한 Zen Coding](https://github.com/mattn/emmet-vim) 45 | - [Fugitive: Git 통합도구](https://github.com/tpope/vim-fugitive) 46 | - [Signify: 코드 라인별 버전관리 상태 표시 도구](https://github.com/mhinz/vim-signify) 47 | - [Gundo: 로컬 버전관리](https://github.com/sjl/gundo.vim) 48 | - [Vim Colorschems: Vim 테마팩](https://github.com/flazz/vim-colorschemes) 49 | - [Molokai: My Favorite Theme!!](https://github.com/tomasr/molokai) 50 | 51 | ### Best Examples 52 | 53 | - [Vimrc for Vim/NeoVim by posquit0](https://github.com/posquit0/vimrc) 54 | - [Vimrc by junegunn(Vim Plug 개발자)](https://github.com/junegunn/dotfiles/blob/master/vimrc) 55 | - [Vimrc by mutewinter](https://github.com/mutewinter/dot_vim) 56 | - [Vimrc by amix](https://github.com/amix/vimrc) 57 | - [SpaceVim](https://github.com/SpaceVim/SpaceVim) 58 | 59 | ### Misc 60 | 61 | - [Vim Galore: Everything you need to know about Vim](https://github.com/mhinz/vim-galore) 62 | - [VimAwesome: Vim 플러그인 큐레이션](http://vimawesome.com/) 63 | - [Vim Shortcut Wallpaper: Vim 단축키 배경화면](https://github.com/LevelbossMike/vim_shortcut_wallpaper) 64 | - [NeoVim](https://neovim.io/) 65 | - [NeoVim GitHub](https://github.com/neovim/neovim) 66 | - [Github Dotfiles](https://dotfiles.github.io/) 67 | 68 | 69 | ## Quest 70 | 71 | - 나만의 Vim 설정을 위한 GitHub Repository를 만들어 본다. 72 | - **Vim Plug**를 이용하여 플러그인을 설치/삭제해본다. 73 | - **NeoVim**을 자신의 개발환경에 설치한다. 74 | - GitHub에서 `dotfiles`를 검색해본다. 75 | - GitHub에서 `vimrc`를 검색해본다. 76 | 77 | 78 | ## Checklist 79 | 80 | - dotfiles은 무엇인가? 81 | - Vim과 Emacs같은 CLI 환경의 에디터를 익혀 두어야 하는 이유는 무엇인가? 82 | - 에디터가 Programmable하다는 것은 무엇을 의미하는지 설명하시오. 83 | - Vim과 Emacs는 모두 Turing Complete한가? 84 | - Vim 설정파일을 Git으로 관리하는 이점은 무엇인가? 85 | - NeoVim과 Vim의 큰 차이점을 설명하시오. 86 | - 비동기와 동기에 대해 설명하시오. -------------------------------------------------------------------------------- /94-be-nerd-of-zsh/README.md: -------------------------------------------------------------------------------- 1 | # Be Nerd of Zsh 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - **설정파일(dotfiles)**란 무엇인가? 9 | - [**Oh My Zsh**](http://ohmyz.sh/)을 이용한 Zsh 플러그인 관리 10 | - Git 저장소로 Zsh 설정파일 관리하는 법 11 | - Bash vs Zsh vs Fish 12 | 13 | 14 | ## Resources 15 | 16 | ### Zsh Plugins 17 | 18 | - [Oh My Zsh: Zsh 프레임워크](https://github.com/robbyrussell/oh-my-zsh) 19 | - [Zsh History Substring Search](https://github.com/zsh-users/zsh-history-substring-search) 20 | - [Zsh Autosuggestions](https://github.com/zsh-users/zsh-autosuggestions) 21 | - [Zsh Syntax Highlighting](https://github.com/zsh-users/zsh-syntax-highlighting) 22 | - [Alias Tips](https://github.com/djui/alias-tips) 23 | 24 | ### Best Examples 25 | 26 | - [Zshrc by posquit0](https://github.com/posquit0/zshrc) 27 | 28 | ### Misc 29 | 30 | - [Oh My Zsh Plugins](https://github.com/robbyrussell/oh-my-zsh/wiki/Plugins) 31 | - [Awesome Zsh Plugins](https://github.com/unixorn/awesome-zsh-plugins) 32 | - [Zsh와 Oh My Zsh를 이용해 셸 꾸미기](https://youngbin.xyz/blog//2015/05/17/using-zsh-and-oh-my-zsh-instead-of-bash-for-shell-customizing.html) 33 | - [Github Dotfiles](https://dotfiles.github.io/) 34 | 35 | 36 | ## Quest 37 | 38 | - 나만의 Zsh 설정을 위한 GitHub Repository를 만들어 본다. 39 | - **Oh My Zsh**를 이용하여 Zsh 플러그인을 설정해본다. 40 | - **Zsh**을 설치 후 `chsh` 명령어를 통해 기본 로그인 셸로 설정한다. 41 | - GitHub에서 `dotfiles`를 검색해본다. 42 | - GitHub에서 `zshrc`를 검색해본다. 43 | 44 | 45 | ## Checklist 46 | 47 | - 셸(Shell)이란 무엇인가? 48 | - dotfiles은 무엇인가? -------------------------------------------------------------------------------- /95-be-nerd-of-tmux/README.md: -------------------------------------------------------------------------------- 1 | # Be Nerd of TMUX 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - **설정파일(dotfiles)**란 무엇인가? 9 | - [**TPM**](https://github.com/tmux-plugins/tpm)을 이용한 TMUX 플러그인 관리 10 | - Git 저장소로 TMUX 설정파일 관리하는 법 11 | - Screen vs TMUX 12 | 13 | 14 | ## Resources 15 | 16 | ### TMUX Plugins 17 | 18 | - [TPM: TMUX 플러그인 관리자](https://github.com/tmux-plugins/tpm) 19 | 20 | ### Best Examples 21 | 22 | - [TMUX Conf by posquit0](https://github.com/posquit0/tmux-conf) 23 | 24 | ### Misc 25 | 26 | - [TMUX Plugins in GitHub](https://github.com/tmux-plugins) 27 | - [Awesome TMUX](https://github.com/rothgar/awesome-tmux) 28 | - [TMUX Quick Reference](https://tmuxcheatsheet.com/) 29 | - [TMUX Shortcuts & Cheatsheet](https://gist.github.com/MohamedAlaa/2961058) 30 | - [GitHub Dotfiles](https://dotfiles.github.io/) 31 | 32 | 33 | ## Quest 34 | 35 | - 나만의 Tmux 설정을 위한 GitHub Repository를 만들어 본다. 36 | - **TPM**를 이용하여 TMUX 플러그인을 설치/제거 해본다. 37 | - **TMUX**을 설치 후 단축키 `prefix`를 CTRL+a로 변경한다. 38 | - GitHub에서 `dotfiles`를 검색해본다. 39 | - GitHub에서 `tmux`를 검색해본다. 40 | 41 | 42 | ## Checklist 43 | 44 | - dotfiles은 무엇인가? -------------------------------------------------------------------------------- /99-github-pages-and-cloudflare/README.md: -------------------------------------------------------------------------------- 1 | # Github Page and Cloudflare 2 | 3 | ## Introduction 4 | 5 | 6 | ## Topics 7 | 8 | - **정적 웹 사이트(Static Web Site)**란 무엇인가? 9 | - **Static Site Generators**란 무엇인가? 10 | - **Markdown** 소개 및 문법 기초 11 | - **React** 기반의 **Gatsby** 소개 12 | - **Github Pages** 소개 및 사용법 13 | - **Cloudflare** 소개 및 사용법 14 | 15 | 16 | ## Resources 17 | 18 | - [Gatsby Github](https://github.com/gatsbyjs/gatsby) 19 | - [Gatsby Official](https://www.gatsbyjs.org/) 20 | - [Github Pages](https://pages.github.com/) 21 | - [StaticGen: Top Open-Source Static Site Generators](https://www.staticgen.com/) 22 | - [Cloudflare](https://cloudflare.com) 23 | - [Secure and Fast Github Pages with Cloudflare](https://blog.cloudflare.com/secure-and-fast-github-pages-with-cloudflare/) 24 | 25 | 26 | ## Quest 27 | 28 | - **Gatsby**를 사용하여 *Markdown* 기반의 블로그 웹을 만들어 본다. 29 | - 빌드된 파일들을 Git Repository로 관리하여 Github에 업로드한다. 30 | - **Github Pages** 옵션을 설정하여 블로그를 무료로 호스팅해본다. 31 | - 개인 도메인을 `CNAME` 파일을 통해 Github Page에 연결시킨다. 32 | - **Cloudflare**로 도메인 네임서버를 이전하여 무료 SSL 인증서 설정 및 캐시 옵션을 설정하여 성능을 향상시켜 본다. 33 | 34 | 35 | ## Checklist 36 | 37 | - Github Pages와 Cloudflare로 호스팅한 개인 블로그가 HTTPS로 접근이 되는가? -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Byungjin Park 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

    2 | 3 | React 4 | 5 |
    6 | React Tutorial 7 |

    8 | 9 |

    10 | A Tutorial for learning React 11 |

    12 | 13 | 21 | 22 |
    23 | 24 | **React Tutorial**은 [포애퍼](http://www.poapper.com)에서 대학생들에게 모던 웹 개발 입문을 가르치기 위하여 작성된 커리큘럼입니다. 25 | 26 | 27 | ## Curriculum 28 | 29 | 페이스북에서 만든 UI(User Interface) 라이브러리, [**리액트(React)**](https://facebook.github.io/react/)를 활용한 모던 웹 개발 방법을 다룹니다. 30 | 31 | | # | Title | Estimated Time | 32 | | :--: |----------------------------------------------------------------- | :------------- | 33 | | 0x00 | [Hello React!](00-hello-world/) | 40 mins | 34 | | 0x01 | [Create React App](01-create-react-app/) | 20 mins | 35 | | 0x02 | [Simple Contacts](02-simple-contacts/) | 40 mins | 36 | | 0x03 | [Oh My Youtube](03-oh-my-youtube/) | 50 mins | 37 | | 0x04 | PropTypes & Lifecycle | xx mins | 38 | | 0x05 | React Router | xx mins | 39 | | 0x06 | React + Redux | xx mins | 40 | 41 | 42 | ## Extra Curriculum 43 | 44 | 이 커리큘럼을 이해하기 위한 이해하고 있어야 할 선수지식을 추가 커리큘럼을 통해 다룹니다. 그 외 웹 개발에 도움이 될 수 있는 내용도 다룹니다. 해당 내용이 필요하다 생각되는 경우 학습하도록 합니다. 45 | 46 | | # | Title | Estimated Time | 47 | | :--: |----------------------------------------------------------------- | :------------- | 48 | | 0x90 | [Web Basics](90-web-basics/) | 110 mins | 49 | | 0x91 | [Component based Design](91-component-based-design/) | 30 mins | 50 | | 0x92 | [Git Basics](92-git-basics/) | 60 mins | 51 | | 0x93 | [Be Nerd of Vim](93-be-nerd-of-vim/) | 50 mins | 52 | | 0x94 | [Be Nerd of Zsh](94-be-nerd-of-zsh/) | 20 mins | 53 | | 0x95 | [Be Nerd of TMUX](95-be-nerd-of-tmux/) | 20 mins | 54 | | 0x96 | [Nginx Basics](96-nginx-basics/) | 40 mins | 55 | | 0x97 | [Introduction of LetsEncrypt](97-intro-of-letsencrypt/) | 40 mins | 56 | | 0x98 | [Introduction of DNS Management](98-intro-of-dns/) | 50 mins | 57 | | 0x99 | [GitHub Pages & Cloudflare](99-github-pages-and-cloudflare/) | 50 mins | 58 | | 0x9A | Webpack & Babel | xx mins | 59 | 60 | 61 | ## Troubleshooting 62 | 63 | - 되도록이면 검색을 통해 스스로 해결하는 것을 권장합니다. 64 | - 라이브러리의 경우 공식 문서(Documentation)을 천천히 한 번 읽어 보시고 사용하는 것이 좋습니다. 65 | - 국문보다는 영문 문서를 읽는 것이 최신 정보를 따라가기 수월합니다. 66 | - 문제 해결에 어려움을 겪는 경우 이슈(Issue)로 질문을 등록해주시면 도와드립니다. 67 | 68 | 69 | ## Further Reading 70 | 71 | - [**React Documentation**](https://facebook.github.io/react/docs/) 72 | - [**Exploring ES6**](http://exploringjs.com/es6/) 73 | 74 | 75 | ## Links 76 | 77 | - [**React**](https://facebook.github.io/react) 78 | - [**PoApper**](http://www.poapper.com) 79 | 80 | 81 | ## Contribute 82 | 83 | 프로젝트에 도움이 될 수 있는 의견은 언제든지 환영입니다. [이슈 등록](https://github.com/posquit0/react-tutorial/issues/new) 혹은 Pull Request을 이용해주세요. 84 | 85 | React Tutorials follows the [**Contributor Covenant**](http://contributor-covenant.org/version/1/4/) Code of Conduct. 86 | 87 | 88 | ## Contact 89 | 90 | If you have any questions, feel free to join me at [`#posquit0` on Freenode](irc://irc.freenode.net/posquit0) and ask away. Click [here](https://kiwiirc.com/client/irc.freenode.net/posquit0) to connect. 91 | 92 | 93 | ## License 94 | 95 | - [MIT](https://github.com/posquit0/react-tutorial/blob/master/LICENSE) 96 | --------------------------------------------------------------------------------