본문 바로가기

All

(48)
[개발생각] Apache Camel에 대해서 아파치 카멜 처음 잠깐 써본게, 18년 정도 된거같은데... 최근에 각잡고 써보니 쓸만하다!! 인터넷 찾아보니, 최초 릴리즈가 2007년...ㅎㄷㄷ잠깐 사용했을때가, 나온지 1-2년된 따끈따끈한때였구나 ㅋ그때도 어느정도 성숙한 오픈소스여서, 꽤 유용했던것으로 기억한다.특히 간단한 ETL, BATCH 잡에 사용하기 정말 강력했던 기억이다.물론, 스프링배치가 배치쪽은 아직 꽉 잡고있다고는 하지만, 스프링배치는 너무 초기 러닝커브가 있다는 점이 아쉽다.최근에 카멜을 다시 쓸일이 있어서, 좀 자세히 알아봤는데, 실시간 이벤트 처리에 관해서는 꽤 괜찮은 솔류션으로 보인다. 우선 병렬처리에 대한 접근이 쉽다.샤딩을 직접 해서 대상을 만들거나, 파티션으로 데이터를 읽거나 하는 방법을 쓰지않아도 (물론 쓰면 더좋다),..
[개발생각] 오래걸리는 작업에 대한 처리 오래걸리는 외부 API의 결과를 데이터베이스에 저장하는 기능을 개발해야한다면, 어떻게 구현해야할까? 내부 API는 30ms~100ms 내외의 응답속도를 보장해야하기도 해서, 큰부담없이 사용할수있겠지만,외부에서 제공하는 API들은 기능에 따라서 길게는 수초에서 수십초가 걸리는 것도 있다.(스크래핑, 대용량 데이터 응답(빅데이터 조회)등) 이경우 해당 응답을 데이터베이스에 저장을 해야하는 비즈니스 로직이 존재한다면,어떻게 구현을 해야, 개발 잘했다고 소문이날까?!! 우리는 몇가지를 고려해야한다. >>>1) 외부API의 장애에 대한 처리가 있어야 한다. - 외부API의 응답속도가 현저히 떨어지거나, 장애로 인해 접속에 문제가 있는경우는 지속적으로 외부API를 호출하지 않도록,방어장치가 있어야 한다. - 간단..
[개발생각] Kafka 이벤트와 트랜잭션에 대해서 트랜잭션과 비동기 프로세스의 처리에 대해서, 인지하고 있어야 할것이 있다. 가끔 카프카 이벤트와 트랜잭션에 대해서 혼돈이 일어날때가 있어서, 적어두고자 한다. @Transactionalfun saveUser() { userRepository.save(User(id = "test")) kafkaEventPublisher.send(Event("SaveUser"))}@Transactional@KafkaListenerfun listener(event:String) { val user = userRepository.findById("test") user?.let { println("user is not null") } ?: println("user is null")} 이경우..
[개발생각] 우수한 개발 집단이란? 개발력이 우수한 집단에는 공통된 특징이 있다. 기획자 집단과 개발자 집단이 모두 우수하다는 것이다.개발력이 우수하다는것을 일반인들은 단순히 개발자들이 뛰어나서, 뚝딱 무언가를 잘 만들어 낸다는것으로 착각한다.하지만 개발자들이 서비스를 잘 만들기 위해서는,각자의 실력이 뛰어나야 함은 기본이고, 잘 기획된 기획서가 필수가 되어야한다.아무리 우수한 병사들이라도, 이 산,저 산으로 목적성없이 이동하면 힘이 빠지는 경우랄까? 따라서, 잘 만든 서비스를 위해서는,기획자 집단의 서비스에 대한 꼼꼼한 기획서는 필수가 된다.내가 개인적으로 생각하는 각 집단의 역할은 명확하다. 1) 기획자 집단- 만들려는 서비스를 '문서'로 만들어 내는 역할이다.- '문서'를 보면, 서비스가 A-Z까지 모두 파악이 되는 꼼꼼한 기획서..
[개발생각] Webview앱 vs Native앱 앱을 만들때, 웹뷰로 만들지, 네이티브로 만들지는 한번쯤 고민해 보는것 같다. 참고로, 개인프로젝트면 웹뷰가 편하긴 한것같다..ㅋ(Dart, Swift등 또 배우기, 귀찮아...) 웹뷰앱과 네이티브앱 장단점을 생각했을때, 만약 최고의 앱을 만들 목표라면, 너의 선택은? 이라고 누군가 묻는다면, 나는 '네이티브앱'을 선택할듯하다. 외국어도 네이티브가 제일 외국어 잘하지... 앱도 네이티브가 성능, 기능면에서 더 뛰어난건 반론을 할수가 없지 않을까? ㅋ 그렇다면, 네이티브앱이 가장 큰 단점이라고 생각하는것은? 이라고 묻는다면, 배포/장애대응등이지 않을까..하지만, 이걸 단점이라고 생각하기보다는, 장점을 얻기위한 트레이드오프라고 보고, 배포/장애에 대한 대응을 잘 할수있도록, 프로세스를 만들고, 실수를 줄이도..
[개발생각] CI/CD unittest를 위한 인프라 환경 구성의 방법 Embadded infrastructure환경을 구축하자. (어디서든 테스트코드가 동작하게 만들자, 생각만해도 편하네) 로컬에서 유닛테스트 코드를 작성하고, 로컬 도커에 설치된 인프라환경(mysql, kafka, redis등등)으로 붙어서,유닛테스트를 돌리게 구성을 해놨었다.참, 로컬에서 인프라환경을 도커로 구성하니, 유닛테스트하기도 좋기 참 편했다. (나름 만족!! ^^) 그러던중, 이제 마지막 단계, CI/CD로 배포가 되는 파이프라인에도 unittest를 동작하도록 하고, 모든 테스트가 성공할때, 빌드를 진행하려고 하니, 고민스러운 부분이 생겼다. 바로 unittest infra환경이다.ci/cd가 독립적으로 인프라 환경을 구성하고, 해당 인프라 환경으로 접근하여, 유닛테스트가 실행되도록 하고싶었다..
[개발생각] 어플리케이션 레이어에서 UseCase와 Service의 동일시 DDD, 클린아키텍쳐기반으로 설계를 하다보면, UseCase와 Service를 동일시 보고, 하나 개념으로 합치고 싶은 욕망이 들때가 있다. 책이나, 블로그등에 따르면 뭔가 잘못된 생각같고, 찜찜하고 아닌것같은 생각을 하고, 잠시 욕망을 접었던 기억이 많다. 대부분 책에서는 어플리케이션 레이어에서의 UseCase를 '행위의 정의'로 보고, Service는 이런 UseCase들을 이용한 '퍼사드 개념'으로 본다. 그런데, 이론은 그렇다고 해도, 일반적인 서비스에서 저렇게 UseCase와 퍼사드 Service로 나뉘는 경우가 많을까? 의구심이 든다. 그리고 Service를 UseCase의 정의대로 구현하면 (UserGetService, UserLoginService등), 행위의 정의와 퍼사드 개념을 펄쳐서 ..
[개발생각] Test코드 작성시, Fixture의 관리에 대해서 Mock용 객체를 기준값에서 파생되게 만들면, Mock객체의 통일성을 유지할수있고, 서로다른 테스트코드에서도 일관성을 유지하며 테스트코드를 작성할수있다. 테스크 코드를 작성할때, Mock용 User정보, Address정보, Device정보등, 테스트 실행시 필요한 정적인, 준비된 데이트들을Fixture라는 명아래, UserFixture, AddressFixture,DeviceFixture 등의 이름으로 모아두고, 활용하게 된다. 여기서 조금만 관리를 소홀히 하면, Fixture클래스는 온갖 데이터가 난무하는고, 중복 코드가 난무하는 클래스, 즉, 애물단지가 되버린다.여기서 Fixture를 더럽히는 가장 큰 요인하나가, 일관성없는 Mock용 데이터들 정의다. val user1 = User(id=1, na..
[개발생각] 익숙치않은 개발(론)에 팀원들을 적응시키는 방법에 대해서 개발자라면, 같은 회사에서 오랜기간 개발하게 되면, 그 회사만의 방식/방법에 익숙해지게 마련이고, 마치 관습과도 같이 코드를 작성하게 된다.이런게 '콘웨이 법칙'의 예가 아닐까? ㅎㅎ 만약 위와 같은 상황에 지속적으로 노출된다면, 개발자는 점점 관습으로 개발을 하게 되고,(관습이 나쁘다는 이야기는 아니다. 다만, 필연적으로, 개발에 고민하는 시간이 줄어든다는 이야기이다)어느 순간 개발자가 아닌 코더로 전락하게 된다.그런데 정말 무서운것은 코더가 된것을 자신은 모른다는것이다... 정말 무섭다.. 나도 코더였던 경험이 있다. (지금은 당연히 코더가 아니라고 자신있게 말할수있다 ㅎ)대학 졸업후에, 작은 SI개발회사에서 몇년 일하게 됬는데, 어느 순간, 내가 일명 CCCV (컨트롤 C + 컨트롤 V)의 고수가 ..
[개발생각] SOLID원칙에서 I의 경험에 대해서 여러 같은 행위를 하는 Service 빈을 만들어야 할때가 있다. 이경우, 각각의 공통된 행위/과정을 인터페이스 스펙으로 설계하고,그 인터페이스 스펙을 구현하는 AService, BService, CService를 만든다.첫단계에서는 이런 스펙들이 하나의 인터페이스 클래스에 같이 존재하게 되는데,이 스펙들이 많아지고, 성격이 틀리게 되면, 적절하게 그룹핑을 하고, 나눠야 하는 시점이 오게된다. ASpec, BSpec, CSpec등으로 인터페이스 클래스로 나누고, 해당 스펙을 구현하는 구현체를 만든다.구현체는 한개의 클래스에서 모두 구현하는게 아닌, 각각의 스펙별로 별개의 역할을 하는 구현체로 별도로 만드는게 훨씬 깔끔해진다.(일정부분, 단일책임원칙과도 맞는 부분이다) 이 스펙 클래스를 구현한 구현체들은 ..