백엔드를 하다가 프론트로 전향한 입장에서, 이건 프론트엔드의 역할 때문에 그런거라고 생각해요 ㅎㅎ 보통 백엔드에서 객체지향을 하는 이유는 복잡한 도메인 로직을 관리하고, 도메인 로직과 네이티브간의 격리를 위해서라고 생각하거든요. 그런데 프론트엔드에서 도메인 로직을 처리하는 경우가 거의 없기 때문에 굳이 객체지향을 깊게 적용할 필요가 있을까? 하는거죠 가령 계산기를 만든다고 치면 이건 객체지향 없이 관리하기가 무척 힘들어요 계산기라는 앱을 다루기 위해선 UI를 그리는 부분과 계산기 도메인을 다루는 부분을 분리해야 할텐데 대부분의 웹서비스는 UI에서 입력 받고 서버에 요청 보내서 응답 받고 출력해주는거죠 도메인 로직이 거의 완전히 백엔드에 위임된 상태입니다 그러니까 굳이 객체지향이 필요할까? 하는거죠 반대로, 리액트로 UI를 만드는게 아니라 리액트 자체를 만든다고 생각하면 객체지향이 빠질 수 있을까요? 다루는 영역의 차이라고 생각합니다 ㅎㅎ 그래서 객체지향을 경외시 하기 보단 객체지향이 추구하는 목표나 개념은 꼭 숙지할 필요가 있다고 생극해요 그래야 어려운 난이도의 일을 할 때 조금 더 수월하지 않을까 싶네요 ㅋㅋ
1 왜 웹 프론트엔드에서는 정해진 대표적인 MVVM, MVC 와 같은 이러한 아키텍쳐가 없나요? 웹에서 프론트엔드 백엔드 경계가 없던 2000년대 시절에는 이미 웹에서 HTML+CSS+JS 영역을 View라고 부르고 데이터를 Model, 라우터 서버스크립트 영역을 Controller라 부르면서 MVC 패턴이나 아키텍쳐는 이미 존재했습니다. 이후 jQuery시절이 끝나고 웹 프론트엔드가 생겨날 무렵 backbone이나 ember와 같은 기존의 MVC 개념을 바탕으로 하는 프레임워크들도 나왔으나, knockoutjs, angularjs와 같이 HTML에서 템플릿과 치환자 그리고 데이터 바인딩과 자동 업데이트라는 방식이 기존의 MVC 개념보다 훨씬 더 효율적이고 쉽게 화면과 모델을 만들 수 있다는 것을 알게 되면서 이러한 방식이 대세가 되어 웹은 MVC를 건너뛰고 MVVM 아키텍쳐가 주류가 되었고 이 기조는 지금까지 이어집니다. 이후 FLUX 패턴이나 현재에 이르는 상태관리처럼 웹이 훨씬 더 이러한 아키텍쳐에 대해서 선구자적인 역할을 했고 이것들이 MVVM이나 MVI처럼 이름이 붙여지고 정리되는 것들은 나중의 일입니다. 당시에는 이러한 방식을 두고 MVC 옹호론자들이 이게 MVC에 맞느냐 뷰와 컨트롤러가 너무 강결합이 되어 있다 라던가 반대파들이 아니다 이건 MVP(Presenter)로 불러야 한다던가 등의 논쟁이 있었는데, angularjs의 경우는 하면서 MVW (Whatever)이라 부르면서 굳이 이런방식에 이름을 붙이고 정하려 하지말고 모델과 뷰 사이에서 가장 효율적인 패턴을 적용한다는 의미로 불러달라고 했습니다. 이게 2010년도 입니다. 이렇게 선언형 뷰를 만드는 방식은 이후 안드로이드나 ios Swift등에서 나중에 도입되면서 이게 MVVM 아키텍쳐가 되었고 이후에 나온 스토어를 따로 두고 행동에 의해 데이터가 변경되고 이를 반영하는 방식의 FLUX 패턴들이 MVI 등으로 정리가 되면서 이러한 아키텍쳐들이 벤더에 나중에 정리가 되며 적용이 되고 있는데 반해 웹은 계속 발전 중입니다. 2020년도에 MVVM을 웹에서 해보려고 시도한것이라기 보다는 이미 웹 프론트에서 하고 있던 방식이 ios, android에서 가서 MVVM 아키텍쳐로 정립이 되면서 swift UI등의 개념들이 소개가 되면서 웹과 같이 엮었던거며 이미 웹은 오래전부터 MVVM 형태의 아키텍쳐가 주류였습니다. 웹 프로트엔드가 과도기라고 하면 과도기가 맞지만 (20년째 과도기...) 어떻게 보면 벤더가 없기에 계속 선구자의 역할을 하고 있고 그러다 보니 매년 새로운게 나오고 뭔가 정리가 되려고 하면 새로운 개념들이 또 나오고 있다보니 아키텍쳐로 정리가 되기 보다는 하나의 라이브러리와 넘쳐나는 새로운 개념과 아젠다들로 뒤덮여 있다보니 뭔가 웹 프론트엔드를 보기에는 이렇다 할 만한것으로 하나의 좋은 형태가 정해지지 못한것처럼 느껴진다고 볼 수 있을 것 같아요.
2 DI와 같은 방식을 코드로 보고 싶어요. 일단 웹 프론트엔드에서 쓰는 자바스크립트가 완전 함수형 프로그래밍 언어도 아니고 객체 지향 기반의 언어도 아니면서 프로토타입 객체지향을 기반으로 언어이지만 class는 잘 사용하지 않으려고 하는 경향이 있다는 것에 대해서 이해를 한다고 했기에 전제로 적어보려고 합니다. 특히 React가 클래스 기반에서 완전히 함수형 기반으로 넘어가면서 주류 된 만큼 점점 더 class보다는 function을 쓰는 형태로 발전해가고 있다고 생각합니다. 웹은 과도기가 맞는데 다시 class 전성기가 돌아올수도 있겠지만 지금까지는 오히려 class 과도기가 지나가고 function을 쓰는 방향으로 안정화가 되어가고 있다고 느껴집니다. 위와 같은 이유로 일단 class를 잘 쓰지 않으니 굳이 DI(Dependecy Injection)이라는 것이 FE에서는 자주 쓰이지 않는 개념인 것이지지, 유연함을 위해서 모듈을 분리하고 상황에 맞게 모듈을 끼워넣을 수 있도록 하는 방법들은 함수형 프로그래밍에서 얼마든지 있다고 생각하빈다. 완전 돌아가는 형식의 코드가 아니라 일부만 적어보겠지만 이해는 해주실거라 생각합니다. 1 가령 클래스에서 이렇게 분리된 코드를 DI를 통해서 결합하면서 사용한다고 한다면, public class MyApp { private readonly RepositoryLayer _repository; public MyApp(RepositoryLayer repository) { _repository = repository _repository.fetch(....) } } 리액트에서 Context API를 이용한 Provider에서 Service 바꾸기 (이것이 일종의 DI라고 볼 수 있다고 생각합니다.) import {repositoryService} const MyApp = () => { const repositoryService = useContext(Service); repositoryService.fetch(...) } 2 이러한 방식이 React에거나 아니라 비지니스 로직을 짜는데 있어서 class를 활용하고 있지 않기 때문에 이건 DI라고 보기 힘들다라고 하셨는데... const fetch_items = (service, params) => { return service.fetch(params) } 이런식으로 작성을 해서 인자로 받아와도 동적으로 처리를 한다거나 import {MyService } from "..." const service = MyService // 조건부나 빌드환경에 따라서 다른 서비스로 교체할수도 있음. const fetch_items = (params) { return service.fetch(params) } 와 같이 만들어도 DI와 같은 목적을 충분히 달성할 수 있고 아니면. create MyRepositoryServce = (serviceLayer) => { const fetch_items = (params) { return service.fetch(params) } return {fetch_items) } const m1 = MyRepositoryServce(serviceForProd) const m2 = MyRepositoryServce(serviceForTest) 이런식으로도 사용할 수 있을 거라고 생각합니다. 프론트엔드가 클래스를 사용하지 않아도 되는 상황이면 클래스보다는 함수를 사용하는 식으로 사고의 체계가 잡혀있게 되었는데 정확하게 어떤 목적과 의도에 맞는 코드를 원하는지는 정확하게 캐치못했을수도 있다고 생각을 합니다. 어떠한 의도와 목적인지를 안다면 그리고 그러한 취지에 맞는 코드를 구현하는데 있어서 더 나은 방식이 있는 거라면 억지로 우기는게 아니라 진짜 같이 고민을 해보고 싶습니다. 이 주제가 어그로가 끌리는 이유는 그럴 의도와 무관하게 논조가 다분히 '왜 백엔드에는 전통적인 객체지향 방식에서는 이러한 좋은 것들이 있는데 왜 프론트엔드에서는 이런것들을 안 사용하려고 하는 건지 이해가 안된다' 라는 식으로 전개가 되고 있는데 그 부분이 뭔지 얘기가 안되다보니까 각자 자기 입장에서의 얘기를 할 수 밖에 없는 것 같아요. FE 입장을 대변하고 함수형이 객체지향보다 낫다라고 말하고 싶은 것은 절대 아니며 자바스크립트는 특히 객체지향과 함수형의 밸런스가 중요하다고 생각하기에 프론트엔드 일변도가 아닌 다른 관점에서 좋은 방향성 특히 테스트와 아키텍쳐에 관해서는 FE에서도 늘 답을 찾고 싶어 하는 주제이기에 이러한 얘기들이 자주 논의되면서 괜찮은 방법들을 찾고 새로운 시각을 갖추고 싶습니다. (이렇게 말을 하지만 저도 제 입장과 관점으로만 말할 거라고 생가합니다. 배우고 해온게 있으니까요... ㅎㅎ)
인터페이스는 고정하고 스토어는 바꿀수 있는 구현체라는 관점에서 보면 DI를 실현하는 방법이 맞고 실제로 리액트 쿼리나 리액트 리덕스도 그렇게 쓰라고 애초에 컨텍스트 기반으로 설계되어있죠. 상위 프로바이더만 변경하면 되는 아주 깔끔한 부분적인 DI가 가능합니다. 꼭 클래스로만 IOC나 DI가 가능한건 아닙니다 ㅎㅎ
이 분들은 Class와 어노테이션으로 DI하는게 아니면 납득못하실거같아요, 본인들이 정말 언어에 상관없이 좋은 실력을 갖고있다면 언어의 특성을 이해하고 그 언어가 제공하는 추상화도구를 활용해서 정말 원하는 높은 응집도와 낮은 결합도를 지향하고 커플링을 최소화하는 OOP개념을 구현할수있는데 말이죠
Q. 앵귤러에서 제가 궁금했던 그런 내용이 풀리려나? 조금은 더 풀린다고 생각합니다 lit element도 마찬가지고 @, DI와 유사한 방식으로 코드를 구현할 수 있습니다 Q. 리액트로 테스트 짤 때 모킹이 아닌 테스트 짜는걸 본 적이 없고 테스트 아키텍쳐도 부족하다. Kent C. Dodds의 블로그 글과 강의를 보는 게 어떠신지 추천해봅니다. 하지만 보고도 그 갈증은 해결이 될 것 같지는 않네요.. 여전히 FE 영역의 테스트는 성장할 여지가 많이 남아있습니다. BE에 비해 축척된 연구와 사례가 부족한 것이 사실입니다. 또한 모킹은 MSW의 성장세를 봤을때 그 역할을 잘 할 수 있을 것으로 기대됩니다. Q. 리액트 아키텍처인 플럭스 아키텍쳐는 있지만 작성하는 사람이 그 아키텍처를 짜지 않으며 자유분방하고 통일된게 없고 세계적으로 평타치는 패턴을 보지 못했다 Next.js, Gatsby, Remix, Nuxt 말씀하신 그런 역할을 제법 잘해주고 있는 프레임워크들입니다. 성숙하고 진보되어 있으며 그래도 부족할 수 있지만 앞으로도 더 발전된 아키텍쳐로 FE 생태계를 이끌 수 있다고 봅니다. Q. 왜 웹 프론트엔드에서는 클래스를 잘 안쓰지? Q, DI 없이 어떻게 서로의 결합도를 낮출 수 있지? 저번 영상에서부터 계속 언급되는데요 클래스 쓰는 곳은 정말 많이 사용합니다. 생태계가 이끄는 트렌드가 모든 것을 대변한다고 느낄 수도 있지만 그 환경이 모든 것을 대변하는 것은 아니니까요 React 생태계는 횡단 관심사를 HOC로 해결해왔고 이제는 Hooks를 활용합니다 또한 DI도 이제 정식 스펙으로 등록될 일이 얼마 남지 않았습니다. 이미 과거에도 사용가능했고요 React에서는 이제 Context API와 Hooks라는 DI와 꽤 유사한 시스템을 제공합니다. 그리고 React를 기반으로 하는 유사한 라이브러리는 대부분 Context API와 Hooks를 활용하여 제공됩니다. 즉 고민하시는 DI는 React 생태계에서 use-Prefix로 사용하고 있다고 보시는 게 그나마 마음이 편하실 거라는 생각이 듭니다. Q. 프론트엔드 공부를 할걸 이미 한 분야의 훌륭한 개발자이신데 다른 영역에 대한 이해를 위해 노력하시는 것은 언제나 존경스럽습니다 Q. 고수 나와서 직접 코드로 설명해봤으면 좋겠다. 밑에 등장하셨네요 ㅎㅎ 코드스피츠라는 컨텐츠를 추천드립니다. 비사이드소프트 대표님의 훌륭한 강의들을 볼 수 있습니다. 아마 많은 인사이트를 얻으실 수 있을 것 같네요 --- 회사를 이끄는 테크리더인 두 분의 이야기에 왜 UI/UX에 대한 고민은 없는지 HTML CSS JS 그리고 브라우저에 대한 생각은 없는지 궁금했었습니다. 저는 FE가 주는 가치는 말씀하신 것에서만 나오지 않는다고 보거든요. 물론 귀사에서 가지고 있는 기술 부채나 해결해야하는 것들은 다를 수 있지만 사용자에게 좋은 환경을 주는 고민과 해결만으로도 충분히 할게 많습니다. 그러다보니 UI와 비즈니스 로직을 분리하려는 노력, 웹뷰 대응은 기본이 되고 있고 그 외에 디자인 시스템, BFF를 담당하는 개별적인 업무까지 생기고 있으니까요. 왜 프론트는 클래스와 DI를 안쓰지? 고수의 코드는 없나? 라고 느끼시고 고통받으시는 만큼 동영상을 보는 많은 분들도 왜 이렇게 클래스와 DI만 찾지? 없어도 되는데? 라고 생각하시는 경우가 있을 겁니다. 아직은 프론트엔드 생태계가 성장 중이라 답답하시겠지만 그래도 나름 성숙해지고 있다고 느껴요. 지금처럼 좋은 인사이트로 (고통과 고민ㅠㅠ)으로 많이 기여해주시면 생태계에 큰 도움이 될겁니다 앞으로도 좋은 활약 기대할게요!!
사실 클래스를 쓰던 뭘하던 저는 이게 저에게 큰 관심사가 아니에요. 어떻게 하면 최대한 프레임워크에 종속적이지 않게 코드를 작성하느냐? 플랫폼 비종속까지 아니더라도 적어도 js 내에서 최대한 생명을 유지 할 수 있게 코드할 것 인가? 이죠. 사실 좋은 코드는 어디에서든 쉽게 쓸 수 있다는 거죠. 근데, 리엑트를 보면 타 프레임 워크에서는 리엑트 코드의 커스텀 훅 같은 것을 불러다 쓸 수 없죠. 프레임워크 종속적이죠. 로직과 뷰의 경계가 애매할 때도 많아요. 또한 스파게티 코드가 될 가능성 많이 있기도 하고, 그래서 리엑트를 별로 좋아 하진 않는데,... 과거로 거슬러 올라 가면 이런 경험이 있죠. jquery 같은 것들이 과거 오랫동안 지배해왔고, 수많은 발전을 하였지만, 그 때 작성했던 수많은 플러그인들은 이제 언젠가는 사장될 산물이라는 것. 마찬가지로 리엑트 역시 영원하지 않다는 가정하에 그 길을 가고 있죠. 물론 영원한 것은 있을 수 없겠지만, 가능하면 수명을 연장하게 하고 싶죠. 그러기 위해서는 어느 프레임워크에 비종속적이어야 하고 로직의 영역과 뷰의 영역이 철저히 분해 되는 형태이어야 한다고 생각 해요. 그런 점에서 js내에서 코드를 그룹화 또는 추상화하는 가장 작은 레벨은 함수라고 생각 하고, 그러면 그 함수라는 것을 기반으로 어떻게 코딩해야 좋을 것인가의 대해 생각해보게 되네요. 그런 면에서 좀 더 순수 함수를 활용하기 좋은 svelt 같은 녀석들도 괜찮고, 또한 프레임워크 종속적이긴 하지만, 비지니스 코드가 명확히 분리되는 점, 의존성 주입, Rxjs에서 지원하는 수많은 유틸리티와 함수 pipe 등 rxjs들의 장점, 또한 svelt 대비 좀 major 하다는 점이 장점이 될 수 있죠. 하지만, svelt나 앵귤러나 리엑트 만큼의 인기를 구가하지는 못하고 있죠. 안타깝지만....
프론트엔드 개발을 하고 있는 입장에서 개발바닥에서 프론트엔드 컨텐츠를 다뤄주셔서 정말 너무 좋고 감사합니다. 이런 논의들이 더 많이 나왔으면 해요. 영상에서도 언급주셨듯, 다시 꺼내기 어려우실만한 내용들이었을텐데도 2편 만들어주셔서 너무 감사하고.. 3편 4편 더더 계속 기다리는 사람이 있다는걸 알아주셨으면 합니다. 향로님 준비중이시라는 블로그 글도 기대가 됩니다.!!
흥미로운 주제에 대해서 영상이 올라왔네요. 백엔드 -> 안드로이드 -> 웹프론트쪽으로 개발을 하고 있는데, 그렇게 고수라고 부를 정도의 실력도 안되고 이론적인 지식도 부족하지만 제가 느낀 점을 써보면 일단 웹프론트는 DI나 MVVM 같은 그런걸 쓸 필요를 잘 못느끼는것 같습니다. 일단 백엔드와 프론트의 차이점을 이야기 하면 백엔드는 독립성을 유지해야 하는 단위가 업무이며 이는 클래스로 구성을 하고 있습니다. 하지만 프론트의 경우는 독립성을 유지를 해야하는 단위가 화면이죠. 업무에 필요한 데이터의 경우는 각종 모델링 등을 통해서 계층 관계가 이루어 지지만, 프론트의 경우는 다루어야 할 대상이 눈에 보이는 화면의 조각의 모음입니다. 그리고 이 화면의 경우는 복잡한 업무가 필요한게 아니라 서버에서 데이터를 받아서 표시를 하고 UX,인터렉션 처리가주 업무입니다. 데이터의 경우는 이미 서버에서 인터페이싱된 데이터를 보내주기 때문이죠. 실제로 웹프론트에서도 MVVM이 안쓰인건 아니었습니다. 영상에서 나왔듯이 angular에서 먼저 mvvm 패턴을 도입을 했지만 결국 시장의 선택을 받은건 리액트나 뷰와 같은 컴포넌트 중심의 툴입니다. 리액트나 뷰에서 state라는 개념을 통해서 어느정도 mvvm의 개념(observer)을 가지고 있고, 서버의 경우는 인터페이스를 통해서 각 객체간의 독립성을 보장을 해주지만, 리액트나 뷰의 컴포넌트의 경우는 props가 그 인터페이스 역할을 하며 컴포넌트의 독립성을 보장을 해줍니다. 실제로 리액트의 경우는 초기에는 클래스 기반이었다가 16버전에서는 클래스를 버리고 hook이라는 작은 function개념으로 돌아섰습니다. 리액트 개발진들이 밝히기를 여러가지 개발 프로젝트를 관찰한 결과 클래스를 써야할만큼 복잡한 업무가 거의 없고 클래스는 오히려 코드의 난이도만 높힌다고 했습니다. 심지어 예전에는 mobx나 redux를 이용해서 업무영역을 store 분리하는게 대세였지만 요즘에는 이러한 거대 store도 조금씩 버려지고(?) 있는 추세인것 같습니다. 실제 개발코드 store중 70%~80% 이상이 단순 repository의 연계이고 소수의 업무코드를 위해 store를 유지하는게 오히려 더 비효율적이라고 생각되기 때문입니다. 즉, 화면을 만들때 가장 큰 관심사항은 얼마나 빨리 적은 비용으로 화면을 구성을 하고, 화면의 변화에 빠르게 대응을 할 수 있고 유지보수에 용이하냐 입니다. 그러한 개념으로 볼때 컴포넌트 기반의 리액트나 뷰는 제격인거죠. 눈에 보이는 구성요소를 컴포넌트로 작게 분리를 할 수 있고, 컴포넌트는 적은 비용으로 빠르게 제작이 가능합니다. 그리고 이러한 컴포넌트는 독립성을 유지하며 재활용성이 띄어납니다. mvvm이나 di를 쓰지 않더라도 좋은 코드의 특성을 지니면서 mvvm이나 di 대비 개발 비용 조차 저렴합니다. 이러한 요소들이 프론트에서는 OOP보다 함수형언어가 더 잘맞다고 보고 있구요. (개인적으로는 백엔드 분야에서도 OOP보다는 함수형언어쪽이 더 작은 비용으로 더 좋은 목적을 수행할 수 있다고 보고 서서히 변화해 나갈꺼라고 생각합니다.) 영상이나 댓글을 보면 안드로이드나 아이폰이 경우는 MVVM이나 DI가 있다고 말씀하시는데 저는 오히려 이러한 native 영역이 과도기라고 보고 있습니다. native와 같이 전체 화면을 하나의 요소(클래스)로 두고 mvvm 및 di 등을 통한 각종 객체지향적인 기법으로 개발을 하는것 보다 화면을 조각내어서 컴포넌트 기반으로 하나의 화면 조각을 작게 가져가는게 효율이 더 좋기 때문입니다. 이러한 작은 컴포넌트 조각들은 mvvm과 같은 패턴이나 OOP는 어울리지가 않죠. native영역도 native 개발툴 보다는 flutter와 같은 통합툴로 이전이 될꺼라고 생각되고, 이러한 툴 들은 컴포넌트 기반으로 구성이 되고 있습니다. 즉, 프론트는 발전방향이 MVC -> MVVM -> 리액트와 같은 component 형태의 개발방식으로 진화가 되는것이죠. 암튼, 정리하면 백엔드와 프론트는 다루는 데이터가 다르기 때문에, 발전되는 아키텍처의 모습도 다르다고 보고 있습니다 ^^
안녕하세요 저는 신입 FE 개발자입니다 개인적으로 이 주제가 굉장히 반갑고 재밌고 많이 이야기 되면 좋겠어요 저도 프론트엔드 개발은 OOP가 어렵다, 단위 테스트보다 통합 테스트가 쉽다, 라고 말하면서도 왜 그런건지, 왜 그래야만 하는지 설명하지 못해서 좀 찜찜했거든요 주니어 FE 개발자로서도 명확하게 이해가 되는 설명은 아직 보지 못한 것 같아요 React에서 DI가 필요할 땐 Context API를 사용 한다는 이야기를 트위터 해외개발자들 사이에서 얘기한걸 언뜻 본 기억이 있어요 thunk의 custom argument를 이용해서 api를 주입하는 방법도 있는데 개인적으로는 보일러플레이트가 너무 많이 필요해서 불편했던 기억이...
지나가는 저의 생각은 데이터를 생각해봤을 때 자바같은 백단은 DB조회하면서 클래스 객체로 받아서 데이터와 기능이 동작하게 하고 싶으니, 자바빈즈클래스같은 클래스에 데이터와 메서드 기능 연동을 시키는데, 프론트단은 데이터가 있는 json 으로 데이터를 받으면 그 데이터 객체에서 어떤 기능이 필요하면 JSON 오브젝트에다가 그냥 Object assign 해서 함수 연결하면 되기도하고 이 받은 데이터를 여러 컴포넌트간에 공유를 할 때..로컬스토리지에 저장을 한다던가, redux 에 객체 저장을 할때 기본 단위가 직렬화할 수 있는 JSON 정도로 저장이 되게되서.. 주고받는 데이터들이 JSON 기준으로 데이터를 생각하게 되다보니 그러다보니 자연스럽게 그냥 JSON 데이터 기준으로 기능이 필요하면 함수를 연결하는 함수형이 좀 더 편하게 생각되게 된 것같습니다. 그리고 자바진영에서 (오래된 이야기지만 )뒤늦게서야 람다식이 적용되면서 메서드의 일급객체로써의 적용이 늦은 반면에 js 진영은 그냥 콜백함수 전달하면 되니까, DI 같은 것을 굳이..? 사용하기보다는 다르게 동작할 부분이라면, 그냥 함수 쪼개서 콜백 함수 전달하면 될 걸.. 정도로 생각하지 않나 싶습니다. 사실 이 콜백 부분도 커링같은 부분으로 해서 함수형js 같은 쪽이 궁극적으로가게 되는 것같더라구요. --- 그리고 위에서 말씀하신 axios 같은 것을 사용할 때는.. 동감되는 부분이 이 네트워크 호출이라는 작업이 여러가지 부수작업을 해야하는 굉장히 비싼 작업이기 때문에 당연히 여기서는 객체클래스를 섞어 쓰게 되는 것같습니다. 사실 이 부분도 저도 다시 함수형으로 다시 짜보고 싶긴합니다.. -- 이참에 자바 JPA 진영이 있듯이 JS 함수형 진영에 유명한 분들이 계십니다. 회사차원에서 사용하는 라이브러리도 직접 만들어서 배포해주신 분이 계신데.. (아 인프런에 js 함수형 치면 바로 관련된 분들이 나오시는 분들이죠..) 한번 그분들과 라이브러리 소개도 해보시면서 토킹어바웃해보시는 시간 가지시면 재미있을 것같습니다.
많은 분들이 브라우저, api에 의존적인 개발을 이유로 FE에서 OOP가 유행하지 않았고, 맞지도 않다고 이야기 하시지만 그 주장이 맞을려면 IOS, AOS 진영에서 DI 프레임워크가 유행하는 것에 대해서도 납득할만한 이유를 댈 수 있어야 합니다. IOS, AOS도 플랫폼 의존적이고 마찬가지로 서버 API에 의존적인 영역입니다. 하지만 DI OOP가 이쪽에선 근본 of 근본이죠. 제가 생각하는 FE에서 OOP가 유행하지 않은 이유는 "개발 관성" 이라고 생각이 듭니다. AOS는 개발을 자바로 했어야 하니 당연히 자바 철학에 맞춰 OOP에 친숙할 수 밖에 없고 IOS도 마찬가지 Objective C 를 사용하다 보니 똑같았다고 봅니다. 하지만 FE의 자바스크립트는 그렇지 않죠. 초기엔 Class 자체가 없었고, 타입도 없었으며 XMLHttpRequest나 이벤트 함수를 보면 콜백 함수를 엄청 적극적으로 장려하며 사용했었습니다. this도 문제가 많습니다. 언제 어떻게 호출되냐에 다라서 this 값이 달라집니다. OOP스러운 코드를 작성하기엔 불편한 구조이죠. IOS, AOS는 OOP를 활용하는 방법으로 개발자가 짱구를 굴렸고, 반대로 FE는 함수를 잘 사용하는 방법으로 짱구를 굴리다 보니 서로 코드를 작성하는 방법이 달라진거죠. 최근에서야 타입스크립트가 나오고 Class도 나오고 하니 객체지향스러운 코드를 작성할 수 있지만 옛날엔 아니었잖아요. 인터페이스도 없는데 DI해서 뭐 하나요? 잘못 참조하면 에러만 펑펑 터지는 코드가 나오는데 툴들이 성숙하지 않았던 시절엔 독이었습니다. 이런 "개발 관성" 때문에 유행하지 않은것이지, 도메인 로직, 브라우저 DOM 특성 때문이 아닌것 같습니다. IOC Container 있으면 굉장히 편합니다. 지금 리액트는 Context API도 생성 순서를 맞춰야 하는데 IOC Container 있으면 그럴 필요도 없죠 코드 분리도 깔끔합니다. 하지만 없어도 충분히 구현 가능합니다. 대안책은 얼마든지 있으니까요. 그러니 필요성을 못느끼는것 같습니다.
공감되는 부분이 많은 영상입니다. 앱 개발은 객체지향을 잘 사용하는데 유독 웹 분야만 객체지향에 거부감이 있는게 의문입니다. contextApi가 DI의 역할을 할 수도 있다는 이야기도 있는데, 다수의 context를 주입하면 context hell 같은 이상한 현상도 보게 되구요... FLUX패턴도 너무 과하게 엔지니어링 되서 막상 쓰기도 힘들고 협업하는 사람들이 이해하기도 힘든 코드가 많이 발생합니다. Singleton + Observer 패턴이면 훨씬 간단하게 추릴수 있을거 같은데 Recoil이 이런 형태와 유사한거 같네요. 사실 class를 이용하지 않고 더 나은 코드가 나왔더라면 이런 의문도 없었을텐데, 정말 이게 맞는 코드인가? 이런 의문만 남게되는 상황이 너무 많아요.
UI 템플릿과 관련되지 않은 부분들은 class로 가능하겠지만 렌더링 관점에서보면 완전히 같은방식으로 처리되는부분들은 거의 보기 힘든것같은데. 아랫분 말씀처럼 특정 모듈을 만든다고 하면 class를 사용했을때 이점이 있겠지만 그러한 모듈들을 사용해서 렌더링을 해야하는부분에서는 그런식으로 관리하기 힘든것같습니다 경험상.
영상 정말 재미있게 잘 보고 있습니다. 저도 처음에는 프론트엔드에서 객체지향이 필요할까 싶었지만, 규모가 커지고 복잡한 웹 어플리케이션을 개발하게 되면서 oop의 필요성을 인지하게 되었고 그렇게 개발하려고 노력중입니다. 물론 단순 랜딩 페이지 만들자고 oop, typescript를 쓸 필요는 없다고 생각해요. 다만, Typescript가 부흥(?) 하면서 복잡한 프론트엔드 개발 환경에서의 oop 개념이 더 많이 퍼지지 않을까 생각합니다.
앵귤러 쓰시면 ...그 답답함이 ㅋㅋㅋ 풀리실건 같은데 앵귤러 DI 시스템이나 아키텍처는 안드로이드의 대거 같은 것에 아이디어를 많이 가져 왔기 때문에 생각하시는 구조를 구현해볼수 있습니다. 그리고 프론트앤드의 복잡도 크면 클수록 레이어 계층 분리하여 기능별로 쪼개지는 유용성이 있긴합니다. 그냥 랜딩 페이지 만드는데 그 정도까지는 필요하지는 않은거구요 ㅎ
저 배라 ㅊㅈ 입니다 ㅋㅋ 퇴사전에 리엑트 mobx 로 프로젝트 했는데 두분 고민과 똑 같은 고민했는데 di 까진 아니다라도 service(mobx store), repository(axios), 리액트 컴포넌트는 컨트롤러 역할, ui 컴포넌트 따로 빼구요 npm에서 라이브러리 하나찾아서 mobx store 를 데코레이터로 주입하구요 이렇게 레이어 분리하고 비즈니스로직은 각각에 맞게 적절히 분리하고 로직을 외부에서 구현하지 않고 oop 개념대로 해당 클래스의 상태는 해당 클래스의 메소드로 캡슐화 해서 제공하고 메소드호출(메시지)로만 커뮤니케이션하도록 딱 java spring 백엔드 처럼 구현했는데 충분히 가능하고 그렇게 개발하니 로직이 적절히 분산되어 보통 리액트 컴포넌트에 비즈니스 로직이 모여 있던게 다 흩어 지더라구요 FE 개발 과 java 백엔드 개발(oop) 둘다 어느정도 바삭하면 두분처럼 고민 나올 수 밖에 없는데 대부분 FE 전문 개발자가 더 많고 oop가 단순 클래스 사용이 아니라 아~ 이게 oop 구나 느낄려면 백엔드 개발도 어느정도 실무로 해야지 깨닫는 쉽지 않은 영역이라 FE 전문으로 하시는 개발자분들이 그개념을 바식 이해한 상태가 아닐 가능성이 높은 상황에서 구지 FE 개발에서 oop 까지 필요 있나 라고 의견을 낼 가능성이 높다고 저는 생각이 듭니다(물론 아닐 수도 있구요) 저처럼 또 두분처럼 원래 java 백엔드 개발이 주 포지션이였으면 당연히 동욱님 이야기에 100% 공감합니다 oop 안하면 FE 코드에 로직이 집중 되어 있고 캡슐화 안되서 로직이 오픈되고 걍 로직이 중구난방 장점도 별로 없다고 생각합니다 즉 둘다 바삭한 상태에서 FE 에서 oop vs function 선택한게 아니라 oop 느낌을 100% 잘 이해 못한 상태고 둘중 뭐가 더 유리한지 판단을 할 만한 상태가 아니란게 맞지 싶습니다 배민 블로그에 제가 4년 전에 사용기 쓴거 보시면 스프링 처럼 레이어 나누고 oop 처럼 하나 코드도 정리되고 훨씬 좋았습니다(리덕스 만든 dan 뭐시기 그분이 오히려 리액트 개발 어렵게 만든 장본인 이라고 개인적으론 생각도 들고요… ㅋㅋ)
제가 영상에서 나온 이야기를 면접에서 이야기하면, 쓸모없잖아요라던가 인터페이스 추상화에 대해서 부정적이신건지 아님 제가 설명이 잘못되었는지 공감들을 못하시더라구요 결국에는 테스트에 유리한 코드를 짜려면 의존성주입 + 제어의역전 + 추상화 이런 큰 틀로 가야하는데.. 뭐 그렇습니다..
백엔드에서는 jpa 라는 프레임워크를 이용해서 객체지향스러운 프로그래밍을 하려고 노력하는데요. 여러 백엔드 개발자들이 개발해준 api 를 가져다 사용해야하는 사용처의 개발자들은 제공되는 api 스펙에 맞추어 호출을 하고 결과를 객체로 매핑해서 가져다 사용하는데, 여기서 중복코드(중복 객체, 속성)도 많이 발생하는것 같고, 결국 아무 생각없이 api 호출 코드들이 계속해서 생성되어 쌓이게 되는것 같습니다. 백엔드 api를 사용하는 사용처에서도 객체지향적인 프로그래밍을 하는 좋은 방법이 없을까요?
프레임워크가 가지는 근본적인 컨셉차이 아닐까요 스프링이나 앱 개발의 방향은 객체지향을 토대로 두고 프로그래머의 영원한 숙제인 결합도나 응집도같은 문제를 풀어가고 있는 것이고 웹 프론트앤드 기술들은 선언형이나 함수형으로 그런 문제를 풀어가고 있어서 개발함에 있어서 의존성 주입이나 제어 역전같은 참조가 주가 되는 문제 해결 방식보다는 값 자체로 풀어가기 위해 컴포넌트에 기능 하나만 동작하게 하는 순수함수 철학에 가까워서 생기는 차이 같습니다 .
주제와 부합하는지는 잘 모르겠지만 듣다보니 비슷하게 공감되는게 React 에 뛰어들어가 모든걸 하는게 아니라 UI 제어권한만 React 한테 주고, 비즈니스 로직이나 인프라관련 세부사항은 별도 레이어를 두어서 React에 깊게 엮어들어가지않는게 좀 더 성숙한 개발방법이라고 생각하는디요. 가령 구매상품갯수 카운트 기능 있다하면 ( [ + ] 1 [ - ] 이렇게생긴거) class 로 ProductCounter 기능 구현하고 현재재고갯수, 최대구매갯수 같은거 인스턴스 생성할때 주입하고 React 상태랑 연동하는게 좀 번잡스럽긴할테지만 Count 구독가능하게 만들어서 상태와 바인딩하는식으로 풀 수 있고 얼마든지 가능한것같습니다. 내가 생각하는만큼 매끄럽진 않았지만 이렇게하니 딴건몰라도 테스트짜기 짱편햇어여. 다만 왜 매번 이렇게 안하느냐 할수 있지 않느냐를 따져본다면 매번 공감대를 형성하는것이 힘들다고느끼고 (내 설득능력의 문제가 클것임) 공감대를 형성하기 힘든이유는 트랜드에 민감한 경향이 있는반면 이런 주제에 대해 상대적으로 진지하게 이야기나눌 수 있는 주변인이 적은것같습니다. 저는 리액트 를 하되 리액트랑 적절한 거리감을 두고 싶은데 많은의 분들이 리액트를 너무 사랑해서 리액트랑 결혼하는것같습니다.
프론트는 본질적으로 ui와 밀접해서 객체에 대한 공통의 로직이 중복되는 경우가 적고, 기획이 바뀌고 ui가 변경될 때마다 반영할 수 있는 객체지향의 코드를 작성하기에는 투머치하다 인것 같네요,, 그리고 로직이 중복되는 경우엔 훅으로 추상화를 해서 재사용하면 돼고, 상태도 전역 상태가 아닌 context로 구분해서 해당하는 영역에서만 상태를 관리할 수 있기 때문에 도대체 언제 어느 시점에서 클래스가 필요하다는거지? 라는 의문이 들기는 해요 물론 저도 백엔드를 몰라서 프론트 입장에서 하는 말이긴 하지만요 주제에 대한 논의가 이뤄진다는거는 흥미롭습니다! 저도 프론트 고수분이 나오셔서 정리해주시면 좋을것 같아요
전제가 많이 잘못된 것 같습니다. 프론트엔드에 왜 백엔드에 사용되는 패턴을 사용해야 하는가를 생각해 보시길. 솔직히 말해서 뭔소리를 하는가 싶습니다. JS 디자인 패턴이나 그럴 것들을 찾아보시길. 각각의 패턴은 사용처가 정해져 있는데 백엔드의 패턴을 무작정 프론트엔드에 적용하니 이상한 말이 나옵니다. 프론트엔드는 비지니스 로직 자체보다는 원하는 데이터를 처리해 나타내는게 주목적입니다. 그러니 당연히 DI나 class를 통한 확장성 보다는 데이터의 조합을 위한 hook이나 composition api과 같은 패턴이 사용되는 것 입니다. 아마 단순한 프론트엔드 레벨에서 겉핥기 식으로 접하신 것 같은데 대부분의 OOP 패턴이 프론트엔드에서 잘 먹히지 않습니다. 페이스북이 왜 리엑트를 만들었을까요? 왜 앵귤러는 점유율을 잃어갈까요?
여러 고수분들이 얘기 많이 해주셨는데, 얘기 들어보면 아무래도 Spring 을 오래 하셨고 어노테이션 기반 개발 및 DI 개념에 너무 익숙해서 그런 패턴화가 프론트엔드에 안되어 있는게 어색한 것이 아닐까 하는 생각이 드네요. 어떤 분도 적어주셨지만 mobx 같은 스토어를 사용하여 Service, Repo 레이어를 직접 구현하면 비스무리하게 따라하는건 얼마든지 가능합니다. 단지 이런게 프레임워크 혹은 라이브러리에서 공식적인 패턴화가 안되어 있어서 자유분방한 코드가 만들어 지는 것 같다고 생각합니다. nest.js 나 angular 같은 것은 그런 패턴이 공식적으로 구현되어 있으니 잘 사용하는 것처럼요.
팩토리 패턴 정도를 사용해서 의존성 주입하는건, 당연하고 좋은 패턴이다라고 생각하는데요. C++, Python을 주력으로 사용하다, 안드로이드 쪽 일을 할 일이 생겨 Java를 좀 사용하게 됬는데. Dagger로 정신없이 annotation쓰면서 의존성 주입을 하는게 자바의 패턴이던데, 이렇게 복잡하게 이런짓을 하는 이유가 이해가 안되더라구요. 컴파일 타임에 굉장히 복잡한 의존성 트리가 만들어지는 방식이라, 언어의 시맨틱 만으로 코드패스가 어떤식으로 실행되는지 이해하기만 어려워 진다는 느낌이었습니다. 재빨리 발을 뺀후, 자바쪽을 쳐다보지도 않고 있습니다.
FE개발자 역량이 초중급이라 가정하고, 3개의 FW를 다뤄서 각각 프로젝트 완성도 결과를 점수로 매기면, 앵귤러 : 최소80점+ 리액트, 뷰 : 50점-80점+ 그만큼 앵귤러가 학습곡선은 높지만, 체계적으로 잘 잡혔다고 개인적으로 생각. 현업에서도 어차피 남이 짠 코드를 보게되는데, 앵귤러로 짠 코드면 전체를 훓어봐도 기본 뼈대가 잘 잡혀 있기에, 이해를 빠르게 캣치 할 수 있음. 리액트뷰는.... 엔지니어 실력에 따라 어떻게 잘 구성되어 있고 코드가 짜여 있는가에 따라 많이 많이 달라짐(...화딱지도 많이 생길 수도 있음...) 결론은 앵귤러로 작업한다면 평타는 칠 수 있다.
우선은 언어적 차이가 크지않았나 생각합니다 단순히 역사의 길이와 많은 변화때문에 리엑트진형에 oop의 개념이 정착하지않았다라고 보기는 어려운것같네요 오히려 역사도 짧고 리엑트만큼 많은 변화를 격고있는 안드로이드 진형에서 oop개념이 정착되어가고 있는현상을 보면 언어적으로 javascript는 oop의 개념을구현하기 어렵다고 생각됩니다 하지만 이제 리엑트에서도 typescript를 사용하게되면서 결국 oop로 의 발전이 진행되지않을까 예상이됩니다 결국 타입이 있고 다양한 변화에대응해야된다면 자연스럽게 oop로 손이가게 될꺼같아요 이제는 기존의 관념을 깨는 일만남았는데 개발바닥을 필두로 의문을품는사람들이 나타나기시작했기 때문에 곧 변화하지않을까 생각되네요
프론트엔드는 근본적으로 UI에 종속적이라 백엔드보다는 코드의 변경이 잦게 일어난다고 생각합니다. 그리고 복잡한 로직을 처리하는 일은 서버에 맡기고 있잖아요? 그래서 비즈니스 코드나 구조가 UI에 따라서 변경될 가능성도 크고 객체지향적으로 접근하는 것이 좀 too much 하다는 느낌을 받아요. 그래서 하나의 정형화된 패턴이 존재하기 어려운게 아닐까 생각합니다. 그리고 좀 더 가볍고 쉬운 것을 찾게 되어서 뭔가 새로운게 나왔대! -> 그럼 좀 지켜볼까? -> 시간이 좀 흐름 -> 그거 괜찮대 -> 우리한테 필요한지 적합한지 고려해보고 적용해보자 이런 식의 시도가 되게 많은 거 같아요. 백엔드보다는 변화가 잦고 새롭게 제시되고 떠오르는게 많다보니 이게 딱 좋다! 라고 결론 지어질만한 게 없는ㄱ ㅓ 같습니다.ㅏ
같은 프론트엔드인데 네이티브 앱 (ios, android) 는 클래스와 di 의 이점을 적극 활용하는데 왜 웹 프론트엔드에는 그런게 없는지도 의문점인것 같습니다 ㅠ ㅎㅎ 물혼 프론트엔드가 Ui 에 종속적이고, 핵심 비즈니스로직은 백엔드가 주로 담당하는 것은 맞지만 그렇다면 모든 프론트 (네이티브 앱과 웹)에서 공통적으로 Di 없는 체계가 발달했어야 하지 않나.. 싶어요
프론트는 어설픈 코드로 인해 발생하는 문제가 백엔드만큼 치명적이지 않아서 그런가 싶어요. 복잡하지 않은 로직을 복잡하게 짤 필요를 못느끼는 것 때문인 듯 하기도 하고, 빠르게 적용해보고 아니면 버리는 문화가 있어서 그런거 같기도 합니다. 리팩토링을 하는 것보다 새로운 기술로 다시 만드는 게 낫다고 여겨서 애초에 오래 유지보수할 생각이 없는 거 같기도 하구요!
실제로 오랫동안 유지보수 해야 할 일들이 많지 않은 이유가 제일 크지 않을까요. 몇년 지나면 어차피 갈아엎어야 하는 상황이 발생하고, 그게 아니라도 오래된 코드는 아무리 잘 만들었어도 유지보수성이 떨어질 수밖에 없으니.. 당시 언어를 잘 아는 사람이 아닌 새로 유입된 인력들이 상대하기엔 말이죠.
방법이 없는건 아닙니다. 두분이 원하시는게 단순히 클래스 문법을 쓰는게 아니기에, 리액트 클래스 컴포넌트나 앵귤러가 그 답은 아니라고 생각합니다. 웹과 다른 클라이언트가 다른점은 화면랜더링이 DOM과 브라우저 api들에 의존적이고, 그것들이 OOP와 전혀 다른 패러다임이라는거 아닐까요? 백엔드에서 그렇게 코딩을 할수있는건 툴의 도움이 크다고 생각합니다. 프론트개발자들은 지금 ORM없이 쿼리빌더만 가지고 일하고있는거에요. 왜 그런 툴이 없는지는 잘 모르겠지만, 저보고 간단한 orm을 짜보라면 쉽게 짜겠는데, 객체를 돔으로, 그것도 상태관리까지 가능한 매퍼를 짜라면 전 도망갈게요. 엄두도 안나요. 어차피 상태관리 라이브러리에서 상태를 관리해야하고, 시장지배적인 라이브러리가 있는상황에서, 매번 오버헤드를 감당하기보다는 라이브러리에 의존하는 선택을 해버린거 아닐까요? 답은 있습니다. DOM을 배제하면 되요. 그냥 canvas에 랜더링하면 됩니다. 근데 단점을 생각해보면 seo, 접근성같은 웹바이탈에 안좋겠네요. (블레이저에 대해 언급했었는데 자세히 찾아보니 제가 잘못알고있었네요. 수정합니다)
지극히 개인적인 생각으로 1. 왜 프론트에서 DI는 인기가 없을까? 2. 왜 클래스를 사용 하지 않을까? 의 생각을 해본다면, 실제로 비슷하게 DI 요소를 적용해보면 많이 번거롭기도 하거니와 프론트 쪽에서 최적화 쪽에 더 힘을 싫어서 그런지 더 간결한 코드를 선호한다는 느낌입니다. 정확히 제어역전 까지는 아니라도 비슷하게 그 효과를 볼 수 있겠습니다만, 발전의 방향이 유연하게 만든다기 보다는 그냥 그 부분 다시 만들지 하는 생각이 있는 거 아닐까 하기도 합니다. 어째든 DI를 지원하는 것은 프론트의 디자인 요소로서 마지막을 맟추는 그림이라고 저는 생각합니다. 그렇기에 프레임워크 레벨에서 DI 지원해주는 앵귤러는 장점이긴 하지요. 다만, DI 엄청 중요하게 다가오지는 않는 것 같습니다.( DI 의 유무가 프레임워크의 결정요소로 적용되는 것은 한번도 본 적이 없음.) 2. 왜 클래스를 사용 하지 않을까? 는 사실 리엑트 같은 것들이 클래스보다는 함수 기반이기 때문일 수도 있겠지만, vue, 앵귤러는 클래스 기반이긴 하지만, 그게 중요한 건 아니고, 사실 객체지향보다 함수형을 선호하는 저에게는 왜 클래스를 써야하지? 라는 생각을 하게 하네요. 클래스 특성상 동일한 것에 여러 인스턴스를 만들 수 있다는 특징이 있지만, 실제로 그렇게 쓰는 것은 아니고, 객체지향 패러다임이나 설계원칙을 적용하려고 쓰려는 것이 겠지만, 동일하게 함수형 프로그램 모델에서도 대부분 해결 되기에 굳이 객체지향 적용되어야 하나 싶네요. (일부 객체를 사용할 수 있겠지만, ..) 논란이 많은 이야기가 될 수 있겠지만, 흔히 이야기 하는 개방폐쇠의 원칙. 확장에는 열려 있지만, 수정에는 폐쇠적인 것... 사실 설계가 완벽하면 문제가 안되겠지만, 실제로 시간이 지나고 요구사항이 변하면서 처음 부터 코드를 다시 써야 하는 상황이 오거나, 또는 덕지덕지 말도 않되게 코드를 작성해야 하는 상황이 오면 꽤나 불편하다고 느껴지네요. 오히려 코드를 함수 단위로 작게 유지하고, 적절히 그룹핑 시키면 그게 더 편하지 않나 하네요. 또한, 클래스를 잘 안쓰는 이유가 적절히 쓸만한 모델을 만나지 않아서 일 수도 있고, 사실 이건 테스트 해보면 더 정확히 알 수 있다고 보여지네요. 말씀 하시것 처럼 풀 클래스 코드로 작성한 프로덕션을 한 6개월 운영해보고 반대로 동일한 코드를 클래스 기반이 아닌 방식으로 작성해서 6개월 운영해보고 무엇이 더 낳은지 상세 비교를 통해서요. 그게 아니라도 지금의 프로덕션을 컨버팅해보는 것도 방법이 되겠죠.
JS에서 스프링 스타일의 DI를 사용하지 않는 이유. 1. 부족한 문법. 스프링 스타일의 DI에서 필요한 인터페이스, 애노테이션등의 문법 부재. 2. 속도. 이게 가장 중요한 문제인데 스프링 스타일의 DI를 쓰면 초기 로드 속도가 느려짐. js가 아닌 다른 언어, 프레임워크들도 DI 구현 시 코드를 생성하는 유틸리티를 사용하여 런타임이 아니라 컴파일 전에 코드를 생성하는 형태로 가는 추세. 프론트엔드 js에서 초기 로드속도는 매우 중요한데, 초기 로드 속도에 따라 비즈니스 결과 차이가 어마어마함. 만약 js에서 스프링 방식의 DI를 사용한다면, 초기 객체 생성 시간 뿐만 아니라 DI의 부수적인 코드들 때문에 스크립트 사이즈 자체가 커져서 초기 로드 시간(스크립트 다운로드 및 초기 코드 로드시간)에 더욱 더 치명적. 3. 모듈시스템. JS 모듈 시스템을 이용하면 어느정도 DI구현이 가능함. 다음은 많이 JS에서 많이 사용하는 싱글턴 DI패턴. //module.js class Repository { findOne() { } } export const repository = new Repository(); //main.js //모듈 로드 시 싱글턴 형태로 객체 생성 및 주입이 됨. import { repository } from "./module.js"; respository.findOne(); import 문법을 사용하면 비동기형태로 Lazy 로드도 가능함. 4. 테스팅 jest등을 사용하면 모킹뿐만 아니라 페이크, 스텁등 다 가능함. 결론: 프론트엔드에서 다른방식으로 DI 구현이 가능하며, 장점보다는 단점이 훨씬 큰 스프링형태의 DI를 js에서 고집할 이유는 없음.
화면 UI는 언제든지 변할 수 있고 지금까지도 그래왔고 변경시 큰 비용이 들지 않지만 백엔드의 경우에는 중요한 데이터를 직접 다루는 일이 많고 로직 하나하나 민감한 부분들이 존재하기에 FE보다는 보다 정해진 형식으로 개발을 해야하며, 그에 맞는 테스트 코드도 필요해서라고 생각합니다.
여러가지 이유가 있겠지만.... 웹이라는 특성, 브라우저라는 환경, 그리고 CSS라는 전역적으로 적용가능한 스타일의 존재 정도로 크게 정리해서 볼 수도 있을 것 같습니다. 1. 웹 서비스는 일단 다른 플랫폼에 비해 빠른 배포가 가능합니다. 그래서 웹을 일종의 신규 기능 실험장 처럼 쓰는 케이스도 많죠. 따라서 구조적 견고함보다는, 주요 프레임워크 위에서 빠르게빠르게 갈아엎는 수준으로 변경할 수 있도록 찍어내는 경우도 많은 것 같습니다. (장점이면서도 단점이기도 하죠) 2. 브라우저라는 환경은 또 다른 복잡도를 제공하는데, 웹 프론트를 사용하고 환경에 대응하는 방식은 굉장히 다양합니다. 2-1. 일단 해상도에 따라, 데스크탑-테블릿-모바일 등 아주 넓은 범위의 해상도 대응 2-2. Full SPA 로 갈수도 있겠지만, 인라인 임포트를 통한 최소단위 사용 (레거시 마이그레이션 시 자주 사용됨) 2-3. 브라우저의 종류 - 데스크탑, 모바일의 브라우저 어플리케이션 뿐 아니라 어플 내 웹뷰 - 에 따른 사용방식의 차이 등등에 따라 특정한 구조를 견고하게 정해두기엔 지나치게 번거롭거나 아예 불가능한 경우도 많죠. 3. 세번째는 기술적으로 아주 크리티컬 한 이슈는 아니지만 인력측면이나 학습 단계에서의 문제입니다. CSS는 브라우저에서 전역적으로 접근 가능한 스타일인데.... 물론 css-in-js 에서는 이걸 컴포넌트 단위의 클래스 난수화로 해결하려 하지만 제한을 걸었을 뿐 강제할 수 있는 부분이 아니고, 또 과거부터 HTML, CSS를 전담하여 판으로 짜내는 퍼블리셔라는 역할이 있어왔고 지금도 계속 그렇게 작업하는 케이스도 여전히 많다보니 더더욱 전환이 어려운게 아닐까... 하는 생각이 드네요.
짧은 식견으로 댓글을 달아보겠습니다. 1. 왜 리액트에선 DI를 사용하지 않는가? 다른 언어(코틀린, 자바 / Swift)들과의 가장 큰 차이는 컴파일러 여부가 아닐까 싶습니다. 리액트 컴파일러가 없는 상황에서 DI가 가성비가 좋은진 잘 모르겠습니다. 2. 왜 axios와 같은 HTTP 라이브러리를 한 번 더 클래스로 감싸서 사용하지 않는가? axios와 같은 HTTP 라이브러리를 한 번 더 클래스로 감싸고 심지어 그걸 커스텀 훅으로 감싸서 사용하는 것은 다른 데에서도 충분히 사용되고 있다고 봅니다.
의존성 주입을 하게 되는 시점은 결국 엔트리 포인트(index.tsx) 또는 App 컴포넌트에서 의존성을 생성한 후 하위 컴포넌트에 Props를 통해 전달하거나 Context API를 통해 전달해야 하는데 전자는 Props Drilling이라는 새로운 문제가 발생하고 후자는 결합도를 낮추기 위한 의존성 주입이 도리어 결합도를 높이는 결과를 낳게 됩니다.
FE 일은 안하지만 개인적인 생각으로는 FE는 일반적으로 변화의 정도가 높아 기존 코드 재활용률이 떨어지는 경우가 많을텐데 내츄럴 하게 컴포넌트기반개발 하는게 DI보다 생산적인 경우가 많아서겠죠. 생뚱맞지만 쿼리 짤 때 생각해봐요.... 테이블 조회 시 인덱스 데이터 분포율에 따라 퍼포먼스 이득이 나는 변곡점이 있죠. 그 변곡점 보다 높으면 FULL SCAN이 빠르고 변곡점 미만에는 INDEX_SCAN이 낫잖아요. 통계적으로 레거시 코드 재활용률이 낮은 부분이라면 생산성을 따져 당장 적용이 빠른 신규 코드로 갈아 엎는 것도 방법이라고 생각합니다. 굳이 OOP 를 적용한다면 툴 자체에서 OOP하게 적용되게 강제하면서 생산성도 높여줄 수 있는 개발 툴이 있다면 그걸 쓰면 좋겠죠.
FE도 FE나름 OOP가 필요한 FE도 있다옹. 예를들어 삽입요소 종류가 아주 다양한 헤비한 에디터... 함수형으론 한계가 있다옹~ 함수형으로 짜다간 막코딩 된다옹. 뭐든 정답은 없다옹. 내 짧은소견으론 FE는 굳이 oop가 필요없다는건 아직 프론트의 진수를 몰라서 하는소리 같다옹. 냐옹 거려서 미안하다옹
원래 자기가 잘 아는 방식만이 유일하다고 생각하기 쉽고 자기가 모르는 것에 대해서까지 걔네는 왜 그래라는 식으로 얘기하다보면 말그대로 어그로 끄는 식이 되는 것 아닌가 싶네요. 개인적으로 리액트가 가고 있는 함수 지향적 방향은 탁월하다고 느낍니다. 함수형 사고로 전환하면서 코드도 훨씬 깔끔해지고 유지보수도 더 용이해진 것 같네요
ㅋㅋㅋ 이걸 왜 백엔드와 프론트의 차이라고 생각하지??? 이건 언어의 차이라고 봐야 더 맞지 않나??? js를 더 공부해 보세요. js가 oop에 가까운지 함수형에 가까운지 그냥 알 것 같은데... 객체도 클래스 선언 따위 필요없이 곧바로 만들어서 사용하는 것이 js임.
백엔드를 하다가 프론트로 전향한 입장에서,
이건 프론트엔드의 역할 때문에 그런거라고 생각해요 ㅎㅎ
보통 백엔드에서 객체지향을 하는 이유는 복잡한 도메인 로직을 관리하고, 도메인 로직과 네이티브간의 격리를 위해서라고 생각하거든요.
그런데 프론트엔드에서 도메인 로직을 처리하는 경우가 거의 없기 때문에 굳이 객체지향을 깊게 적용할 필요가 있을까? 하는거죠
가령 계산기를 만든다고 치면 이건 객체지향 없이 관리하기가 무척 힘들어요
계산기라는 앱을 다루기 위해선 UI를 그리는 부분과 계산기 도메인을 다루는 부분을 분리해야 할텐데
대부분의 웹서비스는 UI에서 입력 받고 서버에 요청 보내서 응답 받고 출력해주는거죠
도메인 로직이 거의 완전히 백엔드에 위임된 상태입니다
그러니까 굳이 객체지향이 필요할까? 하는거죠
반대로, 리액트로 UI를 만드는게 아니라
리액트 자체를 만든다고 생각하면 객체지향이 빠질 수 있을까요?
다루는 영역의 차이라고 생각합니다 ㅎㅎ
그래서 객체지향을 경외시 하기 보단
객체지향이 추구하는 목표나 개념은 꼭 숙지할 필요가 있다고 생극해요
그래야 어려운 난이도의 일을 할 때 조금 더 수월하지 않을까 싶네요 ㅋㅋ
안드로이드와 iOS도 프론트 범주인데
특이하게 웹프론트만 DI를 잘안쓰는 거 같아서 신기하긴하네요 ㅎㅎ
우문현답
정답~ ㅋ
1
왜 웹 프론트엔드에서는 정해진 대표적인 MVVM, MVC 와 같은 이러한 아키텍쳐가 없나요?
웹에서 프론트엔드 백엔드 경계가 없던 2000년대 시절에는 이미 웹에서 HTML+CSS+JS 영역을 View라고 부르고 데이터를 Model, 라우터 서버스크립트 영역을 Controller라 부르면서 MVC 패턴이나 아키텍쳐는 이미 존재했습니다.
이후 jQuery시절이 끝나고 웹 프론트엔드가 생겨날 무렵 backbone이나 ember와 같은 기존의 MVC 개념을 바탕으로 하는 프레임워크들도 나왔으나, knockoutjs, angularjs와 같이 HTML에서 템플릿과 치환자 그리고 데이터 바인딩과 자동 업데이트라는 방식이 기존의 MVC 개념보다 훨씬 더 효율적이고 쉽게 화면과 모델을 만들 수 있다는 것을 알게 되면서 이러한 방식이 대세가 되어 웹은 MVC를 건너뛰고 MVVM 아키텍쳐가 주류가 되었고 이 기조는 지금까지 이어집니다.
이후 FLUX 패턴이나 현재에 이르는 상태관리처럼 웹이 훨씬 더 이러한 아키텍쳐에 대해서 선구자적인 역할을 했고 이것들이 MVVM이나 MVI처럼 이름이 붙여지고 정리되는 것들은 나중의 일입니다. 당시에는 이러한 방식을 두고 MVC 옹호론자들이 이게 MVC에 맞느냐 뷰와 컨트롤러가 너무 강결합이 되어 있다 라던가 반대파들이 아니다 이건 MVP(Presenter)로 불러야 한다던가 등의 논쟁이 있었는데, angularjs의 경우는 하면서 MVW (Whatever)이라 부르면서 굳이 이런방식에 이름을 붙이고 정하려 하지말고 모델과 뷰 사이에서 가장 효율적인 패턴을 적용한다는 의미로 불러달라고 했습니다. 이게 2010년도 입니다.
이렇게 선언형 뷰를 만드는 방식은 이후 안드로이드나 ios Swift등에서 나중에 도입되면서 이게 MVVM 아키텍쳐가 되었고 이후에 나온 스토어를 따로 두고 행동에 의해 데이터가 변경되고 이를 반영하는 방식의 FLUX 패턴들이 MVI 등으로 정리가 되면서 이러한 아키텍쳐들이 벤더에 나중에 정리가 되며 적용이 되고 있는데 반해 웹은 계속 발전 중입니다.
2020년도에 MVVM을 웹에서 해보려고 시도한것이라기 보다는 이미 웹 프론트에서 하고 있던 방식이 ios, android에서 가서 MVVM 아키텍쳐로 정립이 되면서 swift UI등의 개념들이 소개가 되면서 웹과 같이 엮었던거며 이미 웹은 오래전부터 MVVM 형태의 아키텍쳐가 주류였습니다.
웹 프로트엔드가 과도기라고 하면 과도기가 맞지만 (20년째 과도기...) 어떻게 보면 벤더가 없기에 계속 선구자의 역할을 하고 있고 그러다 보니 매년 새로운게 나오고 뭔가 정리가 되려고 하면 새로운 개념들이 또 나오고 있다보니 아키텍쳐로 정리가 되기 보다는 하나의 라이브러리와 넘쳐나는 새로운 개념과 아젠다들로 뒤덮여 있다보니 뭔가 웹 프론트엔드를 보기에는 이렇다 할 만한것으로 하나의 좋은 형태가 정해지지 못한것처럼 느껴진다고 볼 수 있을 것 같아요.
2
DI와 같은 방식을 코드로 보고 싶어요.
일단 웹 프론트엔드에서 쓰는 자바스크립트가 완전 함수형 프로그래밍 언어도 아니고 객체 지향 기반의 언어도 아니면서 프로토타입 객체지향을 기반으로 언어이지만 class는 잘 사용하지 않으려고 하는 경향이 있다는 것에 대해서 이해를 한다고 했기에 전제로 적어보려고 합니다.
특히 React가 클래스 기반에서 완전히 함수형 기반으로 넘어가면서 주류 된 만큼 점점 더 class보다는 function을 쓰는 형태로 발전해가고 있다고 생각합니다.
웹은 과도기가 맞는데 다시 class 전성기가 돌아올수도 있겠지만 지금까지는 오히려 class 과도기가 지나가고 function을 쓰는 방향으로 안정화가 되어가고 있다고 느껴집니다.
위와 같은 이유로 일단 class를 잘 쓰지 않으니 굳이 DI(Dependecy Injection)이라는 것이 FE에서는 자주 쓰이지 않는 개념인 것이지지,
유연함을 위해서 모듈을 분리하고 상황에 맞게 모듈을 끼워넣을 수 있도록 하는 방법들은 함수형 프로그래밍에서 얼마든지 있다고 생각하빈다.
완전 돌아가는 형식의 코드가 아니라 일부만 적어보겠지만 이해는 해주실거라 생각합니다.
1
가령 클래스에서 이렇게 분리된 코드를 DI를 통해서 결합하면서 사용한다고 한다면,
public class MyApp {
private readonly RepositoryLayer _repository;
public MyApp(RepositoryLayer repository) {
_repository = repository
_repository.fetch(....)
}
}
리액트에서 Context API를 이용한 Provider에서 Service 바꾸기
(이것이 일종의 DI라고 볼 수 있다고 생각합니다.)
import {repositoryService}
const MyApp = () => {
const repositoryService = useContext(Service);
repositoryService.fetch(...)
}
2
이러한 방식이 React에거나 아니라 비지니스 로직을 짜는데 있어서 class를 활용하고 있지 않기 때문에 이건 DI라고 보기 힘들다라고 하셨는데...
const fetch_items = (service, params) => {
return service.fetch(params)
}
이런식으로 작성을 해서 인자로 받아와도 동적으로 처리를 한다거나
import {MyService } from "..."
const service = MyService // 조건부나 빌드환경에 따라서 다른 서비스로 교체할수도 있음.
const fetch_items = (params) {
return service.fetch(params)
}
와 같이 만들어도 DI와 같은 목적을 충분히 달성할 수 있고 아니면.
create MyRepositoryServce = (serviceLayer) => {
const fetch_items = (params) {
return service.fetch(params)
}
return {fetch_items)
}
const m1 = MyRepositoryServce(serviceForProd)
const m2 = MyRepositoryServce(serviceForTest)
이런식으로도 사용할 수 있을 거라고 생각합니다.
프론트엔드가 클래스를 사용하지 않아도 되는 상황이면 클래스보다는 함수를 사용하는 식으로 사고의 체계가 잡혀있게 되었는데 정확하게 어떤 목적과 의도에 맞는 코드를 원하는지는 정확하게 캐치못했을수도 있다고 생각을 합니다. 어떠한 의도와 목적인지를 안다면 그리고 그러한 취지에 맞는 코드를 구현하는데 있어서 더 나은 방식이 있는 거라면 억지로 우기는게 아니라 진짜 같이 고민을 해보고 싶습니다.
이 주제가 어그로가 끌리는 이유는 그럴 의도와 무관하게 논조가 다분히 '왜 백엔드에는 전통적인 객체지향 방식에서는 이러한 좋은 것들이 있는데 왜 프론트엔드에서는 이런것들을 안 사용하려고 하는 건지 이해가 안된다' 라는 식으로 전개가 되고 있는데 그 부분이 뭔지 얘기가 안되다보니까 각자 자기 입장에서의 얘기를 할 수 밖에 없는 것 같아요.
FE 입장을 대변하고 함수형이 객체지향보다 낫다라고 말하고 싶은 것은 절대 아니며 자바스크립트는 특히 객체지향과 함수형의 밸런스가 중요하다고 생각하기에 프론트엔드 일변도가 아닌 다른 관점에서 좋은 방향성 특히 테스트와 아키텍쳐에 관해서는 FE에서도 늘 답을 찾고 싶어 하는 주제이기에 이러한 얘기들이 자주 논의되면서 괜찮은 방법들을 찾고 새로운 시각을 갖추고 싶습니다. (이렇게 말을 하지만 저도 제 입장과 관점으로만 말할 거라고 생가합니다. 배우고 해온게 있으니까요... ㅎㅎ)
인터페이스는 고정하고 스토어는 바꿀수 있는 구현체라는 관점에서 보면 DI를 실현하는 방법이 맞고 실제로 리액트 쿼리나 리액트 리덕스도 그렇게 쓰라고 애초에 컨텍스트 기반으로 설계되어있죠. 상위 프로바이더만 변경하면 되는 아주 깔끔한 부분적인 DI가 가능합니다. 꼭 클래스로만 IOC나 DI가 가능한건 아닙니다 ㅎㅎ
이 분들은 Class와 어노테이션으로 DI하는게 아니면 납득못하실거같아요, 본인들이 정말 언어에 상관없이 좋은 실력을 갖고있다면 언어의 특성을 이해하고 그 언어가 제공하는 추상화도구를 활용해서 정말 원하는 높은 응집도와 낮은 결합도를 지향하고 커플링을 최소화하는 OOP개념을 구현할수있는데 말이죠
클래스랑 객체지향이랑 아무 상관없습니다. 클린 아키텍쳐 책 찍먹만 해도 나오는 내용이죠.?
클래스는 그냥 자료형일 뿐이고. OOP는 패러다임 입니다.
ㅔㅔㅔ
혹시 개발자 정년관련 영상도 만들어 주실 수 있나요?
개발을 몇살까지 할 수 있을지, 회사는 나이든 개발자를 어떻게 생각할지 궁금합니다
음 이번에 회사에서 프론트 엔드 앵귤러 백엔드 스프링부트로 개발했는데요.
리액트는 태생이 라이브러리라서 프레임워크가 아닌 DI나 IOC 이런걸 제공하지 않고 프론트 엔드 개발자 분들이
굳이 레이어를 나누고 이렇게까지 TM 해야할까 ? 라는 공감대가 형성이 안되서 그런거 아닐까요?
앵귤러 써보니까 정말로 그런부분은 깔끔하더라구요.뭐 리액트도 ContextAPI를 통해서 가능하다고 들었는데 리액트쪽 지식이 짦아서 잘 모르겠네요.
리액트의 태생이 철학은 UI 라이브러리여서. UI 만드는게 저런 레이어까지 넣어야 하나 싶기도 합니다만..
Q. 앵귤러에서 제가 궁금했던 그런 내용이 풀리려나?
조금은 더 풀린다고 생각합니다
lit element도 마찬가지고 @, DI와 유사한 방식으로 코드를 구현할 수 있습니다
Q. 리액트로 테스트 짤 때 모킹이 아닌 테스트 짜는걸 본 적이 없고 테스트 아키텍쳐도 부족하다.
Kent C. Dodds의 블로그 글과 강의를 보는 게 어떠신지 추천해봅니다.
하지만 보고도 그 갈증은 해결이 될 것 같지는 않네요..
여전히 FE 영역의 테스트는 성장할 여지가 많이 남아있습니다.
BE에 비해 축척된 연구와 사례가 부족한 것이 사실입니다.
또한 모킹은 MSW의 성장세를 봤을때 그 역할을 잘 할 수 있을 것으로 기대됩니다.
Q. 리액트 아키텍처인 플럭스 아키텍쳐는 있지만 작성하는 사람이 그 아키텍처를 짜지 않으며 자유분방하고 통일된게 없고 세계적으로 평타치는 패턴을 보지 못했다
Next.js, Gatsby, Remix, Nuxt 말씀하신 그런 역할을 제법 잘해주고 있는 프레임워크들입니다.
성숙하고 진보되어 있으며 그래도 부족할 수 있지만 앞으로도 더 발전된 아키텍쳐로 FE 생태계를 이끌 수 있다고 봅니다.
Q. 왜 웹 프론트엔드에서는 클래스를 잘 안쓰지?
Q, DI 없이 어떻게 서로의 결합도를 낮출 수 있지?
저번 영상에서부터 계속 언급되는데요
클래스 쓰는 곳은 정말 많이 사용합니다.
생태계가 이끄는 트렌드가 모든 것을 대변한다고 느낄 수도 있지만 그 환경이 모든 것을 대변하는 것은 아니니까요
React 생태계는 횡단 관심사를 HOC로 해결해왔고 이제는 Hooks를 활용합니다
또한 DI도 이제 정식 스펙으로 등록될 일이 얼마 남지 않았습니다.
이미 과거에도 사용가능했고요
React에서는 이제 Context API와 Hooks라는 DI와 꽤 유사한 시스템을 제공합니다.
그리고 React를 기반으로 하는 유사한 라이브러리는 대부분 Context API와 Hooks를 활용하여 제공됩니다.
즉 고민하시는 DI는 React 생태계에서 use-Prefix로 사용하고 있다고 보시는 게 그나마 마음이 편하실 거라는 생각이 듭니다.
Q. 프론트엔드 공부를 할걸
이미 한 분야의 훌륭한 개발자이신데 다른 영역에 대한 이해를 위해 노력하시는 것은 언제나 존경스럽습니다
Q. 고수 나와서 직접 코드로 설명해봤으면 좋겠다.
밑에 등장하셨네요 ㅎㅎ
코드스피츠라는 컨텐츠를 추천드립니다.
비사이드소프트 대표님의 훌륭한 강의들을 볼 수 있습니다.
아마 많은 인사이트를 얻으실 수 있을 것 같네요
---
회사를 이끄는 테크리더인 두 분의 이야기에 왜 UI/UX에 대한 고민은 없는지 HTML CSS JS 그리고 브라우저에 대한 생각은 없는지 궁금했었습니다.
저는 FE가 주는 가치는 말씀하신 것에서만 나오지 않는다고 보거든요.
물론 귀사에서 가지고 있는 기술 부채나 해결해야하는 것들은 다를 수 있지만 사용자에게 좋은 환경을 주는 고민과 해결만으로도 충분히 할게 많습니다.
그러다보니 UI와 비즈니스 로직을 분리하려는 노력, 웹뷰 대응은 기본이 되고 있고 그 외에 디자인 시스템, BFF를 담당하는 개별적인 업무까지 생기고 있으니까요.
왜 프론트는 클래스와 DI를 안쓰지? 고수의 코드는 없나? 라고 느끼시고 고통받으시는 만큼 동영상을 보는 많은 분들도 왜 이렇게 클래스와 DI만 찾지? 없어도 되는데? 라고 생각하시는 경우가 있을 겁니다.
아직은 프론트엔드 생태계가 성장 중이라 답답하시겠지만 그래도 나름 성숙해지고 있다고 느껴요.
지금처럼 좋은 인사이트로 (고통과 고민ㅠㅠ)으로 많이 기여해주시면 생태계에 큰 도움이 될겁니다
앞으로도 좋은 활약 기대할게요!!
사실 클래스를 쓰던 뭘하던 저는 이게 저에게 큰 관심사가 아니에요. 어떻게 하면 최대한 프레임워크에 종속적이지 않게 코드를 작성하느냐? 플랫폼 비종속까지 아니더라도 적어도 js 내에서 최대한 생명을 유지 할 수 있게 코드할 것 인가? 이죠. 사실 좋은 코드는 어디에서든 쉽게 쓸 수 있다는 거죠. 근데, 리엑트를 보면 타 프레임 워크에서는 리엑트 코드의 커스텀 훅 같은 것을 불러다 쓸 수 없죠. 프레임워크 종속적이죠. 로직과 뷰의 경계가 애매할 때도 많아요. 또한 스파게티 코드가 될 가능성 많이 있기도 하고, 그래서 리엑트를 별로 좋아 하진 않는데,... 과거로 거슬러 올라 가면 이런 경험이 있죠. jquery 같은 것들이 과거 오랫동안 지배해왔고, 수많은 발전을 하였지만, 그 때 작성했던 수많은 플러그인들은 이제 언젠가는 사장될 산물이라는 것. 마찬가지로 리엑트 역시 영원하지 않다는 가정하에 그 길을 가고 있죠. 물론 영원한 것은 있을 수 없겠지만, 가능하면 수명을 연장하게 하고 싶죠. 그러기 위해서는 어느 프레임워크에 비종속적이어야 하고 로직의 영역과 뷰의 영역이 철저히 분해 되는 형태이어야 한다고 생각 해요. 그런 점에서 js내에서 코드를 그룹화 또는 추상화하는 가장 작은 레벨은 함수라고 생각 하고, 그러면 그 함수라는 것을 기반으로 어떻게 코딩해야 좋을 것인가의 대해 생각해보게 되네요. 그런 면에서 좀 더 순수 함수를 활용하기 좋은 svelt 같은 녀석들도 괜찮고, 또한 프레임워크 종속적이긴 하지만, 비지니스 코드가 명확히 분리되는 점, 의존성 주입, Rxjs에서 지원하는 수많은 유틸리티와 함수 pipe 등 rxjs들의 장점, 또한 svelt 대비 좀 major 하다는 점이 장점이 될 수 있죠. 하지만, svelt나 앵귤러나 리엑트 만큼의 인기를 구가하지는 못하고 있죠. 안타깝지만....
프론트엔드 개발을 하고 있는 입장에서 개발바닥에서 프론트엔드 컨텐츠를 다뤄주셔서 정말 너무 좋고 감사합니다. 이런 논의들이 더 많이 나왔으면 해요. 영상에서도 언급주셨듯, 다시 꺼내기 어려우실만한 내용들이었을텐데도 2편 만들어주셔서 너무 감사하고.. 3편 4편 더더 계속 기다리는 사람이 있다는걸 알아주셨으면 합니다. 향로님 준비중이시라는 블로그 글도 기대가 됩니다.!!
흥미로운 주제에 대해서 영상이 올라왔네요.
백엔드 -> 안드로이드 -> 웹프론트쪽으로 개발을 하고 있는데, 그렇게 고수라고 부를 정도의 실력도 안되고 이론적인 지식도 부족하지만 제가 느낀 점을 써보면 일단 웹프론트는 DI나 MVVM 같은 그런걸 쓸 필요를 잘 못느끼는것 같습니다.
일단 백엔드와 프론트의 차이점을 이야기 하면 백엔드는 독립성을 유지해야 하는 단위가 업무이며 이는 클래스로 구성을 하고 있습니다.
하지만 프론트의 경우는 독립성을 유지를 해야하는 단위가 화면이죠.
업무에 필요한 데이터의 경우는 각종 모델링 등을 통해서 계층 관계가 이루어 지지만, 프론트의 경우는 다루어야 할 대상이 눈에 보이는 화면의 조각의 모음입니다.
그리고 이 화면의 경우는 복잡한 업무가 필요한게 아니라 서버에서 데이터를 받아서 표시를 하고 UX,인터렉션 처리가주 업무입니다.
데이터의 경우는 이미 서버에서 인터페이싱된 데이터를 보내주기 때문이죠.
실제로 웹프론트에서도 MVVM이 안쓰인건 아니었습니다.
영상에서 나왔듯이 angular에서 먼저 mvvm 패턴을 도입을 했지만 결국 시장의 선택을 받은건 리액트나 뷰와 같은 컴포넌트 중심의 툴입니다.
리액트나 뷰에서 state라는 개념을 통해서 어느정도 mvvm의 개념(observer)을 가지고 있고, 서버의 경우는 인터페이스를 통해서 각 객체간의 독립성을 보장을 해주지만, 리액트나 뷰의 컴포넌트의 경우는 props가 그 인터페이스 역할을 하며 컴포넌트의 독립성을 보장을 해줍니다.
실제로 리액트의 경우는 초기에는 클래스 기반이었다가 16버전에서는 클래스를 버리고 hook이라는 작은 function개념으로 돌아섰습니다.
리액트 개발진들이 밝히기를 여러가지 개발 프로젝트를 관찰한 결과 클래스를 써야할만큼 복잡한 업무가 거의 없고 클래스는 오히려 코드의 난이도만 높힌다고 했습니다.
심지어 예전에는 mobx나 redux를 이용해서 업무영역을 store 분리하는게 대세였지만 요즘에는 이러한 거대 store도 조금씩 버려지고(?) 있는 추세인것 같습니다.
실제 개발코드 store중 70%~80% 이상이 단순 repository의 연계이고 소수의 업무코드를 위해 store를 유지하는게 오히려 더 비효율적이라고 생각되기 때문입니다.
즉, 화면을 만들때 가장 큰 관심사항은 얼마나 빨리 적은 비용으로 화면을 구성을 하고, 화면의 변화에 빠르게 대응을 할 수 있고 유지보수에 용이하냐 입니다.
그러한 개념으로 볼때 컴포넌트 기반의 리액트나 뷰는 제격인거죠.
눈에 보이는 구성요소를 컴포넌트로 작게 분리를 할 수 있고, 컴포넌트는 적은 비용으로 빠르게 제작이 가능합니다. 그리고 이러한 컴포넌트는 독립성을 유지하며 재활용성이 띄어납니다.
mvvm이나 di를 쓰지 않더라도 좋은 코드의 특성을 지니면서 mvvm이나 di 대비 개발 비용 조차 저렴합니다.
이러한 요소들이 프론트에서는 OOP보다 함수형언어가 더 잘맞다고 보고 있구요.
(개인적으로는 백엔드 분야에서도 OOP보다는 함수형언어쪽이 더 작은 비용으로 더 좋은 목적을 수행할 수 있다고 보고 서서히 변화해 나갈꺼라고 생각합니다.)
영상이나 댓글을 보면 안드로이드나 아이폰이 경우는 MVVM이나 DI가 있다고 말씀하시는데 저는 오히려 이러한 native 영역이 과도기라고 보고 있습니다.
native와 같이 전체 화면을 하나의 요소(클래스)로 두고 mvvm 및 di 등을 통한 각종 객체지향적인 기법으로 개발을 하는것 보다 화면을 조각내어서 컴포넌트 기반으로 하나의 화면 조각을 작게 가져가는게 효율이 더 좋기 때문입니다.
이러한 작은 컴포넌트 조각들은 mvvm과 같은 패턴이나 OOP는 어울리지가 않죠.
native영역도 native 개발툴 보다는 flutter와 같은 통합툴로 이전이 될꺼라고 생각되고, 이러한 툴 들은 컴포넌트 기반으로 구성이 되고 있습니다.
즉, 프론트는 발전방향이 MVC -> MVVM -> 리액트와 같은 component 형태의 개발방식으로 진화가 되는것이죠.
암튼, 정리하면 백엔드와 프론트는 다루는 데이터가 다르기 때문에, 발전되는 아키텍처의 모습도 다르다고 보고 있습니다 ^^
띵댓글…
인사이트 있는 좋은 댓글 감사합니다!
속이시원하네요. 👍
멋진 댓글이에요!
댓글 정독했네요 감사합니다 ㅎㅎ
안녕하세요 저는 신입 FE 개발자입니다 개인적으로 이 주제가 굉장히 반갑고 재밌고 많이 이야기 되면 좋겠어요 저도 프론트엔드 개발은 OOP가 어렵다, 단위 테스트보다 통합 테스트가 쉽다, 라고 말하면서도 왜 그런건지, 왜 그래야만 하는지 설명하지 못해서 좀 찜찜했거든요 주니어 FE 개발자로서도 명확하게 이해가 되는 설명은 아직 보지 못한 것 같아요
React에서 DI가 필요할 땐 Context API를 사용 한다는 이야기를 트위터 해외개발자들 사이에서 얘기한걸 언뜻 본 기억이 있어요 thunk의 custom argument를 이용해서 api를 주입하는 방법도 있는데 개인적으로는 보일러플레이트가 너무 많이 필요해서 불편했던 기억이...
주7회 업로드.... 해조!
지나가는 저의 생각은 데이터를 생각해봤을 때
자바같은 백단은 DB조회하면서 클래스 객체로 받아서 데이터와 기능이 동작하게 하고 싶으니, 자바빈즈클래스같은 클래스에 데이터와 메서드 기능 연동을 시키는데,
프론트단은 데이터가 있는 json 으로 데이터를 받으면 그 데이터 객체에서 어떤 기능이 필요하면 JSON 오브젝트에다가 그냥 Object assign 해서 함수 연결하면 되기도하고
이 받은 데이터를 여러 컴포넌트간에 공유를 할 때..로컬스토리지에 저장을 한다던가, redux 에 객체 저장을 할때 기본 단위가 직렬화할 수 있는 JSON 정도로 저장이 되게되서..
주고받는 데이터들이 JSON 기준으로 데이터를 생각하게 되다보니
그러다보니 자연스럽게 그냥 JSON 데이터 기준으로 기능이 필요하면 함수를 연결하는 함수형이 좀 더 편하게 생각되게 된 것같습니다.
그리고 자바진영에서 (오래된 이야기지만 )뒤늦게서야 람다식이 적용되면서 메서드의 일급객체로써의 적용이 늦은 반면에
js 진영은 그냥 콜백함수 전달하면 되니까, DI 같은 것을 굳이..? 사용하기보다는 다르게 동작할 부분이라면, 그냥 함수 쪼개서 콜백 함수 전달하면 될 걸.. 정도로 생각하지 않나 싶습니다.
사실 이 콜백 부분도 커링같은 부분으로 해서 함수형js 같은 쪽이 궁극적으로가게 되는 것같더라구요.
---
그리고 위에서 말씀하신 axios 같은 것을 사용할 때는.. 동감되는 부분이
이 네트워크 호출이라는 작업이 여러가지 부수작업을 해야하는 굉장히 비싼 작업이기 때문에 당연히 여기서는 객체클래스를 섞어 쓰게 되는 것같습니다.
사실 이 부분도 저도 다시 함수형으로 다시 짜보고 싶긴합니다..
--
이참에 자바 JPA 진영이 있듯이 JS 함수형 진영에 유명한 분들이 계십니다.
회사차원에서 사용하는 라이브러리도 직접 만들어서 배포해주신 분이 계신데.. (아 인프런에 js 함수형 치면 바로 관련된 분들이 나오시는 분들이죠..)
한번 그분들과 라이브러리 소개도 해보시면서 토킹어바웃해보시는 시간 가지시면 재미있을 것같습니다.
자주바뀌기 때문에 객체지향이나 di 개념을 사용하지 않는다고 하는데
모든 설계 아키텍처는 변경에 유연하게 대응하기 위해 시스템을 분해하는 과정이죠..
Di 객체지향 또한 마찬가지구요.
DI가 큰 변경에 대한 대비로 매우 좋긴한데, 좋소나 스타트업들이 그런게 어딨겠어요. 그냥 빠른 프로토타이핑과 엎고 새로 개발하고의 반복이죠.
웹프론트엔드 코드 수명과도 영향이 있을까요?
백엔드 코드는 10년도 넘게 쓰기도 하니 여러 유지보수에 유리한 개념을 적극 사용하지만 프론트는 아닌가 해서요..
많은 분들이 브라우저, api에 의존적인 개발을 이유로 FE에서 OOP가 유행하지 않았고, 맞지도 않다고 이야기 하시지만
그 주장이 맞을려면 IOS, AOS 진영에서 DI 프레임워크가 유행하는 것에 대해서도 납득할만한 이유를 댈 수 있어야 합니다.
IOS, AOS도 플랫폼 의존적이고 마찬가지로 서버 API에 의존적인 영역입니다. 하지만 DI OOP가 이쪽에선 근본 of 근본이죠.
제가 생각하는 FE에서 OOP가 유행하지 않은 이유는 "개발 관성" 이라고 생각이 듭니다.
AOS는 개발을 자바로 했어야 하니 당연히 자바 철학에 맞춰 OOP에 친숙할 수 밖에 없고 IOS도 마찬가지 Objective C 를 사용하다 보니 똑같았다고 봅니다.
하지만 FE의 자바스크립트는 그렇지 않죠. 초기엔 Class 자체가 없었고, 타입도 없었으며 XMLHttpRequest나 이벤트 함수를 보면 콜백 함수를 엄청 적극적으로 장려하며 사용했었습니다. this도 문제가 많습니다. 언제 어떻게 호출되냐에 다라서 this 값이 달라집니다. OOP스러운 코드를 작성하기엔 불편한 구조이죠.
IOS, AOS는 OOP를 활용하는 방법으로 개발자가 짱구를 굴렸고, 반대로 FE는 함수를 잘 사용하는 방법으로 짱구를 굴리다 보니 서로 코드를 작성하는 방법이 달라진거죠.
최근에서야 타입스크립트가 나오고 Class도 나오고 하니 객체지향스러운 코드를 작성할 수 있지만 옛날엔 아니었잖아요. 인터페이스도 없는데 DI해서 뭐 하나요? 잘못 참조하면 에러만 펑펑 터지는 코드가 나오는데 툴들이 성숙하지 않았던 시절엔 독이었습니다.
이런 "개발 관성" 때문에 유행하지 않은것이지, 도메인 로직, 브라우저 DOM 특성 때문이 아닌것 같습니다.
IOC Container 있으면 굉장히 편합니다. 지금 리액트는 Context API도 생성 순서를 맞춰야 하는데 IOC Container 있으면 그럴 필요도 없죠 코드 분리도 깔끔합니다.
하지만 없어도 충분히 구현 가능합니다. 대안책은 얼마든지 있으니까요.
그러니 필요성을 못느끼는것 같습니다.
사실 이 내용은 클린아키텍처에 잘 나와있죠. 변경이 자주 발생하는 부분과 그렇지 않은 부분을 어떻게 설계해야하는지… 변경이 자주 발생하는 컴포넌트에서 처음부터 과도한 추상화를 하게 되면 어떤 참사가 발생하는지 말이죠.
공감되는 부분이 많은 영상입니다.
앱 개발은 객체지향을 잘 사용하는데 유독 웹 분야만 객체지향에 거부감이 있는게 의문입니다.
contextApi가 DI의 역할을 할 수도 있다는 이야기도 있는데, 다수의 context를 주입하면 context hell 같은 이상한 현상도 보게 되구요...
FLUX패턴도 너무 과하게 엔지니어링 되서 막상 쓰기도 힘들고 협업하는 사람들이 이해하기도 힘든 코드가 많이 발생합니다.
Singleton + Observer 패턴이면 훨씬 간단하게 추릴수 있을거 같은데 Recoil이 이런 형태와 유사한거 같네요.
사실 class를 이용하지 않고 더 나은 코드가 나왔더라면 이런 의문도 없었을텐데, 정말 이게 맞는 코드인가? 이런 의문만 남게되는 상황이 너무 많아요.
UI 템플릿과 관련되지 않은 부분들은 class로 가능하겠지만 렌더링 관점에서보면 완전히 같은방식으로 처리되는부분들은 거의 보기 힘든것같은데.
아랫분 말씀처럼 특정 모듈을 만든다고 하면 class를 사용했을때 이점이 있겠지만 그러한 모듈들을 사용해서 렌더링을 해야하는부분에서는 그런식으로 관리하기 힘든것같습니다 경험상.
영상 정말 재미있게 잘 보고 있습니다. 저도 처음에는 프론트엔드에서 객체지향이 필요할까 싶었지만,
규모가 커지고 복잡한 웹 어플리케이션을 개발하게 되면서 oop의 필요성을 인지하게 되었고 그렇게 개발하려고 노력중입니다.
물론 단순 랜딩 페이지 만들자고 oop, typescript를 쓸 필요는 없다고 생각해요. 다만,
Typescript가 부흥(?) 하면서 복잡한 프론트엔드 개발 환경에서의 oop 개념이 더 많이 퍼지지 않을까 생각합니다.
앵귤러 쓰시면 ...그 답답함이 ㅋㅋㅋ 풀리실건 같은데
앵귤러 DI 시스템이나 아키텍처는 안드로이드의 대거 같은 것에 아이디어를 많이 가져 왔기 때문에
생각하시는 구조를 구현해볼수 있습니다.
그리고 프론트앤드의 복잡도 크면 클수록
레이어 계층 분리하여 기능별로 쪼개지는 유용성이 있긴합니다. 그냥 랜딩 페이지 만드는데 그 정도까지는 필요하지는 않은거구요 ㅎ
저 배라 ㅊㅈ 입니다 ㅋㅋ 퇴사전에 리엑트 mobx 로 프로젝트 했는데 두분 고민과 똑 같은 고민했는데 di 까진 아니다라도 service(mobx store), repository(axios), 리액트 컴포넌트는 컨트롤러 역할, ui 컴포넌트 따로 빼구요 npm에서 라이브러리 하나찾아서 mobx store 를 데코레이터로 주입하구요 이렇게 레이어 분리하고 비즈니스로직은 각각에 맞게 적절히 분리하고 로직을 외부에서 구현하지 않고 oop 개념대로 해당 클래스의 상태는 해당 클래스의 메소드로 캡슐화 해서 제공하고 메소드호출(메시지)로만 커뮤니케이션하도록 딱 java spring 백엔드 처럼 구현했는데 충분히 가능하고 그렇게 개발하니 로직이 적절히 분산되어 보통 리액트 컴포넌트에 비즈니스 로직이 모여 있던게 다 흩어 지더라구요
FE 개발 과 java 백엔드 개발(oop) 둘다 어느정도 바삭하면 두분처럼 고민 나올 수 밖에 없는데 대부분 FE 전문 개발자가 더 많고 oop가 단순 클래스 사용이 아니라 아~ 이게 oop 구나 느낄려면 백엔드 개발도 어느정도 실무로 해야지 깨닫는 쉽지 않은 영역이라 FE 전문으로 하시는 개발자분들이 그개념을 바식 이해한 상태가 아닐 가능성이 높은 상황에서 구지 FE 개발에서 oop 까지 필요 있나 라고 의견을 낼 가능성이 높다고 저는 생각이 듭니다(물론 아닐 수도 있구요)
저처럼 또 두분처럼 원래 java 백엔드 개발이 주 포지션이였으면 당연히 동욱님 이야기에 100% 공감합니다 oop 안하면 FE 코드에 로직이 집중 되어 있고 캡슐화 안되서 로직이 오픈되고 걍 로직이 중구난방 장점도 별로 없다고 생각합니다 즉 둘다 바삭한 상태에서 FE 에서 oop vs function 선택한게 아니라 oop 느낌을 100% 잘 이해 못한 상태고 둘중 뭐가 더 유리한지 판단을 할 만한 상태가 아니란게 맞지 싶습니다
배민 블로그에 제가 4년 전에 사용기 쓴거 보시면 스프링 처럼 레이어 나누고 oop 처럼 하나 코드도 정리되고 훨씬 좋았습니다(리덕스 만든 dan 뭐시기 그분이 오히려 리액트 개발 어렵게 만든 장본인 이라고 개인적으론 생각도 들고요… ㅋㅋ)
제가 영상에서 나온 이야기를 면접에서 이야기하면, 쓸모없잖아요라던가 인터페이스 추상화에 대해서 부정적이신건지 아님 제가 설명이 잘못되었는지 공감들을 못하시더라구요
결국에는 테스트에 유리한 코드를 짜려면 의존성주입 + 제어의역전 + 추상화 이런 큰 틀로 가야하는데.. 뭐 그렇습니다..
IOC있는 앵귤러도 테스트 코드 짤려면 리액트처럼 TestBed 안에서 목으로 가득 채운후 짜야합니다. 그냥 FE는 테스트 하기 어려운것 같아요
백엔드에서는 jpa 라는 프레임워크를 이용해서 객체지향스러운 프로그래밍을 하려고 노력하는데요.
여러 백엔드 개발자들이 개발해준 api 를 가져다 사용해야하는 사용처의 개발자들은 제공되는 api 스펙에 맞추어 호출을 하고
결과를 객체로 매핑해서 가져다 사용하는데, 여기서 중복코드(중복 객체, 속성)도 많이 발생하는것 같고,
결국 아무 생각없이 api 호출 코드들이 계속해서 생성되어 쌓이게 되는것 같습니다.
백엔드 api를 사용하는 사용처에서도 객체지향적인 프로그래밍을 하는 좋은 방법이 없을까요?
웹쪽은 상태리스하게 짜고 서버쪽을 객체지향이든 뭐든 괜찮은 설계를 해두는게 제일 나은거 같습니다. 웹이 아무리 복잡해져봤자 유튜브 대시보드 창 정도밖에 더 되지 않나 싶네요.
프레임워크가 가지는 근본적인 컨셉차이 아닐까요 스프링이나 앱 개발의 방향은 객체지향을 토대로 두고 프로그래머의 영원한 숙제인 결합도나 응집도같은 문제를 풀어가고 있는 것이고 웹 프론트앤드 기술들은 선언형이나 함수형으로 그런 문제를 풀어가고 있어서 개발함에 있어서 의존성 주입이나 제어 역전같은 참조가 주가 되는 문제 해결 방식보다는 값 자체로 풀어가기 위해 컴포넌트에 기능 하나만 동작하게 하는 순수함수 철학에 가까워서 생기는 차이 같습니다 .
저도 프론트엔드 개발하면서 항상 그런 생각을 하긴 했는데 이렇게 다시 생각할 수 있는 기회를 주신게 감사하네요!
흠 객체지향을 추구한다면 진지하게 Angular와 Nest.js 조합으로 가는 것도 좋아보이긴 해요
주제와 부합하는지는 잘 모르겠지만 듣다보니 비슷하게 공감되는게
React 에 뛰어들어가 모든걸 하는게 아니라 UI 제어권한만 React 한테 주고,
비즈니스 로직이나 인프라관련 세부사항은 별도 레이어를 두어서 React에 깊게 엮어들어가지않는게 좀 더 성숙한 개발방법이라고 생각하는디요.
가령 구매상품갯수 카운트 기능 있다하면 ( [ + ] 1 [ - ] 이렇게생긴거)
class 로 ProductCounter 기능 구현하고 현재재고갯수, 최대구매갯수 같은거 인스턴스 생성할때 주입하고
React 상태랑 연동하는게 좀 번잡스럽긴할테지만 Count 구독가능하게 만들어서 상태와 바인딩하는식으로 풀 수 있고
얼마든지 가능한것같습니다. 내가 생각하는만큼 매끄럽진 않았지만 이렇게하니 딴건몰라도 테스트짜기 짱편햇어여.
다만 왜 매번 이렇게 안하느냐 할수 있지 않느냐를 따져본다면 매번 공감대를 형성하는것이 힘들다고느끼고 (내 설득능력의 문제가 클것임)
공감대를 형성하기 힘든이유는 트랜드에 민감한 경향이 있는반면 이런 주제에 대해 상대적으로 진지하게 이야기나눌 수 있는 주변인이 적은것같습니다.
저는 리액트 를 하되 리액트랑 적절한 거리감을 두고 싶은데 많은의 분들이 리액트를 너무 사랑해서 리액트랑 결혼하는것같습니다.
저도 동일한 생각으로 state와 logic을 분리해놓고 logic 자체를 캡슐하하여 테스트하고 state에 바인딩하는 방식으로 레이어를 나누고 있습니다. 리액트에서 가장 oop스럽게 문제를 해결하는 방법이라고 생각해요
프론트는 본질적으로 ui와 밀접해서 객체에 대한 공통의 로직이 중복되는 경우가 적고, 기획이 바뀌고 ui가 변경될 때마다 반영할 수 있는 객체지향의 코드를 작성하기에는 투머치하다 인것 같네요,,
그리고 로직이 중복되는 경우엔 훅으로 추상화를 해서 재사용하면 돼고, 상태도 전역 상태가 아닌 context로 구분해서 해당하는 영역에서만 상태를 관리할 수 있기 때문에 도대체 언제 어느 시점에서 클래스가 필요하다는거지? 라는 의문이 들기는 해요 물론 저도 백엔드를 몰라서 프론트 입장에서 하는 말이긴 하지만요
주제에 대한 논의가 이뤄진다는거는 흥미롭습니다! 저도 프론트 고수분이 나오셔서 정리해주시면 좋을것 같아요
전제가 많이 잘못된 것 같습니다. 프론트엔드에 왜 백엔드에 사용되는 패턴을 사용해야 하는가를 생각해 보시길. 솔직히 말해서 뭔소리를 하는가 싶습니다. JS 디자인 패턴이나 그럴 것들을 찾아보시길. 각각의 패턴은 사용처가 정해져 있는데 백엔드의 패턴을 무작정 프론트엔드에 적용하니 이상한 말이 나옵니다. 프론트엔드는 비지니스 로직 자체보다는 원하는 데이터를 처리해 나타내는게 주목적입니다. 그러니 당연히 DI나 class를 통한 확장성 보다는 데이터의 조합을 위한 hook이나 composition api과 같은 패턴이 사용되는 것 입니다. 아마 단순한 프론트엔드 레벨에서 겉핥기 식으로 접하신 것 같은데 대부분의 OOP 패턴이 프론트엔드에서 잘 먹히지 않습니다. 페이스북이 왜 리엑트를 만들었을까요? 왜 앵귤러는 점유율을 잃어갈까요?
여러 고수분들이 얘기 많이 해주셨는데, 얘기 들어보면 아무래도 Spring 을 오래 하셨고 어노테이션 기반 개발 및 DI 개념에 너무 익숙해서 그런 패턴화가 프론트엔드에 안되어 있는게 어색한 것이 아닐까 하는 생각이 드네요. 어떤 분도 적어주셨지만 mobx 같은 스토어를 사용하여 Service, Repo 레이어를 직접 구현하면 비스무리하게 따라하는건 얼마든지 가능합니다. 단지 이런게 프레임워크 혹은 라이브러리에서 공식적인 패턴화가 안되어 있어서 자유분방한 코드가 만들어 지는 것 같다고 생각합니다. nest.js 나 angular 같은 것은 그런 패턴이 공식적으로 구현되어 있으니 잘 사용하는 것처럼요.
API가 백엔드에 의존적이다보니 여러 정보를 한번에 뭉개서 보내주는 경계를 구분 짓기가 쉽지 않더라구요
팩토리 패턴 정도를 사용해서 의존성 주입하는건, 당연하고 좋은 패턴이다라고 생각하는데요. C++, Python을 주력으로 사용하다, 안드로이드 쪽 일을 할 일이 생겨 Java를 좀 사용하게 됬는데. Dagger로 정신없이 annotation쓰면서 의존성 주입을 하는게 자바의 패턴이던데, 이렇게 복잡하게 이런짓을 하는 이유가 이해가 안되더라구요. 컴파일 타임에 굉장히 복잡한 의존성 트리가 만들어지는 방식이라, 언어의 시맨틱 만으로 코드패스가 어떤식으로 실행되는지 이해하기만 어려워 진다는 느낌이었습니다. 재빨리 발을 뺀후, 자바쪽을 쳐다보지도 않고 있습니다.
답답한 이유: 왜 백엔드 패턴을 프론트엔드에 적용해야 하는가 생각을 안함 (백엔드 패턴이 답이라고 결정해서 그런 듯?)
FE개발자 역량이 초중급이라 가정하고, 3개의 FW를 다뤄서 각각 프로젝트 완성도 결과를 점수로 매기면,
앵귤러 : 최소80점+
리액트, 뷰 : 50점-80점+
그만큼 앵귤러가 학습곡선은 높지만, 체계적으로 잘 잡혔다고 개인적으로 생각.
현업에서도 어차피 남이 짠 코드를 보게되는데, 앵귤러로 짠 코드면 전체를 훓어봐도 기본 뼈대가 잘 잡혀 있기에, 이해를 빠르게 캣치 할 수 있음.
리액트뷰는.... 엔지니어 실력에 따라 어떻게 잘 구성되어 있고 코드가 짜여 있는가에 따라 많이 많이 달라짐(...화딱지도 많이 생길 수도 있음...)
결론은 앵귤러로 작업한다면 평타는 칠 수 있다.
뷰도 나름대로 코드 짜는 방식 자체가 틀에 맞춰져 있어서 누가 짜도 읽기는 쉽다고 생각함 근데 리액트는 얄짤 없음 ㅋㅋ
프론트엔드 공부중인데 이 주제에 대해서 정말 관심있게 보고있습니다!! 계속해서 이야기 많이 올려주셨으면 좋겠어요 ㅎㅎ
진짜 FE고수님들 한번 총대 부탁드려요~
프론트엔드 라이트한 개발을 하던 JS 개발자들이 만든 프레임 워크 이다 보니 프로그램밍의 본질인 일반화 추상화 를 위한 다양한 패턴을 사용하지 못하고 그냥 기능과 화면 구현을 위한 목적에 급급함 이로 이한 요구사항 변경에 따른 끝없는 코드 변경 에 휘말리게 된다.
1:24 에 모바일은 MVVM 으로 말씀하셨는데 자막에는 MVM 으로 작성해주셨어요~!
우선은 언어적 차이가 크지않았나 생각합니다
단순히 역사의 길이와 많은 변화때문에 리엑트진형에 oop의 개념이 정착하지않았다라고 보기는 어려운것같네요 오히려 역사도 짧고 리엑트만큼 많은 변화를 격고있는 안드로이드 진형에서 oop개념이 정착되어가고 있는현상을 보면 언어적으로 javascript는 oop의 개념을구현하기 어렵다고 생각됩니다
하지만 이제 리엑트에서도 typescript를 사용하게되면서
결국 oop로 의 발전이 진행되지않을까 예상이됩니다
결국 타입이 있고 다양한 변화에대응해야된다면 자연스럽게 oop로 손이가게 될꺼같아요
이제는 기존의 관념을 깨는 일만남았는데
개발바닥을 필두로 의문을품는사람들이 나타나기시작했기 때문에 곧 변화하지않을까 생각되네요
두분이 함수형 사고가 아니라, OOP 사고에 익숙해서 아닐까요?
그건 맞기도 틀리기도 하지 않을까요
FE도 앱 종류마다 천차만별입니다. 에디터 같은거 한번 뜯어보시면 FC에서 아득히 멀어져 있는 코드들을 볼 수 있습니다.
프론트엔드는 근본적으로 UI에 종속적이라 백엔드보다는 코드의 변경이 잦게 일어난다고 생각합니다.
그리고 복잡한 로직을 처리하는 일은 서버에 맡기고 있잖아요?
그래서 비즈니스 코드나 구조가 UI에 따라서 변경될 가능성도 크고
객체지향적으로 접근하는 것이 좀 too much 하다는 느낌을 받아요.
그래서 하나의 정형화된 패턴이 존재하기 어려운게 아닐까 생각합니다.
그리고 좀 더 가볍고 쉬운 것을 찾게 되어서
뭔가 새로운게 나왔대! -> 그럼 좀 지켜볼까? -> 시간이 좀 흐름 -> 그거 괜찮대 -> 우리한테 필요한지 적합한지 고려해보고 적용해보자
이런 식의 시도가 되게 많은 거 같아요.
백엔드보다는 변화가 잦고 새롭게 제시되고 떠오르는게 많다보니 이게 딱 좋다! 라고 결론 지어질만한 게 없는ㄱ ㅓ 같습니다.ㅏ
출근길에 재밌게 봤네요~
브래드 프로스트 같이 back of frontend, front of frontend 를 구분하시는 분도 있습니다. 저는 완전 동의하지는 않지만요...
몸 상태가 안좋으신가부다.. 몸 관리 잘하셔요😢
각 컴포넌트는 자신만의 상태를 갖고 다른 필요한것은 프로퍼티로 받아 사용한다 이런것도 di 아닐까요?
컴포넌트 베이스 개발 방법이 프론트와 잘맞아서 그렇지 않을까요.
개발방법론이 다른데 왜 사용안하는지 모르겠다라는건
방법론 자체를 바꿔버리자는 말로 들립니다.
백엔드도 컴포넌트베이스 개발 시절도 있었고, 현재는 oop 개발이 대세가 된 걸로 알고 있는데 말이죠
같은 프론트엔드인데 네이티브 앱 (ios, android) 는 클래스와 di 의 이점을 적극 활용하는데
왜 웹 프론트엔드에는 그런게 없는지도 의문점인것 같습니다 ㅠ ㅎㅎ
물혼 프론트엔드가 Ui 에 종속적이고, 핵심 비즈니스로직은 백엔드가 주로 담당하는 것은 맞지만
그렇다면 모든 프론트 (네이티브 앱과 웹)에서 공통적으로 Di 없는 체계가 발달했어야 하지 않나.. 싶어요
프론트는 어설픈 코드로 인해 발생하는 문제가 백엔드만큼 치명적이지 않아서 그런가 싶어요. 복잡하지 않은 로직을 복잡하게 짤 필요를 못느끼는 것 때문인 듯 하기도 하고, 빠르게 적용해보고 아니면 버리는 문화가 있어서 그런거 같기도 합니다. 리팩토링을 하는 것보다 새로운 기술로 다시 만드는 게 낫다고 여겨서 애초에 오래 유지보수할 생각이 없는 거 같기도 하구요!
실제로 오랫동안 유지보수 해야 할 일들이 많지 않은 이유가 제일 크지 않을까요.
몇년 지나면 어차피 갈아엎어야 하는 상황이 발생하고,
그게 아니라도 오래된 코드는 아무리 잘 만들었어도 유지보수성이 떨어질 수밖에 없으니..
당시 언어를 잘 아는 사람이 아닌 새로 유입된 인력들이 상대하기엔 말이죠.
환승길 최고의 선택
ㅋㅋㅋ 리액트 사과? 방송 보고 와서 보는데, 늘 그렇듯, 백엔드 관점에서 프론트엔드를 바라보는 ㅋㅋ 근데 이해는 합니다. 딱히 잘못된 의견도 아니지만 ㅋㅋ, 모든 분야의 정보를 다 관장할순 없으니 ㅋㅋ 당현한 이치겠지만.
방법이 없는건 아닙니다.
두분이 원하시는게 단순히 클래스 문법을 쓰는게 아니기에, 리액트 클래스 컴포넌트나 앵귤러가 그 답은 아니라고 생각합니다. 웹과 다른 클라이언트가 다른점은 화면랜더링이 DOM과 브라우저 api들에 의존적이고, 그것들이 OOP와 전혀 다른 패러다임이라는거 아닐까요?
백엔드에서 그렇게 코딩을 할수있는건 툴의 도움이 크다고 생각합니다. 프론트개발자들은 지금 ORM없이 쿼리빌더만 가지고 일하고있는거에요. 왜 그런 툴이 없는지는 잘 모르겠지만, 저보고 간단한 orm을 짜보라면 쉽게 짜겠는데, 객체를 돔으로, 그것도 상태관리까지 가능한 매퍼를 짜라면 전 도망갈게요. 엄두도 안나요.
어차피 상태관리 라이브러리에서 상태를 관리해야하고, 시장지배적인 라이브러리가 있는상황에서, 매번 오버헤드를 감당하기보다는 라이브러리에 의존하는 선택을 해버린거 아닐까요?
답은 있습니다. DOM을 배제하면 되요. 그냥 canvas에 랜더링하면 됩니다. 근데 단점을 생각해보면 seo, 접근성같은 웹바이탈에 안좋겠네요. (블레이저에 대해 언급했었는데 자세히 찾아보니 제가 잘못알고있었네요. 수정합니다)
찾아보니 제가 말한 방식의 zebkit이란 재미난 프레임워크가 있네요. 역시나 easy JS OOP approach를 컨셉으로 내세우고 있습니다
지극히 개인적인 생각으로
1. 왜 프론트에서 DI는 인기가 없을까?
2. 왜 클래스를 사용 하지 않을까? 의 생각을 해본다면,
실제로 비슷하게 DI 요소를 적용해보면 많이 번거롭기도 하거니와 프론트 쪽에서 최적화 쪽에 더 힘을 싫어서 그런지 더 간결한 코드를 선호한다는 느낌입니다. 정확히 제어역전 까지는 아니라도 비슷하게 그 효과를 볼 수 있겠습니다만, 발전의 방향이 유연하게 만든다기 보다는 그냥 그 부분 다시 만들지 하는 생각이 있는 거 아닐까 하기도 합니다. 어째든 DI를 지원하는 것은 프론트의 디자인 요소로서 마지막을 맟추는 그림이라고 저는 생각합니다. 그렇기에 프레임워크 레벨에서 DI 지원해주는 앵귤러는 장점이긴 하지요. 다만, DI 엄청 중요하게 다가오지는 않는 것 같습니다.( DI 의 유무가 프레임워크의 결정요소로 적용되는 것은 한번도 본 적이 없음.)
2. 왜 클래스를 사용 하지 않을까? 는 사실 리엑트 같은 것들이 클래스보다는 함수 기반이기 때문일 수도 있겠지만, vue, 앵귤러는 클래스 기반이긴 하지만, 그게 중요한 건 아니고, 사실 객체지향보다 함수형을 선호하는 저에게는 왜 클래스를 써야하지? 라는 생각을 하게 하네요. 클래스 특성상 동일한 것에 여러 인스턴스를 만들 수 있다는 특징이 있지만, 실제로 그렇게 쓰는 것은 아니고, 객체지향 패러다임이나 설계원칙을 적용하려고 쓰려는 것이 겠지만, 동일하게 함수형 프로그램 모델에서도 대부분 해결 되기에 굳이 객체지향 적용되어야 하나 싶네요. (일부 객체를 사용할 수 있겠지만, ..) 논란이 많은 이야기가 될 수 있겠지만, 흔히 이야기 하는 개방폐쇠의 원칙. 확장에는 열려 있지만, 수정에는 폐쇠적인 것... 사실 설계가 완벽하면 문제가 안되겠지만, 실제로 시간이 지나고 요구사항이 변하면서 처음 부터 코드를 다시 써야 하는 상황이 오거나, 또는 덕지덕지 말도 않되게 코드를 작성해야 하는 상황이 오면 꽤나 불편하다고 느껴지네요. 오히려 코드를 함수 단위로 작게 유지하고, 적절히 그룹핑 시키면 그게 더 편하지 않나 하네요. 또한, 클래스를 잘 안쓰는 이유가 적절히 쓸만한 모델을 만나지 않아서 일 수도 있고,
사실 이건 테스트 해보면 더 정확히 알 수 있다고 보여지네요. 말씀 하시것 처럼 풀 클래스 코드로 작성한 프로덕션을 한 6개월 운영해보고 반대로 동일한 코드를 클래스 기반이 아닌 방식으로 작성해서 6개월 운영해보고 무엇이 더 낳은지 상세 비교를 통해서요. 그게 아니라도 지금의 프로덕션을 컨버팅해보는 것도 방법이 되겠죠.
진짜 그냥 백엔드 관점에서만 바라보는 프론트엔드 인것같네요
JS에서 스프링 스타일의 DI를 사용하지 않는 이유.
1. 부족한 문법.
스프링 스타일의 DI에서 필요한 인터페이스, 애노테이션등의 문법 부재.
2. 속도.
이게 가장 중요한 문제인데 스프링 스타일의 DI를 쓰면 초기 로드 속도가 느려짐. js가 아닌 다른 언어, 프레임워크들도 DI 구현 시 코드를 생성하는 유틸리티를 사용하여 런타임이 아니라 컴파일 전에 코드를 생성하는 형태로 가는 추세. 프론트엔드 js에서 초기 로드속도는 매우 중요한데, 초기 로드 속도에 따라 비즈니스 결과 차이가 어마어마함. 만약 js에서 스프링 방식의 DI를 사용한다면, 초기 객체 생성 시간 뿐만 아니라 DI의 부수적인 코드들 때문에 스크립트 사이즈 자체가 커져서 초기 로드 시간(스크립트 다운로드 및 초기 코드 로드시간)에 더욱 더 치명적.
3. 모듈시스템.
JS 모듈 시스템을 이용하면 어느정도 DI구현이 가능함.
다음은 많이 JS에서 많이 사용하는 싱글턴 DI패턴.
//module.js
class Repository {
findOne() {
}
}
export const repository = new Repository();
//main.js
//모듈 로드 시 싱글턴 형태로 객체 생성 및 주입이 됨.
import { repository } from "./module.js";
respository.findOne();
import 문법을 사용하면 비동기형태로 Lazy 로드도 가능함.
4. 테스팅
jest등을 사용하면 모킹뿐만 아니라 페이크, 스텁등 다 가능함.
결론: 프론트엔드에서 다른방식으로 DI 구현이 가능하며, 장점보다는 단점이 훨씬 큰 스프링형태의 DI를 js에서 고집할 이유는 없음.
재택근무 최고의 선택
화면 UI는 언제든지 변할 수 있고 지금까지도 그래왔고 변경시 큰 비용이 들지 않지만 백엔드의 경우에는 중요한 데이터를 직접 다루는 일이 많고 로직 하나하나 민감한 부분들이 존재하기에 FE보다는 보다 정해진 형식으로 개발을 해야하며, 그에 맞는 테스트 코드도 필요해서라고 생각합니다.
내가 느끼는 자바스크립트, 코틀린
가가 가가가?? 가가가가가각??
08:43 진짜 엄청난 명언 이심다!!!
가훈으로 삼아야 겠다
여러가지 이유가 있겠지만.... 웹이라는 특성, 브라우저라는 환경, 그리고 CSS라는 전역적으로 적용가능한 스타일의 존재 정도로 크게 정리해서 볼 수도 있을 것 같습니다.
1. 웹 서비스는 일단 다른 플랫폼에 비해 빠른 배포가 가능합니다. 그래서 웹을 일종의 신규 기능 실험장 처럼 쓰는 케이스도 많죠. 따라서 구조적 견고함보다는, 주요 프레임워크 위에서 빠르게빠르게 갈아엎는 수준으로 변경할 수 있도록 찍어내는 경우도 많은 것 같습니다. (장점이면서도 단점이기도 하죠)
2. 브라우저라는 환경은 또 다른 복잡도를 제공하는데, 웹 프론트를 사용하고 환경에 대응하는 방식은 굉장히 다양합니다.
2-1. 일단 해상도에 따라, 데스크탑-테블릿-모바일 등 아주 넓은 범위의 해상도 대응
2-2. Full SPA 로 갈수도 있겠지만, 인라인 임포트를 통한 최소단위 사용 (레거시 마이그레이션 시 자주 사용됨)
2-3. 브라우저의 종류 - 데스크탑, 모바일의 브라우저 어플리케이션 뿐 아니라 어플 내 웹뷰 - 에 따른 사용방식의 차이
등등에 따라 특정한 구조를 견고하게 정해두기엔 지나치게 번거롭거나 아예 불가능한 경우도 많죠.
3. 세번째는 기술적으로 아주 크리티컬 한 이슈는 아니지만 인력측면이나 학습 단계에서의 문제입니다. CSS는 브라우저에서 전역적으로 접근 가능한 스타일인데.... 물론 css-in-js 에서는 이걸 컴포넌트 단위의 클래스 난수화로 해결하려 하지만 제한을 걸었을 뿐 강제할 수 있는 부분이 아니고, 또 과거부터 HTML, CSS를 전담하여 판으로 짜내는 퍼블리셔라는 역할이 있어왔고 지금도 계속 그렇게 작업하는 케이스도 여전히 많다보니 더더욱 전환이 어려운게 아닐까... 하는 생각이 드네요.
아키텍처 레이어링을할때 클래스를 꼭 두고싶으신거같은데 React 라면 hooks랑 전역상태관리도구를 잘 엮어서 구성해보시는게 더 낫다는 결론에 이르게될겁니다
의존성 관리는 설계라서 어려움
짧은 식견으로 댓글을 달아보겠습니다.
1. 왜 리액트에선 DI를 사용하지 않는가?
다른 언어(코틀린, 자바 / Swift)들과의 가장 큰 차이는 컴파일러 여부가 아닐까 싶습니다. 리액트 컴파일러가 없는 상황에서 DI가 가성비가 좋은진 잘 모르겠습니다.
2. 왜 axios와 같은 HTTP 라이브러리를 한 번 더 클래스로 감싸서 사용하지 않는가?
axios와 같은 HTTP 라이브러리를 한 번 더 클래스로 감싸고 심지어 그걸 커스텀 훅으로 감싸서 사용하는 것은 다른 데에서도 충분히 사용되고 있다고 봅니다.
의존성 주입을 하게 되는 시점은 결국 엔트리 포인트(index.tsx) 또는 App 컴포넌트에서 의존성을 생성한 후 하위 컴포넌트에 Props를 통해 전달하거나 Context API를 통해 전달해야 하는데 전자는 Props Drilling이라는 새로운 문제가 발생하고 후자는 결합도를 낮추기 위한 의존성 주입이 도리어 결합도를 높이는 결과를 낳게 됩니다.
테스트에 대해선 테스트 환경과 실제 환경이 너무나 다르기 때문에 발생한다고 봅니다. 브라우저 환경을 테스트 환경에서 재현하는 것은 가성비가 정말 떨어져서 차라리 리액트 컴포넌트를 테스트하기보다는 유틸 함수나 훅들을 테스트하는 게 더 적절하다고 봅니다.
리액트가 컴파일이 왜 안되죠? 바벨로 컴파일 충분히 돌릴수있습니다, 컴파일은 전혀 이유가 되지않습니다.
@@mattmurdock1355 혹시 후자의 경우 결합도라 올라가는 이유가 뭘까요??
@Herb 모던 자바스크립트는 타입스크립트 바벨을 통해서 컴파일 과정을 거칩니다.
FE 일은 안하지만 개인적인 생각으로는 FE는 일반적으로 변화의 정도가 높아 기존 코드 재활용률이 떨어지는 경우가 많을텐데 내츄럴 하게 컴포넌트기반개발 하는게 DI보다 생산적인 경우가 많아서겠죠. 생뚱맞지만 쿼리 짤 때 생각해봐요.... 테이블 조회 시 인덱스 데이터 분포율에 따라 퍼포먼스 이득이 나는 변곡점이 있죠. 그 변곡점 보다 높으면 FULL SCAN이 빠르고 변곡점 미만에는 INDEX_SCAN이 낫잖아요. 통계적으로 레거시 코드 재활용률이 낮은 부분이라면 생산성을 따져 당장 적용이 빠른 신규 코드로 갈아 엎는 것도 방법이라고 생각합니다. 굳이 OOP 를 적용한다면 툴 자체에서 OOP하게 적용되게 강제하면서 생산성도 높여줄 수 있는 개발 툴이 있다면 그걸 쓰면 좋겠죠.
예시 코드 보고싶네여... 정확한 의도 파악이 인되요...
FE도 FE나름 OOP가 필요한 FE도 있다옹. 예를들어 삽입요소 종류가 아주 다양한 헤비한 에디터... 함수형으론 한계가 있다옹~ 함수형으로 짜다간 막코딩 된다옹. 뭐든 정답은 없다옹. 내 짧은소견으론 FE는 굳이 oop가 필요없다는건 아직 프론트의 진수를 몰라서 하는소리 같다옹. 냐옹 거려서 미안하다옹
이 말이 정답입니다.
원래 자기가 잘 아는 방식만이 유일하다고 생각하기 쉽고 자기가 모르는 것에 대해서까지 걔네는 왜 그래라는 식으로 얘기하다보면 말그대로 어그로 끄는 식이 되는 것 아닌가 싶네요. 개인적으로 리액트가 가고 있는 함수 지향적 방향은 탁월하다고 느낍니다. 함수형 사고로 전환하면서 코드도 훨씬 깔끔해지고 유지보수도 더 용이해진 것 같네요
뭐지? 영상 제목 누가 씀? 영상 중심내용과 무슨 상관있지? 완전 걍 대충 제목 씀?
뭐가 문제임
왜 웹프론트 영역에서 정형화된 패턴이 잘 보이지 않는가가 주제인거 같은데, 썸네일이랑 제목은 React랑 Vue 갈땐가더라도... 솔직히 잘 와닿지 않네요.
썸낼 보고
리엑트와 뷰말고 새로운 무언가가 나타났나? 했쥬
제 생각에 제목과 내용의 연관성은 갈땐가더라도(욕을 더 먹더라도) 현재 직면한 react vue 등 프론트엔드 프레임워크 코드들의 문제를 속시원히 해결 할 수가 없으니 더좋은 방법을 찾기위한 활동이 아니실까 합니다 ㅎㅎ
@@aigo3272 다시 보니 저도 그렇게 보이네요 ㅎㅎ 그냥 직접적으로 쓰시지 왜 돌려말하시다 오해의 여지를 만드셨는지 ㅠㅠ
ㅋㅋㅋ 이걸 왜 백엔드와 프론트의 차이라고 생각하지??? 이건 언어의 차이라고 봐야 더 맞지 않나??? js를 더 공부해 보세요. js가 oop에 가까운지 함수형에 가까운지 그냥 알 것 같은데... 객체도 클래스 선언 따위 필요없이 곧바로 만들어서 사용하는 것이 js임.
오늘은 제목이 이해가잘 안되요.
갈덴 가더라도...... 어딜 간다는 거에여?
나 왜ㅜ못알아 듣지?
됐고 걍 이거나 저거나 재밌음 된거여. 재밌는데 3개월 지나면 알아서 답을 찾어
👍
JS로 더 유명해지세요ㅋㅋㅋ
로버트 c 마틴도 cleancode로 해라라고 해도 js하는 몇몇 분들한테는 듣보잡이 뭐라는거야.
라고 할수있습니다
그냥 언어가 구려서 그래. 타입스크립트의 데코세이터를 이용해 그 문제를 해결하려고 시도 할텐데. 자바 같은 고차 함수에 비해 너무 구려. 리플렉션 도구도 정말 구려. 안하는게 아니라 못한다고 봐야지.
왜 말을 못해~~~~~~~~~~~ㅎㅎ