Series 26

Custom LocalDateUtils 리팩토링

이번에 회사 업무의 일부를 확장/분리하는 업무를 맡았습니다. 프로젝트의 세팅부터 해야 되는 작업이었기에 제가 주도적으로 개발할 수 있었는데요. 이 과정에서 작업한 Legacy의 공통 Util 리팩토링의 일부를 기록해봅니다. AS-IS의 문제점 // 0. 이 프로젝트에 의존적인 로직이 존재합니다. // ex) 입력 값이 파싱할 수 없는 isEmpty() 라면 빈 값을 반환. (에러가 아니라) @UtilityClass public class LocalDateUtils { // 1. LOCAL_DATE_FORMAT_WITH_HYPHEN, LOCAL_DATE_FORMAT 이 String 변수로 존재합니다. public static final String LOCAL_DATE_FORMAT_WITH_HYPHEN = ..

Series/실전! 2022.01.04

Datadog 에서 GraphQL 모니터링 맛보기

이 글에서는 널리 쓰이는 모니터링 솔루션 중 하나인 datadog을 적용하면서 알게 된 정보를 기록해봅니다. 공식문서에 있는 내용은 언급만 하고 넘어가며, 완결되지 않은 이슈들도 있기에 맛보기로 생각하고 읽어주세요! AS-IS 자동화된 모니터링 룰이 없으며, cloudwatch로 사후 모니터링만 가능. datadog를 도입하기로 했으나, graphql이 제대로 지원되지 않음. datadog 은 공식 문서가 잘 나와있는 편이기에 설치나 일반적인 세팅에는 어려움이 없었습니다. 특히 resource를 기반으로 제공되는 기능들이 강력해서 REST API를 쓰는 환경이라면 크게 어려움 없이 세팅이 가능했습니다. 하지만 당사에서 사용하는 graphql 은 resource 가 모두 POST /graphql로 통일되어..

Series/실전! 2021.12.14

느슨한 결합도의 설계를 위해! (2)

요구 사항 정리와 AS-IS 분석은 끝났지만 설계하기 전에 개발 범위 산정과 제약 조건을 먼저 생각해야 합니다. 목표 달성을 위한 리팩토링은 끝이 없기에 일정과 범위를 조율해야 하고, 개인의 이해도는 차이가 있기에 실무의 설계는 범용적인 구성을 해야 합니다. 디자인 패턴 공부의 필요성을 느끼는 요즘입니다. 이런 생각을 가지고 개발한 과정을 기록해봅니다. 개발 범위 산정 최소 개발 범위는 심플하지만 앞으로 알림 톡의 종류가 많아질 것을 대비하면 AlarmGqlService의 호출도 interface로 만들고 내부 서비스들도 표준화시키는 것이 좋을 것 같습니다. 하지만 개발 범위를 AlarmGqlService까지 확장하면 입력부에 대한 검증과 interface 설계에 따른 리팩토링도 추가되어야 해서 '알림 ..

Series/실전! 2021.12.04

느슨한 결합도의 설계를 위해! (1)

높은 응집도와 느슨한 결합도의 설계는 객체 지향을 공부하는 사람이라면 누구나 고민하는 주제입니다. 공부는 했었지만 부끄럽게도 잘 활용하지 못하던 중 같이 공부하는 로치의 글을 보고, 또 운 좋게 설계가 필요한 업무를 맡게 되면서 개발한 내용을 기록해봅니다. 응집도와 결합도 응집도와 결합도는 소프트웨어 품질을 결정 짓는 요소이다. 대다수의 사람들은 코드를 작성할때 "응집도" 와 "결합도" 를 생각하지 않은채 관성적으로 코드를 적고는 한다. 응집도와 결합도는 devroach.tistory.com 업무 배경 알림 톡 발송의 주체는 외부 업체로 Lambda를 통해 연동되어 있습니다. 발송 기록은 저장되고 있습니다. (백엔드 - RDB, Lambda - DynamoDB) 개발 요건 Lambda API의 주소가 변..

Series/실전! 2021.12.03

DB 값을 enum 으로 표현해보자

enum 은 서로 연관된 상수들의 집합으로 반복적으로 사용되는 코드 값을 표현할 때 유용합니다. 실무에서는 개발 편의성을 위해 DB에 있는 업무 코드들을 표현하기도 합니다. (등급 코드, 사용 여부 등) 하지만 프로젝트가 나눠지면 매번 복사해줘야 되고, 변경점이 생기면 반영이 필요하기에 썩 좋은 아이디어는 아닙니다. 때문에 쉬운 방법으로는 코드 테이블을 만들거나, 최신의 개발에서는 코드 정보를 MSA로 나누기도 합니다. 그럼에도 불구하고 업무 성격상 변경이 매우 적은 경우에는 개발 편의성과 성능 향상을 위해 사용할 수 있기에 실무에서 해본 리팩토링 내용을 기록해봅니다. Java Enum 활용기 | 우아한형제들 기술블로그 {{item.name}} 안녕하세요? 우아한 형제들에서 결제/정산 시스템을 개발하고 ..

업무에 적절한 pagination 선택하기

pagination은 백엔드 구현에서 가장 많이 고려해야 되는 기술 중 하나입니다. 일반적으로 알려진 pagination 기술에는 page, slice 가 있고 특수한 경우에 사용되는 noOffset과 Covering Index 기술이 있는데요. 이번 글에서는 실무에서 만난 특이한 pagination 사례에 대해 각색하여 기록해봅니다. 업무 요건 전체고 조회가 필요합니다. 상품군이 신설되었습니다. 기존에는 회사와 상품이 존재했으며 M:N 관계입니다. 상품군과 상품은 1:N 관계입니다. 상품군과 회사의 관계는 M:N 관계입니다. 서로 다른 재고처에 있는 재고를 합쳐야 합니다. 각 상품군별, 회사별로 소계를 보여주어야 합니다. 페이지당 300개 안팎은 허용 범위입니다. 기술적 배경 각 도메인별 조인이 많이 ..

Series/실전! 2021.11.07

Elastic Beanstalk 구성 삽질기 - 글쑤시개

개발 초기에는 AWS 구성을 하는 것도 일이기에, 지금까지는 프론트 개발자가 백엔드 소스를 받아서 local에서 서버를 띄우는 방식으로 진행했습니다. 물론 매번 DB를 올리지 않아도 되도록 local h2 구성을 해주고, 실행 편의 방법과 README를 제공해줬지만 프론트 개발자 입장에서는 불편한 게 현실이었습니다. 그러던 중 슬슬 목표한 앱의 한바퀴가 성공했기에 AWS 구성을 해보았고 그 기록을 남겨봅니다. ⚠️ 주의! 이 글은 사이드 프로젝트 구성을 위한 삽질기이기에 접근 제어 및 보안이 실무 수준에 미치지 못합니다. 실무에서 고려해야될 사항이나 도움이 될만한 내용은 코멘트했지만, 개인적인 경험에서 나온 기록이기에 선별적으로 이해해주시면 감사하겠습니다. # 계획 작업 전 배경 지식 실물 장비 기반의 ..

Slack Bot 으로 채널에 글쓰기

옛날에 채널에 글을 작성하는 슬랙 연동을 했을 때는 webhook으로 했던 것 같은데, 다시 해보니 잘 안됐습니다. 정확히는 local 에서는 됐지만 github에 올리면 webhook url 이 바뀌는 현상이 발생했습니다. 이상해서 검색해보니 요즘은 slack API 를 연동하는 것이 최신이기도 하고 webhook 보다 다양하게 쓸 수 있을 것 같아서 연동해본 내용을 기록합니다. 사전 조사 Using Slack APIs Every Slack app has access to a bag of tricks—a range of APIs that provide access to read, write, and update all kinds of data in Slack. api.slack.com 먼저 slack ..

DynamicUpdate 활용기

GitHub - Hyune-c/blog-code: https://hyune-c.tistory.com/ 의 예제 code https://hyune-c.tistory.com/ 의 예제 code. Contribute to Hyune-c/blog-code development by creating an account on GitHub. github.com 팀으로 진행하고 있는 사이드 프로젝트에서는 회원 관리를 자체적으로 구현했습니다. 로그인도 별 문제없고 잘 되는 줄 알았는데, 어느 순간 로그인이 되지 않는 현상이 발생했습니다. 다행히도 문제는 금방 해결했지만 생각할게 많아진 주제였기에 기록을 남겨봅니다. 1. 회원 구현 @Entity public class Member { @Id @GeneratedValue(..

표준 예외 처리에서 로깅까지 (2)

Step 3. 비동기 로직 @Configuration @EnableAsync public class AsyncConfiguration implements AsyncConfigurer { } 먼저 비동기 사용을 위한 설정을 추가합니다. @RestController public class AsyncTestController { private final AsyncService asyncService; @GetMapping("/api/test/async") public void asyncTest() throws InterruptedException { for (int i = 1; i { if (copyOfContextMap != null) { MDC.setContextMap(copyOfContextMap); }..