{"id":13726616,"url":"https://github.com/reason-seoul/reason-todomvc","last_synced_at":"2025-05-07T21:33:22.110Z","repository":{"id":136398762,"uuid":"280845536","full_name":"reason-seoul/reason-todomvc","owner":"reason-seoul","description":"Online Workshop #1. TodoMVC example in Reason React","archived":false,"fork":false,"pushed_at":"2023-04-26T10:55:19.000Z","size":77,"stargazers_count":18,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-08-03T01:29:12.380Z","etag":null,"topics":["bucklescript","reason-react","reasonml","todomvc"],"latest_commit_sha":null,"homepage":"","language":"Reason","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reason-seoul.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-07-19T10:50:26.000Z","updated_at":"2023-04-26T10:55:24.000Z","dependencies_parsed_at":"2024-01-06T07:39:01.578Z","dependency_job_id":"6b79a8fc-67d9-43e8-abf7-4d644aae4264","html_url":"https://github.com/reason-seoul/reason-todomvc","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reason-seoul%2Freason-todomvc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reason-seoul%2Freason-todomvc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reason-seoul%2Freason-todomvc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reason-seoul%2Freason-todomvc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reason-seoul","download_url":"https://codeload.github.com/reason-seoul/reason-todomvc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224654332,"owners_count":17347727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bucklescript","reason-react","reasonml","todomvc"],"created_at":"2024-08-03T01:03:14.730Z","updated_at":"2024-11-14T16:34:13.552Z","avatar_url":"https://github.com/reason-seoul.png","language":"Reason","funding_links":[],"categories":["Reason"],"sub_categories":[],"readme":"# Reason Seoul Workshop #1\n\n[![Discord](https://img.shields.io/discord/717436122480902225.svg?label=\u0026logo=discord\u0026logoColor=ffffff\u0026color=7389D8\u0026labelColor=6A7EC2)](https://discord.gg/RzShCNp)\n[![Twitter Follow](https://img.shields.io/twitter/follow/ReasonSeoul.svg?style=social)](https://twitter.com/ReasonSeoul)\n\nReason Seoul 커뮤니티에 놀러오세요!\n\n## Reason React로 TodoMVC 만들기\n\n워크샵 기록:\n\n- [Reason React로 TodoMVC 만들기\n](https://www.meetup.com/Reason-Seoul/events/271960396/)\n- (TBD) Youtube\n\n### 둘러보기\n\n#### 초기화\n\n이 저장소를 클론합니다.\n\n```bash\ngit clone https://github.com/reason-seoul/reason-todomvc.git\n```\n\n저장소는 탄소를 절감하고 우리들의 SSD 수명을 조금 더 보존하기 위해 [pnpm](https://pnpm.js.org/) 패키지 매니져를 사용하고 있습니다 :wink:\n\n```bash\n# 아직 pnpm이 없다구요? 바로 설치하세요!\n# npx pnpm add -g pnpm\n\n# 이제부턴 npx도 pnpx로 바꿔씁니다.\n\npnpm install\n```\n\n코드를 직접 작성하고 싶은 분들은 `basic-setup` 태그를 체크아웃 하세요! 제가 여러분들을 위해 귀찮은 웹 팩 설정을 대신 해드렸답니다.\n\n```bash\ngit checkout basic-setup\n```\n\n#### 이게 뭔가요?\n\n##### BuckleScript\n\n[BuckleScript](https://bucklescript.github.io/)는 OCaml/Reason 으로 작성된 코드를 JavaScript 로 바꿔주는 컴파일러입니다.\n\n```bash\npnpm add bs-platform\n```\n\n다른 도구들과 다르게 표현식 레벨에서의 변환만 일어나고, Minify등의 처리는 직접 다루지 않습니다.\n\nHighlights:\n\n- 컴파일 속도가 눈부시게 빠르고,\n- Dead-code elimination, Inline caching optimization, recursion optimization 등의 최적화가 적용되면서,\n- 여전히 읽을 수(!) 있는 JavaScript 코드가 생성됩니다.\n\n##### Belt\n\n[Belt](https://reasonml.org/apis/javascript/latest/belt)는 BuckleScript에 포함된 표준라이브러리 입니다. Array/List/Option 등의 표준 자료형을 다루기 위한 라이브러리들을 제공하고 있습니다.\n\n##### Reason React\n\n[Reason React](https://reasonml.github.io/reason-react/)는 Reason 커뮤니티가 관리하는 React 바인딩입니다.\n\nReason은 JSX를 지원하며, React의 API를 거의 유사한 방식으로 지원하기 때문에 JavaScript와 차이점이 거의 방식으로 React 앱을 만들 수 있습니다.\n\n```re\nmodule Hello = {\n  [@react.component]\n  let make = (~name) =\u003e {\n    \u003cdiv\u003e{React.string(name)}\u003c/div\u003e;\n  };\n};\n\n[@react.component]\nlet make = () =\u003e {\n  let name = \"World!\";\n  \u003cHello name\u003e;\n};\n```\n\n**Fun fact 1:** 그거 아시나요? [React 의 초기 프로토타입은 JavaScript 보다 Reason에 더 가까웠습니다!](https://dev.to/andrefbsantos/reasonml-react-as-first-intended-2020-25j0) (완성이 가까워지면서 JavaScript로 재작성되었습니다) Reason React 는 종종 React 보다 더 낫게 느껴집니다.\n\n**Fun fact 2:** Reason React 의 API는 React보다 발전이 빠릅니다. Hooks가 도입되기 전에 [Subscription Helper](https://reasonml.github.io/reason-react/docs/en/subscriptions-helper#docsNav) API가 존재했고, Reducer가 컴포넌트 기본 프리미티브로 제공되기 전부터 [Reducer Component](https://reasonml.github.io/reason-react/docs/en/state-actions-reducer)를 제공했습니다. 지금은 [Concurrent Mode API를 *공식*으로 먼저 지원](https://reasonml.github.io/reason-react/blog/2020/05/05/080-release)합니다!\n\n### 타입\n\nReason은 정말 강력한 타입 시스템을 통해 프로그램의 안정성을 보장합니다.\n\n```re\ntype todo = {\n  id: int,\n  completed: bool,\n  text: string,\n};\n\ntype action =\n  | NewTodo(string)\n  | CompleteTodo(int);\n\ntype state = {\n  todos: array(todo),\n};\n```\n\nRecord 와 Tuple 타입을 통해 기본적으로 **불변인 값**들을 다루고, ADT를 활용해서 액션을 모델링 할 수 있습니다.\n\n그리고 모든 Reason 타입을 **패턴 매칭**이 가능합니다.\n\nADT 매칭을 이용한 리듀서:\n\n```re\nopen Belt;\n\nlet reducer = (state, action) =\u003e {\n  switch (action) {\n  | NewTodo(text) =\u003e {\n      todos: state.todos-\u003eArray.concat([| Todo.make(~text) |]),\n    }\n  | TodoCompleted(id, completed) =\u003e {\n      todos:\n        state.todos\n        -\u003eArray.map(todo =\u003e todo.id == id ? {...todo, completed} : todo),\n    }\n};\n```\n\n튜플 매칭을 이용한 투두 아이템 필터:\n\n```re\n// Reason React는 라우터도 기본으로 제공합니다.\nlet url = ReasonReactRouter.useUrl();\n\ntype filter =\n  | All\n  | Active\n  | Completed;\n\nlet filter =\n  switch (url.hash) {\n  | \"active\" =\u003e Active\n  | \"completed\" =\u003e Completed\n  | _ =\u003e All\n  };\n\n// 와 너무 직관적이다\nstate.todos\n-\u003eArray.keep(todo =\u003e switch (filter, todo.completed) {\n  | (Completed, true) =\u003e true\n  | (Active, false) =\u003e true\n  | (All, _) =\u003e true\n  | _ =\u003e false\n})\n```\n\n그냥 투두 레코드 필터:\n\n```re\nlet isFirstThree = switch (todo) {\n  | { id: 1 | 2 | 3, _ } =\u003e true\n  | _ =\u003e false\n};\n```\n\n그런데 타입 어노테이션들은 다 어디갔나요?\n\n걱정 마세요! Reason은 여러분이 무엇을 원하는지 이미 다 눈치챘답니다!\n\nReason의 강력한 타입 추론으로 여러분의 손가락 관절을 구원하세요.\n\n### 모듈 시스템\n\nReason의 모듈 시스템은 정말 강력해서, 여러분을 파일 당 수십 라인의 `import` 문을 타이핑 하는 고통해서 해방시켜줍니다.\n\n여러분이 만든 파일은 이미 하나의 식별가능한 모듈입니다! (그렇기 때문에 파일명은 프로젝트 안에서 고유해야 합니다.) `module`을 통해 직접 모듈을 정의할 수도 있습니다.\n\n```re\n// Model.re\n\nmodule Todo = {\n  type t = {\n    // ...\n  };\n  let make = () =\u003e { /* ... */ }\n}\n```\n\n이제 다른 프로젝트의 어떤 곳에서든 `Model.Todo.t` 타입에 바로 접근할 수 있고, 모듈을 `open`해서 내부의 타입에 접근할 수도 있습니다.\n\n```re\n// Whereever\ntype t = Model.Todo.t;\n\nmodule Nested = {\n  open Model;\n  type t = Todo.t;\n};\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freason-seoul%2Freason-todomvc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freason-seoul%2Freason-todomvc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freason-seoul%2Freason-todomvc/lists"}