반응형

안녕하세요~ 오늘의 5분개발지식라디오! 오늘은 일반적으로는 잘 쓰이지 않는 고급 자바스크립트 문법을 배워보려고 합니다. 어떤 개념인지, 어떤 용도로 쓸 수 있을지를 한번 이야기해보도록 하겠습니다. Proxy에 대한 설명과 예제, 그리고 어떻게 사용할 수 있을지까지 쭉 달려볼 예정이니 끝까지 시청해주세요~

 

먼저 단어의 어원을 알아보겠습니다. Proxy라는 단어의 번역을 보면 “대리”라는 뜻입니다. 단어의 뜻과 동일하게 proxy는 어떠한 객체를 “대리”하는 역할을 합니다.

 

Proxy를 어떠한 객체에 대해서 생성을 하면 타겟 객체의 속성에 대한 읽기, 쓰기 등을 대리해서 먼저 처리할 수 있습니다. 코드를 보면서 이야기하는 것이 더 빠를 것 같습니다.

 

위쪽의 target과 handler를 지나쳐서 프록시를 생성하는 부분을 먼저 보겠습니다. new Proxy를 해서 프록시 객체를 생성할 수 있고, 첫번째 인자로는 프록시할 대상인 타겟 객체, 두번재 인자로는 해당 객체에 오는 요청 중 가로채서 대신할 동작들을 재정의한 메소드로 가지고 있는 handler, 공식용어로는 트랩을 넘겨줍니다.

 

두번째인자인 핸들러의 경우 이미 약속된 이름의 메소드들을 재정의해야됩니다. 가장 일반적으로 쓰일만한 get, set, has, apply들이 먼저 눈에 띕니다. 개발하시면서 가로채고 싶은 동작들을 선택적으로 불러다가 정의하면 됩니다.

 

그럼 다시 코드로 돌아오면 아까보다는 조금 더 이해가 되기 시작합니다. 우리는 target이라는 원본 객체를 프록시하기위해 proxy를 생성했습니다. 그리고 핸들러에는 get 동작을 가로채는 메소드를 추가했습니다. get메소드는 아무런 조건 없이 무조건적으로 world를 반환합니다.

 

그래서 마지막 줄의 콘솔로그를 보시면 proxy의 message1을 조회했지만 world가 찍히는 것을 보실 수 있습니다. 그럼 조금 더 복잡한 심화예제를 보도록 하겠습니다.

 

눈치가 빠르신 분들은 미리 파악하셨을수도 있지만 핸들러의 메소드들은 2가지 변수들을 인자로 받고 있습니다. 첫번째인자는 프록시의 원본 객체이고, 2번째는 코드가 접근하고 있는 속성의 이름을 줍니다. 따라서 현재 보이는 코드처럼 만약 message2를 접근할때는 world를 반환하고 나머지는 그대로 반환하도록 분기처리를 할 수 있습니다.



그래서 프록시는 간단하게 설명을 하자면 원본 객체 접근하기전에 가로채서 내마음대로 요청을 조작할 수 있는 객체인데요, 어떤 경우에 사용하게될까요? 사용방법은 무궁무진하지만 제가 공유드릴 유즈케이스는 유효성 검사, 데이터 싱크, 접근 제어입니다.

 

유효성 검사는 proxy에 대한 설명을 듣다보면 가장 먼저 떠오르는 유즈케이스입니다. 객체에 값이 쓰여질때 가로채서 validation을 통과하는지 확인할 수 있습니다. 코드를 보시죠:

 

자 공용으로 사용하는 person이라는 객체가 있다고 생각을 해보겠습니다. 이 객체는 여러 파일들에서 사용되고 있을때, person 객체에 age라는 속성을 세팅하려고 합니다. age는 나이이기때문에 정수타입으로 저장되고, 200살이 넘는 사람은 없기때문에 200이상을 에러를 내는 것이 타당합니다. 따라서 해당 조건들을 확인하는 setPersonAge라는 함수를 같이 작성해두었다고 하겠습니다.

 

팀으로 작업을하다보면 해당 함수의 존재를 알고 있는 사람도 있지만, 모르고 잇는 사람도 있을 수 있습니다. 아는 사람은 파일A처럼 잘 작성하였지만 setPersonAge라는 함수가 있는지도 모르고 정수로 저장되어야한다는 스펙도 모르는 사람은 파일B처럼 작성할 수도 있습니다. 파일B가 실행된 다음에는 person의 age를 참조하는 코드는 에러가 발생하겠죠.

 

하지만 Proxy를 사용하면 근본적으로 set을 가로채서 유효성검사를 해버릴 수 있습니다. person은 빈객체를 원본객체로 인라인으로 넣어서 원본객체에는 접근이 불가능하도록 만들고 set을 가로챕니다. 그리고 age를 set하려고 하면 유효성검사를 진행하여 필요한 경우 에러를 뱉어줍니다.

 

Proxy는 객체에 값이 변경될때 이를 알아챌 수 있습니다. 이 특징을 사용해서 연관된 다른 값들도 같이 업데이트를 하는 개념인데요, 간단한 예시를 보겠습니다.

 

가끔 프론트엔드 작업을 하시다보면 성과 이름을 입력받는 Input 태그가 분리되어있는 경우가 있습니다. 하지만 유저정보를 수정하거나 생성할때는 이 두개의 값을 합쳐서 하나의 문자열로 보내야되는 경우가 있을 수 있습니다.

 

이런 경우 name이라는 객체에 firstName과 lastName 속성이 업데이트될때 어딘가에 있는 fullName을 같이 업데이트해줄 수 있습니다. 물론 나중에가서 필요할때 합치는 것이 어렵지는 않지만 개념적으로 이해하시면 좋을 것 같습니다. 본 예시처럼 하나의 데이터의 변화를 어딘가에 싱크를 맞춰줘야되는 경우 사용할 수 있습니다. 마치 react의 useEffect를 사용해서 싱크해주는 것과 비슷합니다.

 

Proxy는 속성에 접근할때 이를 가로채고 미리 확인할 수 있습니다. 따라서 사용자가 접근 가능한 속성들을 미리 선언해두고, 이 리스트에 없을 경우 임의로 다른 값을 내려주는 것도 가능합니다.

코드를 보시면 age가 아닌 다른 속성에 접근하려고 하면 ‘ACCESS-DENIED’를 내려줘서 막습니다. 이전에는 특정 속성에 접근하지 못하게 하기 위해 메소드를 통해서만 속성들을 내려주거나 변수명에 특정 기호를 붙여 private 변수임을 명시했는데요,  proxy를 사용하면 이를 원천적으로 차단할수도 있습니다.



자 오늘은 여기까지해서 Proxy에 대해서 알아보았는데요, 영상을 찍다보니 좀 길어졌네요 ㅎㅎ 무궁무진한 사용방법들이 있겠지만 간단하게 느낌을 잡기에는 이 정도면 충분한 것 같습니다. 다른 참신한 사용법이 잇다면 댓글에 공유해주세요

오늘도 같이 공부해주셔서 감사합니다. 유용했다면 구독 좋아요 부탁드립니다.

 

끝!

 

반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 Git flow입니다.많은 기업들에서 가장 일반적으로 사용하는git 브랜치 관리 전략인데요, 혹시 취준 중이시거나 입사예정이시라면 꼭 숙지하고 가시길 추천드립니다. 그럼 빠르게 알아보도록 하겠습니다.

가장 먼저 git flow를 구성하는 브랜치 타입들을 먼저 살펴보겠습니다.

 

첫번째는 master 브랜치입니다. master 브랜치는 실제로 사용자들에게 서비스가 되고 있는 코드를 담고 있는 브랜치입니다. 따라서 master에는 검증이 완료되고 빌드 에러 등이 없는 상태의 코드가 들어있어야합니다. 일반적으로 master 브랜치는 오직 pull request 머지를 통해서 코드를 넣도록 설정하여 직접 푸쉬를 할 수 없도록 막아둡니다.

 

실제 사용자들에게 서비스가 되는 코드는 이 master 브랜치를 배포하여 제공됩니다.

 

두번째는 develop 브랜치입니다. master에서 checkout하여 파생된 브랜치입니다. 실제로 사용자들을 가지고 있는 서비스의 경우 대부분 매일 혹은 수시로 배포를 하지 않고 일주일에 1번, 2주일에 1번처럼 배포 주기를 정해두는데요, 다음 배포일에 master로 병합될 코드들이 있는 브랜치입니다.

 

시간이 지나 다음 배포일이 다가오게 되면 develop에 있는 커밋, 코드들을 master로 병합시켜 실제 사용자들이 사용하고 있는 프로덕션에 반영하게 됩니다.

 

세번째는 feature 브랜치입니다. feature브랜치는 하나의 스펙을 개발할때 모든 검증 과정을 거친 후에 develop 브랜치에 넣을 수 있도록 각 스펙별로 분리한 브랜치입니다. 따라서 feature 브랜치는 develop 브랜치에서 생성하게 되는데요, 새로운 스펙의 기획이 나오고 개발이 시작될 때 그 시점의 develop 브랜치에서 feature/{스펙명}으로 생성합니다.

 

해당 스펙을 개발하는 개발자들을 개발하면서 develop으로 코드를 넣는 것이 아니라 feature 브랜치에 작업물을 넣습니다. 일련의 개발과정이 완료되면, QA를 거쳐 코드를 검증하고 develop 브랜치로 머지됩니다. 앞서 말씀드렸듯, develop 브랜치 또한 배포되기 직전의 코드들을 모아놓은 브랜치이기때문에 버그가 있는 코드, 미완성 코드들은 들어있으면 안됩니다. 따라서 feature브랜치에서 모든 코드 작업을 마무리하고 들어오게 됩니다.

 

이렇게 master, develop, feature 브랜치가 git flow의 가장 핵심적은 3개의 브랜치입니다. 하지만 이 3개만으로 큰 서비스를 운영하기엔 애로사항들이 있습니다. 그래서 추가적인 브랜치들이 3개 더 있습니다.

 

스펙이 매우 작은 것이 아니면 보통 최소 2~3명 정도가 같이 하나의 스펙을 개발하게 되는데요, 이 때 feature 브랜치에 바로바로 푸쉬를 하게되면 매번 푸쉬할때마다 다른 동료들의 코드를 pull 받고 conflict가 있을 경우 해결하고 다시 푸쉬를 해야됩니다. 또, pull request를 통한 리뷰도 받을 수 없습니다. 

 

그렇기때문에 각각의 작업자는 본인의 작업을 개인브랜치에서 진행합니다. 이 개인브랜치는 feature 브랜치에서 그때그때 checkout을 통해 생성하며 정해진 룰은 없지만 다른 개발자들이 리뷰하는게 힘들지 않도록 기능 단위로 생성하고 머지합니다. 

 

개발해야되는 스펙을 기능 단위로 분리하고 기능단위로 개인 브랜치를 생성하여 개발하고 pull request를 생성하여 feature 브랜치에 머지하고, 로컬에서 feature 브랜치를 pull하여 최신화한 뒤 다시 개인브랜치를 checkout하여 새로운 기능을 개발하는 프로세스를 스펙개발완료시까지 반복합니다. 이렇게 스펙개발이 완료되면 앞서 말씀드린 것 처럼 QA를 거친 후 완료된 스펙의 feature 브랜치를 develop으로 머지하게 됩니다.

 

저희 팀 기준으로는 이니셜/기능명으로 브랜치명을 짓고 있지만 개인브랜치는 pr을 통해 feature 브랜치로 머지되고 나면 없어지는 일회용 브랜치이기때문에 브랜치이름이 그렇게 중요하지는 않습니다.

 

다음은 릴리즈 브랜치 입니다. 브랜치 이름 그대로 배포용 브랜치인데요, 앞서 develop 브랜치에 대해서 설명드릴때 develop브랜치가 배포하기 전 모아두는 브랜치라고 말
씀드렸습니다. release는 여기서 조금 더 배포일이 임박했을때 코드 프리징을 하는 용도로 사용합니다.

 

코드 프리징이란 코드에 더 이상 변화를 주지 않는 것인데요, 배포 직전까지 코드가 계속해서 변경되면 안정성을 장담할 수 없기때문에 배포일로부터 몇일전쯤 develop브랜치에서 release 브랜치를 하나 생성하여 배포 당일에는 develop이 아니라 release 브랜치를 master 브랜치에 머지합니다. release 브랜치가 생성된 다음에 develop 머지되는 feature 브랜치들은 그 다음 배포일에 서비스에 반영되게 되는 것이구요.

 

릴리즈 브랜치는 코드프리징을 하기때문에 이 브랜치의 코드가 진짜로 더 이상의 변화없이 몇일 뒤에 실제 서비스에 반영된다는 것을 뜻합니다. 따라서 회사에 QA가 있을 경우 이 브랜치에서 최종 QA를 진행하여 배포 직전 마지막으로 에러나 버그가 없는지 확인하고 있을 경우 수정하는 작업을 거칩니다.

 

마지막으로 핫픽스 브랜치가 있습니다. 앞서 master 브랜치가 실제로 사용자들이 사용하고 있는 배포되어있는 서비스의 코드라고 설명드렸는데요, 그럼 개발과정에서 발견하지 못한 중대한 버그가 있다면 어떡해야될까요? 페이지가 접근되지 않는다거나 의도한대로 동작하지 않는데 다음 정기배포일까지 방치할 수 없다거나 하는 경우가 생길 수 있습니다.

 

이 때, develop에서 오류사항을 수정하고 master에 머지를 하려고 하면 현재 배포되어있지는 않지만 다음 정기배포일에 배포하기 위해 머지해둔 스펙이 있을 수 있습니다. 이번에 빠르게 배포되어도 문제가 없는 스펙이라면 그래도 그나마 괜찮지만, 만약 마케팅팀과 연동되어 다음 배포일에 대대적인 홍보와 함께 같이 출시되어야하는 스펙이라면 절대 오류 수정과 같이 일정보다 빨리 배포되면 안됩니다.

 

그렇기때문에 정기배포일이 아니지만 프로덕션 환경에서 에러가 발생했을때는 master 브랜치에서 hotfix 브랜치를 하나 생성하여 발생한 오류만 수정하여 바로 master 브랜치에 머지한 후 재배포를 통해 오류를 프로덕션을 제거해줍니다.

 

끝!







반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 지난번 영상에 이어 한번 더 React의 신규 기능에 대한 영상입니다. 오늘은 Server component에 대해서 알아볼텐데요, 아직 지난 영상을 보지 않으신 분은 우측 상단의 배너를 누르셔서 시청하고 오시면 훨씬 더 이해가 쉬우실 것 같습니다. 그럼 시작해보겠습니다.

 

서버컴포넌트는 예전 NextJS 영상에서도 언급한적이 있습니다. 서버컴포넌트 또한 서버사이드 렌더링, SSR을 고도화시키기 위한 기능입니다. 서버사이드 렌더링은 서버에서 작업을 마친, 즉 렌더링을 마친 페이지를 클라이언트에게 먼저 보냅니다. 이 페이지는 자바스크립트가 연결되지 않아 사용자와 상호작용이 불가능한 상태인데요, 사용자와 상호작용이 가능하도록하는 과정을 한번 더 거치는데요, 이것을 hydration이라고 합니다.

 

그럼 만약 이런 hydration이 필요없는 컴포넌트가 있다면 어떨까요? 대표적으로 단순히 텍스트를 보여주기만하는 컴포넌트들이 있습니다. 이렇게 서버에서 렌더링이 된 이후에는 추가적인 작업이 필요없다고 구분해둔 컴포넌트들을 서버컴포넌트라고 합니다. 서버컴포넌트는 파일명.js로 쓰는 대신 파일명.server.js로 파일을 생성하면 사용할 수 있습니다.

 

서버컴포넌트는 특히 사용자와 상호작용을 하지는 않지만 무거운 라이브러리를 사용하는 경우 가장 큰 효과를 볼 수 있습니다. 화면의 코드를 보시겠습니다.

 

코드를 보시면 컴포넌트는 marked와 sanitizeHtml이라는 라이브러리를 사용하고 있는데요, 각각 11.2K바이트와 63.3K바이트의 사이즈를 가지고 있습니다. 일반적인 SSR의 경우에는 서버에서 이 2개의 라이브러리를 사용하여 NoteWithMarkdown 컴포넌트를 렌더링을 한 결과를 클라이언트에게 보내고, hydration을 위해서 marked와 sanitizeHtml 라이브러리를 또 보냅니다.

 

하지만 서버컴포넌트를 사용하게되면, React는 서버에서 렌더링을 한 결과물을 보내주면, 클라이언트에서 다시 hydration을 할 필요가 없기때문에 marked와 sanitizeHtml 라이브러리가 필요없다는 것을 알고 있습니다. 그래서 SSR을 한 결과물을 보내준 뒤에 라이브러리 번들은 아예 보내지 않습니다. 클라이언트에서 이 컴포넌트를 hydration하는데 드는 컴퓨팅 비용이 줄어드는 것은 덤이구요.

 

(원래대로)

하지만 주의하실 점은 서버컴포넌트는 처음에 렌더링된 마크업 결과물을 보낸뒤 자바스크립트 번들을 추가적으로 보내지않기때문에 일반적인 컴포넌트처럼 effect나 state를 가질 수 없습니다. 그래도 일반적인 클라이언트 컴포넌트를 내부적으로 사용할 수는 있기 때문에 파일분리를 잘 하시면 문제 없을 것 같습니다. 

 

이 것이 가능한 이유는 내부적으로 클라이언트 컴포넌트를 사용하더라도 코드 스플릿팅으로 인해 사용되는 클라이언트 컴포넌트만 hydration 시킬 수 있기 때문인 것으로 보입니다. 클라이언트 컴포넌트는 서버컴포넌트와 반대로 파일명.client.js로 생성하시면 됩니다.

 

서버컴포넌트가 서버에서만 모든 작업을 처리하기때문에 가능해진 것이 있는데요, 좋은 패턴은 아닌 것 같지만 마치 서버 파일처럼 사용할 수 있습니다. 데이터베이스 접근도 가능하구요. 클라이언트로 보내질 때는 모든 작업이 처리되고 렌더링된 마크업만 전해지기때문에 문제가 없습니다.

 

이 기능은 아직 알파단계에 있습니다. 나중에 React 18버전의 마이너 업데이트로 공식 출시된다고 합니다. 

 

끝!

 

반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 React인데요, 새로운 렌더링 방식이 나온다고 하여 이에 대해 알아보도록 하겠습니다.

 

저희가 일반적으로 아는 렌더링 방식은 크게 2가지가 있습니다. Client-Side Rendering, CSR이 첫번째고, Server-Side Rendering, SSR이 두번째입니다.

 

간단하게 짚고 넘어가자면, CSR은 서버는 빈 껍데기 HTML파일을 보내주고, 이 HTML파일이 필요한 js파일을 받아오면 이 js파일이 라우팅과 페이지 요소들을 렌더링하는 역할을 하게 되죠.

 

CSR의 장점은 

  1. 유저나 상황별로 다른 파일을 주는 것이 아니기때문에 캐싱이 용이하고 CDN을 사용하기 쉽습니다.
  2. 클라이언트에서 라우팅을 포함한 모든 작업을 처리하기 때문에 페이지 이동간 리프레시가 없습니다. SPA의 장점이기도 하죠.
  3. HTML이 사실상 비어있기때문에 Time To the First Byte(TTFB)가 정말 빠릅니다. 완벽하진 않더라도 사용자가 화면을 조금 더 빨리 받아볼 수 있습니다.

 

하지만 이에따른 단점도 존재합니다.

  1. 클라이언트의 기기에서 모든 작업을 처리하기때문에 어플리케이션이 돌아가는 기기에 따라 성능이슈가 발생할 수 있습니다.
  2. 클라이언트에서 구동에 필요한 js뿐만이 아니라 모든 데이터 fetching까지 진행해야되므로 받아야되는 데이터의 양이 많고 경우에따라 느릴 수 있습니다.
  3. 검색엔진 최적화, SEO에 불리합니다.

 

다음은 SSR에 대해서 알아보겠습니다. SSR은 서버에서 사용자에게 보여주기 위한 HTML안의 내용물을 완성시켜서 사용자에게 내려주는 방식입니다. 이렇게 HTML을 보내준 다음에 사용자의 인터렉션에 반응할 수 있도록 js를 다시 보내줍니다.

 

SSR의 장점은

  1. 검색엔진 크롤러가 접근했을때 완성된 페이지를 바로 받아보기 때문에 검색엔진최적화에 좋습니다. 
  2. 서버에서 모든 작업을 해서 주기때문에 비교적 안정적인 성능을 보여줍니다.

 

반대로 SSR의 단점은

  1. 서버에서 페이지를 만들어서 줘야되기때문에 TTFB가 느립니다.

 

이렇게 CSR와 SSR의 장단점을 알아보았는데요, 이번에 React가 18버전으로 올라가면서 Streaming SSR이라는 새로운 렌더링 방식을 제시하였습니다. CSR과 SSR의 장점을 섞은 차세대 렌더링 방식이라고 볼 수 있을 것 같습니다.

 

브라우저에서는 HTTP stream이라는 것을 열 수 있습니다. 다른 여타 stream과 개념은 동일합니다. 브라우저와 서버가 stream으로 연결되면 서버는 stream을 통해서 브라우저에게 HTML뿐만아니라 데이터를 여러번에 걸쳐서 보낼 수 있게됩니다.

 

일반적인 HTTP연결은 한번 데이터를 보내면 연결이 종료되기때문에 이와는 차이점이 있습니다.

 

이 기능을 사용하는 것이 React18의 신기능, Suspense입니다.

화면의 간단한 예시코드를 보시면 좀 더 쉽게 이해가 될 것 같은데요, 게시물 화면을 간단하게 구성해보았습니다. 여기서 댓글들을 불러오는 Comments가 시간이 오래걸리는 작업이라고 가정을 해보겠습니다.

 

그럼 React는 Comments는 오래걸리기때문에 제외하고 나머지 HTML만을 먼저 구성해서 사용자에게 보내줍니다. 그리고 Comments의 자리는 그냥 비워두는 것이 아니라 처음에 Suspense의 fallback으로 받은 Spinner로 채워서 보내줍니다.



그리고 Comments가 준비가 되면 HTTP stream을 통해서 페이지 전체가 아니라 Comments에 해당하는 HTML부분만 다시 보내줍니다. 일단 HTTP는 한번 데이터를 보내고 나면 connection이 종료되지만 HTTP stream은 유지시킬 수 있고, 이를 통해서 Comments HTML을 준비가 되는대로 뒤늦게 보낸 것입니다. 그럼 사용자는 이전의 일반적인 SSR과 달리 준비가 된 결과물부터 먼저 받아볼 수 있게됩니다.

 

SSR의 장점은 챙기면서 오래걸리는 작업은 빼놓고 먼저 보냄으로서 SSR의 단점을 많이 상쇄시킨 방식이라고 할 수 있습니다.

 

Streaming HTML을 사용하면 HTML을 부분적으로 먼저 받아올 수 있다는 것은 이제 이해했습니다. 하지만 궁극적으로 사용자가 어플리케이션과 인터렉션을 하려면 동작을 위한 자바스크립트 파일도 받아야합니다. 이를 위한 기능이 Selective Hydration입니다.

 

예전에도 React에는 React lazy라는 기능을 사용해서 코드 스플릿팅을 할 수 있었는데요, 문제는 이 기능이 서버에서는 동작하지 않았습니다. 하지만 이제는 Suspense를 사용하면 별다른 코드 추가 없이도 이 기능을 사용할 수 있습니다.

 

아까 봤던 예시 코드를 다시 가져왔습니다. 이렇게 Comments를 Suspense로 감싸게되면 Comments의 자바스크립트 코드는 자동으로 다른 번들로 코드 스플릿팅이 되며, HTTP stream을 통해서 보낼때 알아서 제외하고 보냅니다. 이제 자바스크립트 번들도 Comments를 포함할 필요가 없기때문에 사이즈도 더 작아지는 효과도 있습니다.

 

반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 Rust입니다. Rust라는 프로그래밍 언어가 있다라는 것을 여기저기서 들으셨을텐데요, 왜 쓰는지, 무엇이 장점인지를 살펴보도록 하겠습니다.

 

Rust의 장점을 알아보기 전에 Rust의 가장 큰 특징중 하나인 Ownership에 대해서 알아보겠습니다.

 

Rust는 garbage collector가 없는데요, 대신 ownership이라는 개념이 있습니다. 각 값에는 owner가 있고, 한번에 하나의 owner만 존재할 수 있습니다. 만약 이 owner가 scope에서 벗어나면, 값은 메모리에서 해제됩니다.

 

현재의 코드를 보시면 hello라는 값은 변수 s가 ownership을 가지고 있고, s가 괄호를 벗어나면, 즉, scope를 벗어나면 메모리에서 해제가됩니다. 괄호안의 scope에서는 s를 자유롭게 사용할 수 있죠.

 

다음 코드를 보시겠습니다. s1은 hello라는 값을 가지는 String타입입니다. 정확하게는 hello라는 값을 가지는 메모리에 대한 레퍼런스를 가지고 있죠. 그 다음 s2에게 s1의 레퍼런스를 넣어주는데요, 대부분의 언어에서 위의 코드는 지극히 정상적인 코드입니다. 

 

하지만 Rust는 다릅니다. s2에 s1의 레퍼런스를 넣는 과정에서 hello라는 값을 가지는 메모리의 ownership은 s2에게 넘어가고 s1은 더이상 해당 메모리에 접근할 수 없기때문에 가장 하단의 print에서 에러가 발생합니다. 위의 예시가 Rust의 ownership에 대해서 가장 잘 설명해주는 예시인 것 같습니다.

 

따라서 만약 같은 값을 사용하고 싶다면 현재의 코드처럼 clone을 해주어야합니다. 그럼 s1과 s2는 각각 다른 메모리를 참조하게 되기때문에 s1도 여전히 ownership을 가지고 있게 되고 계속해서 메모리에 접근할 수 있습니다.

 

밑의 예시는 변수의 값이 정수인 예시인데요, 정수와 같이 stack에 할당되는 primitive 타입들은 동작이 다릅니다. 다른 언어들도 primitive 타입은 변수를 통해 할당을 하더라도 값을 복사하는데요, Rust도 동일합니다. 따라서 y에 x를 할당한 이후에도 x도 여전히 메모리에 접근할 수 있습니다. 이는 x와 y가 서로 다른 메모리에 대해 ownership을 가지게 되기 때문입니다.

 

마지막으로 조금 더 복잡한 예시로 정리해보겠습니다. 다른부분은 비슷한데요, takes_ownership이라는 함수를 호출하는 부분을 살펴보겠습니다. s라는 변수가 takes_owneship의 인자로 넘어갈때, ownership은 takes_ownership함수의 some_string으로 넘어갑니다. 따라서 takes_ownership이 끝나는 시점에 hello라는 값을 가지는 메모리는 해제되고 some_string와 s모두 더이상 접근할 수 없습니다.

 

하지만 makes_copy로 넘어가는 x는 다릅니다. x는 정수타입이기때문에 makes_copy의 인자로 넘어가더라도 stack에 복사되어 some_integer가 복사본을 사용합니다. 따라서 makes_copy가 끝난 이후에도 x는 여전히 값에 접근할 수 있습니다.

 

Rust의 장점을 먼저 알아보겠습니다. 첫번째로 Rust는 성능이 매우 빠릅니다. 벤치마크 결과를 보면 C++와 비슷한 성능을 보여줍니다. 벤치마크용 알고리즘을 어떤것을 사용하는지에 따라 조금씩 달라질 수 있다는 점을 감안해주시면 될 것 같습니다.

 

두번째로 Rust는 크로스 플랫폼을 지향합니다. Rust는 3대 메이저 OS인 리눅스, 윈도우, 맥OS에서 모두 동작하며 이외에도 여러 플랫폼을 지원합니다. 이 때문에 최근에 Rust를 Web assembly로 컴파일하여 웹프로그래밍에서도 성능의 병목현상이 일어나는 곳에 rust를 부분적으로 도입하는 경우가 늘어나고 있죠. 컴파일이 완료되면 필요한 모든 소스는 바이너리에 같이 들어있기때문에 OS를 제외한 추가적인 runtime은 필요없다고 합니다. 

 

세번째로 Memory-safe합니다. C언어로 코딩을 해보셨다면 null이나 dangling 포인터로 애를 먹은 경험이 다들 있으셨을텐데요, Rust는 컴파일하는 과정에서 이런 에러들을 전부 걸러내준다고 합니다.

 

네번째로 앞서 설명드린 ownership방식을 사용하기 때문에 garbage collector가 없어 overhead가 적습니다.

 

마지막으로 Rust는 사용편의성이 좋다고 합니다. 다양한 내장 유틸리티 함수들을 가지고 있고, c와 c++ 개발자들이 rust를 사용하도록 하기위하여 c와 c++의 standard library들을 거의 모두 다 본인들의 standard library로 편입했다고 합니다.

 

하지만 Rust는 cross-platform을 지향하고 있기때문에 다른 플랫폼에서도 안정적으로 동작하는 것들만 가져왔다고 합니다. 그외에도 js개발자들이 많이 사용하는 npm처럼 cargo라는 써드파티 라이브러리 패키지 매니저를 사용하여 외부 라이브러리를 쉽게 가져다 쓸 수 있다고 합니다.



자 이제 Rust의 단점을 살펴보겠습니다.

 

첫번째로 일단 최신 언어라는 점입니다. Rust는 2015년에 1.0버전이 출시되었는데요, c와 c++와 달리 최근에 출시됐기때문에 아직까지 변동이 많습니다. 또, 무언가 문제가 생겼을때 비교적 레퍼런스가 적다는 점도 문제가 될 수 있습니다.

 

두번째로 어렵습니다. 앞서 설명들이 ownership 개념외에도 기성 프로그래밍 언어를 사용하시던 분들은 생소하실 컨셉들이 여러가지가 있고, 이는 처음 Rust를 접하는 개발자들에게 큰 러닝커브로 다가올 것 같습니다.

 

마지막으로 Rust는 시스템 레벨 언어로 사용될 수 있습니다. c와 c++과 동일하게 rust는 메모리에 직접 접근할 수 있습니다. 이 특징때문에 시스템 프로그래밍을 할때 많이 사용되는데요, 이게 왜 단점이 되냐면 개발자들이 많이 사용하는 파이썬과 같은 하이레벨 언어에 비해 코드가 길어질 여지가 있습니다.

 

성능이 그렇게 크리티컬한 요소가 아니라면 파이썬으로 1분만에 작성하여 돌아가는데 1초가 걸리는 것이 Rust로 30분걸려 작성하고 돌아가는데 300밀리세컨드 걸리는 것보다 더 효율적일 수 있습니다.

 

끝!

반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 Turbopack입니다. Turbopack은 NextJS를 개발한 Vercel에서 만든 차세대 번들링툴인데요, 간단하게 알아보도록 하겠습니다.

 

Vercel은 빌드시간을 줄이기 위해서 다양한 작업을 진행하고 있는데요, 자바스크립트로 작성된 툴들을 Rust기반 툴들로 변경할 때마다 엄청난 성능 향상이 있었다고 합니다.

 

트랜스파일링 툴인 Babel을 대체했을때는 transpilation이 17배빨라졌고, 코드 사이즈를 줄이는 minification툴인 Terser를 대체했을때는 6배빨라졌다고 합니다.

 

그리고 마지막으로 Vercel에게 남은 숙제가 JS로 만들어진 가장 유명하고 널리쓰이는 번들링툴인 Webpack이었고 이를 대체하기 위한 툴이 오늘 소개하고자 하는 Turbopack입니다. 아 그리고 혹시 Rust가 어떤 언어인지 궁금하신 분들은 다음영상으로 소개하고자하니 구독하고 놓치지 마세요

 

Vercel이 공개한 자료에 따르면 규모가 있는 어플리케이션에서 Vite보다는 10배빠르고 Webpack보다는 700배 빠르다고 합니다. 그럼 Turbopack은 어떻게 이렇게 빠를 수 있을까요?

 

Turbopack의 구조는 Turborepo와 구글의 Bazel과 같은 툴에서 많은 영감을 받았다고 하는데요, 같은 일을 2번하지 않고 캐시를 사용하는것이 가장 핵심아이디어라고 합니다.

 

Turborepo는 이를 위해 Turbo라는 프레임워크를 사용하였는데요, Turbo는 Rust기반의 프레임워크로서 프로그램의 어떤 함수의 결과라도 캐싱할 수 있다고합니다. 따라서 프로그램이 재실행됐을 때 이전에 실행되었던 함수의 입력값이 변경되지않았다면 재계산을 하지 않기때문에 압도적으로 빠를 수 있는 것이죠. 이게 사이즈가 큰 어플리케이션에 적용되면 대부분의 작업을 스킵할 수 있다고 합니다.

 

지금 화면에 보이는 플로우차트를 보시면 좀 더 감이 오실 것 같은데요, api.ts와 sdk.ts라는 파일을 읽어서 bundle을 하고 concat으로 합쳐서 fullBundle을 만드는 일을 한다고 가정해보겠습니다. sdk.ts의 파일내용만 변경되었다면 api.ts는 readFile과 bundle을 모두 스킵하고 이전 결과물을 그대로 사용하고, sdk.ts만 새로 읽고 번들링을 적용합니다. 

 

위의 경우 전체 6개의 작업 중 2개를 스킵했으니 단순 수치로도 33%감소인데요, 실제 작업상으로는 파일 입출력이 상대적으로 더 많은 시간을 잡아먹을테니 실질적으로는 더 큰 시간감소가 있을 것으로 예상됩니다.

 

캐싱은 현재로써는 인메모리캐시에 저장된다고 합니다. 즉 프로세스가 살아있는 동안에만 저장될 것 같습니다만 나중에는 이 캐시를 영구적으로 저장할 수 있도록 파일시스템이나 리모트 서버로 보내도록 할 예정이라고 합니다.

 

Next13부터는 개발용 서버에 Turbopack이 사용된다고 합니다. 페이지의 일부분을 리렌더링하는 Hot module replacement을 하는 경우에 매우 빠른 구동이 가능할 것으로 보입니다.

 

현재로써는 인메모리캐시이기 때문에 개발용 서버에만 사용되지만 나중에 캐시가 영구저장이 가능해지면 프로덕션에까지 확장시키고, 미리 만들어져있는 캐시들을 공유할 수 있도록 한다고하니 훨씬 빠른 빌드와 배포가 가능해질 것 같습니다.

 

반응형
블로그 이미지

개발자_무형

,
반응형

안녕하세요 오늘의 5분개발지식라디오~ 오늘의 주제는 팩토리 패턴입니다. 팩토리 메소드 패턴이라고도 하는데요, 팩토리 패턴이 무엇인지 코드를 통해서 먼저 알아보고 팩토리 패턴의 장단점에 대해서 알아보겠습니다.

 

화면에 보이는 것은 자바로 쓰여진 코드인데요, 상속에 대한 개념만 있다면 쉽게 이해할 수 있습니다. 먼저 부모 클래스인 Shape 클래스를 통해서 인터페이스를 정의해줍니다. Shape의 자식 클래스들은 draw라는 메소드를 구현해야하는데요,

 

Reactangle, Square, Circle 모두 부모클래스인 Shape를 상속받고 각자 draw를 구현합니다. 단순하게 출력만 해주도록 하였습니다. 여기서 모두 같은 부모클래스를 가지고 있다는 점을 기억해주시면 됩니다.

 

팩토리 패턴의 핵심은 현재 화면에 보여지는 코드인데요, 이름부터가 ShapeFactory입니다. ShapeFactory는 getShape라는 메소드를 가지고 있으며 Shape 클래스를 리턴해줍니다. 이는 앞의 슬라이드에서 모두 같은 부모클래스인 Shape을 가지기 때문에 가능합니다.

 

getShape 메소드는 인자로 넘어오는 shapeType에 따라서 Circle, Rectangle, Sqare를 생성하여 반환하여줍니다. 이렇듯 팩토리 패턴은 팩토리 메소드를 통해서 인자로 넘어온 값에 따라 맞는 클래스를 생성하여 주는 패턴을 말합니다.

 

먼저 장점을 알아보겠습니다.

첫번째로 확장성이 좋습니다. 새로운 타입의 추가가 쉽습니다. 동일한 부모 클래스를 상속하는 클래스를 생성하고 팩토리 메소드에 분기를 하나만 추가하면 됩니다. 이는 SOLID 원칙의 Open-closed 원칙을 따른다고 볼 수 있습니다.

 

두번째로 테스트가 용이합니다. 팩토리 메소드가 따로 분리되어있기때무에 이 부분을 직접적으로 테스트 가능하고, 필요하다면 자식클래스들도 따로 테스트 할 수 있습니다.

 

다음은 단점입니다.

첫번째로 코드양이 증가합니다. 결과론적으로 팩토리 클래스를 선언해야되기때문에 근소하지만 추가적인 공수가 발생합니다.

 

다음은 팩토리메소드의 단점이라고 보기는 어렵지만 실제 동작코드가 팩토리 메소드에 한번 추상화되어있기때문에 전체적인 코드를 파악하기에 조금 더 힘들 수 있습니다.

 

 

반응형

'디자인패턴' 카테고리의 다른 글

[디자인패턴] Facade패턴 쉽게 이해하기  (0) 2023.04.26
블로그 이미지

개발자_무형

,
반응형

 

 

오늘의 5분 개발지식 라디오! 안녕하세요~ 오늘은 NextJs가 2022년 10월말에 새로 메이저 넘버링 업데이트가 되어 간략하게 살펴보려고 합니다. 새롭게 13버전이 출시되었네요~

 

 

먼저 page폴더가 없어지고 app폴더가 생깁니다. 그와 동시에 예약된 파일명들을 통해서 주로 많이 사용되는 기능들을 쉽게 추가할 수 있게 되었습니다.

 

간략하게 살펴보자면 기존에 pages안에 생성하던것과 동일하게 자신이 생성하고 싶은 경로명으로 폴더를 생성하면되는데요, 각각의 파일이 개별적인 경로가 되던 것이 이제는 page.js가 UI를 나타내도록 변경되었습니다.

 

화면을 보시면 예전에는 pages 폴더 하위의 모든 파일들이 하나의 경로였다면 이제는 app하위에서 page라고 지어진 파일만 접근이 가능합니다. 예전에는 컴포넌트를 쪼갤때 pages밖에 따로 분리했어야됐다면 이젠 app안에 같이 정리해둘 수 있을 것 같네요.

 

 

그 외에도 많은 페이지들에 기본적으로 들어가는 layout, loading, error 등은 예약된 파일로써 지원한다고 합니다.

 

다만 13버전에서는 기존의 pages를 새로운 app과 동시에 사용이 가능하다고 하니 점진적으로 마이그레이션이 될 수 있을 것 같긴합니다. 하지만 pages의 지원이 중단되는 시점부터는 더이상 next 버전을 간단하게는 올릴 수 없는 레거시 코드가 될 것 같네요.

 

 

13버전부터는 app폴더안에 들어가는 컴포넌트들은 기본으로 React Server Component가 된다고 합니다. Server component는 서버에서 렌더링되는 컴포넌트이고, 반대로 Client component는 클라이언트에서 받아서 렌더링되는 컴포넌트입니다. Server component는 필요한 자바스크립트 작업들을 최대한 다 해서 클라이언트에게 보내주기 때문에 클라이언트가 받게되는 js파일 사이즈가 줄어든다고 합니다.

 

추가적으로 이제는 streaming 기능을 지원하여 데이터를 기다릴 필요가 없는 부분은 먼저 보내서 사용자에게 보내주고 나머지 기다려야되는 부분은 로딩상태로 보여준다고 합니다. 사용자들에게 더 빠른 피드백을 줄 수 있을 것 같습니다.

 

 

Next13에서는 번들링툴로 Turbopack이 추가된다고합니다. vercel측에 따르면 웹팩보다 700배빠르고, Vite보다 10배빠르다고 합니다. 

 

그 외의 자잘한 변경사항들은 스킵하도록 하겠습니다

 

next의 13버전을 사용하려면 최소 18.2버전의 React가 필요하고, 14.6버전의 노드가 필요합니다. 그리고 이제는 더이상 인터넷 익스플로러를 지원하지 않는다고 하네요.

 

끝!

 

반응형
블로그 이미지

개발자_무형

,