📝 문제점 및 보완 리스트
문제점
- MPA 사용으로 인한 코드의 흐름을 읽기 어렵고 어플리케이션이 무거워지는 문제 발생
- MPA로 제작하여 EndPoint가 따로 존재하지 않고 무분별한 .html, .js 확장자가 존재해서 가독성이 매우 떨어짐
- 모듈을 사용하지 않아서 js file이 분리되어 있어도 전역 스코프는 공통으로 사용하여 암묵적 전역 현상이 발생할 수 있다.
- 식별자 네이밍이 명확하지 않아서
- 중복된 코드로 레거시 코드가 발생
- 잘못된 비동기 로직을 사용
- Type을 정적으로 컴파일하지 않아서 프로퍼티 접근 시 null, undefind를 대처하지 못하는 경우가 많이 발생하는 코드가 존재한다.
보완 리스트
- MPA로 만들어져 있는 코드를 SPA와 Ajax 네트워크 통신으로 어플리케이션을 가볍게 만들기 (1번 문제)
- Webpack을 도입해서 모듈 스코프를 사용하고 EndPoint 설정 후 Babel을 사용해서 JS 크로스브라우징 문제 해결하기 (2번, 3번 문제)
- 깔끔한 코드 작성
- 명확하게 의미로 작성하지 않은 식별자 수정 및 무분별한 변수 사용 억제, 상수 식별자 대문자 네이밍 규칙을 통해서 가독성 높이기 (4번 문제)
- 중복된 코드로 레거시 코드가 발생한 부분을 함수 단위로 묶어 명확한 작업 만들기(너무 과도한 작업을 하는 함수는 작은 단위로 분리하기) (5번 문제)
- aync, await 문법으로 모든 비동기 로직을 통일하여 비동기로 자동하는 코드를 을 동기로 작동하는 코드처럼 만들기 (6번 문제)
- TypeScript을 도입하여 정적으로 컴파일하여 타입 문제 해결 및 런타임에 발생하던 에러를 컴파일 단계에서 에러를 캐치하여 효율성 높이기 (7번 문제)
⌨️ 코드 컨벤션
- 상수는 대문자와 파스칼 케이스로 작성
- 자주 사용되는 상수는 따로 상수 관련 파일을 지정
- EventHandle의 명칭 통일
🖌 작업하며 배우고 느낀 것
📖 라우터를 통해 SPA 구현

History 기본으로 Router API를 구현했습니다.
Router가 동작하는 원리를 설명하면 router 변수에 URL의 address를 문자열로 미리 지정하여 화면이 변경될 때마다 history.pushState function을 호출하여 URL의 address를 변경하고 변경 후에 root dom에 접근하여 innerHTML을 사용하여 이전 화면을 바뀐 화면으로 새롭게 교체하는 방식을 사용했습니다.
그렇다면 innerHTML function을 호출할 때 마다 리렌더링이 발생하는 문제가 있는데 왜 굳이 사용했는가 하는 의문이 들 수 있습니다. 저도 처음에 createElement와 DocumentFragment를 사용하여 최소한의 리렌더를 발생하면 되지 않을까 하는 생각을 했지만, 코드를 분석하고 보니 화면을 바꿀 때는 고정적으로 변하지 않는 화면을 제외하고는 모든 부분이 바뀌어야 한다는 것을 알게 되었고, createElement와 DocumentFragment를 사용하면 가독성이 떨어지고 막노동 같은 코드가 많이 생길 수 있다는 생각을 가지게 되었고 innerHTML의 문제점을 정확히 인지하고 사용하면 유용하게 사용할 수 있겠다는 생각에 innerHTML을 사용하여 DOM 업데이트를 진행했습니다.
위의 image의 코드에서는 Router를 사용하기 위해 중요한 두 가지 function으로 구축되어 있습니다.

첫 function은 initialRoutes를()의 동작은 처음 화면을 렌더링하기 위해서 만든 function으로 entry point(index.ts)에서 initialRoutes를 호출하면 Login page를 보여주는 기능입니다.
두 번째 function은 Router를 구축하는 가장 중요한 기능으로 pushRouter()입니다. pushRouter()는 첫 화면을 제외하고 모든 router가 이동하기 위해 거쳐야 하는 과정으로
pushRouter(pathName: string, qureyId?: string, backPageType?:
cuisine|
recommend)
의 매개변수를 넣어서 호출하면 새로운 화면을 보여주는 역할입니다.
위의 예시 Image는 ingredient page의 일부 logic으로 다음으로 이동할 URL의 address pathName을 DOM에서 추출하여
pushRouter(url address pathName)
호출로 동작을 구현할 수 있습니다.Router 작업을 통해 어떻게 SPA가 동작하는지 알게 되었습니다. 처음에는 History API만을 사용하여 모든 Router 작업을 수행하려고 생각했지만, 검색을 통해 Location API 같은 쉽게 URL에 접근할 수 있는 여러 가지 Web API에 대해서도 알게 되었습니다.
📖 DRY(Don't Repeat Yourself) 원칙 적용
처음 코드를 분석하면서 중복되는 코드가 많다는 생각을 가지게 되었습니다. 그래서
EMO/src/utils
dir 경로에 중복되는 utils function들은 재사용할 수 있게 만들었습니다.
대표적인 중복 function으로 찜하기를 눌렀을 경우 전체 화면의 배경 화면의 opacity를 투명하게 만들고 modal을 2초 정도 띄워주는 UI를 만들었습니다. 하지만 찜하기 기능은 cuisine page, recipe page, recommed page에서 모두 사용했고 중복된 Logic을 찾아서
timeModel()
으로 공통 Logic을 옮기고 과정을 거쳐서 어디서나 재사용할 수 있게 만들었습니다.
timeModel()의 UI 모습
DRY 원칙을 적용하여 획일적인 코드 스타일을 가지게 되었고, Refactoring을 하면서 아무 생각 없이 Logic을 작성하면 이렇게 중복되는 코드가 많을 수 있다는 경험을 하게 되었습니다. 중복 Logic을 제거 후 재사용할 수 있는 function을 만드는 경험을 통해 다음 Project에서는 기능 구현만을 생각하기보다 재사용할 수 있으며, 가독성 있는 Logic을 목표로 세우고 Project를 진행하겠습니다.
📖 상수에 대한 명시적인 코드 작성
EMO Project 보완을 진행할 때는 혼자서 모든 Logic에 대해서 작업을 진행하여 획일적인 코드 스타일을 쉽게 가질 수 있었습니다. 물론 위에서 설명한 DRY 원칙도 많은 도움이 되었습니다. 그러나 모든 Project에 대해서 혼자서 코드 작성을 할 수 있는 게 아니며, 언젠가는 협업을 진행해야 한다는 생각을 가지게 되었습니다. 그래서 혼자서 지킬 수 있는 협업 규칙을 정하게 되었고 명시적인 코드를 상수로 작성하는 규칙을 EMO Project에 적용하게 되었습니다.


Server 통신을 위해 사용되는 URL은 많은 Logic에서 중복되어 사용되는 점을 생각하여 따로 file을 분리하여 중복 Logic을 제거하고 수정하는 경우에는 하나의 Logic만을 수정하면 의존성을 통해 사용된 부분도 쉽게 수정할 수 있었고(DRY 원칙 적용) JavaScript의 문법 const 변수 선언으로 상수로 URL 변수를 지정하여 상수로 만들었습니다. 상수로 변수를 선언할 때 가장 중요하게 생각했던 점으로는 변수 네이밍으로 의미를 정확하게 알려 주어 다른 사람이 Logic의 흐름을 읽지 않고 변수 네이밍만으로 의미를 알 수 있게 만들었습니다.


위의 Logic은 Cuisine Page로 Number Type을 사용해야 하는 경우가 있었습니다. 처음에는
addToCartElement.style.opacity = "1";
같이 Number를 바로 삽입하는 방식을 사용했지만, Number의 의미가 정확하지 않다고 생각하여 Object의 Property로 지정하였습니다. 그러나 문제가 되는 부분으로는 객체 리터럴의 Property는 불변이 아니면서 Private 지정도 안 된다는 문제가 있어 어디서나 쉽게 접근하여 변경할 수 있었습니다. 해결 방안을 고민하였고 TypeScript의 readonly 문법을 통해 읽기 전용으로 변경할 수 있어서 상수의 의미를 가진 Property로 만들 수 있었습니다.💻 후기
EMO-v2 Project를 작업하면서 많은 부분을 배우게 되었습니다. 특히 Vanilla JS로 모든 작업을 진행하여 JS Library, Framework에서 내부적으로 작동되는 부분에 대해서 깊이 있게 알게 되었습니다. 물론 아쉬운 점도 많이 있었습니다. 특히 가장 아쉽게 생각했던 부분으로는 Vanilla JS로 모든 작업을 진행하여서 Library와 Framework을 사용할 때보다 더 많은 자유도로 작업을 진행할 수 있어서 구조에 관한 생각 및 상태 관리에 대해서 생각할 수 있었는데 그 부분을 신경 쓰지 못했던 게 가장 아쉽게 생각이 들었습니다.
하지만 많은 내부 동작을 Library가 마법을 부리는 것처럼 보이는 부분에 대해서 library 사용자들은 알기가 쉽지 않습니다. 저는 Library가 마법을 부리는 부분에 대해서 많은 궁금증을 가지게 되었고 Library의 내부 코드에 대해서 찾아보니 모든 부분이 Vanilla JS로 만들어졌다는 것을 알게 되었습니다. 그래서 Vanilla JS의 중요성을 더 크게 느끼게 되었고 EMO-v2 Project를 Vanilla JS로 진행하였습니다.
EMO-v2 Project를 끝내고 나서는 Webpack의 동작 원리, React에서 SPA 동작 원리, TypeScript의 사용 방법 및 컴파일 방법, Reflow, Repaint 고려한 Logic 작성, 획일적인 코드 스타일 적용 방법과 같은 많은 부분에 대해서 알게 되었고 이러한 경험에서 배운 것에만 만족하지 않고 더 많은 부분에 호기심을 가지게 되었고 내가 아직 많이 부족하다는 것을 알게 되었습니다. 여기서 멈춰서 뒤처지지 말고 계속해서 앞으로 나아가야 한다는 것을 깨닫는 계기가 되었습니다.