NextJS의 4가지 Rendering 방식과 그 구현

NextJS의 4가지 Rendering 방식과 그 구현 Next.js는 React 기반의 프레임워크로, 다양한 종류의 렌더링을 지원하며 쉽게 구현할 수 있도록 도와줍니다. 1. 4가지 렌더링 방법과 그 구현 방법 Static Generation (정적 생성): 정적 생성은 빌드 타임에 페이지의 HTML을 생성하는 방식입니다. 동적 데이터를 포함할 수도 있습니다. 구현 방법: // pages/about.js function AboutPage({ data }) { return ( About Page {data} ); } export async function getStaticProps() { const data = 'This is dynamic data.'; return { props: { data, }, }; } export default AboutPage; Server-side Rendering (서버 사이드 렌더링): 서버 사이드 렌더링은 요청이 들어올 때마다 서버에서 페이지의 HTML을 생성하는 방식입니다. 동적 데이터를 포함할 수 있습니다. 구현 방법: // pages/blog/[slug].js import { useRouter } from 'next/router'; function BlogPost({ post }) { return ( {post.title} {post.content} ); } export async function getServerSideProps(context) { const { params } = context; const res = await fetch(https://api.example.com/posts/${params.slug}); const post = await res.json(); return { props: { post, }, }; } export default BlogPost; Client-side Rendering (클라이언트 사이드 렌더링): 클라이언트 사이드 렌더링은 초기 HTML은 서버에서 제공하지만, 페이지의 구성 요소들은 JavaScript를 통해 클라이언트 측에서 렌더링되는 방식입니다. 구현 방법: // pages/products.js import { useState, useEffect } from 'react'; function ProductsPage() { const [products, setProducts] = useState([]); useEffect(() => { // Fetch products data using client-side API calls fetch('/api/products') .then((response) => response.json()) .then((data) => setProducts(data)); }, []); return ( Products {products.map((product) => ( {product.name} ))} ); } export default ProductsPage; Incremental Static Regeneration (증분 정적 생성): 증분 정적 생성은 빌드 타임에 정적 페이지를 생성하고, 일정 주기마다 페이지를 다시 생성하여 업데이트하는 방식입니다. 구현 방법: // pages/blog/[slug].js function BlogPost({ post }) { return ( {post.title} {post.content} ); } export async function getStaticProps(context) { const { params } = context; const res = await fetch(https://api.example.com/posts/${params.slug}); const post = await res.json(); return { props: { post, }, revalidate: 60, // Re-generate after 60 seconds }; } export default BlogPost; 이렇게 Next.js는 다양한 렌더링 종류를 제공하며 각각의 요구에 맞게 선택하여 사용할 수 있습니다. 2. 각 렌더링 방법의 장단점 다음은 Next.js의 4가지 주요 렌더링 방법인 정적 생성(Static Generation), 서버 사이드 렌더링(Server-side Rendering), 클라이언트 사이드 렌더링(Client-Side Rendering), 그리고 증분 정적 생성(Incremental Static Regeneration)의 간단한 장단점을 요약한 것이다. 정적 생성 (Static Generation): 장점: 초기 로딩 속도가 빠르고 SEO에 좋음. CDN 캐싱 가능. 단점: 동적 데이터 처리가 어려울 수 있음. 서버 사이드 렌더링 (Server-side Rendering): 장점: 동적 데이터 처리가 용이하며, 초기 로딩 속도와 SEO에 좋음. 단점: 서버 부하가 있을 수 있고, 초기 로딩 속도가 정적 생성보다 느릴 수 있음. 클라이언트 사이드 렌더링 (Client-Side Rendering): 장점: 초기 로딩이 빠르고, 복잡한 인터랙션 구현 가능. 단점: SEO와 초기 렌더링 속도에 제약이 있을 수 있으며, 검색 엔진 크롤링에 문제가 될 수 있음. 증분 정적 생성 (Incremental Static Regeneration): 장점: 정적 생성의 이점을 유지하면서 일부 페이지만 주기적으로 업데이트 가능. 단점: 정적 생성에 비해 복잡할 수 있고, 주기적 갱신이 필요한 페이지에 적합. 각 방법은 상황과 요구에 따라 선택되며, 성능, SEO, 데이터 업데이트 빈도 등의 요소를 고려하여 결정하는 것이 중요하다. 2. 요약 정리 Next.js의 4가지 주요 렌더링 종류와 간단한 구현 방법을 요약하자면 다음과 같다. 정적 생성 (Static Generation): 빌드 타임에 페이지의 HTML을 생성. getStaticProps 함수를 사용하여 데이터를 가져옴. 주로 동적 데이터를 포함할 수 있음. 서버 사이드 렌더링 (Server-Side Rendering): 요청 시 서버에서 페이지의 HTML을 생성. getServerSideProps 함수를 사용하여 데이터를 가져옴. 동적 데이터를 포함 가능. 클라이언트 사이드 렌더링 (Client-Side Rendering): 초기 HTML은 서버에서 제공. 페이지의 요소들은 클라이언트에서 JavaScript로 렌더링. 주로 동적 로딩에 사용. 증분 정적 생성 (Incremental Static Regeneration): 빌드 타임에 정적 페이지 생성 후 일정 주기마다 업데이트. getStaticProps에서 revalidate 값을 설정하여 갱신 주기 설정.

javascript

nextjs

ssr

ssg

2023-08-28, 20:03

Node.js 웹 서버가 JAVA 웹 서버보다 성능이 뛰어날까?

Node.js 웹 서버가 JAVA 웹 서버보다 성능이 뛰어날까? Node.js 웹 서버가 JAVA 웹 서버보다 성능이 뛰어나다는 소문에 대한 진실을 파해쳐겠다. 이 글에서는 해당 소문을 재시하는 다양한 사람들의 근거와 진실 여부를 파악하여 결론을 도출하겠다. 1. 많은 사람들이 그 이유를 제대로 설명하지 못한다. 아래는 여러 블로그 글들을 읽어보고 가장 많이 사람들이 근거로 드는 내용을 정리 한 것이다. Node.js는 싱글 쓰레드 기반의 논블로킹 방식의 I/O를 사용하고, 멀티 쓰레드와 블로킹 방식 I/O를 사용하는 자바 웹 서버보다 빠르다. 왜냐하면 멀티 쓰레드 방식은 컨텍스트 스위치 오버헤드가 있기 때문이다??? 정말 어이없다. 이는 더 성능이 빠른 이유가 될수 없고, 그나마 싱글 쓰레드 기반인 Node.js가 멀티 쓰레드 기반인 자바 웹 서버 처럼 여러 요청에 대한 동시적인 처리를 할 수 있는 이유가 될 뿐, 이 사실 자체로는 더 나은 성능을 나타내는 이유가 될 수는 없다. 생각해보라, 논블로킹 방식의 I/O를 지원하는 것도 결국 Node.js가 내부적으로 멀티 쓰레드를 구현하고 있다라는 의미 밖에 안되고, 이도 마찬가지로 자체적인 컨텍스트스위칭이 필요할 것이다. 즉, 단순히 논블로킹 싱글 쓰레드라서 블로킹 멀티 쓰레드보다 빠르다는건 논리적으로 근거가 빈약하다 2. 내가 여러 기술 스펙들을 읽어보고 정리해 보았다 개인적인 주장이니 어디가서 정답인양 말하지 말라. 2.1. NodeJS가 비동기 I/O 시스템 콜의 활용성이 더 좋다. 본래 태초에 OS가 등장 했을 때는 I/O 시스템 콜[1]은 동기 요청 방식만 제공하였었다. 프로그램은 I/O요청에 대한 비동기적인 처리를 위해 별도의 쓰래드를 생성하는 것이 일반적이 었다. 그리고 이러한 비동기 방식의 사용자 I/O 요청이 보편화 되자 이를 표준화한 POSIX 1.b의 AIO도 등장하여 이를 따르는 많은 OS들에서 더욱 쉽게 비동기 I/O 요청을 사용할 수 있게 되었다. 물론 오직 API 규격으로써 당시에 그 내부적인 구현이 있지도 않은 비동기 I/O 시스템 콜을 이용한다는 말은 아니다. 태초의 OS는 동기 방식의 I/O 시스템 콜만을 지원. 사용자 레벨의 쓰레드와 동기 I/O 시스템 콜을 활용하여 사용자 레벨의 비동기 I/O를 구현. [1] 여기서 말하는 시스템 콜은 POSIX 시스템 콜이 아니다.(시스템 콜에 대한 POSIX 규격 인터페이스를 POSIX 시스템 콜이라고 부르기도 한다) 그러나 얼마전부터 자체적으로 비동기 I/O 시스템 콜을 지원해 주는 OS들이 등장하기 시작했다. 대표적으로 linux AIO(kernel ver 2.6부터 표준)을 들수가 있다. 이들은 모두 커널 레벨의 비동기 I/O 요청을 구현함으로서 커널에서 내부적으로 비동기 처리에 쓰일 쓰레드를 생성 관리하기 때문에 성능이 아주 우수하다. 물론 그 구현과 지원 여부는 OS마다 다른데, Node.js는 구동 OS의 지원 여부에 따라 이러한 커널 수준의 비동기 I/O를 사용한다. 그렇다면, JAVA는 커널 수준의 비동기 I/O를 사용하지 않는가? 아니다. JAVA도 OS 커널의 비동기 I/O 시스템 콜을 사용하는 java.nio 가 마련되어 있다. JAVA 1.4 때 등장해서 웹 서버에 사용되기 시작했는데, Tomcat에서는 NIO Connector를 통해 소켓 연결할 때 사용한다. NIO Connector 같은 경우 Tomcat 6.0때 등장해서 8.0부터는 개선된 java.nio2를 사용하는 기본 Connector가 되었으니, Tomcat 8.0부터 본격적으로 커널 레벨의 비동기 I/O를 사용하기 시작했다고 할 수 있다. 이후 9.0부터는 블로킹(동기)방식의 BIO Connector는 아예 사라졌다고 한다. 톰켓 8.0 나온 시점보다 한참 전인 2009년에 Node.js가 나왔으니, 적어도 그 기간 동안에는 Node.js의 비동기 I/O 성능이 압도적이었다고 할 수 있다. 각종 OS에 비동기 I/O 시스템 콜의 등장하고 이를 활용하는 Node.js가 등장했다. 이는 비동기 I/O에 있어서 기존의 동기방식 I/O 시스템 콜과 멀티 쓰레드를 활용하는 자바 웹 서버보다 성능이 뛰어났다. 2.2. Node.js 웹 서버는 보다 I/O 집약적인 Thread Pool을 가진다 Tomcat 8.0이후 시점으로 봤을 때도, 여전히 Node.js의 비동기 I/O속도가 빠른가? 라는 의문이 생기는데, 이 부분에서도 Yes라고 할 수 있다. 우선 Node.js에서는 기본적으로 Network I/O를 이벤트 루프에서 Polling 메커니즘[1]을 통해 처리한다.[2] Node.js는 Polling을 통한 Single Thread Non-Blocking Network I/O 방식을 OS와 무관하게 제공한다. 이를 위해 Node.js가 각 OS에서 사용하는 기술들은 다음과 같다. linux : epoll OSX, BSDs : kqueue SunOS, windows : event ports \* 자세한 내용은 libuv 공식 홈페이지에서 확인할 수 있다. Network I/O를 제외하고도 프로그램이 정상적으로 구동되기 위해 반드시 비동기로 처리해야할 것들은 크게 2종류가 있다. Network를 제외한 I/O-Intensive 작업과 CPU-Intensive 작업들이다. 이 둘은 긴 처리시간으로 프로그램의 흐름을 막을 것이다. Node.js는 OS에서 제공하는 비동기 시스템 콜을 우선적으로 활용하면서 제공되지 않는 요청에 대해서는 자체적인 Thread Pool인 Worker Pool에 작업을 할당해 처리한다. 그런데 여기서 중요한 점은, Node.js는 오로지 웹 서버의 수행에 필수적인 작업에 한해 Worker Pool에 할당된 API를 제공한다는 점이다. 따라서, CPU-Intensive 작업들은 극히 일부의 필수 항목만이 기본적으로 Worker Pool에 할당되어진다.[3] 다음은 대부분의 경우 Worker List에서 수행되어지는 작업 목록이다. I/O-Intensive DNS: dns.lookup(), dns.lookupService(). File System: fs.FSWatcher()와 libuv의 스레드 풀을 명백하게 동기적으로 사용하는 경우를 제외한 모든 파일 시스템 API.[4] CPU-Intensive Crypto: crypto.pbkdf2(), crypto.scrypt(), crypto.randomBytes(), crypto.randomFill(), crypto.generateKeyPair(). Zlib: libuv의 스레드 풀을 명백하게 동기적으로 사용하는 경우를 제외한 모든 zlib API. \* 자세한 내용은 Node.js Doc를 참조. 따라서, Node.js는 Thread Pool의 상당부분을 비동기 시스템 콜 미지원 I/O-Intensive 작업의 처리에 사용한다는 점이다. 이는 기본적으로 각 Connection에 대해 Thread를 생성하고 사용자 코드를 포함한 모든 CPU-Intensive를 각 Thread에서 처리하는 대부분의 JAVA 웹 서버에 비해 I/O-Intensive 작업의 응답속도가 빨라질 수 밖에 없다. Node.js는 사용자 코드가 야기하는 CPU-Intensive 작업의 스케줄링을 포기하고 대신 I/O-Intensive 작업의 추가적인 할당을 선택했기 때문이다. Worker Pool 또는 커널을 통해 수행될 수 없는 작업은 모두 이벤트 루프에서 수행되기 때문에 이벤트 루프를 사용자가 작성한 CPU-Intensive한 코드로 막지 말아야 한다.[5] 복잡한 연산이 요구되는 사용자 코드의 작성은 Node.js의 설계 방향성과 맞지 않기에 그 장점을 살리지 못한다. Node.js는 I/O 특화 Thread Pool을 가진다, Thread Pool 자원은 일부 필수 CPU-Intensive 작업을 제외하고 모두 I/O-Intensive 작업에게 할당되어진다. 정리하자면, 필수가 아닌 CPU-Inensive 작업들의 평균 응답속도를 포기해서 I/O-Intensive 작업의 평균 응답속도를 높혔다. [1] Polling은 Socket이나 Pipe에서 사용될 수 있는 다중 입출력 방식으로, 여러 FD들을 모니터링하다가 특정 FD에 읽기/쓰기가 가능한 상태가 되었을 때 데이터가 해당 FD에 읽고 쓰는 방식으로, 예를 들어 읽을 데이터가 없는 FD에 대한 Blocking이나 현재 쓸수 없는 상태인 fd에 대한 Blocking을 발생시지 않기 때문에 다중 네트워크 입력을 Single Thread Non-blocking I/O 방식으로 처리할 수 있게 한다. [2] 이벤트 루프를 I/O 루프라고도 부른다. [3] 사용자 코드에서 API에서 제공하지 않는 자신만의 I/O-Intensive 요청을 작성할 일이 없지만, CPU-Intensive 코드는 비즈니스 로직에 따라, 기타 사용자 의도에 따라 그 종류가 무한하므로 사용자가 사용할 수 있는 모든 CPU-Intensive를 API로 제공하기는 것은 불가능 하다. [4] 사실 여기서 더 자세히 들어가면, 커널 레벨의 비동기 시스템 콜이 없다고 해서 무조건 Worker Pool로 관리 되는 것도 아니다. OS 편차에 따라 다음과 같은 API를 사용한다고 한다. linux AIO (supported in kernel) posix AIO (supported by linux, BSD, Mac OS X, solaris, AIX, et) Windows'overlapped I/O [5] Node.js공식 문서에서는 이벤트 루프에 수행될 이벤트 콜백에 시간 복잡도가 높은 연산을 포함시켜 서버 전체의 평균 응답시간으로 늘리는 것을 "막는다"라고 표현했다.

node.js

libuv

2023-07-14, 13:15

전세보증보험

전세보증보험의 종류와 특징 1. 전세보증보험은 전세보증금반환보증이다 정식 명칭은 전세보증금반환보증 이다. 그러나 임차인에게 전세 사기등의 사고가 발생했을 시 전세보증금의 반환을 보장해주는 일종의 보험 처럼 작용하기 때문에 임차인들 사이에서 주로 전세보증보험이라는 별명으로 불리는 듯 하다. 전세보증보험을 들면 계약 만기 시 전세금을 돌려받지 못하는 사고가 발생했을 때, 일정 조건하에 보장된 금액만큼을 임대인을 대신해서 임차인에게 대위변제 해주고 임차인을 대신해서 임대인에게 해당 금액만큼의 구상권을 행사하게 된다. 2. 전세보증보험은 전세자금보증과는 다르다 흔히, 은행에서 전세 대출을 받기위해 심사를 통해 가입하게되는 전세자금보증은 대출 만기시 임차인이 대출금을 상환하지 못하는 사고가 터졌을 때 기관이 임차인을 대신해 보증된 금액만큼의 전세보증금을 대위변제해주고 임차인에게 그 금액에 대한 구상권을 행사하게 된다. 임차인이 임대인으로 부터 전세보증금을 돌려받았는지 여부는 중요하지 않고 오로지 은행의 자산만 보호해주는 보험인 것이다. 그러나 전세자금보증을 임차인이 대출시 가입할 수 밖에 없는 이유는 가입을 안하면 은행이 전세자금대출특유의 높은 한도의 저금리 대출을 해줄수 있는 이유이기 때문에 가입을 하고 보증할 수 있는 금액만큼 대출해주게 되는 것이다. 3. 전세보증보험의 종류 전세보증보험을 제공하는 기관은 크게 3가지이며, 각각 자신만의 이름이 있다. HUG : 전세금반환보증 HF : 전세지킴보증 SGI : 전세금보장신용보험 4. 각 전세보증보험별 특징 *목적물 유형별, 보증금액별 세부 조건등은 미기입 | 기관 | 보증료율 | 보증한도(보증목적물) | 보증한도(지역별) | | ---- | --------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | | HUG | 0.128% ~ 0.154% | 주택가격 x 담보인정비율(90%) – 선순위채권 | 수도권 7억, 이외 5억 | | HF | 0.04% | 주택가격의 90% - 선순위채권 총액(선순위근저당권설정액과 선순위임대차보증금의 합), 선순위채권 총액은 주택가격의 70% 이내 필수 | 7억원(서울/경기/인천 이외 지역은 5억원) | | SGI | 0.183 ~ 0.208% | 주택가격 ≥ 선순위채권+선순위 보증금액(선순위 설정총액이 주택가격의 60%이내)(홈페이지에서 찾질 못했다... 확인필요) | 제한없음 | 크게 두드러지는 특징을 정리하자면, 최대 보증가능 금액 : SGI > HUG > HF 보증료율 : HF < HUG < SGI 결론적으로, 나 같이 1억 이내의 전세 대출을 알아보고있는 사회 초년생에게는 HF의 전세지킴보증이 딱인거 같다.

전세지킴보증

hf

hug

sgi

전세보증보험

전세보증금반환보증

2023-07-11, 14:05

Github Page's Dependencies

Github Page가 제공하는 의존성들 1. Github Page가 제공하는 의존성을 왜 알아야하는가 Github Page를 사용할 때, 사용자는 Github Page가 기본적으로 재공하는 Gem 패키지들만 사용해야한다. Github Page의 빌드 서버에 설치된 Gem 패키지 목록을 관리하거나 사용자가 제공한 Gemfile내의 의존성 설치를 위한 Bundle install을 실행할 수 있는 옵션을 제공하지 않는다. 서버 기능, 성능, 용량에 제한을 두기위해서는 어쩔수 없는 조치이기도 하다. 따라서 우리는 Github Page가 제공하는 의존성을 알아야한다. 2. Github Page가 제공하는 의존성들 다음 링크에서 확인 가능하다. https://pages.github.com/versions/ 현재 기준으로 다음과 같은 의존성을 제공한다. | Dependency | Version | | ---------------------------- | ------- | | jekyll | 3.9.3 | | github-pages-health-check | 1.17.9 | | github-pages | 228 | | html-pipeline | 2.14.3 | | jekyll-avatar | 0.7.0 | | jekyll-coffeescript | 1.1.1 | | jekyll-commonmark-ghpages | 0.4.0 | | jekyll-default-layout | 0.1.4 | | jekyll-feed | 0.15.1 | | jekyll-gist | 1.5.0 | | jekyll-github-metadata | 2.13.0 | | jekyll-include-cache | 0.2.1 | | jekyll-mentions | 1.6.0 | | jekyll-optional-front-matter | 0.3.2 | | jekyll-paginate | 1.1.0 | | jekyll-readme-index | 0.3.0 | | jekyll-redirect-from | 0.16.0 | | jekyll-relative-links | 0.6.1 | | jekyll-remote-theme | 0.4.3 | | jekyll-sass-converter | 1.5.2 | | jekyll-seo-tag | 2.8.0 | | jekyll-sitemap | 1.4.0 | | jekyll-swiss | 1.0.0 | | jekyll-theme-architect | 0.2.0 | | jekyll-theme-cayman | 0.2.0 | | jekyll-theme-dinky | 0.2.0 | | jekyll-theme-hacker | 0.2.0 | | jekyll-theme-leap-day | 0.2.0 | | jekyll-theme-merlot | 0.2.0 | | jekyll-theme-midnight | 0.2.0 | | jekyll-theme-minimal | 0.2.0 | | jekyll-theme-modernist | 0.2.0 | | jekyll-theme-primer | 0.6.0 | | jekyll-theme-slate | 0.2.0 | | jekyll-theme-tactile | 0.2.0 | | jekyll-theme-time-machine | 0.2.0 | | jekyll-titles-from-headings | 0.5.3 | | jemoji | 0.12.0 | | kramdown-parser-gfm | 1.1.0 | | kramdown | 2.3.2 | | liquid | 4.0.4 | | minima | 2.5.1 | | nokogiri | 1.15.2 | | rouge | 3.26.0 | | ruby | 2.7.4 | | safe_yaml | 1.0.5 | | sass | 3.7.4 | 3. Github Page에 플러그인 추가시 주의할 점 3.1. Github Page 제공 의존성이 아니거나 다른 버전을 플러그인으로 추가한다면 다음과 같은 경고 로그를 볼 수 있다. Warning: github-pages can't satisfy your Gemfile's dependencies. Github Page 제공 의존성 버전과 호환되지 않는 버전을 플러그인에 추가 해 사용할 때, 별도의 Gemfile을 통해 사용자가 명시한 그 버전으로 빌드되지는 않는다. 최종적으로 사용자 명시 버전은 빌드 시 Warning 로그를 남긴채 무시되며, Github Page가 제공하는 버전을 통해 빌드를 수행한다. Github Page 에서 제공하지 않는 의존성을 플러그인에 추가한다면, 최종적으로 해당 Gem 패키지를 빌드에서 제외한 상태로 Warning 로그를 남긴 채 빌드를 수행한다. 3.2. Github Page가 기본으로 플러그인에 추가하는 의존성이 있다 다음 항목들은 Github Page가 기본으로 프로젝트 플러그인에 추가시키는 의존성들이다. \_config.yml에 사용자가 직접 플러그인에 추가할 필요가 없다. 또한 비활성화가 불가능하다 jekyll-coffeescript jekyll-default-layout jekyll-gist jekyll-github-metadata jekyll-optional-front-matter jekyll-paginate jekyll-readme-index jekyll-titles-from-headings jekyll-relative-links 기본적으로 플러그인된 의존성 목록이 Jekyll에 대한 의존성을 재귀적으로 포함하고 있기 때문에 Jekyll도 기본적으로 포함되게 된다. 3.3. Github Page에서 제공하지 않는 의존성을 추가하고 싶다면 Github Page에 업로드 하기 전에 먼저 로컬에서 지원 되지 않는 의존성들만 플러그인을 사용하여 따로 빌드를 마치고, 빌드 결과물을 일종의 정적 파일로 포함시켜 업로드 하면된다.

2023-07-10, 13:14

Javascript: this 키워드

1. Javascript의 this 키워드도 대체로 자기 자신(객체)을 가리킨다 보통 Java같은 객체지향 언어에서 this가 가리키는 대상은 this 을 선언한 해당 메서드를 수행 중인 자기 자신(객체)이다. Javascript에서 this 는 이와 비슷한 역할을 한다. 우선, 기본적으로 Javascript의 this키워드는 다른 객체지향 언어와 마찬가지로 this가 선언된 메서드를 수행 중인 객체를 가리킨다. function person() { this.name = '강아무개'; //person클래스의 생성자 메서드에서 선언. 즉, 생성자를 통해 생성할 person 객체를 가리킨다. } //ES6 문법에서 등장한 class 선언 문법 class person { constructor() { this.name = '강아무개'; //마찬가지로 this는 새로 생성할 person 객체를 가리킨다. } } 2. Javascript this를 메서드 블록 밖에서도 사용할 수 있다 Javascript에서의 this는 특별하다. 자신의 객체를 가리키는 this의 용도상 메서드 선언 블록에서만 this를 사용해야 하는 게 보통의 언어지만, Javascript는 this를 사용자 코드 어디에서든지 사용이 가능하다. 메서드를 포함한 모든 종류의 함수 내부에서 사용되며, 함수 밖 전역에서 단독으로 사용될 수도 있다. 2.1. 함수 내부에서 사용된 this 키워드 함수 내부에서 사용된 this 키워드는 호출 형태에 따라 참조하는 값이 달라진다. 2.1.1. 객체의 메서드로서 호출될 때 this는 함수가 어떤 객체의 메서드로서 호출될 때, 해당 객체를 참조한다. ES6의 클래스 문법 또는 리터럴 방식으로 메서드를 선언할 수 있다. 메서드로 선언되지 않은 함수들도 동적으로 임의의 객체에 메서드로 할당될 수 있다. Javascript의 객체는 메서드를 프로퍼티로 가지기 때문에 그 값을 동적으로 갱신시켜줄 수 있다. 따라서 객체 이름. 메서드 이름=함수 이름의 형식으로 함수를 할당하게 된다면, 객체의 메서드 프로퍼티를 통해 함수를 메서드로써 호출할 수 있다. 이 경우, 함수의 this키워드는 자신을 메서드로써 소유하는 객체를 참조할 수 있다. 아래 예제는 메서드가 아닌 함수로 선언된 person 함수가 객체 p의 메서드 프로퍼티로 할당되어 메서드로써 호출될 때, this가 p를 참조함을 나타낸다. function person() { this.height = 178; } const p = { height: 150, weight: 40, }; //p:{height: 150, weight: 40} p.update = person; //객체 p의 update메서드로 person을 할당. p.update(); //person함수의 this가 참조하는 값은 객체 p이다. //p:{height: 178, weight: 40, update: ƒ} new 키워드를 이용한 생성자 메소드의 호출에서, this는 생성될 객체를 참조한다 ES6에서 등장한 화살표 함수를 제외한 모든 함수는 new키워드를 통해 객체의 생성자 메소드로 사용될 수 있다. 이때, 함수는 새로 생성되는 객체의 메소드로서 this 키워드를 통해 생성할 객체를 참조할 수 있다. function person() { this.height = 178; } const p = new person(); //호출에서 this는 새 person 객체를 참조하게 된다. 2.1.2. 객체의 메서드가 아닌 함수로서 호출될 때 메서드가 아닌 함수에서 this는 엄격 모드일 경우 undefined를, 아닐 경우 전역 객체의 참조를 값으로 가진다. Javascript에서는 객체의 메서드를 외부에서 직접 접근 가능한 프로퍼티로 갖기 때문에, ES6 클래스 문법, 혹은 리터럴 방식으로 선언된 메서드 프로퍼티의 참조값을 전역 변수에 담을 수 있다. 이렇게 객체 메서드의 참조값을 담은 전역 변수를 그대로 함수 호출해버리면, 더 이상 객체의 메서드가 아닌 전역 함수로서 호출되어지고 객체가 메서드로 가지고 있는 함수와 같은 함수이지만, this는 더 이상 메서드를 소유한 객체를 참조하지 않는다. 아래 예제는 ES6의 클래스 문법으로 선언된 메서드를 메서드가 아닌 함수로 호출했을 때, this가 메서드를 소유한 객체를 참조하지 않고 undefined를 가지고 있는 것을 나타낸다. 엄격 모드가 적용된 환경에서의 결과이다 'use strict'; //엄격 모드 적용. class Obj1 { show() { console.log(this); } } const obj1 = new Obj1(); obj1.show(); //Obj1 {} const func = obj1.show; func(); //undefined 위의 예시에서 엄격 모드가 적용되지 않았다면, 메서드가 아닌 함수로 호출된 경우의 this는 브라우저에선 window NodeJs에선 global을 참조했을 것이다. 이는 전역 객체이며, 자바스크립트 엔진은 엄격 모드가 아닐 때, 자동으로 undefined 상태인 this에 전역 객체를 할당해준다. 2.2. 전역에서 사용된 this 키워드 전역에서 사용된 this키워드는 전역 객체를 참조한다. 엄격 모드의 유무와는 상관없다. 전역 객체는 브라우저에서는 window NodeJS에서는 global이다. console.log(this); //window {} 3. this의 정체 this는 실행 컨텍스트 객체의 프로퍼티 this는 실행 컨텍스트에서 바인딩이 관리되기 때문에 항상 런타임 바운딩을 가진다. 또한 bind()함수를 통해 사용자가 임의로 this에 값을 할당해 줄 수도 있다.

javascript

this

2022-11-28, 17:50

알고리즘의 자바 솔루션에서 GC로 인한 메모리 초과를 방지하는법

1. 자바 솔루션에서 메모리 초과가 나는 이유 1.1. 메모리 누수? 먼저, 메모리 누수는 아니다. 메모리 누수는 고려하지 않는다. 알고리즘 문제는 대게 메모리 요구사항이 있고 메모리 요구사항은 GC가 돌아가는 조건에 한참 못미친다. 애초에 후술하겠지만 GC가 수행도중에 돌아가서도 안된다. GC가 돌아가지 않으니 해당 솔루션이 메모리 누수가 나는 설계를 하였다고 하여도 메모리 초과의 직접적인 원인이라 할 수 없다. 그러나 현업에서는 GC가 비정상적인 상황이 아니며, 따라서 현업 앱 설계에는 메모리 누수에대한 고려가 필요하다. 1.2. 주요 2가지 원인 경험상 크게 2가지 이유가 있다. 문제에서 요구하는 공간 복잡도를 만족시키지 못한 경우. 이런 경우는 오히려 알고리즘의 재설계를 통해 쉽게 해결될 수 있다. 문제 해결이 쉽다. 공간 복잡도는 만족했지만 GC가 제때 되지 않아 메모리 초과가 나는경우 대게 자바는 2번 이유로 메모리 초과가 나는경우가 많다. 알고리즘의 공간 복잡도를 따져보면 조건을 만족하지만, 메모리 초과가 뜨는 경우이다. System.gc()를 코드 중간에 삽입해서 강제로 gc를 돌려주면 메모리 요구사항을 만족하는 것을 확인할 수 있다. 2. GC 강제로 돌리기 System.gc()는 강제로 GC를 수행시켜주는 시스템 메소드이다. 이 메소드를 Unreachable Object가 생기는 시점마다 강제로 호출시켜주면 C언어의 malloc() 동적할당 변수에 free()를 써준 것처럼, 즉시 모든 Unreachable Object들의 메모리가 해제된다. 이렇게 강제로 GC를 돌려주면 알고리즘이 자신이 가진 공간복잡도를 온전히 발휘하여 문제의 메모리 요구사항을 만족시킬 순 있다. 하지만, GC는 기본적으로 시간이 오래 걸리는 연산이다. c 언어의 free()와는 다르게 GC는 그 대상을 명시해서 사용하지 않는다. GC는 스스로 자신이 해제시켜야할 Unreachable Object들을 찾아야하며, 이 과정은 기본적으로 루트로부터의 참조 관계로 얽힌 깊은 트리 구조를 순회하고 비교하는 문제이기 때문에 수행시간이 상당히 걸린다. 게다가 가장 큰 문제는 GC가 수행되는동안 JVM은 어플리케이션의 수행을 잠시 중단시킨다는 것이다. 이를 Stop the World라고 한다. 2.1. Stop the World GC는 자신이 실행되는 메소드를 제외한 모든 쓰래드를 일시적으로 정지시킨다. 이건 GC가 완료될 때까지 애플리케이션 실행을 중단시킨다는 것이다. 따라서 GC는 대게 메모리가 부족한 상황에서만 자동적으로 호출되게 되어있다. 3. 객체를 최대한 재활용하기 따라서 GC없이 메모리 요구사항을 맞추기 위해서는 객체를 최대한으로 재활용 할 필요가 있다. 또한 GC의 Stop the World를 예방하기 위해서도 객체를 최대한 재활용하는 설계가 중요하다. 3.1. 연산에 사용되는 객체, 배열을 재활용 반복적으로 수행되는 어떤 연산에있어서 임시적으로 값을 저장하거나 전달하기 위해 생성해야하는 객체나 배열이 있다면, 해당 객체나 배열을 싱글톤으로 생성, 관리하고 매번 연산의 시작 전에 알맞은 초기값으로 초기화해주는 방법을 쓰면 객체의 효율적인 재활용이 가능하다. 멀티쓰래드에서는 각 쓰래드 별로 사용할 객체 및 배열을 생성 및 할당해주면 된다. 3.2. String 보단 StringBuilder 사용 String은 그 값이 변할때마다 매번 새로 객체가 생성되어 Primitive 타입처럼 사용이 가능하다. 그러나 이러한 특징 때문에 String으로 선언한 변수를 통해 문자열 값을 변경하는 코드를 짠다면, 해당 변수의 값이 새롭게 할당 될 때 마다 새 Unreachable Object가 생기게 되어 메모리를 낭비하게 된다. 반면 StringBuilder 객체를 사용한다면 값이 변경될때마다 새롭게 객체가 생성되는 일이 없다. 3.3. 메소드의 바깥에서 객체, 배열을 생성 메소드 내부에서만 생성되어 사용되는 객체나 배열이 있을 수 있다. 메소드는 대게 코드의 중복성을 없에기 위해 사용하므로 여러번 호출되어 사용되는데, 메소드 내부에서만 사용하기 위해 생성된 객체나 배열은 메소드의 종료와 함께 Unreachable Object가 되어 메모리에 남게된다. 이는 GC를 유발하는 메모리의 낭비이다. 따라서 메소드 내부에서만 생성되어 사용되는 객체나 배열이라도 메소드의 외부에서 선언하여 후에 메소드가 또 다시 호출될 때 인자로 넘겨주고 알맞게 초기화하여 사용하게 해야한다.

algorithm

java

memory

memory exceed

2022-11-21, 15:12

JVM에서 가장 빠른 비교연산자

1. 비교연산자의 구분 Equal과 Less, Greater Equal과 not Equal은 not을 하나 추가, 1클럭 차이나므로 어떤 CPU에서도 연산속도가 같을 수 밖에 없다. 이와 동일하게 =와 같고 > 는 not =** >, <= 일단 결론부터 말하자면, ==과 !=이 현저히 느리고 나머지 비교연산은 동등하게 빠르다. 2. 테스트 나중에 이어쓰기 3. 이유 나중에 이어쓰기

2022-10-27, 09:49

가장 빠르게 시스템 출력에 쓰는

1. 시스템 출력 스트림 객체에 직접 접근. 시스템 출력 스트림 객체에 System.out을 통해 직접 접근해서 사용한다. 내가 필요한 기능만 사용 가능하므로, 다른 데코레이터 클래스를 사용해서 생기는 불필요한 작동으로 인해 소모되는 시간과 메모리를 절약할 수 있다. 2. 출력 버퍼를 쓰기 시스템의 출력 스트림에 데이터를 쓰는 작업은 언제나 시간이 소모되는 작업이다. 따라서 데이터를 하나하나 써가는 것 보다는 버퍼에 한번에 쓰고 출력 스트림에 버퍼를 한번에 쓰게하는 편이 훨신 빠르다. 3. 예제 코드 byte[] outBuf = new byte[1024];//1024바이트의 버퍼 //outBuf에 직접 값을 입력 예제. for(int i=0 ;i<1024; i++){ outBuf[i] = 'a';//전부 a로 채워 넣기 } System.out.write(outBuf);

2022-10-26, 11:44

상하의 트위스트

온라인에서 옷을 쉽게 매치해볼수 있는 차세대 쇼핑몰

강호신 LIS

웹 기반 진단검사 시스템

오목판

웹 & 안드로이드 오목 앱