가계부 앱을 개발하면서 가장 먼저 고민한 것은 **"사람들이 정말 편하게 가계부를 작성할 수 있을까?"**라는 질문이었습니다. 많은 가계부 앱이 존재하지만, 기능이 지나치게 많아 복잡하거나, 특정 기기에서만 사용 가능해 불편하다는 문제점을 발견했습니다. 우리가 만들고자 했던 것은 누구나 쉽게, 어떤 환경에서도 사용할 수 있으며, 여러 사람이 함께 관리할 수 있는 가계부였습니다.
모든 기기에서 끊김 없이 사용 가능해야 한다
가계부는 하루에도 여러 번 작성하는 경우가 많습니다. 하지만 기존의 가계부 앱들은 특정 운영체제나 기기에 종속적인 경우가 많아 스마트폰에서는 되지만 PC에서는 안 되거나, 반대로 PC에서 입력한 데이터를 스마트폰에서 확인하기 어렵다는 문제점이 있었습니다.
이 문제를 해결하기 위해 같이가계부는 웹 기반으로 동작하면서도, iOS와 Android에서 앱으로도 사용할 수 있도록 개발했습니다.
"매달 책 한권 읽기"를 새해 목표로 정하고 나서 읽은 첫번째 책이 "Incognito: 무의식은 어떻게 나를 설계하는가" 였다. 평소에도 관심이 있는 주제였고, 어떻게보면 부분적으로 무의식적으로 직감하고 있었던 내용들이 근거와 함께 정리되어있어 완권을 하지는 못했지만.. 재밌게 읽었다.
> 내용정리
세상에는 수없이 많은 일들이 매일, 매시간, 매초마다 일어난다. 이 수많은 일을 우리는 모두 다 알 수는 없을 것이다. 그렇기에 우리에게 필요한, 관심이 있을 법한 일만 정리해서 알려주는 것이 신문과 뉴스이다. 우리의 의식이 이 신문과 뉴스와 같은 역할을 한다. 즉, 우리의 의식은 우리의 뇌에서 일어나는 모든 일들을 알지 못하며 활동 중 일부만을 전달받을 뿐이다.
지크문트 프로이트는 자신의 심리적 장애를 다루는 개인병원에서 환자를 다루면서 환자들의 문제행동들의 원인을 환자들의 의식에서는 전혀 찾을 수 없을 때가 많다는 사실을 깨달았다. 그래서 우리의 의식 너머, 훨씬 더 큰 부분이 보이지 않는 부분이 존재한다는 생각을 하기에 이른다. 이러한 생각이 있기 전에는 의식만이 우리의 정신세계의 전부라고 생각했기때문에 의식으로 설명되지 않는 이상행동들은 약한 의지력, 악마 빙의 등으로 밖에 설명할 수 없었다.
무의식의 기능을 설명하기 위해 책에서는 시각에 대해서 이야기를 하는데, 우리가 보는 시각 또한 무의식의 기능 중 하나이다. 수십년 동안 앞을 보지 못하다가 수술 등으로 시각을 회복한 사람들은 세상을 보는 법을 다시 배워야한다고 한다. 눈의 기능에는 문제가 없을 수 있지만 뇌는 들어오는 데이터를 해석하는 방법을 다시 배워야한다. 이렇듯 시각이라는 기능자체가 학습으로 구축되는 "기능"에 속하기 때문에 여러 착각을 일으킨다. 그렇기때문에 우리의 시각은 카메라처럼 세상을 충실하게 표현해주지 않는다. 우리가 틀린그림 찾기를 할 때에 잘 찾지 못하는 것도 비슷한 이유이다. 우리는 틀린 그림을 보고 있지만 시각적으로는 잘 인지하지 못하고 주의를 기울여 구석구석 살펴보았을 때에만 차이를 인지할 수 있고, 경우에 따라서는 말해주기 전까지는 인지하지 못하기도 한다.
시각이라는 것은 단순히 보는 것만을 의미하지 않는다. 뇌에서 정보처리를 하는 과정까지를 포함한 단어이다. 따라서 눈이 어딘가를 보고 있더라도 뇌가 정보를 처리하지 않고 있다면 우리는 그 정보를 보지 못한다. 뇌는 2.5D 스케치 정도만 구축하여 언제 어디를 봐야하는지 정도만을 대충파악하고 있기만 한다. 우리가 카페에 있다고 가정했을 때, 우리의 뇌는 대략적인 카페구조를 머리에 그려두었다가 누군가가 "각설탕이 몇 개 남았어?"라고 물으면 그제서야 설탕그릇으로 주의를 돌려 데이터를 추가한다. 설탕 그릇은 줄곧 우리 시야 안에 있었지만 우리 뇌에는 설탕그릇에 대한 자세한 정보는 없었던 것이다.
따라서 우리는 실제 세상을 인식하는 것이 아니라 뇌가 우리에게 보여주는 것을 인식할 뿐이다. 그렇기 때문에 우리의 기대는 시각에도 영향을 미친다. 아래의 사진을 화분이라고 생각하고 볼 때와 사람얼굴이라고 생각하고 볼 때 다르게 보이는 것이 그 때문이다.
도널드 매카이는 시각피질이 세상의 모델을 만들어내는 기계와 같다는 의견을 내놓았는데, 피질은 자신의 예측을 시상으로 내보내고, 시상은 눈을 통해 들어오는 정보와 비교하여 예측과의 차이를 보고하는 방식이다. 이 때문에 우리는 감각기관의 정보가 예측과 어긋났을 때에만 주의에 대한 의식이 발생한다. 우리가 자전거를 탈 때 의식적으로 페달에 가하는 압력을 신경쓰지 않지만 만약 평소에 타던 것과 기어가 다르게 세팅되어있다거나 다른 자전거를 타서 페달의 뻑뻑함이 다를때에만 페달을 밟는 동작을 의식적으로 하게되는 것이다.
우리는 뇌가 지속적으로 수행하는 수많은 활동을 의식하지 못한다. 일부러 의식하려고 했다가는 오히려 잘 굴러가는 뇌에 방해가 될 것이다. 피아노 연주를 망치는 가장 좋은 방법은 손가락에 정신을 집중하는 것이다. 이런 것들은 무의식이 알아서 할 수 있도록 두어야한다. 우리는 직접 어떤 손가락이 어떤 건반을 눌러야하는지 일일히 컨트롤하지 않지만 아름다운 연주를 할 수 있다.
우리의 의식은 우리 뇌가 갖고 있는 지식에 직접 접근할 수는 없다(폐를 활용하여 숨을 쉬는 것을 컨트롤하지 못하는 것처럼). 뇌가 해낼 수 있는 일과 우리가 의식적으로 접근할 수 있는 정보 사이에는 격차가 있다. 살면서 새로 경험하는 일을 의식적으로 기억하지 못하는 선행성 기억상실증 환자들에게 테트리스를 가르쳐주었을 때, 다음날에 테트리스에 대해 물어보면 전혀 기억하지 못한다. 하지만 회차를 거듭할 수록 테트리스 실력은 점점 늘어간다.
***
2006년, 배우 멜 깁슨은 술에 취한 상태에서 경찰에게 단속되었다. 이때 깁슨은 인종차별적인 발언들을 하였다고 하는데 이 때 깁슨을 비난하는 사람들은 술에 취하면서 깁슨의 본성이 들어났다고 하지만, 깁슨을 옹호하는 사람들은 그가 반유대주의자라면 다른 유대인들과 많은 시간을 보낸 것이 말이 되지 않는다고 한다. 깁슨은 인종차별자일까, 아닐까? 많은 사람들은 사람의 진정한 모습은 하나뿐이고 나머지는 모두 거짓된 모습이라고 생각한다. 하지만 저자는 사람은 여러 부분이 동시에 존재할 수 있다고 주장한다. 즉, 깁슨의 뇌에 인종차별적인 부분과 그렇지 않은 부분이 동시에 존재한다고 생각한다.
저자는 뇌를 대의민주주의에 비유하는데 뇌는 서로 분야가 겹치는 여러 전문가로 구성되어 있으며 전문가들은 다양한 선택지를 제시하며 경쟁한다고 주장하였다. 만약 멈출 수 없는 기차가 5명의 선로수리를 하고 있는 기술자가 있는 길과 1명이 있는 길 중 5명이 있는 길로 달려가고 있을 때 내 앞에 있는 스위치로 1명이 있는 길로 바꿀 수 있다라고 했을 때, 대부분의 사람들은 스위치를 누른다. 하지만 만약 내가 기차 위에 육교에서 비만한 남자를 밀어서 떨어뜨려 기차를 멈춰 5명의 기술자를 살릴 수 있다고 했을 때는 그렇게 선택하지 못한다.
육교 시나리오에서는 운동계획과 감정을 담당하는 영역이 활성화 되는 반면, 선로 스위치에서는 이성적인 사고를 담당하는 측명 영역만이 활성화된다. 둘 다 한명을 희생해야되는 상황이지만 뇌에서 더 큰 목소리를 내는 영역이 달라짐에 따라 결과가 바뀌는 것이다. 현대의 버튼 하나만으로 수천 수만의 사람들이 희생될 수 있는 전쟁의 방식이 더 쉽게 전쟁이 발발하는 이유 중 하나로 생각하는 의견도 있다.
***
사람들은 미래를 할인한다. 대부분의 사람들은 당장 100달러를 받는 것과 일주일 뒤에 110달러를 받는 것 중 바로 100달러를 받는 것을 선택한다. 사람은 즉각적이거나 가까운 미래의 보상을 선택할 때 뇌에서 감저엥 관여하는 부위가 크게 활성화된다. 반면, 먼 미래에 더 높은 보상을 받는 선택을 할 때는 고등 인지기능과 신중한 사고를 담당하는 피질 측면 부위들이 더 활성화된다. 따라서 저자는 고결한 사람이란 유혹받지 않는 사람이 아니라 유혹에 저항할 수 있는 사람이라고 한다.
파티에서 초콜릿 케이크를 추천받았을 때, 내 뇌의 일부는 단기적인 이득(단 것)을 생각하고, 다른 부분은 장기적인 전략(다이어트)를 생각한다. 이 싸움의 승패가 감정 쪽으로 기울어지면 케이크를 먹기로 결정하게 되는 것이다. 이 과정에서 내일은 운동을 가겠다라는 다짐을 하기도 하는데 이렇게 자유의지로 미래에 자신을 묶는 결정을 하는 것을 율리시스의 계약이라고 부른다.
***
앞서 뇌는 서로 분야가 겹치는 여러 전문가로 구성되어 있다고 했다. 이를 뒷받침하는 케이스 중 하나가 살아 있을 때는 아무런 증상이 없었지만 사망한 뒤 부검을 해보면 알츠하이머병(치매) 때문에 신경이 마구 망가진 것이 발견되는 사례가 많다고 한다. 이런 사람들의 공통점은 나이를 먹은 뒤에도 활발히 일을 계속하여 뇌를 자극한 사람들이었다. 이 과정중에서 뇌의 일부가 퇴행하는 와중에도 이전에 구축해둔 중복된 역할을 할 수 있는 다른 영역들이 대체하는 것이다.
여러영역으로 나뉘어있다는 또 다른 예시가 뇌 분리 수술로 인해 발생할 수 있는 외계인 증후군(두 손이 서로 상충하는 욕망을 드러내는 현상)과, 스트룹 테스트이다. 스트룹 테스트는 인쇄된 글자의 색깔을 말하는 테스트인데 초록색으로 인쇄된 "파란색"이라는 글씨를 제시하면 "파란색!"이라고 읽는 경우를 뜻한다. 스트룹 간섭은 단어를 읽으려는 강력하고 비자발적이며 자동적인 충동과 인쇄된 글자의 색깔을 말하기 위해 의식적으로 노력을 하는 상황 사이의 충돌을 보여준다.
우리의 뇌는 여러 외계인 서브루틴을 운영하면서도 정당화하기도 한다. 숨은 프로그램들이 행동을 주도하면 우리 뇌의 좌반구는 그 행동을 정당화한다. 우리의 좌반구 해석메커니즘은 항상 열심히 일하면서 사건들의 의미를 찾아내려하는데, 질서와 이성이 전혀 없는 곳에서도 항상 질서와 이성을 찾아내려하기 때문에 실수를 저지른다. 뇌가 많이 손상된 한 여인은 두눈을 감으라고 했을 때 한쪽 눈만을 감고는 다 감았다고 한다. 이때 손가락 세개를 펴고 숫자를 물으면 여인은 3개라고 답한다. 그리고 의사가 두 눈을 감았는데 어떻게 손가락의 개수를 셀 수 있었느냐고 물어보면 여인의 뇌는 서로 충돌하면서 아무 말도 하지 않고 아무 결론도 내리지 못한다. 그 문제에 갇혀버리는 것이다.
***
이렇게 무의식이 많은 일들을 하고 우리의 의식이 접근할 수 없는 영역도 있다면 우리에게는 왜 의식이 있을까? 우리는 왜 회로에 각인되어 문제를 해결해주는 자동 루틴의 집단일뿐이 아닐까? 저자는 의식은 자동화된 외계인 시스템을 제어하고 제어권을 분배하기 위해서 존재한다고 결론을 내렸다. 의식은 마치 회사의 CEO와 같아서 CEO가 모든 부서의 내부사정을 속속들이 알 필요없어 큰 결정과 방향만을 잡는 것과 비슷하다. 다만 문제가 생겼을 때는 CEO에게 보고가 되는 것처럼, 우리 의식은 세상에 일어나는 사건들이 우리의 기대나 예상과 어긋날때만 개입한다. 새로운 게임을 할 때, 뇌는 활발하게 활동하다가 익숙해지면 뇌 회로에 각인되면서 에너지 효율이 높아지고 뇌 활동이 줄어든다.
대부분의 동물들은 특정한 작업을 잘 수행한다. 외계인 서브루틴(좀비 시스템)이 잘 돌아간다는 것이다. 하지만 새로운 서브루틴을 역동적으로 개발해내는 유연성을 갖춘 인간같은 생물은 매우 소수이다. 이 유연성의 대가로 인간은 비실용적으로 소수의 아기를 낳아서 긴 육아기간을 가져야만 한다. 반대로 매우 간단한 몇몇의 서브루틴을 가진 생물들은 많이 낳고 그냥 잘 되기를 바라자는 전략을 취한다.
큰가시고기 암컷이 수컷의 영역을 침범하면 수컷은 공격행동과 구애행동을 동시에 나타낸다. 가시고기는 단순한 입력신호로 동작하는 좀비프로그램 덩어리에 지나지 않아 이 서브루틴들을 중재할 의식이 부재하다. 즉, 여러 프로그램을 조정하고, 만족을 뒤로 미루고, 새로운 프로그램을 배우는 능력이 뛰어날수록 의식이 있을 가능성이 높다. 인간은 이러한 의식을 가지고 있기때문에 다른 생물들은 교착상태에 빠질 상황에서도 우리를 탈출 시킬 수 있다. 우리 뉴런들이 수행하는 전체 기능에서 아주 작은 역할을 할 뿐인 의식이지만 꼭 필요한 이유가 이것이다.
> 느낀점
이 책을 읽으면서 회사에서 일을 하면서 알림이 오지않았음에도 카톡에 읽지않은 메세지가 있어 확인해보면 방금 온 경우가 많았던 것처럼 내가 의식하고 있지 않았지만 인지를 하는 경우가 어떻게 생기는 것인지에 대한 이해를 할 수 있게 되었다. 또, 우리가 학습을 한다는 것이 결국 무의식의 레벨까지 뇌의 회로에 각인시키는 작업이라는 것이라는 것을 알게 되었다.
우리가 보고 듣고 느끼는 많은 것들이 사실 우리의 무의식이 만들어낸 결과물이라는 사실을 다시금 깨닫게 되어 하나의 감각의 결과물을 무조건적으로 맹신하지 않아야겠다는 생각을 하였으며 나의 경험에 의한 생각, 가치관이 틀릴 수도 있다는 사실을 항상 인지하고 열린 마음으로 다른 사람들의 생각을 수용하여야겠다는 생각을 했다.
그리고 멜 깁슨의 케이스처럼 으레 말하는 취중진담처럼 한 사람이 여러가지 말을 할 때, 그 사람이 특수한 상황(일반적으로는 더 극한의 상황)에서 하는 말이나 행동이 진심이다라는 생각을 많이 했는데 한 사람도 여러가지 상충하는 면모를 동시에 가질 수도 있다는 생각을 할 수 있게되어 너무 일부분만으로 판단하지 않아야겠다고 생각했다(물론 일부분이라고 할지라도 너무 맞지 않는 사람까지 이해할 수는 없겠지만..)
안녕하세요~ 오늘의 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의 장점은
유저나 상황별로 다른 파일을 주는 것이 아니기때문에 캐싱이 용이하고 CDN을 사용하기 쉽습니다.
클라이언트에서 라우팅을 포함한 모든 작업을 처리하기 때문에 페이지 이동간 리프레시가 없습니다. SPA의 장점이기도 하죠.
HTML이 사실상 비어있기때문에 Time To the First Byte(TTFB)가 정말 빠릅니다. 완벽하진 않더라도 사용자가 화면을 조금 더 빨리 받아볼 수 있습니다.
하지만 이에따른 단점도 존재합니다.
클라이언트의 기기에서 모든 작업을 처리하기때문에 어플리케이션이 돌아가는 기기에 따라 성능이슈가 발생할 수 있습니다.
클라이언트에서 구동에 필요한 js뿐만이 아니라 모든 데이터 fetching까지 진행해야되므로 받아야되는 데이터의 양이 많고 경우에따라 느릴 수 있습니다.
검색엔진 최적화, SEO에 불리합니다.
다음은 SSR에 대해서 알아보겠습니다. SSR은 서버에서 사용자에게 보여주기 위한 HTML안의 내용물을 완성시켜서 사용자에게 내려주는 방식입니다. 이렇게 HTML을 보내준 다음에 사용자의 인터렉션에 반응할 수 있도록 js를 다시 보내줍니다.
SSR의 장점은
검색엔진 크롤러가 접근했을때 완성된 페이지를 바로 받아보기 때문에 검색엔진최적화에 좋습니다.
서버에서 모든 작업을 해서 주기때문에 비교적 안정적인 성능을 보여줍니다.
반대로 SSR의 단점은
서버에서 페이지를 만들어서 줘야되기때문에 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을 하는 경우에 매우 빠른 구동이 가능할 것으로 보입니다.
현재로써는 인메모리캐시이기 때문에 개발용 서버에만 사용되지만 나중에 캐시가 영구저장이 가능해지면 프로덕션에까지 확장시키고, 미리 만들어져있는 캐시들을 공유할 수 있도록 한다고하니 훨씬 빠른 빌드와 배포가 가능해질 것 같습니다.