우테코 5기

[레벨 2 미션] 쇼핑 주문 협업 미션 학습 기록(1)

teo_99 2023. 6. 20. 20:45

이번 미션은 첫 협업 미션이었습니다. 프론트엔드 크루분들을 포함해 총 5명으로 구성된 팀으로 협업을 진행했습니다. 그 과정에서 얻었던 다양한 경험들을 기록하고자 합니다.

 

배포 및 인프라

협업 미션을 진행하면서, 백엔드는 기본적인 뼈대 코드를 제공받았습니다. 이 뼈대 코드를 통해 우선 배포 및 인프라 구성을 해보는 것이 첫번째 미션이었습니다. 그리고 이 과정에서 계정을 지급받아 AWS를 사용했습니다.

 

배포 플로우는 다음과 같았습니다.

간단한 배포 플로우

정말 간단하게 구성했는데 이 과정에서 AWS 개념, 네트워크 개념, 그리고 다양한 리눅스 명령어들을 접해보게 되었습니다. 각각에 대해 모두 다루기엔 너무 방대해질 것 같아, 이들에 대해서는 아래에 따로 정리하겠습니다.

 

AWS, EC2, VPC, AZ, Subnet?

각 개념에 대해서 간단하게 정리해보겠습니다. 심화 개념은 이후 필요할 때 개별 포스팅으로 정리하려 합니다.

AWS

아마존닷컴이 제공하는 클라우드 컴퓨팅 플랫폼이며 네트워킹을 기반으로 가상 컴퓨터와 스토리지, 네트워크 인프라 등 다양한 서비스를 제공한다. 대표적인 IaaS(Infrastructure as a Service) 제공 업체이며, 이외에도 마이크로소프트 Azure 등이 있다.

 

EC2

EC2란, Amazon Elastic Compute Cloud의 약자로 안전하고 크기 조정이 가능한 컴퓨팅 파워를 클라우드에서 제공하는 웹 서비스를 의미한다. 또한 안전하고 확장 가능한 인프라에 온디맨드로 액세스할 수 있다. 인텔, AMD, Arm 프로세서를 지원한 최초의 클라우드 공급자이며, EC2 Mac 인스턴스를 지원하는 유일한 클라우드 공급자이기도 하다.

온디맨드(On-demand)란, 사용자가 원하는 시점에 서비스를 바로 사용할 수 있다는 것을 의미합니다.

 

VPC

VPC란, Virtual Private Cloud의 약자로 이 개념을 통해 논리적으로 격리된 가상 네트워크에서 AWS 리소스를 사용할 수 있다. VPC는 여러 가용 영역에 걸쳐 하나의 논리적인 단위를 구성할 수 있다.

 

AZ

AZ란, Availability Zone의 약자로 1개 이상의 물리 데이터센터를 묶은 논리적 데이터센터이다. 각 AWS 리전에는 독립적으로 운영되도록 설계된 여러 개의 AZ(가용 영역)이 존재한다. 가용 영역은 여러 자연 재해로부터 연쇄적으로 문제가 발생하는 것을 방지하기 위해 물리적으로 적절한 거리를 두고 설치된다. 

 

Subnet

서브넷이란, 하나의 네트워크가 분할되어 나누어진 작은 네트워크이다. 서브넷을 통해 패킷이 대상까지 비효율적인 경로로 이동하지 않도록 할 수 있다. 즉, 서브넷 + IP 개념을 통해 쉽게 패킷이 도달할 위치를 특정시킬 수 있다는 의미이며, 이 과정에서 서브넷 마스크가 활용된다.

 

 

github actions + github secrets 사용

사실 첫 배포이기도 하고 코치분들이 CI/CD를 권장하지는 않았지만 캠퍼스가 이외의 IP에서는 EC2에 접근할 수 없었기에 집에서도 EC2에 접근할 수 있게 CI/CD를 구축했습니다. 그 과정에서는 github actions를 사용했고, 백엔드 크루인 누누가 작성해준 포스팅을 통해 쉽게 self-hosted runner를 구축할 수 있었습니다.

https://be-student.tistory.com/75#CI%2FCD%20%EB%9E%80%3F-1

 

github 에 Self Hosted Runner 로 EC2 에 CD 구축하기

우아한테크코스 미션을 하던 도중에 있던 CI/CD 에서 CD를 구축한 과정을 정리하게 되었습니다 코드는 여기서 확인하실 수 있습니다 CI/CD 란? 아주 간단한 설명을 드리겠습니다 CI(Continuous Integratoin

be-student.tistory.com

 

그리고 저는 추가적으로 데이터베이스에 접근하기 위한 URL, USERNAME, PASSWORD 등의 비밀 키를 관리하기 위해 github secrets까지 사용해보았습니다.

 

하지만 workflow 작성 과정에서 export 명령어로 환경변수를 설정하는 방법이 어쩐일인지 통하지 않았고, 많은 시간을 삽질했지만 해결책은 찾지 못했습니다. (혹시 아시는 분 있을까요 🥲)

 

그래서 다른 방법인 jar 파일을 실행시킬 때 환경변수를 지정해주는 방법을 사용했습니다. 

환경변수가 늘어나면 문제일 것 같긴 하지만, 정상적으로 작동은 되기 때문에 이번 CI/CD 구축 과정에서는 여기까지만 학습하기로 결정했습니다. export 명령어가 왜 제대로 작동하지 않는지 알아내려면 runner에 대한 이해도도 필요할 것 같았습니다.

 

이처럼 이번 기회를 통해 1. github actions을 통한 CI/CD 맛보기, 2. github secrets를 통한 시크릿 키 관리를 경험해보았습니다.

 

API 설계

처음으로 협업 미션을 경험했고, API 설계도 처음 진행해보았습니다. 사실 이전까지는 API 설계가 백엔드의 몫이라 생각했습니다. 정말 이론적으로 생각하면 클라이언트(프론트엔드)는 단순히 데이터를 어떻게 렌더링할지만 결정하면 된다고 생각했는데요.

 

실제 API 설계 과정을 통해 느낀 점은 다음과 같습니다.

  1. 웹 백엔드 개발자는 클라이언트(Ex. 프론트엔드, 안드로이드 등)와의 결합도가 존재할 수 밖에 없다.
  2. 따라서 클라이언트의 요청사항이 API 설계에 영향을 끼칠 수 밖에 없다.

다만 API 설계에 클라이언트의 요구사항을 어느정도까지 반영할것인가? 는 고려해봐야 할 것 같습니다.

 

이번 미션에서 API를 설계할 때 실제로 다음과 같은 시나리오가 있었는데요.

  1. 주문 페이지에서는 사용자에게 적립될 포인트를 보여줘야 한다.
  2. 하지만 적립될 포인트는 프론트엔드가 계산할 수 있다.(필요한 모든 정보를 갖고 있다)
  3. 그러니, 백엔드에게 굳이 API 요청을 보내지말고 UX를 위해 프론트엔드가 미리 계산해서 보여주자.
  4. 이후 주문할 때 프론트엔드에서 계산된 값이 백엔드가 계산한 값과 맞는지만 검토하면 되지 않나?

그 결과 주문 API는 다음과 같았습니다.

POST /orders HTTP/1.1

- Http Headers
Authorization: value
Content-Type: application/json

- Http body
{
	"cartItemIds": [value, value, value],
	"originalPrice": value,
	"usedPoint": value,
	"pointToAdd": value
}

사실 'pointToAdd' 필드는 백엔드에서 계산 가능한 값이므로 넘겨줄 필요가 없습니다. 하지만 UX를 위해 프론트엔드에서 이 값을 미리 계산해 사용자에게 보여준 상태이고, 이에 따라 API에도 검증을 위해 필드가 추가되었습니다.

 

저는 이런 설계가 좋은 설계인지 의문이 들었습니다. 서버가 결국 UX에 관여하고 있는 구조이기 때문입니다. 서비스 내로 UX 로직들이 침투합니다. 따라서 리뷰어님께도 여쭤봤는데요.

 

이에 대한 리뷰어님의 답변은,

  1. 일차적으로 서버에서 내려주는 값만 사용하는게 좋아보인다.
  2. 하지만 클라이언트에서 어떠한 이유든 연산을 해 미리 보여줘야 하는 경우, 데이터 자체를 바꾸는 등의 복잡한 연산을 하는게 아니라면 굳이 검증 로직이 들어가야 하나 싶다.
  3. 하지만 검증을 반드시 해야 할 필요가 있다면 API를 따로 분리할 필요가 있는지를 검토해본다(검증 전용 API).

이었습니다. 사실 저도 이상적인 건 서버에서 내려주는 값만 클라이언트에서 사용하는 것이라 생각하지만 (데이터의 정합성을 위해) UX를 위해 일정 부분을 내어줘야 할 때도 있다는 것을 느끼는 계기였습니다!