주요 변화 중 하나 Mendix 7은 상태가 런타임에서 클라이언트로 이동된 상태 없는 런타임의 도입이었습니다. Mendix 7, 클라이언트는 이제 상태를 추적하고 브라우저와 모바일 앱에 대한 요청과 함께 런타임으로 전송합니다. 이 기능을 통해 런타임은 수평적으로 확장할 수 있어 애플리케이션에 더 많은 서버 리소스가 필요할 때 엄청난 유연성을 제공합니다.
이 블로그 시리즈의 1부에서는 앱을 살펴보고 각 단계에서 상태 관점에서 무슨 일이 일어나는지 알아보겠습니다. 이를 통해 클라이언트 상태가 어떻게 작동하는지 더 잘 이해할 수 있습니다.
면책 조항: 이 블로그 게시물은 다음에 적용됩니다. Mendix 7.23.1. 상태 동작은 이전 릴리스와 다를 수 있으며 추가 릴리스에서 사전 통지 없이 변경될 수 있습니다.
국가란 무엇이고, 국가는 실제로 무엇을 포함하고 있는가?
사용자로서 Mendix 앱에서 작업하는 일부 데이터는 아직 데이터베이스에 저장되지 않았을 수 있습니다. 정확히 말해서 상태는 다음으로 구성됩니다.
- 새로 생성되고 아직 커밋되지 않은 모든 지속 가능 개체(PE)
- 모든 지속 불가능한 객체(NPE)
- 객체에 대해 수행된 모든 속성 및 연결 변경 사항(연결 및 속성은 클라이언트에서 동일하게 처리되므로 이 게시물의 나머지 부분에서는 연결에 대해 언급하지 않음)
이러한 객체와 변경 사항은 상태를 구성합니다. 아직 앱의 데이터베이스에 저장되지 않았으므로 데이터베이스에 저장되거나 삭제되거나 앱에서 더 이상 필요하지 않을 때까지 상태에 저장해야 합니다.
국가에 대한 수정은 다양한 방법으로 도입될 수 있습니다.
- 새 객체는 런타임의 마이크로플로, 클라이언트의 나노플로 또는 객체 생성 클라이언트 작업을 통해 생성될 수 있습니다.
- 속성 변경은 마이크로플로, 나노플로, 사용자 정의 위젯 또는 최종 사용자에 의해 수행될 수 있습니다.
상태의 관점에서, 객체나 변경의 출처는 중요하지 않습니다. 모든 객체와 변경은 클라이언트 상태에서 끝납니다.
상태는 이전에 설명한 것보다 더 많은 객체를 포함할 수 있습니다. 때로는 상태에 커밋된 객체가 포함되기도 합니다. 이는 종종 앱의 성능을 높이기 위해 수행됩니다.
변경이란 무엇이고 어떻게 상태에 저장되나요?
변경 사항은 커밋되지 않은 값을 참조합니다. Mendix 객체의 속성. 예를 들어, 사용자가 텍스트 상자를 사용하여 속성의 값을 변경하는 경우, Mendix 편집된 객체의 상태 변경으로 새 값을 저장합니다. Mendix 객체 자체는 아직 변경되지 않았습니다.
변경 사항을 별도로 유지 Mendix 객체는 롤백을 가능하게 합니다. 롤백할 때마다 Mendix 마이크로플로우, 나노플로우 또는 취소 변경 클라이언트 작업의 객체 Mendix 해당 상태의 객체에 대해 변경된 모든 내용을 삭제합니다.
이는 사용자가 저장 버튼을 클릭할 때마다 Mendix 편집된 객체에 대한 모든 변경 사항을 수집하여 전송하여 해당 변경 사항을 런타임 데이터베이스에 저장할 수 있습니다. 이는 마이크로플로우 호출과 같이 변경된 객체가 필요한 다른 런타임 요청의 경우에도 마찬가지입니다.
국가의 범위
와 Mendix 7, 상태는 브라우저의 메모리에 저장됩니다. Mendix 클라이언트. 즉, 웹 앱의 경우 상태가 현재 브라우저 탭에 로컬합니다. 별도의 탭에서 앱을 열면 이전 탭의 상태에 액세스할 수 없습니다. 또한 현재 브라우저 탭을 새로 고치면 해당 상태가 손실됩니다.
마지막 사례에는 하나의 예외가 있습니다. Mendix 클라이언트는 상태를 저장합니다. 세션 저장 브라우저의 빠른 배포 기능을 위해 잠시 동안. 이를 통해 모델을 변경했을 때의 페이지 또는 상태에서 앱 내에서 작업을 계속한 다음 실행할 수 있습니다. 이 기능은 개발 중에만 사용할 수 있습니다.
위의 두 가지 동작은 모두 새로운 것입니다. Mendix 7이며 내장된 앱과 호환되지 않습니다. Mendix 6 및 이전. Mendix 6. 해당 상태는 다양한 탭에서 계속 접근할 수 있으며 새로 고침 후에도 유지됩니다.
국가와 안보
클라이언트에 상태를 저장하면 보안에 다음과 같은 문제가 발생합니다.
현재 사용자에 대한 읽기 전용 속성 Mendix 현재 사용자의 읽기 전용 속성 값을 값 옆에 해시로 보호하므로, 해당 값을 불법적으로 변경하려는 모든 시도가 적발되어 거부됩니다.
현재 사용자의 접근 불가능한 속성에 대한 변경 사항 로그인한 사용자가 액세스할 수 없는 속성에 대한 변경 사항은 상태에 저장할 수 없습니다. 클라이언트에 보내면 기밀 데이터가 공개될 위험이 있습니다. 따라서 이러한 변경 사항은 삭제됩니다.
상태는 런타임에 어떻게 전달되나요?
따라서 Mendix 클라이언트는 특수 엔드포인트를 통해 런타임과 통신합니다. /xas예를 들어 데이터 그리드에 대한 데이터를 로드하거나 마이크로플로를 호출할 때. 이 API에 대한 각 유형의 호출을 액션이라고 하며 상태의 필요한 부분이 함께 전송됩니다. 다음을 검사할 수 있습니다. xas 요청 사항 네트워크 브라우저 개발자 도구의 탭을 클릭하고 요청을 필터링합니다. xas 경로입니다. 우리는 방문할 것입니다 xas API는 나중에 게시물에서 설명하겠습니다.
부인 성명: xas 는 사이의 개인 API입니다. Mendix 클라이언트 및 런타임은 향후 릴리스에서 사전 통지 없이 변경될 수 있습니다. 여기에 제공된 세부 정보는 이해도를 높이기 위한 것입니다. Mendix 앱은 런타임과 통신하므로 더 나은 앱을 모델링하고 앱 문제를 보다 효과적으로 해결할 수 있습니다.
때마다 xas 동작(예: 마이크로플로우 호출)이 트리거됩니다. Mendix 클라이언트가 상태도 전송합니다. Mendix 클라이언트는 전체 상태를 런타임에 전송하지 않습니다. 이렇게 하면 심각한 성능 문제가 발생할 수 있기 때문입니다. Mendix 애플리케이션을 배포하는 동안 각 마이크로플로를 분석하여 상태의 어느 부분을 보내야 할지 결정합니다.
고객의 상태를 검사할 수 있나요?
누르면 Ctrl 키+다른+G 키 조합은 클라이언트 상태 요약을 그 순간 브라우저 콘솔에 덤프하므로 저장된 내용을 검사할 수 있습니다. 이 단축키를 사용하여 예제 앱을 검사합니다.
아트워크 등록 앱
클라이언트 상태를 보여주기 위해 아티스트에 대한 정보를 저장할 수 있는 간단한 아트워크 레지스트리 앱을 만들었습니다.
프로젝트를 다운로드 할 수 있습니다 여기에서 확인하세요 그리고 우리가 상황을 검토하면서 그 상태를 조사합니다.
다음은 간단한 도메인 모델입니다. 예술가 ~을 가진 실체 FullName 속성을 사용하지 않는 것입니다.
앱을 실행해 보겠습니다. 홈페이지는 의도적으로 비어 있으므로 Mendix 클라이언트는 빈 상태에서 시작합니다.

우리는 이것을 열어서 확인할 수 있습니다 콘솔에서 개발자 도구에서 다음을 누릅니다. Ctrl + Alt + G 지름길.

여기서는 상태가 JSON 객체로 표현되었지만 현재는 비어 있는 것을 볼 수 있습니다.
클릭 연예인 메뉴 항목. 여기에는 앱에서 정의된 모든 아티스트의 목록 보기가 있습니다. 현재는 없습니다.

새로운 아티스트를 만들려면 다음을 클릭하세요. 새로운 아티스트 만들기 버튼을 눌러서 무슨 일이 일어나는지 검사하세요 네트워크 개발자 도구의 탭입니다. 첫 번째 요청을 선택합니다. xas/ 경로를 따라 아래로 스크롤하세요 헤더 세부 보기의 탭:

요청 페이로드를 추출하여 검사합니다.
Switch to "Text" tab and paste code here
위에서 전형적인 것을 볼 수 있습니다 xas 요청. 각 필드를 살펴보겠습니다.
action: 모든 런타임 작업이 다음을 거쳐 진행된다고 언급했습니다.xasAPI이므로 각 작업은 구별 가능해야 합니다. 여기서action필드는 이 목적을 위해 사용됩니다. 현재 작업은 다음과 같습니다.instantiate, 런타임에 생성을 요청합니다. Mendix 목적.params: 각각xas액션에는 자체 매개변수 집합이 있을 수 있으므로params작업별 매개변수를 포함합니다.instantiate호출 시 런타임은 어떤 유형의 객체를 생성해야 하는지 알아야 하므로 이를 전달합니다.objecttype입력란입니다.changes: 이것은 클라이언트 상태와 관련된 필드 중 하나입니다.xas요청이 이루어지면, Mendix 클라이언트는 요청과 함께 관련 상태를 보냅니다.changes는 해당 상태의 일부입니다. 새 객체를 만드는 데는 상태가 필요하지 않으므로 여기서는 비어 있습니다.objects: 이것은 클라이언트 상태와 관련된 두 번째 필드입니다. 여기서 Mendix 클라이언트는 요청 중에 런타임이 필요로 할 수 있는 상태에서 객체를 제공합니다. 새 객체를 만드는 데는 객체 상태가 필요하지 않으므로 비어 있습니다.
응답을 확인하려면 다음을 선택하세요. 시사 내 탭 네트워크 요청 세부 정보 보기:

자세한 내용을 살펴보는 동안 개발자 도구의 스크린샷은 건너뛰고 추출된 버전만 보여드리겠습니다.
{
"actionResult": "5629499534213124",
"commits": [],
"changes": {},
"resets": {},
"deletes": [],
"newpersistable": [
"5629499534213124"
],
"objects": [
{
"objectType": "MyFirstModule.Artist",
"guid": "5629499534213124",
"hash": "Nw09VTjCQKib7DbE5Agxgm3Bg6fEGL4mPRyNrgiUKGs=",
"attributes": {
"FullName": {
"value": null
}
}
}
]
}
위에서 전형적인 것을 볼 수 있습니다 xas 응답. actionResult 필드는 작업 자체와 직접 관련이 있지만 다른 필드는 클라이언트 상태와 관련이 있습니다.
각 통화 후 xas, 런타임 응답은 요청 중에 발생한 일에 대한 정보(예: 어떤 객체가 생성 또는 삭제되었는지)를 유지합니다. 런타임은 클라이언트에 대한 각 응답에서 이를 전달하므로 클라이언트는 해당 변경 사항을 상태에 적용합니다.
클라이언트 상태와 관련된 응답 필드의 개요는 다음과 같습니다.
커밋
이 필드에는 요청 중에 커밋된 guid 목록이 들어 있습니다. 생성 자체로 객체를 커밋하지 않으므로 비어 있습니다. 채워지면 다음과 같습니다.
"commits": ["guid_1", "guid_2", "...guid_n"]
따라서 Mendix 클라이언트는 이 정보를 사용하여 새 객체가 커밋되었는지 아닌지를 알 수 있습니다. 이런 식으로 클라이언트 상태를 그에 따라 업데이트할 수 있습니다.
변경
이 필드에는 모든 변경 사항의 요약이 포함되어 있습니다. Mendix 요청 중에 만들어진 객체입니다. 즉, 해당 변경 사항은 아직 커밋되지 않았으므로 상태에 저장되어야 합니다.
이 필드는 채워지지 않았습니다. instantiate 새로운 변경 사항이 없으므로 호출하십시오. Artist 아직 객체가 없습니다. 그러나 만약 Artist 객체에 아티스트 이름을 기본값으로 변경하는 After Create 이벤트 마이크로플로가 있는 경우 해당 필드는 다음과 같습니다.
"changes": {
"5629499534213124": {
"FullName": {
"value": "Value set in the event microflow"
}
}
}
따라서 Mendix 클라이언트는 여기에서 변경 사항을 가져와 클라이언트 상태에 적용합니다.
리셋
이 필드에는 각 속성의 모든 롤백된 변경 사항 요약이 포함되어 있습니다. Mendix 목적. Mendix 클라이언트는 해당 정보를 사용하여 상태에서 기존 변경 사항을 제거합니다. 다음은 재설정이 어떤 모습인지에 대한 샘플입니다.
"resets": {
"guid_of_the_object": ["attribute_1", "attribute_2"]
}
삭제
이 필드에는 guid 목록이 포함되어 있습니다. Mendix 요청 중에 삭제된 객체입니다. Mendix 클라이언트는 해당 삭제 정보를 사용하여 해당 객체와 해당 변경 사항을 상태에서 제거합니다. 위의 예제 요청에서는 이 필드가 비어 있지만, 삭제가 어떤 모습인지 보여주는 샘플은 다음과 같습니다.
"deletes": ["guid_1", "guid_2", "...guid_n"]
새로운 지속 가능
이 필드에는 요청 중에 생성된 GUID 목록이 포함되어 있습니다. Mendix 클라이언트는 아직 커밋되지 않았다는 사실을 알고 있으며 필요한 만큼 오랫동안 저장해야 합니다. instantiate 호출하면 새로운 것이 생성됩니다. Artist 객체이지만 커밋하지 않았습니다. 그래서 우리는 그 guid가 이 필드의 일부임을 봅니다.
사물
이 필드에는 다음 목록이 포함되어 있습니다. Mendix 런타임 작업이 응답의 일부로 클라이언트에 보내야 하는 객체입니다. 우리의 예에서 런타임은 새 JSON 표현을 보냅니다. Artist 목적.
일반적인 Mendix 객체에는 다음 필드가 있을 수 있습니다.
objectType: 객체의 객체 유형을 정의합니다.guid: 객체의 고유 ID.hash: 이렇게 하면 전체 객체의 내용이 손상되지 않도록 할 수 있습니다.attributes: 다음을 포함합니다 저지른 객체의 각 속성에 대한 값입니다. 새 객체의 경우 속성의 기본값과 같은 값입니다. 현재 사용자가 액세스할 수 있는 속성만 존재한다는 점에 유의하세요.
이 간단한 소개를 마치고 데모 애플리케이션으로 돌아가 보겠습니다. xas 요청과 응답.
새 버튼을 클릭하면 '아티스트' 엔터티의 새 인스턴스가 생성되고 Mendix 클라이언트는 새 개체가 있는 세부 정보 페이지를 보여줍니다.

이제 여기서 우리는 상태 검사 단축키를 사용할 수 있습니다(Ctrl 키+다른+G) 클라이언트 상태를 확인하려면:
{
"MyFirstModule.Artist": {
"5629499534213124 (new)": {
"subscribedWidgets": [
"MyFirstModule.Artist_NewEdit.dataView1",
"MyFirstModule.Artist_NewEdit.textBox1",
null
]
}
}
}
이제 클라이언트 상태에 새로운 것이 있습니다. Mendix 객체이며, 이를 추가하여 표현합니다. (new) gui 뒤에 접두사를 붙여 아직 커밋되지 않았음을 나타냅니다. 또한 subscribedWidgets 필드는 해당 객체를 사용하는 위젯을 나타냅니다. 이것이 이 객체가 상태에 유지되는 이유입니다. 마지막 항목은 다음과 같습니다. null즉, 페이지나 해당 위치에 구성 요소가 하나 더 있다는 의미입니다. Mendix 객체를 사용하지만 설명이 없는 클라이언트 자체입니다.
새로운 아티스트의 이름을 변경하세요 Pablo Picasso, 그런 다음 상태를 다시 검사합니다.
{
"MyFirstModule.Artist": {
"5629499534213124 (new)": {
"changes": {
"FullName": {
"value": "Pablo Picasso"
}
},
"subscribedWidgets": [
"MyFirstModule.Artist_NewEdit.dataView1",
"MyFirstModule.Artist_NewEdit.textBox1",
null
]
}
}
}
}
이번에는 추가된 것이 있는 것을 볼 수 있습니다. changes 객체에 대한 필드로, 객체에 대한 변경 사항을 표시합니다. FullName 입력란입니다.
지금 이순간, Mendix 클라이언트는 초기값과 변경된 값을 모두 저장합니다. FullName 필드입니다. 콘솔에서 객체를 요청하여 이를 확인할 수 있습니다. mx.데이터.get 그리고 반환된 값을 비교합니다. MxObject.get MxObject.getOriginalValue 방법 :

이 아티스트를 저장하려면 다음을 클릭하세요. Save 버튼을 클릭하고 트리거하는 요청을 검사합니다(명확성을 위해 일부 필드는 생략됨):
{
"action": "commit",
"params": {
"guids": [
"5629499534213124"
]
},
"changes": {
"5629499534213124": {
"FullName": {
"value": "Pablo Picasso"
}
}
},
"objects": [{
"objectType": "MyFirstModule.Artist",
"guid": "5629499534213124",
"hash": "31doiDAq6u7/rMnqwWno01jhLkhpeQ+vKU/rI+IQor8=",
"attributes": {
"FullName": {
"value": null
}
}
}]
}
이번에는 commit 런타임에 대한 작업 요청이 생성됩니다. guid 데이터베이스에 커밋할 객체의 params 필드. 또한 changes 필드에는 Pablo Picasso 우리가 만든 변화와 objects 포함 Mendix 우리가 이전에 만든 객체입니다.
응답은 다음과 같습니다.
{
"commits": [
"5629499534213124"
],
"changes": {},
"resets": {
"5629499534213124": [
"FullName"
]
},
"deletes": [],
"newpersistable": [],
"objects": [{
"objectType": "MyFirstModule.Artist",
"guid": "5629499534213124",
"hash": "31doiDAq6u7/rMnqwWno01jhLkhpeQ+vKU/rI+IQor8=",
"attributes": {
"FullName": {
"value": "Pablo Picasso"
}
}
}]
}
없습니다 actionResult 이번에는 필드지만 주에 대한 많은 변경 사항이 있습니다.
- 따라서
commits이제 필드에 다음이 포함됩니다.guid의Artist방금 커밋했기 때문에 클라이언트 상태는 더 이상 새 객체가 아니라는 것을 알고 있습니다. - 따라서
resets필드에는guid의Artist그리고 그것을 언급한다FullName필드 변경이 제거되었습니다(이제 커밋되었기 때문입니다). 이제 클라이언트는 상태에서 이 변경을 제거할 수 있습니다.
따라서 objects 필드는 이제 커밋된 개체의 최신 버전을 나타냅니다. FullName 필드 값이 설정됨 Pablo Picasso.
런타임이 커밋된 객체를 다시 반환하는 이유는 무엇입니까?
클라이언트는 이미 해당 객체를 상태에 두고 재사용할 수 있는데, 왜 런타임이 다시 반환할까요? 이유는 두 가지입니다.
- 객체에는 객체를 추가로 수정한 이벤트 핸들러가 있을 수 있습니다.
- 객체에는 계산된 속성이 있을 수 있으며 해당 값은 커밋될 때 변경되었을 수 있습니다.
이것이 클라이언트가 객체의 최신 값이 필요한 이유이며, 런타임에서 반환되는 이유입니다.
이제 귀하의 신청서는 다음과 같습니다.

지금 상태를 살펴보면 다음과 같습니다. Pablo Picasso 여전히 상태입니다. 목록 뷰에서 사용되기 때문입니다. 하지만 작은 차이가 있습니다. 더 이상 새 것으로 표시되지 않습니다.
{
"5629499534213124": {
"subscribedWidgets": [
"MyFirstModule.Artist_Overview.listView1",
"MyFirstModule.Artist_Overview.textBox1"
]
}
}
따라서 Mendix 클라이언트는 또한 클라이언트 상태를 캐싱 계층의 한 형태로 사용합니다. 객체가 상태에 있고 위젯에 필요한 경우 런타임에서 다시 검색되지 않습니다. 아티스트 편집 “파블로 피카소” 버튼을 클릭하고 확인하세요 네트워크 devtools의 탭입니다. 새로운 것이 없다는 것을 알게 될 것입니다. xas 검색 요청이 이루어질 것입니다 Pablo Picasso 런타임에서. 이미 상태에 있으므로 요청할 필요가 없습니다.
이제 클릭해 보겠습니다. 취소 편집 페이지에서 클릭하여 애플리케이션 홈페이지로 이동합니다. 홈 메뉴 항목을 선택하고 상태를 확인하세요.
{
"MyFirstModule.Artist": {
"5629499534213124": "Going to be garbage collected †"
}
}
약 15초 후에 상태를 확인하세요. 비어 있는 것을 볼 수 있습니다.
하지만 그 이유는 무엇입니까?
이 질문에 대한 답은 새로운 개념, 즉 상태에서 가비지 수집에 있습니다. 이 메커니즘은 상태에서 불필요한 객체를 감지하여 제거하므로, 얼마나 많은 객체를 만들거나 사용하든 애플리케이션이 최상의 성능을 발휘합니다. 애플리케이션에서 Pablo Picasso 홈페이지를 열었기 때문에 더 이상 객체가 필요하지 않습니다. 왜냐하면 그것을 보여주는 위젯이 없기 때문입니다. 그래서 그것은 상태에서 제거됩니다. 그러나 상태에서 가비지 수집은 정교한 주제이므로 이 블로그 시리즈의 두 번째 부분에서 다루겠습니다.
이 글을 읽고 도움이 되셨으면 좋겠습니다. 2부에서 뵙겠습니다!
