-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrss.xml
More file actions
458 lines (445 loc) · 101 KB
/
rss.xml
File metadata and controls
458 lines (445 loc) · 101 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[MichaelHur.dev]]></title><description><![CDATA[일상이 우리가 가진 인생의 전부다]]></description><link>https://github.com/michaelhur</link><generator>GatsbyJS</generator><lastBuildDate>Fri, 26 May 2023 06:13:20 GMT</lastBuildDate><item><title><![CDATA[블로그 필터링 기능 구현 고민 후기]]></title><link>https://github.com/michaelhur/react/블로그-필터링-기능-구현-고민-후기/</link><guid isPermaLink="false">https://github.com/michaelhur/react/블로그-필터링-기능-구현-고민-후기/</guid><pubDate>Thu, 11 May 2023 02:06:19 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[about]]></title><description><![CDATA[허준혁 (Michael Hur) 저는 하는 엔지니어입니다. 사용자 경험을 중요시하는 새로운 것에 대한 호기심과 도전의식을 가진 제품에 대한 오너십을 가진 GitHub https://github.com/michaelhur Blog https…]]></description><link>https://github.com/michaelhur/resume-ko/</link><guid isPermaLink="false">https://github.com/michaelhur/resume-ko/</guid><pubDate>Wed, 03 May 2023 13:21:13 GMT</pubDate><content:encoded><h1 id="허준혁-michael-hur" style="position:relative;"><a href="#%ED%97%88%EC%A4%80%ED%98%81-michael-hur" aria-label="허준혁 michael hur permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>허준혁 (Michael Hur)</h1>
<div align="right"><sub><i>Last updated: 2023.05.03</i></sub></div>
<p><strong>저는 <code class="language-text">______</code> 하는 엔지니어입니다.</strong></p>
<ol>
<li>사용자 경험을 중요시하는</li>
<li>새로운 것에 대한 호기심과 도전의식을 가진</li>
<li>제품에 대한 오너십을 가진</li>
</ol>
<table>
<thead>
<tr>
<th align="center"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><strong>GitHub</strong></td>
<td><a href="https://github.com/michaelhur">https://github.com/michaelhur</a></td>
</tr>
<tr>
<td align="center"><strong>Blog</strong></td>
<td><a href="https://michaelhur.github.io">https://michaelhur.github.io</a></td>
</tr>
<tr>
<td align="center"><strong>Contact</strong></td>
<td><a href="mailto:jhhur716@gmail.com">jhhur716@gmail.com</a></td>
</tr>
</tbody>
</table>
<br />
<h1 id="experiences" style="position:relative;"><a href="#experiences" aria-label="experiences permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Experiences</h1>
<h2 id="linkstarter-lab" style="position:relative;"><a href="#linkstarter-lab" aria-label="linkstarter lab permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Linkstarter Lab</h2>
<table>
<thead>
<tr>
<th align="right"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td align="right"><strong>period</strong></td>
<td>21.08 ~ 22.12</td>
</tr>
<tr>
<td align="right"><strong>position</strong></td>
<td>Frontend Engineer</td>
</tr>
<tr>
<td align="right"><strong>projects</strong></td>
<td>프론트엔드 플랫폼</td>
</tr>
<tr>
<td align="right"><em>tech</em></td>
<td>React, TypeScript, react-query, react-hook-form, emotion</td>
</tr>
</tbody>
</table>
<h4 id="frontend-engineering" style="position:relative;"><a href="#frontend-engineering" aria-label="frontend engineering permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Frontend Engineering</h4>
<ul>
<li>플라스크와 템플릿 언어 (Jinja2)기반 MPA에서 React와 Express 기반 SPA로 재개발</li>
<li>이미지 레이지 로딩, 컴포넌트 레이지 초기화를 통한 초기 로딩 성능 90% 개선</li>
<li>CSS Variable을 이용한 커스텀 테마 적용</li>
<li>React Query를 도입하여 비동기 서버 데이터 통신 및 캐싱 전략 수립</li>
</ul>
<div align="center" class="final">
<p><em>감사합니다.</em></p>
<br/>
<p><sub><sup>Front-End Engineer, <a href="https://github.com/michaelhur">@michaelhur</a></sup></sub></p>
</div></content:encoded></item><item><title><![CDATA[about]]></title><description><![CDATA[허준혁 (Michael Hur) 저는 하는 엔지니어입니다. 사용자 경험을 중요시하는 새로운 것에 대한 호기심과 도전의식을 가진 제품에 대한 오너십을 가진 GitHub https://github.com/michaelhur Blog https…]]></description><link>https://github.com/michaelhur/resume-en/</link><guid isPermaLink="false">https://github.com/michaelhur/resume-en/</guid><pubDate>Wed, 03 May 2023 13:21:13 GMT</pubDate><content:encoded><h1 id="허준혁-michael-hur" style="position:relative;"><a href="#%ED%97%88%EC%A4%80%ED%98%81-michael-hur" aria-label="허준혁 michael hur permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>허준혁 (Michael Hur)</h1>
<div align="right"><sub><i>Last updated: 2023.05.03</i></sub></div>
<p><strong>저는 <code class="language-text">______</code> 하는 엔지니어입니다.</strong></p>
<ol>
<li>사용자 경험을 중요시하는</li>
<li>새로운 것에 대한 호기심과 도전의식을 가진</li>
<li>제품에 대한 오너십을 가진</li>
</ol>
<table>
<thead>
<tr>
<th align="center"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td align="center"><strong>GitHub</strong></td>
<td><a href="https://github.com/michaelhur">https://github.com/michaelhur</a></td>
</tr>
<tr>
<td align="center"><strong>Blog</strong></td>
<td><a href="https://michaelhur.github.io">https://michaelhur.github.io</a></td>
</tr>
<tr>
<td align="center"><strong>Contact</strong></td>
<td><a href="mailto:jhhur716@gmail.com">jhhur716@gmail.com</a></td>
</tr>
</tbody>
</table>
<br />
<h1 id="experiences" style="position:relative;"><a href="#experiences" aria-label="experiences permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Experiences</h1>
<h2 id="linkstarter-lab" style="position:relative;"><a href="#linkstarter-lab" aria-label="linkstarter lab permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Linkstarter Lab</h2>
<table>
<thead>
<tr>
<th align="right"></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td align="right"><strong>period</strong></td>
<td>21.08 ~ 22.12</td>
</tr>
<tr>
<td align="right"><strong>position</strong></td>
<td>Frontend Engineer</td>
</tr>
<tr>
<td align="right"><strong>projects</strong></td>
<td>프론트엔드 플랫폼</td>
</tr>
<tr>
<td align="right"><em>tech</em></td>
<td>React, TypeScript, react-query, react-hook-form, emotion</td>
</tr>
</tbody>
</table>
<h4 id="frontend-engineering" style="position:relative;"><a href="#frontend-engineering" aria-label="frontend engineering permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Frontend Engineering</h4>
<ul>
<li>플라스크와 템플릿 언어 (Jinja2)기반 MPA에서 React와 Express 기반 SPA로 재개발</li>
<li>이미지 레이지 로딩, 컴포넌트 레이지 초기화를 통한 초기 로딩 성능 90% 개선</li>
<li>CSS Variable을 이용한 커스텀 테마 적용</li>
<li>React Query를 도입하여 비동기 서버 데이터 통신 및 캐싱 전략 수립</li>
</ul>
<div align="center" class="final">
<p><em>감사합니다.</em></p>
<br/>
<p><sub><sup>Front-End Engineer, <a href="https://github.com/michaelhur">@michaelhur</a></sup></sub></p>
</div></content:encoded></item><item><title><![CDATA[리액트에서 다크모드 적용하기]]></title><link>https://github.com/michaelhur/react/리액트에서-다크모드-적용하기/</link><guid isPermaLink="false">https://github.com/michaelhur/react/리액트에서-다크모드-적용하기/</guid><pubDate>Wed, 01 Feb 2023 14:05:31 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[스타트업 회고 (+ 퇴사 부검)]]></title><description><![CDATA[2022년 12월. 1년 6개월간 시간과 건강을 모두 갈아넣으며 일했었던 스타트업에서 퇴사하게 되었다. 주 6일. 10 to 1…]]></description><link>https://github.com/michaelhur/review/2023-01-12-스타트업-회고/</link><guid isPermaLink="false">https://github.com/michaelhur/review/2023-01-12-스타트업-회고/</guid><pubDate>Thu, 12 Jan 2023 00:01:44 GMT</pubDate><content:encoded><p>2022년 12월. 1년 6개월간 시간과 건강을 모두 갈아넣으며 일했었던 스타트업에서 퇴사하게 되었다. 주 6일. 10 to 10. 많은 시간을 투자한 만큼 배운 것도 아쉬운 것도 많은 회사였다. 막상 재직중일때는 기록을 남기지 못하였다. 퇴사를 하면서 남아있는 미련을 회고록을 통하여 풀어보고자 한다.</p>
<h1 id="why-startup" style="position:relative;"><a href="#why-startup" aria-label="why startup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Why Startup?</h1>
<p>이전에 일했던 곳은 대기업의 Innovation Lab이라는 팀이었다. 사무실 위치도 본사와 2시간 정도 떨어진 곳에 위치하고 있었으며 무엇보다 업무가 본사 직원들과 달랐다. 말 그대로 Innovation을 위한 Lab이었다. 회사가 가지고 있는 데이터를 어떻게 활용할 수 있을지 연구하고 MVP를 만들어서 영업까지 하는 일을 하였다. 영업에 성공하면 본사의 소프트웨어 엔지니어들이 제품을 만드는 프로세스였다.</p>
<p>난 이 과정이 매우 즐거웠다. 말 그대로 “빠르게” 실패할 수 있었기 때문에. 끊어진 동아줄을 끝까지 놓지않으며 몇년이고 성공할때까지 버틴다! 라는 마인드가 아닌 빠르게 만들어서 빠르게 평가받고 빠르게 다음 가설로 넘어갈 수 있었기 때문에 즐거웠다. 그렇기에 매우 많은 프로젝트에 참여하여 데이터 분석가로서 의견을 제시하고 제품이 만들어지는 과정을 지켜볼 수 있었다.</p>
<p>스타트업은 내가 일하였던 Innovation Lab과 비슷한 성격을 띄고있다. 특히나 초기 단계의 스타트업은 아이디어를 빠르게 MVP로 만들어내고 시장의 반응을 바탕으로 변화를 준다는 점에서 적성에 맞다고 생각하였다.</p>
<h1 id="why-here" style="position:relative;"><a href="#why-here" aria-label="why here permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Why Here?</h1>
<p>크게 3가지 이유가 있었다. 핏이 잘 맞을 것 같은 동료들, 초기 단계, 내가 평소에 불편하다고 느꼈던 문제를 해결하고자 하는 스타트업.</p>
<p>2021년 8월. 년차로는 4년차인 회사이지만 투자 단계로 따지면 아직 Pre-A단계인 채용서비스를 만드는 스타트업에 합류하였다. 개발자 4명, 디자이너 1명, 영상 편집자 2명이 있는 팀이였는데 컬쳐핏 인터뷰때 너무 즐겁게 이야기했던 기억이 남아있었다.</p>
<p>주 업무는 ‘데이터 분석’과 ‘추천 시스템 개발’. 팀원들의 이야기를 들어보니 기존까지는 주먹구구식으로 기획하고 개발했다고 했다. 큰 그림만 그려져있는 상황에서 디테일한 부분이나 생각과 다른 반응에는 오직 “감”에만 의존하였다고. 이야기를 듣다보니 부담감이 생겼지만 오히려 기회라고 생각했다. 프로세스가 없는 곳에서 프로세스를 만들어나가는 과정을 경험해볼 수 있기 때문에.</p>
<p>마지막으로 취직을 준비하면서 여러 구인구직 플랫폼을 이용해보았지만 저마다 불편한 점이 있었다. 예를 들면 A 플랫폼은 검색 기능이 문서 전체를 대상으로 하고있어 검색에 어려움을 주었다. 예를 들면 “프론트엔드 개발자”라고 검색하면 “디자이너” 공고가 검색되었는데 공고내에 “팀에 3명의 프론트엔드 개발자가 있습니다.”라는 문구가 존재하여서 검색 결과에 잡히는 것이였다. 특히나 나처럼 “데이터 분석가”로 검색하면 “빅데이터”, “AI”와 같은 단어때문에 거의 모든 공고가 검색 결과로 잡혀버리는 것이다. 또 다른 플랫폼 B의 경우 검색 필터가 세분화되어 있었는데 정형화되어있지 않아서 모든 variation을 추가해야한다는 단점이 있었다. “리액트”, “React”, “react”, “React.js”, “ReactJS”를 모두 추가해야 한개의 결과도 빠짐없이 볼 수 있었다.</p>
<p>이러한 UX적인 불편함들은 서비스가 커졌을때 쉽게 수정하기 힘들다. 뿐만 아니라 대부분의 채용 플랫폼은 채용 공고를 벼룩시장 마냥 리스트 형태로 제공해주고 있었고, 나에게 맞는 공고를 찾기위해서는 위와 같은 <em>불편한</em> 검색 기능을 이용하여 필터링된 결과값을 보아야 했다. 아직 초기 단계의 스타트업이라는 점에서 사용자들의 불편함을 초반부터 인지하고 해소된 상태로 제품을 시장에 내놓을 수 있다는 점에서 매우 끌렸었다.</p>
<h1 id="멀티-플레이어-그리고-직무-전환" style="position:relative;"><a href="#%EB%A9%80%ED%8B%B0-%ED%94%8C%EB%A0%88%EC%9D%B4%EC%96%B4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A7%81%EB%AC%B4-%EC%A0%84%ED%99%98" aria-label="멀티 플레이어 그리고 직무 전환 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>멀티 플레이어, 그리고 직무 전환</h1>
<p>스타트업, 특히나 초기 단계의 스타트업에는 올라운더, 멀티 플레이어가 필요하다는 말을 들어봤을 것이다. 우리 회사 역시 개발자 2명 모두 풀스택에 인프라까지 다 다루고 있었고, 디자이너는 기획 업무까지 담당하고 있었다. 나 역시 데이터가 부족한 초기 단계이다보니 파이썬을 다룰줄 안다는 이유만으로 Flask기반의 백엔드 시스템 유지보수부터 소소한 프로트엔드 작업을 하게 되었다. 이 과정에서 <strong>직접</strong> 프로덕트를 만들 수 있다는 매력에 빠져버렸고 결과물이 눈에 보이는 웹 프론트엔드 개발자로 직무 전환을 고민하였다.</p>
<p>데이터 분석가로 3~4년 정도 경력을 쌓으면서 아쉬운 점이 있었다. 기존에 했던 업무들은 “실험 설계”를 하거나 “실험, 서비스, 프로덕트”의 결과물인 데이터를 분석하는 일이였다. 프로덕션에는 직접 관여할 수 없다는 것이 가장 아쉬웠다. 머리와 꼬리는 경험해보았지만 몸통을 경험하지 못했다고 할까? 그러다보니 자연스럽게 직접 만들어 볼 수 있는, 그것도 결과물이 눈에 보이는 프론트엔드 직무에 자연스럽게 관심이 생겼고, 주말에 따로 리액트를 공부하기 시작하였다. 처음에는 리액트로 시작하였는데 회사 서비스의 프론트엔드가 템플릿 언어인 Jinja에 일부 기능을 Vue로 구현해두어서 Vue로 선회하여 공부하기 시작하였다.</p>
<p>2022년 2월에는 개발자 2명이 떠나게되었고 프론트엔드과 백엔드에서의 역할 비중이 늘어나게 되었다. 어쩌다보니 너무나도 자연스럽게 직무 전환이 이루어지게 되었다.</p>
<h1 id="중간-결산" style="position:relative;"><a href="#%EC%A4%91%EA%B0%84-%EA%B2%B0%EC%82%B0" aria-label="중간 결산 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>중간 결산</h1>
<p>서비스를 론칭한지 5개월만에 1000명의 구직자와 300개의 기업을 유치하는데 성공하였다. 가파른 성장에 투자 심사역과의 미팅이 여러번 있었다. 심지어 유튜브에서 왕성하게 활동하는 투자사 대표님들 몇 분과도 미팅이 있었고 2개의 투자사와는 투자 유치 직전 단계까지 갔었다.</p>
<p>결론적으로는 실패. 여러가지 이유가 있었지만 가장 큰 이유는 회사의 재정적 문제때문이였다. 서비스는 초기 단계였지만 4년차인 회사로서 재정상태가 좋지 않았기에 투자 유치를 하더라도 <em>마이너스</em>가 유지되었다. 투자사 입장에서는 <strong>밑 빠진 독에 물 붓기</strong>였기에 마지막 단계에서 발을 뺐었다. 뼈아픈 경험이였지만 서비스의 매력은 확인할 수 있었기에 희망을 가지고 더 열심히 달리기로 했었다.</p>
<h1 id="흔들리는-배" style="position:relative;"><a href="#%ED%9D%94%EB%93%A4%EB%A6%AC%EB%8A%94-%EB%B0%B0" aria-label="흔들리는 배 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>흔들리는 배</h1>
<p>고맙게도 많은 투자 심사역과 스타트업 대표님들께서 피드백을 주었다. 피드백을 받을 수 있다는 것은 매우 좋은 일이다. 특히나 사용자 관점에서의 피드백 모두 제품을 만드는 팀으로서 방향성을 찾을 수 있도록 도와준다. 사용자들은 피드백을 잘 남기지 않는다. “작동하지 않네? 버그 리포트 남기자”가 아니라 “작동하지 않네? 대체품 써야지”가 되어버린다.</p>
<p>많은 피드백을 받았을때 우리 팀은 옳바른 결정을 하지 못하였다. <strong>“정답”</strong>을 찾지 못하였다고 자책하는 것이 아니다. 100명 사용자에게서 100개의 다른 의견이 나올 수 있다. 때로는 같은 의견일 수도 있지만 때로는 상반되는 내용이 남겨져있기도 하다. 우리는 <strong>‘가장 자주 언급되는 의견’</strong>또는 <strong>‘우리가 생각해보지도 못했던 시선’</strong>에 대해서 생각해보기 보다는 막무가내로 100가지 모두 시도해보았다.</p>
<p>구인구직 플랫폼이라는 큰 틀안에서 2주에 한번씩 비지니스 모델을 바꾸어 적용하였고 이는 더 큰 이탈로 이어졌다. 우리가 시도했던 모델중 하나가 <strong>정답</strong>이었을 수도 있지만 우리의 가설을 확인해보기도 전에 거의 모든 사용자가 이탈을 해버린 것이다.</p>
<p>2022년 2월부터 6월까지 20번 정도 비지니스 모델를 변경하고 서비스에 적용하였다. 잦은 변경으로 인하여 리텐션이 0에 수렴하는 상황이였다. 가입자는 계속해서 늘어났지만 가입후 재접속하는 일이 없었다. 이렇게 기획이 바뀌면서 사용자들이 입력하는 데이터가 달랐던 점 때문에 실제로 노출되는 구직자와 기업 숫자는 처참했으며, 기존 사용자들은 구성이 변경될때마다 정보 업데이트를 할 이유가 없었기에 이탈로 이어졌다. 2022년 6월 기준으로 약 30명의 구직자와 10개의 기업만이 최신 버전의 서비스에 맞는 데이터를 입력한 상황이었고 나머지 2500명의 구직자와 800개의 기업은 유령 데이터가 되어버린 것.</p>
<p>아마 이 시점에서 사용자와 제작자 모두 실증을 느끼지 않았을까 싶다. 실제로 “왜 자꾸 바뀌나요?” “OO 메뉴 어디로 갔나요?” 등의 피드백만 하루 10번씩 받았었다. 개발을 하는 입장에서도 지치게 되었다. 아무리 열심히 개발을 해도 2주후에는 다른 것을 만들고 있을게 확실시 되어버리니 의욕이 생기지 않았던 것.</p>
<h1 id="리뉴얼-마지막-한방" style="position:relative;"><a href="#%EB%A6%AC%EB%89%B4%EC%96%BC-%EB%A7%88%EC%A7%80%EB%A7%89-%ED%95%9C%EB%B0%A9" aria-label="리뉴얼 마지막 한방 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>리뉴얼: 마지막 한방…?</h1>
<p>6월 중순. 대표님께서 “마지막 한방”을 시도해보고 사업을 접자고 “최후 통첩”을 하셨다. 2주 정도 회의하면서 한가지 모델을 정해서 디자인을 포함하여 마지막 리뉴얼을 해보고 반응을 보자고 하셨다. 그렇게 6월은 회의만 하면서 거의 모든 구인구직 비지니스 모델에 대해서 토론했었다.</p>
<p>6월 말일에 특정 모델을 정하였고 모든걸 0에서부터 다시 만들기 시작했다. 이는 우리가 정했던 모델이 기존 모델과 다른 결이였던 헤드헌팅 모델이였기에 가능했다. 기존 유저들의 데이터를 그대로 활용할 수 있으며 가입한 시점에 따라 다른 데이터가 입력되어있지만 운영으로 커버할 수 있다는 마인드였다.</p>
<p>그렇게 7월내내 리뉴얼 작업을 하고 8월 18일에 오픈을 하였지만 반응은 처참했다. 피드백의 대부분은 “얼마 못가서 또 바꿀건데 우리가 왜 등록해요?”였다. 여러번의 서비스 리뉴얼에도 계속해서 이용해주던 사용자들의 반응이였기에 더 충격적이였다.</p>
<h1 id="퇴사" style="position:relative;"><a href="#%ED%87%B4%EC%82%AC" aria-label="퇴사 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>퇴사</h1>
<p>회사에서는 채용이 아닌 아예 다른 시장에 뛰어들기로 하였고 기획, 디자인 등을 준비중이었다. 회사와 함께하여 새로운 시장에 도전을 해봐야 하는걸까 아니면 이직을 해야하는 것일까 오랫동안 고민한 결과 퇴사를 결정하게 되었다.</p>
<h2 id="왜-떠나는지" style="position:relative;"><a href="#%EC%99%9C-%EB%96%A0%EB%82%98%EB%8A%94%EC%A7%80" aria-label="왜 떠나는지 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>왜 떠나는지?</h2>
<h3 id="임금체불" style="position:relative;"><a href="#%EC%9E%84%EA%B8%88%EC%B2%B4%EB%B6%88" aria-label="임금체불 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>임금체불</h3>
<p>근본적인 이유는 임금체불때문이였다. 조짐은 6월부터 있었다. 6~8월 월급이 보름 정도 늦게 입금되었다. ‘그래도 받았으니 됐어’라는 마인드로 크게 신경쓰지 않았는데, 9월부터 아예 월급이 나오지 않았다. 10월 월급마저 체불된 순간 떠나기로 마음먹었었다.</p>
<p>2개월치 월급이 체납되다보니 생활하는데도 문제가 생겼다. 아무리 오전 8시에 집에서 나와서 밤 10시에 집에 들어간다고 하더라도 한달에 고정적으로 소비되는 비용이 존재했다. 전세대출 금리마저 급격하게 올라서 매달 50만원 가량 내던 이자는 180만원까지 올라버렸다. 교통비와 식비까지 포함하면 남는게 별로 없었는데 임금체불까지 되니 대출을 받아서 생활하는 지경에 이르었다. 생존에 영향을 받는 상황이 생기니 업무에 온전히 집중할 수 없었다.</p>
<h3 id="직무-전문성" style="position:relative;"><a href="#%EC%A7%81%EB%AC%B4-%EC%A0%84%EB%AC%B8%EC%84%B1" aria-label="직무 전문성 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>직무 전문성</h3>
<h4 id="오래된-기술-스택과-사수의-부재" style="position:relative;"><a href="#%EC%98%A4%EB%9E%98%EB%90%9C-%EA%B8%B0%EC%88%A0-%EC%8A%A4%ED%83%9D%EA%B3%BC-%EC%82%AC%EC%88%98%EC%9D%98-%EB%B6%80%EC%9E%AC" aria-label="오래된 기술 스택과 사수의 부재 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>오래된 기술 스택과 사수의 부재</h4>
<p>웹 개발에 대해서 공부하다보니 현재 시스템의 문제점이 눈에 띄기 시작했었다. 8월 리뉴얼 작업때 백엔드와 프론트엔드를 새로 만들었으나 그 전까지는 매우 올드한 시스템에서 구동되고 있었다.</p>
<p>Flask기반의 백엔드 서버였지만 실상은 라우터 기능만을 이용하고 있었고, 하드코딩으로 각 페이지마다 필요한 데이터를 불러와서 해당 페이지에 맞는 HTML에 그려서 보내주고 있었다. 그렇기에 각 페이지를 이동할때마다 20mb 가까이 되는 정적 데이터가 다운로드 되고 있었고 이는 UX적으로도, 유지보수적인 관점으로도 매우 비효율적이였다.</p>
<p>리뉴얼 과정에서 프론트엔드 작업을 담당하였었는데 사수가 없으니 ‘내가 옳바르게 하고 있는가’에 대한 의문이 계속해서 생겼었다. 피드백과 조언을 받을 수 있는 다른 프론트엔드 개발자가 없는 곳에서 더 효율적으로 성장할 수 없다는 판단이 들었다.</p>
<h4 id="주류와-떨어진-기술-스택" style="position:relative;"><a href="#%EC%A3%BC%EB%A5%98%EC%99%80-%EB%96%A8%EC%96%B4%EC%A7%84-%EA%B8%B0%EC%88%A0-%EC%8A%A4%ED%83%9D" aria-label="주류와 떨어진 기술 스택 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>주류와 떨어진 기술 스택</h4>
<p>‘Vue를 왜 사용하나요? React 써요’, ‘장고? 익스프레스? 그래도 자바 스프링으로 해야죠’의 문제가 아니였다. 어느 순간 대표님은 ‘웹빌더’에 흠뻑 빠지셨고 리뉴얼 작업이 끝난 시점에서 모든 것을 웹빌더로 다시 만들 것을 요구하셨다.</p>
<p>웹빌더는 좋은 툴이다. 문제는 한계점이 명확하다는 것이다. 해당 솔루션이 제공해주지 않는 기능은 구현할 수가 없다. 예를 들면 서비스에는 결제 시스템이 붙어야 했는데 사용하라고 하는 웹빌더는 한국의 결제시스템을 붙이지 못한다. 페이팔만 이용 가능하였고 그럼 환전 수수료 등때문에 구매자와 판매자 모두 추가적인 비용이 들 수 밖에 없었다. 그렇다고 한국 회사에서 만든 웹빌더인 카O24, 아O웹 등을 이용하고자고 제안해보니 ‘써봤는데 별로’라는 없다는 이유로 반려되었다.</p>
<p>초기 단계 스타트업이 MVP를 만들어서 시장의 평가를 받기 위해서 웹빌더를 사용하는 것은 좋다고 생각하지만, 이미 개발팀이 구축되어있는 회사에서 구축되어있는 서비스를 웹빌더로 다시 만들어야하는 이유를 찾지 못했다.</p>
<p>개발자들에게 계속하여 ‘웹빌더 전문가’가 되라고 설득하셨는데 여기서 더이상 웹 프로그래머로서 성장하기 힘들다고 느꼈다. 3년후에 회사가 없어지거나, 유니콘이 되거나, 아무튼 모종의 이유로 이직한다고 했을때 ’<strong>카페 24로만 웹사이트 만들어본 사람</strong>이 웹 프로그래머로서 경쟁력이 있을까?’ 라는 생각을 해보았을때 답은 ‘아니오’였다.</p>
<h4 id="방향성을-잃은-기획" style="position:relative;"><a href="#%EB%B0%A9%ED%96%A5%EC%84%B1%EC%9D%84-%EC%9E%83%EC%9D%80-%EA%B8%B0%ED%9A%8D" aria-label="방향성을 잃은 기획 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>방향성을 잃은 기획</h4>
<p>리뉴얼이 끝났음에도 불구하고 다시 ‘기획 회의’ 지옥에 빠졌었다. 리뉴얼 후 가입자 수, 리텐션 수 모두 0에 수렴하였고 대표님이 내린 결론은 <strong>‘그냥 하던것을 하자’</strong> 였다. 이유는 ‘우리가 제일 잘 알고있는 분야’이며 ‘Air BNB도 수백번 기획을 바꾸고 나서 성공했으니 우리도 수백번 바꿔보자’였다.</p>
<p>핀트를 잘못 잡으신 것 같다는 생각이 들었다. 에어비앤비는 ‘그럼에도 불구하고’ 성공했던 것인데 대표님은 ‘수백번 바꿨다’에 꽂히셨고 수백번 바꿔보자 라고 하셨다. 문제는 이 것도 ‘자금’이 있어야 가능한 일이다. 임금체불인 상황에서 어떻게 버텨야할지 감이 생기지않았다.</p>
<h2 id="회사에서-배운-것" style="position:relative;"><a href="#%ED%9A%8C%EC%82%AC%EC%97%90%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EA%B2%83" aria-label="회사에서 배운 것 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>회사에서 배운 것</h2>
<h3 id="대기업과-스타트업의-차이" style="position:relative;"><a href="#%EB%8C%80%EA%B8%B0%EC%97%85%EA%B3%BC-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85%EC%9D%98-%EC%B0%A8%EC%9D%B4" aria-label="대기업과 스타트업의 차이 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>대기업과 스타트업의 차이</h3>
<p>대기업의 신사업팀과 스타트업의 차이점이라고 봐야할까? 전자는 실패하더라도 뒤가 있지만 후자는 없다. 서비스가 출시된 상태에서 구성이 자주 변하게 되면 유저들은 정착하지 못하고 떠나게된다. 대기업 신사업 팀은 다른 사업을 하면 된다. 그 만큼의 리소스가 존재하기 때문에. 하지만 스타트업은 생존과 연관되어있다.</p>
<p>그 동안 나는 <em>책임을 질 것이 적은</em> 위치에서 비슷한 일을 하고 있었다. <em>스타트업</em> 자체에 흥미를 잃은 것은 아니다. 만약 회사가 4,5년차가 아닌 1,2년차 회사였다면 오히려 시행착오가 적었을 것이라고 생각한다. 투자 유치에 실패한 것도 결국 오래된 연차에서 비롯된 자본 잠식이 원인이였으니깐.</p>
<p>회사에서 책임감뿐만 아니라 공동 창업가, 초기 멤버로서의 책임감과 의무감을 배울 수 있었다. 다음 회사도 초기 스타트업을 위주로 지원해볼 생각이다.</p>
<h3 id="사업적-마인드" style="position:relative;"><a href="#%EC%82%AC%EC%97%85%EC%A0%81-%EB%A7%88%EC%9D%B8%EB%93%9C" aria-label="사업적 마인드 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>사업적 마인드</h3>
<p><em>투자자</em>가 원하는 것과 <em>사용자</em>가 원하는 것은 다를 수 있다. 투자자가 이 서비스가 잘 되길 바라는 이유는 돈을 벌기 위해서다. 투자금 이상을 회수하기 위해서 철저하게 ‘돈을 잘 벌 수 있는 방향’을 제시한다.</p>
<p>이 피드백은 사용자가 원하는 것과 일치하지 않을때가 많다. 사용자는 대체제가 존재한다면 금방 갈아탄다. 아니, 여러개의 비슷한 서비스를 이용하면서 자신이 필요한 것을 찾아서 얻어낸다. 그렇기에 대체제가 존재한다면 쉽게 버려질 수 있다.</p>
<p>회사의 목표 역시 <strong>‘돈을 버는 것’</strong>이다. 그렇다고 해서 같은 목표를 가진 투자자의 피드백을 100% 신뢰해서도 안된다. 회사는 사용자의 만족도 역시 고려하면서 밸런스를 맞춰야 한다고 생각한다. 사용자의 만족도만 생각했다가는 영영 매출을 못 올릴 수도 있다. 누가 “공짜”를 마다하겠는가?</p>
<p>이는 사용자 그룹이 2개로 나뉠때 더 어려워진다. 우리 회사의 서비스는 구직자와 기업 모두 만족시켜야 했는데 우리는 ‘투자자’와 ‘기업’의 피드백만 듣고 서비스를 개선했을뿐 막상 구직자의 피드백을 들어보지 못했다. 이 점이 제일 후회된다.</p>
<p>얼마전 서비스 UI 리뉴얼을 하였던 ‘블라인드’ 앱을 보면서 또 한번 느꼈다. 유료 고객인 기업이 불편할 수 있는 ‘회사 리뷰’ 서비스 등은 뒤로 숨기고 채용 공고, 광고가 페이지 이곳 저곳에 위치하게 되었다. 돈을 내는 사용자 그룹만 생각해서 만든 변화라고 생각한다. 정확한 데이터는 가지고 있지 않지만, 블라인드 채널의 글 리젠율이 눈에 띄게 줄었다는 것은 누구나 알 수 이는 사실이다</p>
<h2 id="회사에-아쉬운-점" style="position:relative;"><a href="#%ED%9A%8C%EC%82%AC%EC%97%90-%EC%95%84%EC%89%AC%EC%9A%B4-%EC%A0%90" aria-label="회사에 아쉬운 점 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>회사에 아쉬운 점</h2>
<p>재정적으로 어려웠다는게 아쉽다. 내가 어떻게 할 수 있는 부분이 아니니 더 그랬다.</p>
<p>문화가 별로였다면 개선하기 위해 무언가를 도입해볼 수도, 의견을 제시해볼 수도 있었을 것이다. 서비스의 방향성의 경우 기획 회의때 의견을 자유롭게 제시할 수 있었기에 큰 불만은 없었다.</p>
<p>하지만 재정적으로 힘들다보니 모든 것이 흔들려버렸다. 재정적으로 어려운 상황이 아니였다면 이 회사에서 계속해서 일했을 것이다. 같이 일하는 동료들도 좋았고 ‘기획 회의 지옥’에 빠지게 된 순간도 회사에 돈이 떨어진 시점이였으니깐. 재정적으로 힘들다보니 <strong>뭐라도 하나 걸려라</strong> 라는 생각이 앞선 상태로 계속해서 변경했었다.</p>
<p>그렇다보니 제일 아쉬운 점은 ‘우리가 3년만 일찍 만났다’면 이다.</p>
<p>직무적으로는 좋은 시니어를 만나지 못한 것이 아쉽다. 다른 개발자 모두 최소 7년차였는데 그들이 작성한 코드를 보는 것 이외에는 많은 도움을 받지 못했다. 일에 치여서 시간이 부족했던 것도 있겠지만 도움을 요청해도 기존 코드에서 찾아보라는 대답 정도였다.</p>
<h2 id="앞으로의-게획" style="position:relative;"><a href="#%EC%95%9E%EC%9C%BC%EB%A1%9C%EC%9D%98-%EA%B2%8C%ED%9A%8D" aria-label="앞으로의 게획 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>앞으로의 게획</h2>
<p>2주 정도 개발과는 동 떨어진 삶을 살았다. 매일 1시간 정도 산책로를 걸으며 운동하고 있고, 낮에는 카페에 가서 사람 구경도 한다. 밀렸던 넷플릭스 시리즈도 시청하면서 머리를 식혔다..</p>
<p>2023년이 되고 다시 공부를 시작하였다. 현업에서 경험하면서 배우는 것이 더 빠르게 배운다고 생각하지만, 업무를 하면서 직무 전환한 케이스여서 기초가 부족함을 뼈저리게 느꼈다. 요즘은 자바스크립트와 리액트 공부를 하고있다. 프로젝트를 만들면서 자연스럽게 사용하던 개념들을 왜 이렇게 써야하는건지, 다른 방법은 없는 것인지 고민하고 정리하고 있다.</p>
<p>앞서 서술하였지만 시드~시리즈A 단계 스타트업의 프론트엔드 개발자로 취직하려고 준비중이다. 내가 빨대 꽂고 뽑아먹을 수 있는 시니어 개발자가 있었으면 좋겠다.</p></content:encoded></item><item><title><![CDATA[서비스 리액트 전환기]]></title><description><![CDATA[이번 포스팅에서는 기존 링크스타터 서비스를 React로 전환하게 된 이유, 전환 과정에서 어려웠던 점과 이를 해결해나간 과정들을 소개하고자 합니다. 서비스 리라이팅 계기 2022년…]]></description><link>https://github.com/michaelhur/react/2022-10-04-서비스-리액트-전환기/</link><guid isPermaLink="false">https://github.com/michaelhur/react/2022-10-04-서비스-리액트-전환기/</guid><pubDate>Tue, 04 Oct 2022 13:14:07 GMT</pubDate><content:encoded><p>이번 포스팅에서는 기존 링크스타터 서비스를 React로 전환하게 된 이유, 전환 과정에서 어려웠던 점과 이를 해결해나간 과정들을 소개하고자 합니다.</p>
<h2 id="서비스-리라이팅-계기" style="position:relative;"><a href="#%EC%84%9C%EB%B9%84%EC%8A%A4-%EB%A6%AC%EB%9D%BC%EC%9D%B4%ED%8C%85-%EA%B3%84%EA%B8%B0" aria-label="서비스 리라이팅 계기 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>서비스 리라이팅 계기</h2>
<p>2022년 7월. 링크스타터 개발팀은 서비스를 다시 구현하기로 하였습니다. 비즈니스 모델 변경으로 인한 서비스 리뉴얼과 더불어 UI/UX 디자인 개편이 예정되어 있었고, 이에 맞춰서 DB 설계와 서버 및 클라이언트 개발까지 새롭게 진행하기로 하였습니다. 기존의 시스템을 버리고 모든 것을 처음부터 새로 만드는 일이었습니다.</p>
<h2 id="리라이팅-계기" style="position:relative;"><a href="#%EB%A6%AC%EB%9D%BC%EC%9D%B4%ED%8C%85-%EA%B3%84%EA%B8%B0" aria-label="리라이팅 계기 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>리라이팅 계기</h2>
<h3 id="이게-무엇을-하는-코드인가요" style="position:relative;"><a href="#%EC%9D%B4%EA%B2%8C-%EB%AC%B4%EC%97%87%EC%9D%84-%ED%95%98%EB%8A%94-%EC%BD%94%EB%93%9C%EC%9D%B8%EA%B0%80%EC%9A%94" aria-label="이게 무엇을 하는 코드인가요 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>이게 무엇을 하는 코드인가요?</h3>
<p>웹 개발자로서 일한 6개월 동안 홈페이지의 여러 가지 기능을 추가하고 개선하면서 변화가 필요하다고 생각했습니다. 단순히 ‘다른 사람이 작성한 코드가 별로다.’에서 파생된 결정은 아니었습니다. 알파 서비스를 런칭했던 2020년 9월부터 리뉴얼이 결정된 2022년 7월까지 약 30번가량 비즈니스 모델이 변경되었고 이에 <code class="language-text">지금은 사용되고 있지 않지만, 미래에 사용할지도 모르는</code>코드가 많았고, 많은 외주업체의 손을 거쳐 간 서비스이니만큼 여러 가지 스타일이 뒤섞여져 있는 상황에 문서화 또한 되어있지 않은 상황이었습니다. 새로 합류한 개발자가 코드를 보고 이해하는 데 오랜 시간이 걸렸습니다. 정식 서비스를 론칭하기전 이러한 불필요한 코드를 과감하게 쳐내야 했습니다.</p>
<h3 id="허울뿐인-프레임워크" style="position:relative;"><a href="#%ED%97%88%EC%9A%B8%EB%BF%90%EC%9D%B8-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC" aria-label="허울뿐인 프레임워크 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>허울뿐인 프레임워크</h3>
<p>서비스의 백엔드는 Flask를 이용하여 구현되어 있었고, 프론트엔드는 Flask의 템플릿 언어인 Jinja2가 사용되고 있었습니다. 하지만 서비스는 이러한 프레임워크를 사용하는데서 오는 이점을 전혀 살리지 못하고 있었습니다.</p>
<p>Flask의 라우팅 기능을 제외한 다른 기능은 사용되고 있지 않았으며, 관심사가 분리되어 있지 않고 모든 코드를 한 곳에 작성하여 가독성뿐만 아니라 유지보수에도 어려움을 주고 있었습니다.</p>
<div class="gatsby-highlight" data-language="python"><pre class="language-python"><code class="language-python"><span class="token comment">## 기업이 공고 상세페이지 열람할때</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">'/companies/jobs/&lt;job_id>'</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">company_job_detail_view</span><span class="token punctuation">(</span>job_id<span class="token punctuation">)</span><span class="token punctuation">:</span>
sql1 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""공고 상세페이지 데이터를 불러오는 SQL쿼리"""</span>
sql2 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""기업 정보를 불러오는 SQL쿼리"""</span>
sql3 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""해당 공고 북마크 내역을 불러오는 SQL쿼리"""</span>
sql4 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""해당 공고 지원 내역을 불러오는 SQL쿼리"""</span>
data1 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql1<span class="token punctuation">)</span>
data2 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql2<span class="token punctuation">)</span>
data3 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql3<span class="token punctuation">)</span>
data4 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql4<span class="token punctuation">)</span>
<span class="token triple-quoted-string string">"""
데이터 가공하는 코드
"""</span>
<span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'company_job_detail.html'</span><span class="token punctuation">,</span> manipulated_data<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token comment">## 개인이 공고 상세페이지 열람할때</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">'/people/jobs/&lt;job_id>'</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">company_job_detail_view</span><span class="token punctuation">(</span>job_id<span class="token punctuation">)</span><span class="token punctuation">:</span>
sql1 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""공고 상세페이지 데이터를 불러오는 SQL쿼리"""</span>
sql2 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""기업 정보를 불러오는 SQL쿼리"""</span>
sql3 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""해당 공고 북마크 내역을 불러오는 SQL쿼리"""</span>
sql4 <span class="token operator">=</span> <span class="token triple-quoted-string string">"""해당 공고 지원 내역을 불러오는 SQL쿼리"""</span>
data1 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql1<span class="token punctuation">)</span>
data2 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql2<span class="token punctuation">)</span>
data3 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql3<span class="token punctuation">)</span>
data4 <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql4<span class="token punctuation">)</span>
<span class="token triple-quoted-string string">"""
데이터 가공하는 코드
"""</span>
<span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'person_job_detail.html'</span><span class="token punctuation">,</span> manipulated_data<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token comment">## 구직자 상세페이지</span>
<span class="token decorator annotation punctuation">@app<span class="token punctuation">.</span>route</span><span class="token punctuation">(</span><span class="token string">'/people/&lt;person_id>'</span><span class="token punctuation">)</span>
<span class="token keyword">def</span> <span class="token function">person_detail_view</span><span class="token punctuation">(</span>person_id<span class="token punctuation">)</span><span class="token punctuation">:</span>
sql <span class="token operator">=</span> <span class="token triple-quoted-string string">"""구직자 상세페이지 데이터를 불러오는 SQL쿼리"""</span>
data <span class="token operator">=</span> pysql<span class="token punctuation">.</span>execute<span class="token punctuation">(</span>sql<span class="token punctuation">)</span>
<span class="token triple-quoted-string string">"""
데이터 가공하는 코드
"""</span>
<span class="token keyword">return</span> render_template<span class="token punctuation">(</span><span class="token string">'person_person_detail.html'</span><span class="token punctuation">,</span> manipulated_data<span class="token punctuation">)</span></code></pre></div>
<p>위에 예시 코드와 같이 링크스타터 시스템이 가지고 있던 문제점은 아래와 같습니다.</p>
<ol>
<li>한개의 페이지에서 실행되는 모든 작업을 하나의 함수에서 처리하고 있었습니다.</li>
<li>SQL 쿼리는 JOIN문을 사용하지 않고 불러온 후 메모리에 올려놓고 가공하여 사용하고 있었습니다.</li>
<li>주제별로 구분하지 않고 모든 코드를 하나의 파일에 저장하여 사용하고 있었습니다.</li>
<li>코드의 재사용 없이 같은 작업을 하는 코드를 반복하여 작성하고 있었습니다.</li>
</ol>
<p>이런 ‘하드코딩’은 프론트엔드에서 역시 마찬가지였습니다. 기업이 자신의 공고를 열람할 때 보이는 화면과 구직자가 기업의 공고를 열람할 때 보이는 화면은 다른 점이 존재합니다. 링크스타터는 각각 <code class="language-text">self_job_detail.html</code>, <code class="language-text">person_job_detail.html</code>과 같이 직관적이지 않은 네이밍 컨벤션을 적용하여 관리하고 있었고, 공통된 부분을 재사용하기보다는 하드 코딩하여 사용하고 있었습니다. 만약 ‘공고 상세 페이지’의 디자인이 변경된다면 여러개의 파일을 수정해야 했습니다. 이렇게 관리되고 있는 html파일은 약 400개가 넘어갔고 더 이상 효과적인 유지보수가 불가능할 지경에 이르렀습니다.</p>
<h3 id="배포의-어려움" style="position:relative;"><a href="#%EB%B0%B0%ED%8F%AC%EC%9D%98-%EC%96%B4%EB%A0%A4%EC%9B%80" aria-label="배포의 어려움 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>배포의 어려움</h3>
<p>프론트엔드와 백엔드가 분리되어 있지 않은 서비스의 단점은 배포입니다. 사내 프론트엔드 개발자가 UI를 수정하면 시스템 전체를 다시 배포하는 과정을 거쳐야합니다. 너무 비대해진 서비스를 배포하는 데 15분가량 소요되었기에 ‘버튼을 오른쪽으로 1px만 옮겨주세요’라는 요청도 매우 부담스러운 상황이 되었습니다.</p>
<h3 id="과도하게-느린-속도와-서버-비용" style="position:relative;"><a href="#%EA%B3%BC%EB%8F%84%ED%95%98%EA%B2%8C-%EB%8A%90%EB%A6%B0-%EC%86%8D%EB%8F%84%EC%99%80-%EC%84%9C%EB%B2%84-%EB%B9%84%EC%9A%A9" aria-label="과도하게 느린 속도와 서버 비용 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>과도하게 느린 속도와 서버 비용</h3>
<p>동시 접속 사용자가 50명 미만, <code class="language-text">MAU가 3,000명</code> 정도인 서비스의 서버 비용은 약 150만 원이 청구되고 있었습니다. 페이지별 로딩 속도는 평균 9초에 육박하였습니다. 페이지가 리프레시되거나 클라이언트 상에서 데이터를 업데이트하였을 때 변경된 데이터가 적용된 화면을 보기 위해서 모든 static 파일을 다시 다운로드하는 과정을 거쳤습니다. 이에 페이지별로 평균 20mb의 데이터를 다운로드 받기 시작하였고, 한 사람이 몇 번의 클릭만으로 엄청난 서버 비용을 청구하는 상황이 되었습니다.</p>
<h3 id="채용의-어려움" style="position:relative;"><a href="#%EC%B1%84%EC%9A%A9%EC%9D%98-%EC%96%B4%EB%A0%A4%EC%9B%80" aria-label="채용의 어려움 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>채용의 어려움</h3>
<p>Jinja2와 같은 비주류 스킬 스택의 단점은 채용이 어렵다는 점에 있습니다. 대부분의 개발자는 Jinja2라는 템플릿 언어가 존재한다는 것을 모르고 있었고, 팀에 합류하여 작업을 하다가 단기간에 퇴사하기도 하였습니다. Vue나 Angular와 같은 프레임워크였다면 프레임워크 사용법이 다를 뿐 큰 그림에서 접근법은 비슷하였지만, Jinja2와 같은 템플릿언어는 HTML을 직접 하드 코딩한다는 점에서 거부감이 심했던 것으로 판단됩니다.</p>
<h2 id="리액트를-선택한-이유" style="position:relative;"><a href="#%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%A5%BC-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0" aria-label="리액트를 선택한 이유 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>리액트를 선택한 이유</h2>
<p>리액트는 프론트엔드 영역에서 가장 인기 있는 프레임워크입니다. 가장 많은 수요가 있는 프레임워크로서 채용이 비교적 수월할 뿐만 아니라 가장 많은 레퍼런스가 존재한다는 점에서 작업 시 이점이 가장 크다고 생각했습니다. 또한 기존 프론트엔드 개발자들 역시 모두 리액트를 사용할 수 있었다는 점에서 가장 좋은 선택이라고 생각했습니다.</p>
<h3 id="nextjs를-사용하지-않은-이유" style="position:relative;"><a href="#nextjs%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%9D%B4%EC%9C%A0" aria-label="nextjs를 사용하지 않은 이유 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Next.js를 사용하지 않은 이유</h3>
<p>Next.js 역시 인기 있는 프레임워크입니다. 리액트를 기반으로 만들어진 프레임워크로서 리액트를 알고 있다면 러닝 커브도 높지 않고 빠르게 적용할 수 있다는 장점이 있습니다. 리액트와 Next.js 사이에서 많이 고민하였습니다.</p>
<p>비즈니스 모델의 구조상 <strong><em>SEO가 중요하지 않았습니다.</em></strong> 링크스타터는 폐쇄형으로서 양방향 <code class="language-text">헤드헌팅</code> 모델입니다. 구직자는 이력서를, 기업은 공고를 등록하면 링크스타터의 운영팀이 확인 후 추천해 주는 모델입니다. 그렇기에 ‘구직자 이력서’ 또는 ‘기업 공고’ 링크가 존재해야지만 접속할 수 있었기에 외부에 노출이 되지 않는 사이트의 특성상 SEO를 신경 쓸 이유가 없었습니다.</p>
<p>또한 모든 프론트엔드 개발자가 Next.js로 실무 경험이 없었다는 점에서 리라이팅 기간이 1달밖에 주어지지 않았던 프론트엔드 개발자들은 리액트로 개발하기로 하였습니다.</p>
<h2 id="개발-과정에서의-고민" style="position:relative;"><a href="#%EA%B0%9C%EB%B0%9C-%EA%B3%BC%EC%A0%95%EC%97%90%EC%84%9C%EC%9D%98-%EA%B3%A0%EB%AF%BC" aria-label="개발 과정에서의 고민 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>개발 과정에서의 고민</h2>
<p>기존의 서비스를 점진적으로 변경하는 작업이었다면 매우 어려운 일이 되었을 것입니다. 다행히도 비즈니스 모델의 변경에 따른 서비스 리뉴얼과 UI/UX 디자인 변경이 겹치면서 백지에 새로운 그림을 그리는 작업을 하게 되었습니다.</p>
<p>리라이팅에 착수하기 전 이미 새로운 디자인 시안을 전달받았기에 좀 더 큰 그림을 그려가며 작업할 수 있었습니다. 순차적으로 전달받았다면 만들었던 컴포넌트를 새로운 디자인에 맞게 수정하는 작업을 했을 수도 있지만 모든 디자인을 한 번에 전달받았기에 컴포넌트 단위로 UI 작업을 한 후 페이지별 작업을 하는 Bottom-Up 방식으로 접근하였습니다.</p>
<h3 id="테스트-코드" style="position:relative;"><a href="#%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C" aria-label="테스트 코드 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>테스트 코드</h3>
<p>프론트엔드를 리라이팅하면서 테스트 코드에 대한 고민을 많이 하였습니다. 테스트 코드가 꼼꼼하게 작성된 경우 새로운 기능을 추가하거나 수정할 때 이에 대한 검증을 빠르게 할 수 있다는 장점이 있습니다. 하지만 UI 변경이 잦은 프론트엔드의 경우 테스트 코드는 말 그대로 ‘테스트를 위한 코드’로 변질될 수 있다는 단점도 존재합니다.</p>
<p>또한 링크스타터와 같이 비즈니스 모델이 자주 변경된다면 그에 따라 비즈니스 로직이 자주 변경되게 되고 결국 코드뿐만 아니라 테스트 코드를 수정하는 작업을 하여야 합니다. 이는 배보다 배꼽이 크게 되어버리는 상황이 됩니다. 실제로 서비스 리뉴얼이 결정되고 새로운 디자인 작업이 끝나고 코드 리라이팅 작업이 착수된 이후에도 몇 번의 기획 변경이 있었습니다. 결국 이와 같은 이유로 애플리케이션의 동작을 확인해 볼 수 있는 E2E 테스트를 포기하였습니다.</p>
<p>최종적으로 컴포넌트의 UI 검증을 위하여 <strong>Storybook</strong>을 사용하기로 하였습니다. 각각의 공통 컴포넌트들과 페이지별 Storybook 코드를 작성하였습니다. 페이지 단위 스토리를 작성한 이유는 프로덕션 또는 개발 환경에서 특정 화면을 지속적으로 확인해 보아야 하는데 그때마다 해당 페이지에 접속하는 로직을 수행하여야 하기 때문입니다.</p>
<h2 id="리라이팅-후" style="position:relative;"><a href="#%EB%A6%AC%EB%9D%BC%EC%9D%B4%ED%8C%85-%ED%9B%84" aria-label="리라이팅 후 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>리라이팅 후</h2>
<h3 id="서비스-성능" style="position:relative;"><a href="#%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%84%B1%EB%8A%A5" aria-label="서비스 성능 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>서비스 성능</h3>
<p>전환 전</p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 693px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 22.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsSAAALEgHS3X78AAAAvklEQVQY03WPywrCMBBF/f9fEly4cCG4KYptXfRhFWts0qZNmlSTaxJBRHFgmMM8DszMWgufPgxjMFX1Yi1geQVjDS6qQTnWMK5v7wqPrnTwwCAEKKXve19nn0K9jaCjyI+g8zVMsUJ/b7G4rrG8bdA6tnWMMZ4Djk/nCw5piklPf4Qdx6RUEEqSQNE89FNWIHEZdmjmZgf/A/phACHkLfsRcrcgpQzcMI6uF4HZjYKSJnCWH7HbJ4GFe/lb+AQpkTRpIzXeZgAAAABJRU5ErkJggg=='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="레거시 라이트하우스 점수"
title="레거시 라이트하우스 점수"
src="/static/1d8c0635c11d9354f87b7ce9afb6c9c9/61c63/lighthouse-before.png"
srcset="/static/1d8c0635c11d9354f87b7ce9afb6c9c9/5a46d/lighthouse-before.png 300w,
/static/1d8c0635c11d9354f87b7ce9afb6c9c9/0a47e/lighthouse-before.png 600w,
/static/1d8c0635c11d9354f87b7ce9afb6c9c9/61c63/lighthouse-before.png 693w"
sizes="(max-width: 693px) 100vw, 693px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 192px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 53.125%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAABOUlEQVQoz6VS20rDQBDN//+FT1JfRCxUaAxtsJIYmgRCCn3SR6m5YO6XzR531iaNElFs4CST2dnZc86OgomHc/5vKI7jwHVdGIYBz/PQNM1ZTZU4jhGFIYIgQJIkYIyd13BKctd1Q1OK++I+19f062MoMklFAlVVIcsydIJlWZbynxi3woamqWWOLEnTVG6u63qaYTu7Ap5f8Crk6+s1TNOE7/uwtls8bDZQVRWapkHXddi2DcuyZI58H6uRDUkAPxzA8xwUM5EsiwK1YJeKPMWFALEtBehLG0nJieG4IQVH71ia4H21RHQ9Qxu8IVndg4UB4vkN4rt5P1P0Gs/YV8kyIINpTfiVPD3icHmBfOeh2O/QtS2ixS3i5eKz5u+3fDpVHiDM50d/xgP/26N8v/YBw0gw/FgzgQ/ERlWiO/9UawAAAABJRU5ErkJggg=='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="레거시 라이트하우스 점수"
title="레거시 라이트하우스 점수"
src="/static/eaa9ad69ea01dd98079632081c62f4fb/8514f/lighthouse-before2.png"
srcset="/static/eaa9ad69ea01dd98079632081c62f4fb/8514f/lighthouse-before2.png 192w"
sizes="(max-width: 192px) 100vw, 192px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p>전환 후</p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 585px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 24.333333333333332%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsSAAALEgHS3X78AAABEElEQVQY02WQwVLCMBRF+QkHCm2TNGkoULACRaVVKqOiIwPqwg0rdy79/80xRURnXLx5N3mT+85NQynFTwkpGSUR5VgjQokYWYJigLQaqSP8xZAw66LqWRoTnPeRJkK5d/Lg0ZDuUIu6a9d3t5bPbUIvNXjrMd77nOCyj3+d0vy4orW7QAxi2q9TmvVsmqB88Wv4ly7WirfK8FxGRErilX1amzHh0NE4opP1Ka2FI44U/n1GZzNB9Mye+J9hGAbkec7D6o7l8oYsO6OqKh7XT5Tzwi0zbF62zPIZHa/NZDphXhaEfvD9ZYekR8N9ZK2JrcV2uxhjsE4nTtf36TB1y1YUhTMRAh3pfUmXREl1JPwCx2WUov0EffkAAAAASUVORK5CYII='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="전환 후 라이트하우스 점수 1"
title="전환 후 라이트하우스 점수 1"
src="/static/34aa8e454630b42d295d61a43653d41b/78a22/lighthouse-after1.png"
srcset="/static/34aa8e454630b42d295d61a43653d41b/5a46d/lighthouse-after1.png 300w,
/static/34aa8e454630b42d295d61a43653d41b/78a22/lighthouse-after1.png 585w"
sizes="(max-width: 585px) 100vw, 585px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 724px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 40%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsSAAALEgHS3X78AAABCklEQVQoz21S7U6EMBDsk9DvWktpxXAcMRpjcvGv7/804261RDl+TKDd2ZlhFxFjxDRNMFpjGAZIKaHp/QjFUAqSOJ3HZ66xxjiO8N5DOGMw5YxcKyohU+FM0FIzN3ZeKQXW2lZzzjUxPgtFTjNdfFDKTMLcxM7/wKLEu8ZHvD/VxktkbChM5/TEQhlN6g7FBYQQdtcjDPECGQcbWhrmsuCRJwaj4K8V8+0Fl3VFSulujpzQGYnXNePrc8NlWbAQ2LzPcRfk2bjooUuCphQsdnTmhUml8eAUSpSNw4s5+xJhyXl7zri9bafpesL2JNFB6VOhXZCdvVWYE0Xn+Cdz0b+/jNY/uFvaH3wDqDfi4a2mepIAAAAASUVORK5CYII='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="전환 후 라이트하우스 점수 2"
title="전환 후 라이트하우스 점수 2"
src="/static/c28c77c482a919ef11cd2e6edaf1a5cd/a242d/lighthouse-after2.png"
srcset="/static/c28c77c482a919ef11cd2e6edaf1a5cd/5a46d/lighthouse-after2.png 300w,
/static/c28c77c482a919ef11cd2e6edaf1a5cd/0a47e/lighthouse-after2.png 600w,
/static/c28c77c482a919ef11cd2e6edaf1a5cd/a242d/lighthouse-after2.png 724w"
sizes="(max-width: 724px) 100vw, 724px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p>생각보다 낮은 점수에 매우 당황했습니다. Lighthouse 점수가 서비스의 성공 여부를 뜻하지는 않지만, UX 적인 측면에서 사용자들에게 더 좋은 서비스를 제공하는 데 도움이 되기 때문에 이 부분을 최적화하고자 하였습니다. Lighthouse가 언급했던 애플리케이션의 문제점은 아래와 같습니다.</p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 710px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 16%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAAAsSAAALEgHS3X78AAAAdElEQVQI13XOUQrDIBAEUE/SVaOliVaUIuavvf+lpuNSQijtx2N2RZYxOWe01lBrRYwR1lo45zR/cd/413uv5mzWbUNKSRcRUXP+R+hyIjyUWKqUomlufHyw4dh39N4xxkAI4Wh6ZmksC170/JjzyqN35pXeEZtVuwkSzH0AAAAASUVORK5CYII='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="라이트하우스 문제점"
title="라이트하우스 문제점"
src="/static/4d1123506f4d2e24705aff064f401a4d/7131f/lighthouse-after3.png"
srcset="/static/4d1123506f4d2e24705aff064f401a4d/5a46d/lighthouse-after3.png 300w,
/static/4d1123506f4d2e24705aff064f401a4d/0a47e/lighthouse-after3.png 600w,
/static/4d1123506f4d2e24705aff064f401a4d/7131f/lighthouse-after3.png 710w"
sizes="(max-width: 710px) 100vw, 710px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p>언급된 문제점에는 간단한 해결법이 존재했습니다. 리소스를 gzip 형태로 압축하여서 제공하도록 제시하고 있습니다. 이를 해결하기 위하여 사용 중인 Vite의 설정을 수정하였습니다. 파일의 크기가 1kb가 넘어가면 압축하도록 설정하였습니다.</p>
<div class="gatsby-highlight" data-language="tsx"><pre class="language-tsx"><code class="language-tsx"><span class="token keyword">import</span> viteCompression <span class="token keyword">from</span> <span class="token string">'vite-plugin-compression'</span><span class="token punctuation">;</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span>
plugins<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token function">viteCompression</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre></div>
<p>압축하였을 때 데이터 전송 자원을 70%가량 줄일 수 있었습니다.</p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 439px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 33.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABmElEQVQozz2RW28SURSF+Q+YljO3c5kLQxnoMJVBqIWhBGsRNMaUYhNjYzRGX/z/T59nTqIPO3tlZ+0va5/TMcYglSHPYvppjNSG2JZJYvRFhmm19RilUUWGzhNiq9tZLDV6kGLi+L+vo7VicmE4XKc832XksSIcJPi7Cd77Cv92jPYi/JsCcZzSe5gSFSnKaIL1CP++xLNepZSrzmhg+LHL+bXP+f1hQDM2nC0K/C9zgk9TvIfaLht6xxrxdcHZn4ZgWRBO+ojPM8TzNb2nGTK3F0kLDMKI/auIx5WyJenrgF6m6e5GdO+GdG/6KBHaNGNevBtz/rFCln2X8Hxf0n0zRNiEWtvz24TDYUHTrDkdVtxv11xOKl6WFcu3G5rTns3thixNCb2A2X7NYHrptLRBismY9dOBOElQUjqoBQ4tsKGev2a5ariqKqqrima5YrNs2G63JHZhWtf8/Pad0/GRPM8Jw5BRUThPbD+lfT8HjKIIz/Pwfc/11hgGodPCEwgh3KwsS+rZjPli4YDSJopk5Dz/YG3/C0h51IycAJqwAAAAAElFTkSuQmCC'); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="수정 후 라이트하우스 점수 4"
title="수정 후 라이트하우스 점수 4"
src="/static/f6cb5347252d765d8148bcfa3deb9aa5/e3b18/lighthouse-after4.png"
srcset="/static/f6cb5347252d765d8148bcfa3deb9aa5/5a46d/lighthouse-after4.png 300w,
/static/f6cb5347252d765d8148bcfa3deb9aa5/e3b18/lighthouse-after4.png 439w"
sizes="(max-width: 439px) 100vw, 439px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<p><span
class="gatsby-resp-image-wrapper"
style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 744px;"
>
<span
class="gatsby-resp-image-background-image"
style="padding-bottom: 41%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsSAAALEgHS3X78AAAA+ElEQVQoz3WRa2rDMBCEdZFYD0uyHlZjORhDUwhN73+m6a4bOyWxfwwI9DE7OytiCCilQGmFpmmglILW+k1KaUgpNzHHstYi54xAPswJ4yxSTsghIqUE7/2uoWs1ui4gRGLzkzPGLKasxbChZHbqUW4ThmFAjHGbvkqTgtP4/hxwnSvOxKUdjiWU0bCpQyx/sdu23Sa/JsyRuBgWzjm3y4mGDP30gXqbMdZxWYU7el2ZE/5cK+5fF9Txgr7Pu5ywvHKiPs7pUb56m8qSdJTsaXUrcTrx8eQuJ1ojMdee+pmo9O7wyqspyxz8L4YMeKtRwjG0Jv//PtIvcIjiun0QMCMAAAAASUVORK5CYII='); background-size: cover; display: block;"
></span>
<img
class="gatsby-resp-image-image"
alt="수정 후 라이트하우스 점수 5"
title="수정 후 라이트하우스 점수 5"
src="/static/565d46738bd5232e9aff5b5383181103/cab8c/lighthouse-after5.png"
srcset="/static/565d46738bd5232e9aff5b5383181103/5a46d/lighthouse-after5.png 300w,
/static/565d46738bd5232e9aff5b5383181103/0a47e/lighthouse-after5.png 600w,
/static/565d46738bd5232e9aff5b5383181103/cab8c/lighthouse-after5.png 744w"
sizes="(max-width: 744px) 100vw, 744px"
style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"
loading="lazy"
/>
</span></p>
<h2 id="아쉬웠던-점" style="position:relative;"><a href="#%EC%95%84%EC%89%AC%EC%9B%A0%EB%8D%98-%EC%A0%90" aria-label="아쉬웠던 점 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>아쉬웠던 점</h2>
<p>처음 목표했던 <code class="language-text">정식 서비스 오픈일</code>은 7월 17일이었습니다. 2021년 7월 17일 베타 서비스를 런칭하였기에 2022년 7월 17일은 <code class="language-text">1주년 기념</code>이자 <code class="language-text">리뉴얼 적용일</code>로서 적합하다고 생각됐습니다. 하지만 재단장하기로 결심한 후에도 비즈니스 모델을 정하지 못하여 2주가량 기획 회의만 하였습니다. 6월 마지막 주가 되었음에도 불구하고 <code class="language-text">무엇을 팔 것인가?</code>에 대한 결정을 내리지 못하였습니다. 그렇기에 디자인 시안도 늦어졌고 개발 착수 또한 늦어졌습니다.</p>
<p>결국 <code class="language-text">정식 서비스 오픈일</code>을 8월 1일로 미루고 작업을 시작하였는데, QA 시간까지 고려한다면 약 2주 만에 모든 작업을 끝내야 했습니다. 그렇기에 기능들을 빨리 쳐내는 것에 급급했고 세세하게 확인하지 못한 부분도 많았습니다. 또한 운영팀과의 소통도 전무하여 세 번째 사용자인 운영팀의 의견을 전혀 반영하지 못한 채 개발하게 되었습니다.</p>
<h2 id="후기" style="position:relative;"><a href="#%ED%9B%84%EA%B8%B0" aria-label="후기 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>후기</h2>
<p>리뉴얼이 끝났지만, 아직 해야 할 일이 많습니다. 당분간 새로운 기능을 추가하는 일은 없으나 빠르게 작업을 하면서 생겼던 문제점을 해결하고 리팩토링을 통하여 코드 퀄리티를 개선하는 작업을 하고자 합니다. 또한 리액트를 공부할 때는 <code class="language-text">Create-React-App</code>을 사용하여 코드에 대해 고민만 하였는데 최적화 작업을 진행하면서 빌드 툴 역시 다룰 줄 알아야 한다는 것을 깨달았습니다.</p></content:encoded></item><item><title><![CDATA[SVG 다루기 삽질 후기]]></title><link>https://github.com/michaelhur/react/svg-다루기-삽질-후기/</link><guid isPermaLink="false">https://github.com/michaelhur/react/svg-다루기-삽질-후기/</guid><pubDate>Thu, 01 Sep 2022 23:00:28 GMT</pubDate><content:encoded></content:encoded></item><item><title><![CDATA[재사용 가능한 Draggable List 만들기]]></title><link>https://github.com/michaelhur/react/재사용-가능한-draggable-list-만들기/</link><guid isPermaLink="false">https://github.com/michaelhur/react/재사용-가능한-draggable-list-만들기/</guid><pubDate>Tue, 09 Aug 2022 20:00:18 GMT</pubDate><content:encoded></content:encoded></item></channel></rss>