@@ -83,30 +83,34 @@ export class YjsService
8383 * yXmlFragment에 content를 넣어준다.
8484 */
8585 private async initializePage ( pageId : number , editorDoc : Y . XmlFragment ) {
86- // 초기 세팅할 page content
87- let pageContent : JSON ;
88-
89- const response = await axios . get ( `http://backend:3000/api/page/${ pageId } ` ) ;
90- if ( response . status === 404 ) {
91- this . logger . error ( `${ pageId } 번 페이지를 찾을 수 없습니다.` ) ;
92- pageContent = JSON . parse ( '{}' ) ;
93- return ;
94- }
95-
96- const findPage = response . data . page ;
97- pageContent = JSON . parse ( JSON . stringify ( findPage . content ) ) ;
86+ try {
87+ // 초기 세팅할 page content
88+ const response = await axios . get (
89+ `http://backend:3000/api/page/${ pageId } ` ,
90+ ) ;
91+ const findPage = response . data . page ;
92+ const pageContent = JSON . parse ( JSON . stringify ( findPage . content ) ) ;
93+
94+ // content가 비어있다면 내부 구조가 novel editor schema를 따르지 않기 때문에 오류가 납니다.
95+ // content가 존재할 때만 넣어줍니다.
96+ if ( Object . keys ( pageContent ) . length > 0 ) {
97+ this . transformText ( pageContent ) ;
98+ prosemirrorJSONToYXmlFragment (
99+ novelEditorSchema ,
100+ pageContent ,
101+ editorDoc ,
102+ ) ;
103+ }
98104
99- // content가 비어있다면 내부 구조가 novel editor schema를 따르지 않기 때문에 오류가 납니다.
100- // content가 존재할 때만 넣어줍니다.
101- if ( Object . keys ( pageContent ) . length > 0 ) {
102- this . transformText ( pageContent ) ;
103- prosemirrorJSONToYXmlFragment ( novelEditorSchema , pageContent , editorDoc ) ;
105+ // 페이지 내용 변경 사항을 감지해서 데이터베이스에 갱신합니다.
106+ editorDoc . observeDeep ( ( ) => {
107+ this . observeEditor ( editorDoc ) ;
108+ } ) ;
109+ } catch ( error ) {
110+ this . logger . error (
111+ `페이지 초기화 중 오류 발생 (pageId: ${ pageId } ): ${ error . message } ` ,
112+ ) ;
104113 }
105-
106- // 페이지 내용 변경 사항을 감지해서 데이터베이스에 갱신합니다.
107- editorDoc . observeDeep ( ( ) => {
108- this . observeEditor ( editorDoc ) ;
109- } ) ;
110114 }
111115
112116 handleConnection ( ) {
@@ -121,45 +125,48 @@ export class YjsService
121125 * initialize 관련 메소드
122126 */
123127 private async initializeWorkspace ( workspaceId : string , doc : Y . Doc ) {
124- // workspaceId에 속한 모든 노드와 엣지를 가져온다.
125- const nodeResponse = await axios . get (
126- `http://backend:3000/api/node/workspace/${ workspaceId } ` ,
127- ) ;
128- const nodes = nodeResponse . data . nodes ;
129-
130- const edgeResponse = await axios . get (
131- `http://backend:3000/api/edge/workspace/${ workspaceId } ` ,
132- ) ;
133-
134- if ( nodeResponse . status === 404 || edgeResponse . status === 404 ) {
135- this . logger . error ( '워크 스페이스가 존재하지 않습니다.' ) ;
136- return ;
137- }
138- const edges = edgeResponse . data . edges ;
128+ try {
129+ // workspaceId에 속한 모든 노드와 엣지를 가져온다.
130+ const [ nodeResponse , edgeResponse ] = await Promise . all ( [
131+ axios . get ( `http://backend:3000/api/node/workspace/${ workspaceId } ` ) ,
132+ axios . get ( `http://backend:3000/api/edge/workspace/${ workspaceId } ` ) ,
133+ ] ) ;
134+
135+ if ( nodeResponse . status === 404 || edgeResponse . status === 404 ) {
136+ throw new Error ( '워크스페이스가 존재하지 않습니다.' ) ;
137+ }
139138
140- const nodesMap = doc . getMap ( 'nodes' ) ;
141- const title = doc . getMap ( 'title' ) ;
142- const emoji = doc . getMap ( 'emoji' ) ;
143- const edgesMap = doc . getMap ( 'edges' ) ;
139+ const nodes = nodeResponse . data . nodes ;
140+ const edges = edgeResponse . data . edges ;
144141
145- this . initializeYNodeMap ( nodes , nodesMap , title , emoji ) ;
146- this . initializeYEdgeMap ( edges , edgesMap ) ;
142+ const nodesMap = doc . getMap ( 'nodes' ) ;
143+ const title = doc . getMap ( 'title' ) ;
144+ const emoji = doc . getMap ( 'emoji' ) ;
145+ const edgesMap = doc . getMap ( 'edges' ) ;
147146
148- // title의 변경 사항을 감지한다.
149- title . observeDeep ( this . observeTitle . bind ( this ) ) ;
147+ this . initializeYNodeMap ( nodes , nodesMap , title , emoji ) ;
148+ this . initializeYEdgeMap ( edges , edgesMap ) ;
150149
151- // emoji의 변경 사항을 감지한다.
152- emoji . observeDeep ( this . observeEmoji . bind ( this ) ) ;
150+ // title의 변경 사항을 감지한다.
151+ title . observeDeep ( this . observeTitle . bind ( this ) ) ;
153152
154- // node의 변경 사항을 감지한다.
155- nodesMap . observe ( ( event ) => {
156- this . observeNodeMap ( event , nodesMap ) ;
157- } ) ;
153+ // emoji의 변경 사항을 감지한다.
154+ emoji . observeDeep ( this . observeEmoji . bind ( this ) ) ;
158155
159- // edge의 변경 사항을 감지한다.
160- edgesMap . observe ( async ( event ) => {
161- this . observeEdgeMap ( event , edgesMap ) ;
162- } ) ;
156+ // node의 변경 사항을 감지한다.
157+ nodesMap . observe ( ( event ) => {
158+ this . observeNodeMap ( event , nodesMap ) ;
159+ } ) ;
160+
161+ // edge의 변경 사항을 감지한다.
162+ edgesMap . observe ( async ( event ) => {
163+ this . observeEdgeMap ( event , edgesMap ) ;
164+ } ) ;
165+ } catch ( error ) {
166+ this . logger . error (
167+ `워크스페이스 초기화 중 오류 발생 (workspaceId: ${ workspaceId } ): ${ error . message } ` ,
168+ ) ;
169+ }
163170 }
164171
165172 /**
@@ -261,48 +268,44 @@ export class YjsService
261268 event : Y . YMapEvent < unknown > ,
262269 nodesMap : Y . Map < unknown > ,
263270 ) {
264- for ( const [ key , change ] of event . changes . keys ) {
265- // TODO: change.action이 'add', 'delete'일 때 처리를 추가하여 REST API 사용 제거
266- // if (change.action === 'add') {
267- // const node = nodesMap.get(key);
268- // const { title, id, emoji } = node.data;
269- // const { x, y } = node.position;
270- // axios.post('http://backend:3000/api/page', {
271- // title,
272- // content,
273- // workspaceId,
274- // x,
275- // y,
276- // emoji,
277- // });
278- // }
279- if ( change . action !== 'update' ) continue ;
280-
281- const node : any = nodesMap . get ( key ) ;
282- if ( node . type !== 'note' ) continue ;
283-
284- const { id, color } = node . data ;
285- const { x, y } = node . position ;
286- const isHolding = node . isHolding ;
287-
288- if ( isHolding ) continue ;
289-
290- const pageResponse = await axios . get (
291- `http://backend:3000/api/page/${ id } ` ,
292- ) ;
293- if ( pageResponse . status === 404 ) {
294- this . logger . error ( '페이지가 존재하지 않습니다.' ) ;
295- return ;
271+ try {
272+ for ( const [ key , change ] of event . changes . keys ) {
273+ if ( change . action !== 'update' ) continue ;
274+
275+ const node : any = nodesMap . get ( key ) ;
276+ if ( node . type !== 'note' ) continue ;
277+
278+ const { id, color } = node . data ;
279+ const { x, y } = node . position ;
280+ const isHolding = node . isHolding ;
281+
282+ if ( isHolding ) continue ;
283+
284+ try {
285+ const pageResponse = await axios . get (
286+ `http://backend:3000/api/page/${ id } ` ,
287+ ) ;
288+
289+ const findPage = pageResponse . data . page ;
290+
291+ await Promise . all ( [
292+ this . redisService . setField ( `node:${ findPage . node . id } ` , 'x' , x ) ,
293+ this . redisService . setField ( `node:${ findPage . node . id } ` , 'y' , y ) ,
294+ this . redisService . setField (
295+ `node:${ findPage . node . id } ` ,
296+ 'color' ,
297+ color ,
298+ ) ,
299+ ] ) ;
300+ } catch ( error ) {
301+ this . logger . error (
302+ `노드 업데이트 중 오류 발생 (nodeId: ${ id } ): ${ error . message } ` ,
303+ ) ;
304+ continue ;
305+ }
296306 }
297- const findPage = pageResponse . data . page ;
298-
299- await this . redisService . setField ( `node:${ findPage . node . id } ` , 'x' , x ) ;
300- await this . redisService . setField ( `node:${ findPage . node . id } ` , 'y' , y ) ;
301- await this . redisService . setField (
302- `node:${ findPage . node . id } ` ,
303- 'color' ,
304- color ,
305- ) ;
307+ } catch ( error ) {
308+ this . logger . error ( `노드맵 관찰 중 오류 발생: ${ error . message } ` ) ;
306309 }
307310 }
308311
@@ -355,14 +358,19 @@ export class YjsService
355358
356359 private async observeEditor ( editorDoc : Y . XmlFragment ) {
357360 const document = editorDoc . doc as CustomDoc ;
358- const pageId = parseInt ( document . name . split ( '-' ) [ 1 ] ) ;
359-
360- this . redisService . setField (
361- `page:${ pageId . toString ( ) } ` ,
362- 'content' ,
363- JSON . stringify ( yXmlFragmentToProsemirrorJSON ( editorDoc ) ) ,
364- ) ;
365- return ;
361+ try {
362+ const pageId = parseInt ( document . name . split ( '-' ) [ 1 ] ) ;
363+
364+ await this . redisService . setField (
365+ `page:${ pageId . toString ( ) } ` ,
366+ 'content' ,
367+ JSON . stringify ( yXmlFragmentToProsemirrorJSON ( editorDoc ) ) ,
368+ ) ;
369+ } catch ( error ) {
370+ this . logger . error (
371+ `에디터 내용 저장 중 오류 발생 (pageId: ${ document ?. name } ): ${ error . message } ` ,
372+ ) ;
373+ }
366374 }
367375
368376 /**
0 commit comments