https://dev2-jay.tistory.com/32
회고록 1편에서 전체적인 서비스 소개와 진행과정등을 소개했다.
2편 회고에서는 백엔드 부분을 기획하면서 새롭게 배운 부분을 집중적으로 작성해 보겠다.
- 동시성 제어:
포인트 기능을 구현하는 과정에서 코치님께서 힌트를 던져주셨고, 검색하고 공부하면서 동시성 문제라는 개념을 알게 되었다.
오채완을 기준으로 가정을 해보자, 우리가 만든 서비스는 다중의 유저들이 동시에 사용하는 서비스이다. 그렇기에 발생할 수 있는 문제로, 만약 서버에 대한 서로 다른 요청(명령)이 동시에 처리된다면 어떤 일이 일어날까?
A라는 유저가 자신의 포인트를 이용하여, 농가 쇼핑몰에서 물품을 구매한다고 생각해 보자.
처음에 A유저의 잔여 포인트와 물품의 포인트를 비교하고 "A유저의 잔여 포인트 > 물품 포인트" 일 때만, 구매가 진행이 되어야 할 것이다. 만약 A라는 유저가 시간이 아까워서 여러 대의 기기에서 다른 물건을 동일한 시점에 구매 버튼을 눌렀을 경우 데이터 베이스의 값들은 잘못된 값, 즉 나와서는 안 되는 값들로 기록될 확률이 매우 높아지고 이것은 서비스에서 아주 치명적인 오류일 것이다. (돈에 관련된 서비스는 매우 신중해야 한다라는 것을 배움)
위의 상황을 최대한 방지하고 효율적인 DB성능까지 고려하기 위해 탄생한 아이디어가 바로 Transaction 처리와 Transaction의 Isolation Level을 어떻게 설계할까 하는 부분을 고려하는 것이다. 이 모든 것을 상황에 맞게 설계하는 것이 동시성 제어(Concurrency Control)의 핵심이라고 이해했다.
간단하게 알아보는 Transaction이란?
-독립적인 단일 논리 작업 단위이다. 쉽게 말하자면 여러 SQL문들을 하나의 작업으로 묶어서 따로 실행되어 성공과 실패하지 않고, 다 성공하면 성공이고, 하나라도 실패하면 실패되게 한다. (DB에 반영 X)
mysql에서는 transaction defalut 값으로 autocommit이 지정돼 있다. 하지만 우리의 서비스에서는 수동으로 transaction을 관리하는 코드를 작성해 주었다.
이번 프로젝트를 하면서 공부한 자세한 내용은 아래의 글에서 확인할 수 있다.
https://dev2-jay.tistory.com/34
- 객체지향적 코드 설계
회고록에서는 과거의 나는 이렇게 생각했지만, 프로젝트를 하면서 새로운 것을 배우고 생각이 바뀌었다는 형식으로 작성하겠다.
추후에 객체지향적 코드 설계에 대한 정확하고 자세한 공부내용을 정리해 보겠다.(가능한 빨리...)
현재까지 내가 이해한 객체지향적 & 절차지향적 설계의 핵심 내용은 메모리를 얼마나 효율적으로 사용할 수 있는가?이다.
2차 프로젝트 전까지는 코드 한줄한줄 이해하기보다는 코드가 실행되는 전체적인 흐름을 익히기 위해 노력해 왔다. 이제야 전체적인 흐름과 비즈니스 로직 분리 및 의존성 주입에 대해 받아들였고, 그러고 나니 개별적인 코드가 눈에 들어오기 시작했다.
코드를 쭉 파헤쳐 보면서 의문점이 든 부분이 있었는데, 모든 곳에서 static 키워드를 통일해서 사용하고 있었던 것이다. 사실 개발 초기에 팀원들과 상의에 있어 한 가지 방법으로 통일하면 깔끔해 보이니까 static으로 하자!라는 결론을 내리고 사용했었던 건데,,, 정말 말도 안 되는 결정이라는 것을 알았다.
이전까지 객체지향이라고 하면, 단지 함수에 이름, class 같은 거 만들어서 사람들이 이해하기 쉽고 뭐 어쩌고 저쩌고... 이런 식으로 매우 대충 이해하고 받아들였었다. 하지만 이번 프로젝트에서는 static 이게 왜 문제지? 객체지향적 프로그래밍은 뭐지? 절차지향은? 같은 질문이 꼬리를 물면서 객체지향적 설계 부분 시야가 한층 더 넓어진 경험을 하였다.(물론 공부는 더 열심히 해야 한다)
stactic 키워드를 사용하는 것이 객체지향이 아니다!라고 말 할 순 없지만, 개발하는 기능에 따라 프로세스와 스레드의 메모리 효율성을 생각하고 필요에 따라 작성해야 하는 것을 배웠다.
이해한 것을 간단히 설명하자면, (정답이 아니라는 것을 알아두자) static 키워드는 정적 메서드이기 때문에 클래스의 종속적(의존적)이다. 클래스와는 항상 연결되어 있지만, 다른 특정 인스턴스와는 연결되어있지 않기 때문에 특정 객체 데이터에 접근을 할 수가 없다.
static 키워드로 지정해 놓은 함수들은 새로운 인스턴스를 생성했을 때 이름을 변경하면 같이 다 변경되기 때문에 독립적으로 사용할 수 없는 문제가 있다. ( 유연성이 매우 떨어짐, DI개념도 알아보자 ) -> 그러므로 유지보수가 어려워지는 단점이 있다.
공부를 하면서 디자인 패턴 중 singleton 패턴(객체 인스턴스가 오로지 한 개만 생성하도록 설계)이란 것도 알게 됐는데, 추후에 더 자세히 static 클래스와의 차이는 무엇이 있는지 정리해 보겠다.
구색 없이 말이 길어졌지만, 정리하자면 이번 프로젝트를 하면서 코드 한 줄 한 줄 어떤 식으로 개발할지 어떤 것이 효율적인 것인지 생각하면서 코드를 구현하는 개발자가 되어야겠다는 것을 배웠다.
- 데이터 베이스 & AWS 생태계
역시 사람은 아는 만큼 보인다고 했던가, 첫 번째 프로젝트보다는 발전이 있었던 것이, 간단한 CRUD 로직 짜는 것도 어려웠었는데...
이번에는 서버와 데이터베이스와의 상호작용을 공부하게 되고, 데이터베이스라는 것 하나만 해도 엄청나게 깊이 있게 공부해야 하는구나를 느꼈다. 테이블을 설계할 때 지정해 주는 타입에 대한 고민도 해야 하고, 테이블관의 관계와 인덱스 설정 등등 다음 프로젝트를 하기 전 깊이 공부하고 준비해야겠다.
마지막으로는 AWS가 제공하는 수많은 서비스 제품이 있는 것을 알게 되었고, 모든 것을 자세히 알 수는 없지만, 존재 자체를 알게 되니, 공부해 보면서 익숙해지고, 이용했을 경우 어떠한 장점들이 있는지 정리해야겠다는 생각을 하게 되었다. 부가적으로, 에러 로그 관리를 하기 위해서 필요한 라이브러리를 사용하여 에러 관리를 하는 것도 알게 되었고 (console.log 금지), Jest와 같은 단위테스트 구성을 위한 라이브러리를 통해 TDD(테스트 주도 개발)도 적용해 보는 연습을 해야겠다는 것을 배웠다.
- 마치며
회고록을 마치며, 정리를 해보겠다.
1편과 2편 통틀어 봤을 때, 작성한 내용 외에도 사소하지만 많은 것들을 얻을 수 있었던 프로젝트라 결과물을 떠나서 개인적으로 첫 번째 프로젝트보다 많은 배움이 있었던 프로젝트라고 생각이 든다. 한편으로는 배운 것이 많은 만큼 그 과정 속에서 나의 부족한 부분을 더욱더 많이 느꼈기 때문에, 팀원들에게 많은 도움이 되지 못했다는 생각이 들어 아쉬움이 크기도 하다. 힘든 상황 속에서도 끝까지 지치지 않고 달려준 팀원분들께 감사한 마음을 다시 한번 전하며 마무리 하겠다.