From 558eafac7d62fbab1191faa5655a767119387dd3 Mon Sep 17 00:00:00 2001 From: Avantgarde95 Date: Fri, 22 Nov 2024 06:37:37 +0900 Subject: [PATCH] [bugfix] Fix the image links * Fix Google Drive-based image links --- docs/index.html | 2 +- docs/main.87fdf83cd600d3d84199.js | 1 + docs/main.96a9125fddc10091c51d.js | 1 - src/article/React.md | 8 ++++---- 4 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 docs/main.87fdf83cd600d3d84199.js delete mode 100644 docs/main.96a9125fddc10091c51d.js diff --git a/docs/index.html b/docs/index.html index 2904247..10c574a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1 +1 @@ -Let's react
\ No newline at end of file +Let's react
\ No newline at end of file diff --git a/docs/main.87fdf83cd600d3d84199.js b/docs/main.87fdf83cd600d3d84199.js new file mode 100644 index 0000000..5163f65 --- /dev/null +++ b/docs/main.87fdf83cd600d3d84199.js @@ -0,0 +1 @@ +!function(){"use strict";var n,t,e,o,r,s={1691:function(n,t,e){var o=e(7294),r=e(3935);function s(n){var t=n.split(/\r?\n/),e=[{title:null,content:""}];return t.forEach((function(n){var t=function(n){var t=n.match(/^#[^#]/);if(null===t)return null;var e=t[0];return n.slice(e.length)}(n);null!==t?e.push({title:t,content:""}):e[e.length-1].content+=n+"\n"})),e}function a(n,t){return t>=0&&t=0&&e=0&&localStorage.setItem("sectionIndex",""+t),f(t)}}},s)},p=(0,o.createContext)({}),u=function(n){var t=n.children,e=(0,o.useState)(!1),r=e[0],s=e[1];return o.createElement(p.Provider,{value:{isMenuOpen:r,setMenuOpen:s}},t)},d=function(n){var t=n.index,e=n.section,r=(0,o.useContext)(i).setSectionIndex;return o.createElement("div",{className:"SectionItem",onClick:function(){r(t)}},e.title)},m=function(n){var t=n.article,e=n.isSelected,r=n.onClick;return o.createElement("div",{className:"ArticleItem"},o.createElement("div",{className:"Button "+(e?"selected":""),onClick:r},t.title),e&&o.createElement("div",{className:"Dropdown"},t.sections.map((function(n,e){return null!==n.title&&o.createElement(d,{key:t.title+"-"+n.title,index:e,section:n})}))))},v=function(){var n=(0,o.useContext)(i),t=n.articles,e=n.articleIndex,r=n.setArticleIndex,s=(0,o.useContext)(p).isMenuOpen;return o.createElement("div",{className:"Menu "+(s?"open":"")},t.map((function(n,t){return o.createElement(m,{key:n.title,article:n,isSelected:t===e,onClick:function(){r(t)}})})))},h=e(9657),f=e(5376),g=e(5046),x=e(7852),b=e(6993),y=e(2422),S=e(8272);function w(n){if(void 0!==n){var t=n.toLowerCase();switch(t){case"javascript":return"jsx";case"typescript":return"tsx";case"jsonc":return"json";default:return t}}}h.Z.registerLanguage("jsx",f.Z),h.Z.registerLanguage("tsx",g.Z),h.Z.registerLanguage("json",x.Z),h.Z.registerLanguage("html",b.Z),h.Z.registerLanguage("css",y.Z);var j,C=function(n){var t=n.language,e=n.children;return o.createElement(h.Z,{language:w(t),style:S.Z},String(e).trimRight())},k=function(n){var t=n.href,e=(0,o.useState)(!1),r=e[0],s=e[1];return o.createElement("div",{className:"DemoView"},o.createElement("button",{className:"Show",onClick:function(){s(!r)}},r?"데모 접기":"데모 열기"),r&&o.createElement("div",{className:"Main"},o.createElement("iframe",{className:"Code",src:t,allow:"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking",sandbox:"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"})))},E=e(172),M=function(n){var t=n.src,e=n.alt,r=n.children,s=(0,o.useState)(!1),a=s[0],c=s[1],i=(0,o.useRef)(null);return(0,o.useEffect)((function(){var n=i.current;null!==n&&new E.W(n,{sourceAttribute:"data-src"})}),[]),o.createElement("div",{ref:i,className:"ImageView","data-src":t},!a&&"Loading...",o.createElement("img",{src:t,alt:e,onLoad:function(){c(!0)}},r))},O=(0,o.lazy)((function(){return e.e(456).then(e.t.bind(e,8456,23))})),T={code:function(n){var t=n.inline,e=n.className,r=n.children,s=void 0!==e&&e.startsWith("language-")?e.substring(9):void 0;return t?o.createElement("code",{className:"InlineCodeView"},r):o.createElement(C,{language:s},r)},a:function(n){var t=n.href,e=n.children,r=t;return r.startsWith("https://codesandbox.io/embed")?o.createElement(k,{href:r}):o.createElement("a",{target:"_blank",rel:"noopenner noreferrer",href:r},e)},img:function(n){var t=n.src,e=n.alt,r=n.children;return o.createElement(M,{src:t,alt:e},r)}},A=function(n){var t=n.content;return o.createElement(o.Suspense,{fallback:o.createElement("div",null,"Loading...")},o.createElement(O,{components:T},t))},R=function(n){var t=n.index,e=n.section,r=(0,o.useContext)(i),s=r.sectionIndex,a=r.setSectionIndex,c=(0,o.useRef)(null);return(0,o.useEffect)((function(){t===s&&(c.current.scrollIntoView({behavior:"smooth"}),a(-1))}),[s]),o.createElement("div",{className:"SectionView",ref:c},null!==e.title&&o.createElement("h1",null,e.title),o.createElement(A,{content:e.content}))},J=function(){var n=(0,o.useContext)(i),t=n.articles,e=n.articleIndex,r=(0,o.useContext)(p).setMenuOpen,s=t[e];return o.createElement("div",{className:"Viewer",onClick:function(){r(!1)}},o.createElement("div",{className:"ArticleTitle"},s.title),o.createElement("div",{className:"ArticleSections",key:s.title},s.sections.map((function(n,t){return o.createElement(R,{key:t+"-"+n.title,index:t,section:n})}))))};function N(){return(N=Object.assign||function(n){for(var t=1;t 3 + 4\n7\n> 'abc' + 'def'\n'abcdef'\n>\n```\n\n# npm\n- Node.js는 [npm](https://www.npmjs.com/)이라는 패키지 관리자를 제공합니다. 웹사이트 제작에도 서버 제작에도 모두 사용할 수 있습니다.\n - Python의 pip, Java의 maven과 비슷하게 생각하면 됩니다.\n- \"package.json\" 파일을 이용하여 프로젝트의 정보 및 사용할 라이브러리들을 지정해줄 수가 있습니다.\n- `npm install`을 실행하면 package.json을 읽어서 라이브러리들을 `node_modules` 아래에 설치해줍니다.\n - \"package-lock.json\"이라는 파일이 자동 생성되며, 이는 **사용자가 수정할 필요가 없습니다**.\n - `node_modules`의 크기는 일반적으로 **매우** 크기 때문에 git 저장소에 올리지 않는 것을 권장합니다.\n - 사용하는 패키지(= 라이브러리)의 버전을 바꾸거나 패키지를 추가/제거하고 싶으면, package.json를 수정한 후에 `npm install`을 한번 실행해주면 됩니다.\n- `npm run ABC`를 실행하면 `package.json`의 `scripts`에서 `ABC`에 해당하는 문자열을 실행해줍니다. 빌드 스크립트를 만들 때 유용하게 사용할 수 있습니다.\n\n# Useful links\n- [package.json 알아보기](https://velog.io/@skyepodium/package.json)\n - 패키지 버전 네이밍 (ex. `1.2.3` vs `^1.2.3` vs `~1.2.3`)\n - `dependencies` vs `devDependencies` vs `peerDependencies`\n"},7133:function(n){n.exports="# About\n- [Homepage](https://reactjs.org/)\n- 복잡한 웹사이트를 쉽게 만들 수 있도록 해주는 **웹 프레임워크**입니다.\n- [AngularJS](https://angularjs.org/), [Vue.js](https://v3.vuejs.org/)와 같이 현재 가장 많이 쓰이는 웹 프레임워크 중 하나입니다.\n\n# Virtual DOM\n- 기존의 웹사이트 개발은 HTML로 DOM을 선언한 다음 JavaScript로 DOM을 직접 수정하는 방식으로 이루어집니다.\n예를 들어, 버튼을 클릭하면 화면의 텍스트를 변경하는 웹사이트를 만들어봅시다.\n ```html\n
\n \n
\n
Hello
\n
World
\n
\n
\n ```\n ```javascript\n const button = document.getElementById('Button');\n\n // 버튼을 클릭하면...\n button.addEventListener('click', () => {\n // Text1의 끝에 !를 붙인다.\n const text1 = document.getElementById('Text1');\n text1.innerHTML += '!';\n\n // Text2의 끝에 !를 붙인다.\n const text2 = document.getElementById('Text2');\n text2.innerHTML += '!';\n });\n ```\n \n ![DirectDOMUpdate](https://lh3.googleusercontent.com/d/1Ymh5fekB7WfPzZ-ofVpfCvdsOLbV0GlE)\n- 사용자가 DOM을 수정할때마다 웹 브라우저는 웹사이트를 다시 렌더링합니다. 즉 DOM의 수정은 비싼 작업이며, 만약 DOM의 수정이 잦다면 **성능 저하**를 일으킬 수 있습니다.\n- React는 DOM을 직접 수정하는 기존의 방식 대신, ['가상' DOM(Virtual DOM)](https://ryublock.tistory.com/41)이라는 개념을 도입하여 이 문제를 해결합니다.\n - Virtual DOM은 실제 DOM과 유사한 tree 형태를 가지고 있습니다.\n - 사용자가 데이터를 변경하면 virtual DOM이 업데이트됩니다.\n - React는 virtual DOM의 현재 버전과 이전 버전을 비교하여 달라진 부분들을 찾아서 실제 DOM을 알아서 효율적으로 업데이트 해줍니다.\n- 아래는 위의 예시를 React로 재작성한 코드입니다. 사용자가 버튼을 클릭하여 데이터들을 변경하면, React는 virtual DOM을 비교하여 `Text1`과 `Text2`가 변경되었다는 것을 알아내어 실제 DOM에 반영합니다.\n ```jsx\n // App이라는 component를 선언\n class App extends React.Component {\n constructor(props) {\n super(props);\n\n // App의 상태(state)를 정의\n this.state = {\n text1: 'Hello',\n text2: 'World'\n };\n }\n\n render() {\n return (\n
\n {\n this.setState({\n text1: this.state.text1 + '!',\n text2: this.state.text2 + '!'\n });\n }}\n >\n Run\n \n
\n
{this.state.text1}
\n
{this.state.text2}
\n
\n
\n );\n }\n }\n ```\n \n ![VirtualDOMAbout](https://lh3.googleusercontent.com/d/12PayH2iFwhQpYbyTxond1Znj1bXUnWR9)\n\n# Component\n- React에서 우리가 그릴 요소(**element**)를 만들어주는 틀을 [컴포넌트(**component**)](https://sambalim.tistory.com/117)라고 합니다. Component는 속성(**props**)을 입력으로 받아 element를 반환해주며, 내부에 상태(**state**)를 가질 수 있습니다.\n ![Component](https://lh3.googleusercontent.com/d/1Mer3HX64_lI_WIFNiH-Zlq8_OiS-zVIY)\n- 만약 특정 component의 **state가 변경**되면 React는 [해당 component를 다시 그립니다(렌더링합니다)](https://felixgerschau.com/react-rerender-components/#when-does-react-re-render).\n - 이 때 state 객체를 직접 변경하면 안 되고, React에서 제공하는 기능(클래스 형태인 경우 `setState()`를 사용, 함수 형태인 경우 `useState()`가 만들어주는 함수를 사용)을 사용하여 state를 변경해야 합니다.\n- Component를 클래스 형태로 선언할 수도 있으며, 함수 형태로 선언할 수도 있습니다.\n 예컨대 위의 예시를 함수 형태로 작성하면 아래와 같습니다.\n ```jsx\n // (1) function 키워드를 사용하는 방법\n function App(props) {\n // App의 상태(state)를 정의\n const [text1, setText1] = useState('Hello');\n const [text2, setText2] = useState('World');\n\n return (\n
\n {\n setText1(text1 + '!');\n setText2(text2 + '!');\n }}\n >\n Run\n \n
\n
{text1}
\n
{text2}
\n
\n
\n );\n }\n ```\n ```jsx\n // (2) Arrow function 문법을 사용하는 방법 ((1)과 의미는 동일)\n const App = () => {\n // App의 상태(state)를 정의\n const [text1, setText1] = useState('Hello');\n const [text2, setText2] = useState('World');\n\n return (\n
\n {\n setText1(text1 + '!');\n setText2(text2 + '!');\n }}\n >\n Run\n \n
\n
{text1}
\n
{text2}
\n
\n
\n );\n };\n ```\n \n\n# JSX\n- 위의 예시들을 보면 일반적인 JavaScript 코드랑 다르게 코드에 JavaScript와 HTML이 섞여있는 모양새를 하고 있습니다.\n ```jsx\n const x =
Hello!
;\n ```\n 이는 [**JSX**](https://reactjs.org/docs/introducing-jsx.html)라는 JavaScript의 확장 문법으로, React 등의 라이브러리들을 편리하게 사용할 수 있도록 해줍니다.\n Babel (JavaScript 컴파일러) 등의 도구들은 JSX 코드를 아래와 같이 JavaScript 코드로 변환해줍니다.\n ```javascript\n const x = React.createElement('div', {className: 'Title'}, 'Hello!');\n ```\n- HTML 중간에 다시 JavaScript 코드를 넣으려면 중괄호를 사용해주면 됩니다. 중괄호 안에 다시 HTML을 사용하는 것도 가능합니다.\n ```jsx\n const x =
{5 - 3}
;\n ```\n- HTML 중간에 JavaScript 코드를 넣을 수 있는 것을 이용하여 component를 동적으로 생성하거나 조건에 따라 다른 component를 렌더링하는 등의 응용이 가능합니다.\n ```jsx\n // 조건에 따라 다른 component 렌더링\n const App = props => (\n
\n {props.isRed ? :
Wrong!
}\n
\n );\n\n // Component를 동적으로 생성\n const students = ['Cindy', 'John', 'Paul'];\n\n const App = props => (\n
\n {students.map(name =>
{name}
)}\n
\n );\n ```\n- TypeScript도 JSX와 유사한 **TSX**라는 확장 문법이 존재합니다. 사용 방법은 JSX와 동일합니다.\n\n# Composition\n- React에서는 [합성(**Composition**)](https://blog.sonim1.com/186)을 이용하여 component 코드를 재사용하고 작은 component들을 조합하여 복잡한 component들을 만들 수 있습니다.\n- 위의 예제에서 텍스트를 표시하는 부분들을 `Text`라는 별도의 component로 분리해 봅시다.\n ```jsx\n const Result = props => (\n
\n
{props.text1}
\n
{props.text2}
\n
\n );\n\n const App = () => {\n const [text1, setText1] = useState('Hello');\n const [text2, setText2] = useState('World');\n\n return (\n
\n {\n setText1(text1 + '!');\n setText2(text2 + '!');\n }}\n >\n Run\n \n \n
\n );\n };\n ```\n- JavaScript의 `.map()`을 이용하여 text의 개수에 따라 `
`를 만들도록 할 수도 있습니다.\n ```jsx\n const Result = props => (\n
\n {props.texts.map(text => (\n
{text}
\n ))}\n
\n );\n\n const App = () => {\n const [texts, setTexts] = useState(['Hello', 'World', 'Bye', 'Wow']);\n\n return (\n
\n {\n setTexts(texts.map(text => text + '!'));\n }}\n >\n Run\n \n \n
\n );\n };\n ```\n- 여기서 기존의 `Result` component를 활용하여 텍스트를 대문자 또는 소문자로 바꾸는 component를 만든다고 합시다.\n 우리에게 익숙한 객체지향 프로그래밍에서는 `Result`라는 클래스를 **상속**받는 방식을 택할 것입니다.\n 하지만 React에서는 **합성**을 이용하여 상속을 굳이 사용하지 않고도 component를 확장할 수 있습니다.\n ```jsx\n const Result = props => (\n
\n {props.texts.map(text => (\n
{text}
\n ))}\n
\n );\n\n // 위쪽에 제목 표시.\n const PrettyResult = props => (\n
\n {'[' + props.name + ']'}\n \n
\n );\n\n // 대문자 버전.\n const UpperResult = props => (\n text.toUpperCase())}\n />\n );\n\n // 소문자 버전.\n const LowerResult = props => (\n text.toLowerCase())}\n />\n );\n\n const App = () => {\n const [texts, setTexts] = useState(['Hello', 'World', 'Bye', 'Wow']);\n\n return (\n
\n {\n setTexts(texts.map(text => text + '!'));\n }}\n >\n Run\n \n \n \n \n
\n );\n };\n ```\n ![Composition](https://lh3.googleusercontent.com/d/1_tDCCKObMY-z10tQsh24Bh8g10W4Z_tD)\n \n\n# Useful links\n[React 공식 문서](https://reactjs.org/docs/getting-started.html)에서 자주 읽어보게 되는 부분들을 몇 개 뽑았습니다.\n- [Components and Props](https://reactjs.org/docs/components-and-props.html)\n- [State and Lifecycle](https://reactjs.org/docs/state-and-lifecycle.html)\n- [Context](https://reactjs.org/docs/context.html)\n - 어떤 데이터를 여러 단계 밑에 있는 자식 component로 전달하고 싶을 때 유용합니다.\n - 최상위 component에 state를 달고 context를 이용하여 state와 각 state의 setter 함수들을 자식들에게 뿌리는 식으로 데이터(상태) 관리 시스템을 쉽게 구현할 수 있습니다.\n- [Lists and Keys](https://reactjs.org/docs/lists-and-keys.html)\n - Component의 리스트를 생성할 때 만약 component 여러 개가 동시에 바뀐다거나 의도한 것과 다른 component가 바뀐다거나 하는 버그들이 발생할 경우, **key**를 사용해보세요.\n- [Lifting State Up](https://reactjs.org/docs/lifting-state-up.html)\n- [Conditional Rendering](https://reactjs.org/docs/conditional-rendering.html)\n- [Refs and the DOM](https://reactjs.org/docs/refs-and-the-dom.html)\n - 가끔씩 DOM에 직접 접근해야 할 경우가 있습니다. (ex. ``를 사용할 때, 외부 라이브러리를 사용할 때) 이 때 **ref**를 사용하여 Component가 가리키는 DOM에 접근할 수 있습니다.\n- [Fragments](https://reactjs.org/docs/fragments.html)\n - Component 여러 개를 하나로 묶되 DOM 생성은 하고 싶지 않을 때 유용합니다.\n- [Error boundaries](https://reactjs.org/docs/error-boundaries.html)\n - 에러 발생 시 종종 렌더링이 실패하여 페이지가 아예 그려지지 않는 경우가 있습니다. React의 `componentDidCatch()`를 이용하여 에러를 catch하여 처리할 수 있습니다.\n"},150:function(n){n.exports="# About\nUnder construction...\n"},6004:function(n){n.exports="# About\nUnder construction...\n"},2650:function(n){n.exports="# About\n- [Homepage](https://www.typescriptlang.org/)\n\nJavaScript 기반의 언어로, JavaScript의 문법을 확장하여 C++, Java처럼 **자료형(type)을 명시하고** 체크하여 견고한 프로그래밍이 가능하도록 한 언어입니다.\n\n```typescript\n// JavaScript\nfunction addNumbers(x, y) {\n return x + y;\n}\n\n// TypeScript\nfunction addNumbers(x: number, y: number): number {\n return x + y;\n}\n```\n\n\n\nJavaScript의 기본 자료형뿐만 아니라, 자료형의 조합을 통한 복잡한 자료형 생성도 지원합니다.\n\n```typescript\n// number이거나 string\nconst x: number | string = 3;\n\n// 'A', 'B', or 'C' ('D'를 넣으면 에러)\nconst y: 'A' | 'B' | 'C' = 'A';\n\n// 키는 number, 값은 boolean인 map 형태의 객체\nconst z: {[key: number]: boolean} = {3: true, 4: false};\n```\n\n웹 브라우저는 일반적으로 JavaScript만을 지원합니다. 따라서 TypeScript 컴파일러(tsc)를 이용하여 JavaScript로 변환하여 사용해야 합니다.\n`tsconfig.json` 파일을 이용하여 컴파일러에 여러 옵션(ex. 어떤 버전의 JavaScript로 변환할 것인지)을 줄 수가 있습니다.\n\n```jsonc\n{\n \"compilerOptions\": {\n \"target\": \"es3\", // Target JavaScript version.\n ...\n },\n ...\n}\n```\n\n# Example\n`npm install -g typescript`를 사용하여 TypeScript 컴파일러를 설치하고, 아래 코드를 \"Example.ts\" 파일로 저장하고 터미널에서 `tsc Example.ts`를 실행해보세요.\n\n```typescript\nfunction addNumbers(x: number, y: number): number {\n return x + y;\n}\n```\n\n`Example.js`가 생성됩니다.\n\n```javascript\nfunction addNumbers(x, y) {\n return x + y;\n}\n```\n\n만약 아래와 같이 함수에 잘못된 자료형의 값을 대입한다면 컴파일 에러가 납니다.\n\n```typescript\nfunction addNumbers(x: number, y: number): number {\n return x + y;\n}\n\naddNumbers(3, 'abc'); // Wrong code!\n```\n\n# Keywords\n- **Union type** / Intersection type (자료형의 합집합 / 교집합)\n- **Interface**\n - `interface` vs `type`\n- **Nullable**\n - 예컨대 변수 `x`가 `string` 자료형이라면, `x`는 `null` 또는 `undefined`가 될 수 없습니다.\n - `null`이나 `undefined`를 쓰고 싶으면 `string | null` 또는 `string | undefined`와 같이 union type을 활용해야 합니다.\n- Object type / Mapped type\n - C++의 구조체처럼 객체의 모양 자체를 자료형으로 쓸 수도 있습니다. (ex. `{x: number, y: number}`)\n - 한편 map 형태의 자료형이 별도로 존재합니다. (ex. `{[key: string]: number}`)\n- Generics\n - Java의 generic과 유사합니다.\n- Type alias\n - C++의 typedef, using과 유사합니다.\n\n# Useful links\n- [TypeScript 공식 문서](https://www.typescriptlang.org/docs/)\n"},6778:function(n){n.exports='# About\n\n웹사이트를 구성하는 기본적인 요소들에 대하여 담았습니다.\n\n# HTML / CSS / JS\n\n웹사이트는 일반적으로 아래의 세 가지 언어로 구성됩니다.\n\n## HTML\n웹사이트의 구조(layout)를 표현합니다.\n\n```html\n
\n Hello!\n \n
\n```\n\n## CSS\n웹사이트의 스타일(ex. 색깔, 크기)을 결정합니다.\n\n```css\n.About {\n color: #0000ff;\n}\n```\n\n## JavaScript\n웹사이트의 동작(ex. 상호작용, DOM 변경)을 표현합니다.\n\n```javascript\nconst button = document.getElementsByClassName(\'Run\')[0];\n\nbutton.addEventListener(\'click\', () => {\n alert(\'Yeah!\');\n});\n```\n\n웹페이지는 하나의 HTML 파일로 표현이 됩니다.\n`\n \n \n
\n Hello!\n \n
\n\n