이 모든 포인트는 모바일 개발, 웹 프론트엔드, 백엔드에 적용될 수 있습니다. 저는 지난 6년 동안 직면한 문제를 통해 여러 팀의 이러한 관행을 수집했습니다. 이러한 방법은 프로젝트를 처음부터 빌드할 때 특히 유용할 수 있습니다. 그 중 일부는 귀하에게 완벽하게 적합할 수도 있고 일부는 그렇지 않을 수도 있습니다. 자신만의 접근 방식과 다양한 경험이 있다면 여기에서 공유해 주시면 감사하겠습니다. 그런데 승진을 원하는 중간 또는 하급 개발자라면 팀에서 이러한 관행을 구현하는 것이 정말 도움이 될 수 있습니다. 갑시다!
표준 소프트웨어 개발 프로세스에서는 비즈니스에서 새로운 기능 요청이 들어오면 프런트엔드, 백엔드, 모바일 앱 개발 등 여러 팀에 배포됩니다.
이후 각 팀은 기획 및 업무 분해를 진행합니다. 하지만 백엔드 팀이 해당 부분을 개발하는 데 훨씬 더 많은 시간이 필요하다면 어떻게 될까요? 일주일에 한 번만 엔드포인트를 제공할 수 있다면 어떻게 될까요?
백엔드에 병목 현상이 발생합니다.
모바일 및 프런트 엔드 개발 팀은 결국 다음과 같이 작업하게 됩니다. "아, 백엔드는 이미 이것을 구현했습니다. 이 작업은 제가 맡겠습니다." 그런 다음 휴식을 취하고 상황을 다른 기능으로 전환하면 주기가 계속됩니다. 이는 피로, 속도 감소 및 품질 저하로 이어집니다.
해결책: 백엔드 팀과 계약에 동의하고 모든 요청을 모의합니다.
1. 엔드포인트 및 엔터티에 대해 백엔드 팀과 협력합니다.
2A. 스텁 응답으로 백엔드 API를 구현합니다. Faker 라이브러리는 샘플 데이터 생성에 도움이 될 수 있습니다.
2B. 또는 프런트엔드에 스텁을 구현하세요. 이는 코드에 직접 데이터가 포함된 개체일 수 있습니다. 예를 들어 Node.js에서는 동적 가져오기를 사용하여 이를 효율적으로 구현하고 번들 크기 증가를 방지할 수 있습니다.
getUser() { return import('../../assets/mocks/users') .then(data => data.userById) .then(deserializeUser); };
이는 실제 요청을 하는 대신 자산에서 JSON 파일을 가져오는 모의 HTTP 서비스일 수도 있습니다.
기능 플래그 뒤에 기능을 숨깁니다.
백엔드가 준비되면 프런트엔드 스텁 접근 방식을 사용한 경우 실제 API로 전환하고 모든 것이 예상대로 작동하는지 확인합니다. 그리고 이 기능을 켜보세요.
이제 눈치채셨겠지만 이전 섹션에서 기능 플래그에 대해 언급했습니다. 간단히 말해서, 기능 토글이라고도 불리는 기능 플래그를 통해 개발자는 실제 환경에서 기능을 켜거나 끌 수 있습니다. 새로운 기능을 점진적으로 출시하고, A/B 테스트를 수행하고, 베타 기능을 활성화하고, 핫픽스를 구현하는 등 유용한 경우도 몇 가지 있습니다.
우리는 기능 플래그를 저장하기 위해 Gitlab을 사용합니다. 백엔드 및 프런트엔드 프로젝트 모두에서 사용되는 전용 저장소입니다. 좋은 소식은 사용자 친화적인 UI가 있어 제품 관리자가 스스로 기능을 관리할 수 있다는 것입니다. 이전에는 각 프로젝트 저장소에 대해 개별적으로 기능 플래그를 사용했습니다. 그러나 이 접근 방식은 전체 제품의 기능을 한 번에 비활성화하는 기능을 제공하지 않았습니다. 그래서 우리는 모든 것을 단일 저장소로 옮깁니다.
코드에서는 매우 간단해 보입니다.
if features.YOUR_FEATURE
.
우리 제품이 MVP 단계에서 프로덕션 애플리케이션으로 전환될 때 우리는 재현할 수 없고 인식조차 할 수 없는 오류가 사용자에게 발생할 것을 우려했습니다. 오류 추적 도구를 조사한 후 Sentry를 선택했습니다. 경험은 긍정적이었습니다. 이제 몇 가지 중요한 뉘앙스를 살펴보겠습니다.
내부적으로는 포착되지 않은 모든 예외가 추적됩니다. 애플리케이션과 사용자 수가 증가함에 따라 오류 수가 너무 많아 정말로 중요한 사항을 알아차리는 것이 거의 불가능해집니다. 불필요한 것들을 필터링하지 않으면 Sentry가 쓰레기 수거통으로 변할 수 있습니다. 예를 들어 취소된 요청, 연결 오류 및 연결된 스크립트의 오류와 같은 이벤트는 전혀 쓸모가 없으며 알림과 함께 업무 이메일만 스팸으로 보냅니다. 해결책으로 구성에 필터를 추가할 수 있습니다. 이렇게 하려면 beforeSend
콜백을 정의하고 sentryPackage.init
에 넣기만 하면 됩니다. 이 콜백에서는 발견된 각 오류를 분석한 다음 쓸모 없는 경우 이를 삭제할 수 있습니다(null을 반환하여). 불필요한 오류를 제외하는 필터의 예는 다음과 같습니다.
function beforeSend(event, hint) { const error = hint.originalException; const externalScripts = [ 'gtm.js', // Google Tag Manager 'watch.js', // X Analytics ].join('|'); const errorsToIgnore = [ AxiosError.ERR_NETWORK, AxiosError.ECONNABORTED, AxiosError.ETIMEDOUT ]; if (axios.isCancel(error) || errorsToIgnore.includes(error.code) || error.stack?.match(externalScripts)) { return null; } return event; }
기본적으로 Sentry는 오류 보고서에 요청 및 응답 내용을 포함하지 않을 수 있습니다. 이 정보가 없으면 적절한 디버깅이 불가능합니다. 다행히 beforeSend
핸들러에 이 정보를 포함할 수 있습니다.
function beforeSend(event, hint) { const error = hint.originalException; if (error.isAxiosError) { const url = error.request?.responseURL; const response = error.response?.data; const request = error.config?.data; event.extra = { ...(event.extra || {}), url, response, request }; } return event; }
오류 내용에는 비밀번호, 이메일 주소, 키 등의 데이터가 포함되어서는 안 됩니다. Sentry에는 이러한 유형의 정보를 숨기는 메커니즘이 내장되어 있습니다. 보안 설정에서 구성할 수 있습니다. 게다가 beforeSend
의 이벤트 객체에서 무언가를 제거할 수도 있습니다.
귀하의 비즈니스 특성상 이러한 종류의 데이터를 다른 서버에 저장할 수 없는 경우 Sentry는 해당 데이터를 귀하의 자체 서버에서 사용할 수 있는 기능을 제공합니다.
Sentry에서 오류를 성공적으로 캡처했지만 설명의 정보가 부족한 상황을 상상해 보세요. 로그를 보면 수천 건의 요청과 초당 더 많은 로그 라인 중에서 특정 오류를 어떻게 식별할 수 있습니까? 특히 비즈니스에 여러 팀이 있고 다른 서비스와 통합하는 경우 올바른 팀을 구별하고, 요청 체인을 구성하고, 정확한 오류를 정확히 찾아낼 수 있습니까? 여기서 추적이 시작됩니다.
특정 구현에서는 OpenTracing API를 기반으로 하는 Jaeger를 사용했습니다.
간단히 말해서, 각 요청과 해당 요청의 모든 메서드 호출에는 고유한 레이블이 지정됩니다. 각 라벨에는 해당 상위 라벨과 일부 메타데이터에 대한 참조가 있습니다. 이 번호의 구조는 구현에 따라 다르지만 OpenTracing의 경우 공식 저장소 페이지 에서 작동 방식을 읽고 범위, 참조, 하위, 상위 등과 같은 용어에 익숙해질 수 있습니다. 실생활에서는 운 좋게도 추적이 거의 사용되지 않습니다. 그러나 이러한 드문 사고에서는 시간을 절약할 수 있습니다.
핀테크 앱의 MVP를 구현했을 때 꽤 복잡한 형태를 갖고 있었습니다. 그 당시 나는 아직 어리고 경험이 부족했습니다. 그리고 결국 우리는 프로젝트가 느려지고 있다는 것을 깨달았습니다. 이유를 알아내려면 추가 시간을 소비해야 했습니다. React에서 props와 관련된 기본 규칙을 무시했기 때문에 불필요한 re-render가 많이 발생했습니다. 앞으로는 이런 상황이 발생하지 않도록 최선을 다하고 싶었습니다.
그래서 저는 이와 같은 프로젝트 린터에 추가하고 Why-did-you-render 를 실행하기 위해 package.json에 추가 시작 구성을 추가했습니다. 간단히 말해서, 이 플러그인은 무언가가 불필요하게 다시 렌더링되면 경고를 표시하고 이를 방지하는 방법을 제안합니다. 또한 헤드리스 모드에서 Lighthouse를 실행하는 것도 포함했습니다. 어떤 사람들은 성급한 최적화가 나쁘다고 말하지만, 나에게는 처음부터 올바르게 수행하는 것이 원칙입니다.
깨진 유리창 이론이라는 말을 들어보셨을 겁니다. 건물에 깨진 창문이 하나 있는데 아무도 그것을 교체하지 않는다면 결국 그 건물에는 손상되지 않은 창문이 하나도 남지 않게 될 것입니다.
프로젝트에 규칙과 제어가 적을수록 품질이 낮은 코드를 작성하거나 완전히 다른 스타일로 작성하려는 유혹이 커집니다. 일관되지 않은 코드는 이해하는 데 걸리는 시간을 늘리는 반면, 명확하고 친숙하며 간결한 코드는 빠르게 읽을 수 있도록 해줍니다. 우리 팀 중 한 곳에서는 코딩 스타일을 한 곳에서 설명했습니다. 좋은 출발점으로 Prettier 또는 Airbnb 코드 스타일을 사용할 수 있습니다.
다양한 유형의 테스트, 접근 방식 및 이를 올바르게 작성하는 방법에 대해 이미 상당한 양의 문헌이 작성되었습니다. 여기서 언급할 가치가 있는 유일한 점은 회귀 테스트 없이는 어떤 프로덕션 애플리케이션도 살아남을 수 없다는 것입니다. 그렇기 때문에 우리는 포괄적인 End-to-End 테스트 프레임워크를 만드는 데 모든 노력을 집중했고, 이를 기반으로 BDD 시나리오 및 사용자 스토리와 연결되는 테스트를 작성했습니다. 우리는 페이지 개체 패턴을 사용하여 브라우저와 상호 작용하기 위한 코드와 Playwright 프레임워크를 구성했습니다. Safari를 포함한 다양한 브라우저에서 테스트하려면 Moon 이라는 솔루션을 사용할 수 있습니다. 서버 중 하나에 배포할 수 있습니다.
시간을 내어 이 기사를 읽어주셔서 감사합니다! 결론적으로 이 기사에서는 개발 프로세스와 코드 품질을 향상시키는 주요 소프트웨어 엔지니어링 사례를 강조합니다. 백엔드 응답 모의, 기능 플래그, 오류 모니터링, 성능 최적화, 코드 스타일 표준, 회귀 테스트, 추적과 같은 기술을 채택하면 보다 효율적이고 안정적인 소프트웨어를 만들 수 있습니다. 계속해서 소프트웨어를 개선하고 연락을 유지합시다! :)
이 기사의 리드 이미지는 HackerNoon의AI 이미지 생성기 에서 프롬프트 "speed"를 통해 생성되었습니다.