지난번에 작업한 버전을 배포하면서 사용자경험에 있어 몇 가지 문제들이 보였고, 그 중 시급하다고 판단한 문제들과 그 개선 과정을 정리해 본다.
각 날짜에 발송되는 공관 목록이 태그 형태로 나열되는 UI를 구현하였는데,
문제는 원래 이 날짜에 발송되는 공관인지, 혹은 일정이 변동되어 이동된 일정인지 시각적으로 구분이 되지 않는다는 것.

예를 들어 9월 30일에 발송되는 걸로 표출되는 일정 중에는 원래 23일이나 29일, 10월 1일에 예정되어 있던 공관 일정이 들어와 있기도 하며,
거꾸로 9월 30일에 발송될 예정이던 공관 일부가 다른 날짜로 바뀐 경우도 몇 가지 존재한다.
다음 날 발송되는 공관에 대해 (상세히 밝히기 곤란한)물리적인 조치를 취해야 하는 내 입장에서, 이렇게 '원래 일정'과 '편집된 일정'이 섞여 있으면 두 일정을 구분하기 위해 개별 변동 일정을 직접 체크하는 작업을 한 번 더 거쳐야 하기 때문에 페이지의 활용성이 크게 떨어졌다.
또 해당 서비스를 참고하는 타 부서나 공급업체의 경우에도 '00 공관은 일주일 순연되었습니다'와 같은 개별 공지를 직접 확인하기 전까지는 일정이 변경되었는지를 직관적으로 알 수 없었다.
따라서 다음과 같은 간단한 방법으로 일정 변경 여부를 알 수 있도록 했다:

처음 만든 버전에서는 별도의 공지 텍스트를 띄우는 걸 고려하지 않았지만, 운영 시작과 동시에 세계 곳곳에서 분쟁이 터지며 수 개 공관의 정파 발송이 중단되었다. 이를 계기로 공지사항을 표출할 영역을 상단에 작게 추가하였다.

이때 아래와 같이 별도의 H5태그를 이용해 공지 텍스트를 하드코딩하는 단순한 접근을 택했는데,

이후 7일간의 전례없는 연휴로 인한 무수한 일정 변동을 비롯, 공지사항에의 의존도가 크게 늘어났고, 그때마다 새로 배포를 해야 하는 불편함을 근본적으로 해결해야 했다.
다음과 같이 기능하도록 아키텍처와 프론트 코드를 수정하였다:
아키텍처 변경이 필요하므로 블루-그린 접근법을 택했다.
우선 기존의 S3 버킷 및 Cloudfront 배포, Lambda 함수를 복제하여 하나 더 준비했다.
APIGW는 별도의 Dev 스테이지를 추가하여 활용하였으며,
기존 DynamoDB 테이블 A, B는 업데이트 과정에서 별도로 건드릴 일이 없기 때문에 그대로 두었다.
먼저 공지사항을 저장하기 위한 별도의 테이블'C'를 생성하였다. 이때 ID(S)를 PK로 지정하였으며 ID는 'active-notice'로 항상 저장된다. 즉 공지를 수정하면 새 공지가 'active-notice'로 지정되어 이전 값을 덮어쓴다. 굳이 예전 공지를 살려 둘 필요가 없다고 판단했기 때문.

뒤에서 추가할, APIGW의 /notices 경로에 해당하는 메소드들의 동작을 매개하는 코드를 추가하였다.
Vibe coding 한 결과물이므로 대략적인 구조만 남긴다.
else if (path === '/notices') {
if (method === 'GET') {
// 공지사항 조회 ('active-notice'로 ID 고정)
else if (method === 'POST') {
// 공지사항 저장/업데이트
return {
statusCode: 201,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
},
body: JSON.stringify({ message: '공지사항이 저장되었습니다.' })
};
}
}
APIGW에 /notices 리소스를 추가하고 GET, POST 메소드를 구현하였다. 지울 공지가 딱히 없는 상황이기 때문에 DELETE 메소드는 구현하지 않았다.

그리고 각 메소드는 후술할 Lambda 함수와 Lambda Integration을 수행하였다.
물론 별도 메소드를 추가하는 작업이 현재 구동되는 서비스에 영향을 미치진 않겠지만 블루그린 배포를 위해 별도의 dev 스테이지를 만들어 작업하였음을 다시 한 번 밝힌다.

다음 명령어들을 통해 새 아키텍처가 정상적으로 추가되었는지 확인하였다:
curl -X GET https://******.execute-api.ap-northeast-2.amazonaws.com/dev/notices
curl -X POST https://******.execute-api.ap-northeast-2.amazonaws.com/dev/notices \
-H "Content-Type: application/json" \
-d '{"content":"**테스트 공지**"}'
curl -X GET https://******.execute-api.ap-northeast-2.amazonaws.com/dev/notices
테스트에 성공한 후 dev스테이지에 배포한 내용을 product에 배포하는 것으로 아키텍처 수정을 마무리하였다.

공지사항을 캘린더 위쪽에 표출하여 접속과 동시에 파악할 수 있게 하였으며,

관리자 모드 진입 시 '편집' 버튼을 눌러 기존 공지를 편집하고 저장할 수 있도록 하였다. 특이사항으로 해당 텍스트 박스는 마크다운 서식을 일부 지원하도록 별도 함수를 구현하였다.
const renderMarkdown = (text) => {
if (!text) return '공지사항이 없습니다.';
let html = text;
// **굵게**
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
// *기울임*
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
// [링크텍스트](URL)
html = html.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" class="text-blue-600 hover:underline">$1</a>');
// 리스트
html = html.replace(/^[\-\*] (.+)$/gm, '<li>$1</li>');
html = html.replace(/(<li>.*<\/li>)/s, '<ul class="list-disc pl-5">$1</ul>');
// 줄바꿈
html = html.replace(/\n/g, '<br>');
return html;
};
기존 UI는 크게
세 개의 섹션으로 구분된다.

그런데 실무 환경에서는 PC보다 모바일 환경에서의 사용 빈도가 더 높았지만, 최초로 구축한 모바일 UI는 PC UI를 깨짐 없이 구현하는 데 초점을 맞추었다. 그러다 보니 실제 사용성에서의 부족함이 많이 보였다.
우선 '미리보기' 영역의 네 개의 박스를 그대로 구현하다 보니 세로로 배치되면서 캘린더가 저 아래로 내려가게 되었고, 그 결과 캘린더가 존재하는지조차 모르는 사람들이 많았다.

22:9 비율의 극단적으로 긴 디스플레이를 가진 폰에서 앱을 실행한 화면인데, 이런 상홍에서야 겨우 캘린더가 보일락 말락 할 정도로 기형적인 UI가 탄생했다.
캘린더 영역 또한 크기상의 한계로 '격주' 및 'N째주'표시를 축약하여 표기하였는데, 업무에 익숙한 사람은 이 표기가 아무 문제가 없지만 처음 접하는 이들에게는 다소 불친절했다.


예컨대 사진에서 1일은 '격주 2' 이자 '1번째 월요일'에 해당하는데, 모바일 버전은 공간상 제약으로 인해 이를 '2 ①' 과 같이 지나치게 간소한 표기로 표현하였다.

PC/모바일을 막론하고 달력은 맨 아래에 있는데 달력을 이동하기 위한 네비게이션 버튼은 상단에 있다. PC 버전에서야 '미리보기 영역'의 높이가 차지하는 비중이 높지 않으니 크게 문제가 되지 않았지만, 모바일 버전에서는 상당한 높이를 차지하기에 이 영역이 캘린더와 연동되는 부분이라기보다는 미리보기 영역을 컨트롤하는 버튼으로 오해하는 경우가 많았다.
레이아웃을 상당 부분 수정하였는데, 사용 환경을 고려하여 아예 모바일 UI를 우선적으로 설계하고, 거의 볼 일이 없는 PC UI는 모바일 UI를 그대로 따라가되 달력 모양만 조금 손보는 쪽으로 접근했다.

01
UI에 가장 큰 걸림돌이 되던 미리보기 영역을 삭제하였다. 외교업무 일선에 종사하는 직원들은 '내가 보내고자 하는 특정 공관의 발송일이 언제인지'가 더 중요하지, '오늘 발송되는 공관 목록이 무엇인지'를 볼 일은 그렇게 많지 않음을 확인하였다. 발송을 준비하는 나의 입장에서만 필요하지, 그 외 대부분의 사람들에게는 크게 중요하지 않기 때문에 위에서 서술한 공지사항 부분을 남기고 모두 제거하였다.
02
캘린더 내부 공간 확보를 위해 공관 개수 표기를 삭제하였다. 이것도 대부분의 실무자들에게는 불필요한 정보이다.

좌측이 기존 모바일 캘린더 UI, 우측이 개선된 모바일 캘린더 UI. 공관 개수 표기를 없애고 그 공간을 활용하여 격주 유형 및 요일 카운트 표시를 개선하였다. 수정하면서 공휴일에도 음영을 칠하여 발송이 진행되지 않음을 좀 더 명확히 표현하였다.
03
상단 영역에 있던 공관 검색 섹션(보라색 영역)과 캘린더 월 이동 버튼을 캘린더 바로 위로 옮겼다.

공관을 선택하면 다음 발송 일정이 표출되며 이를 캘린더에도 하이라이트되도록 했다.

04
발송 일정 모달 또한 사용성을 개선하기 위한 몇 가지 작업을 거쳤다.
먼저 모달 안에서도 날짜 이동이 가능하도록 좌우 이동 버튼을 추가했고, 특히 자주 봐야 하는 오늘/내일/모레/다음 주는 아예 버튼으로 만들어 사라진 미리보기 영역의 기능을 부분적으로 대체하도록 하였다. 이때 주말을 고려하여 주말은 건너뛰고 날짜를 이동하도록 했다.

이어지는 내용에서는 또 다른 문제인 로딩 속도 개선 과정을 정리해 보겠다.