주요 내용으로 건너뛰기

라라벨에서 안좋은 것들, 슬픈 것들

좀 멋지게 쓰고 싶다 친구야

좋지 않은 것들,

Eloquent 의 append, with

글로벌한 기능은 때때로 강력하게 동작하지만, 대다수의 경우 끔찍한 결과를 초래합니다. 

이런 모델을 만드는 경우, 의도하지 않게 Brand는 N+1 문제에, Orders 는 Product를 가지고 올 때 언제나 가지고 올 수 밖에 없습니다. 물론 해결할 수 있는 방법이 없는 것은 아닙니다. 그래도 지양하는 편이 좋습니다. Product만 불러오고 싶은데 왜 Orders 가 같이 나와야 하나요?

Eloquent 의 withDefault(...)

Eloquent 는 관계 선언에 있어, 해당 모델의 결과가 없다면 null을 반환합니다. 이 때 특정한 값을 미리 정의해서 비어있는 Eloquent instance에 넣어서 가지고 올 수 있죠. 이것은 꽤 유용한 기능이지만, Model을 어디까지 짬뽕으로 만들 수 있는가에 대한 좋은 결과물로도 나타날 수 있죠. DTO 사용해서 결과를 제한하고, 이것을 직접 컨트롤 하시기 바랍니다. Eloquent는 근본적으로 무거운 인스턴스입니다. 또 withDefault는 2-depth 이상을 지원하지 않습니다. 


이런 코드에선, Group 이라는 Model Instance 가 나오는 것이 아니기에, ->groups->first()->provider 는 나오지 않습니다.

Eloquent in Controller

사실, 라라벨이 편의를 위해 제공하는 기능은 많은 디자인 패턴과 규칙을 깨먹습니다. Eloquent 는 컨트롤러 메소드의 인자로 받아올 수 있는데, 이런 경우 편의성은 무척 올라가지만 정말 끔찍하게도, Controller는 필연적으로 비즈니스 로직을 처리하는 공간으로 바뀌어버리죠. Service Layer 는 어디로 가고요? 아 글쎄요, 그건 잘 모르겠는데 말이죠.

이게 꽤 매력적인 기능이긴 합니다. Service layer를 사용하고 싶다면 해당 메소드의 인자를 id나 특정한 값이 아니라 User instance 를 받아서 처리할 수도 있겠죠.

문제는 Eloquent가 너무 무거운 친구라는 겁니다. AR 패턴을 구현한 모델들은 DB와 강하게 연결되어 있어서, 여러모로 위험하기도 하죠. 개인적으로 이렇게 구현하는 것을 조금 더 선호합니다.

그냥 예시라서 @Autowired는 무시하시고.. 이 편이 조금 더 괜찮은 코드라고 생각하고 있습니다. 

아쉬운 것들,

Request Mapping

대다수의 프레임워크는 Request 로 들어오는 것들에 대해 Mapping을 제공합니다. FormRequest 라는 class가 있지만, 근본적으로 이것은 Form Request 에 대한 요청을 처리하는 것이고, Request instance 는 특성상 도중에 다른 작업이 들어갈 수 없습니다. 이는 라라벨이 Request를 처리하는 방식에 그 이유가 있는데요, 라라벨은 index.php -> boorstrap/app.php -> Http\Kernel.php 순으로 처리합니다. Request Instance는 라라벨 코어가 담당하는 영역이기에 이곳에 자신만의 로직을 추가할 수가 없습니다. macro 같은 특별한(magic) 방식은 가능하나, 명심하시기 바랍니다. IDE 타입 힌트도 불가하며(_ide_helper.php 에 넣어서 사용할 수는 있습니다) 이런 클래스는 캐싱 기능이 동작하지 않습니다.

Request mapping 은 파싱을 의미합니다. ISO 8601 형식에 맞는 데이터를 LocalDateTime 으로 바꿔주는 그런 작업이 필요하죠. 라라벨은 그런 기능이 없습니다. 무척 불편합니다!

이것만 있었다면 라라벨의 생산성이 5할은 넘게 증가했을 것이라 굳게 믿고 있습니다.

느린 속도

누군가는 "생산성이 더 중요하다" 라 할 수 있겠지만, 그러기에는 너무 느립니다. 라라벨을 신규 프로젝트에서는 제외하고 있지만(Spring or Nest.js) 이렇게 보니 정말 끔찍한 속도네요.

열거형의 부재

전 자바의 열거형을 무척 좋아합니다. PHP에는 열거형과 비슷한 그 무엇도 존재하지 않습니다. 아, SplEnum이 있죠! 그런데 이 라이브러리는 사실상(de-facto) 죽었습니다.

열거형은 개발자를 포함한 소스를 한 줄이라도 읽을 일이 있는 그 어느 누구에게나 생산성을 높이는 아주 중요한 개념입니다. 상수를 쓰고 싶다고요? 여러분의 선택지는 const 입니다. 다행스럽게도, 7.1부터 접근 제한자를 const 에도 사용할 수 있게 되었죠. 그렇지만, 열거형은 없습니다.

대다수 환경에서는 열거형은 기본적으로 존재해야 합니다. 상태값이 아주 아주 대표적이죠. 5번 상태값이라고 하는 것보다는 COMPLETE 라고 쓰는 것이 더 가독성이 좋죠.

그나마 다행인 것은 https://github.com/myclabs/php-enum 라는 패키지가 있는 것입니다. 

왜 이게 라라벨의 아쉬운 점이냐 한다면, Eloquent 를 쓸 때 열거형이 강력하게 필요하거든요. Model에 상수를 쓰는 순간 상수를 쓸 때 모델 클래스::상수 가 되어버립니다. 뭔가.. 오묘하죠?

의문점

Helper/Facade 의 사용

간략한 코드를 위해서 new Collection은 collect(...), new JsonResponse 는 response()->json(...) 으로 하는 것을 권장하고 있는데요, 솔직히 잘 모르겠습니다. Eloquent를 보면 간략한 것은 좋으나 Return 이 너무 다릅니다. BelongsTo, With, Builder, Eloquent Model, HasOne, HasMany.. 이 모든 것이 마법처럼 동작하고 있습니다. 마법같은 방식으로 동작 원리를 숨기는 것은 좋다고 하기 어렵지 않을까요?

Eloquent Polymorphic

다형성은 정말로 간단하고, 유용한 기능이지만 사실 독이 든 성배라고 생각하고 있습니다. 가장 근본적인 이유 딱 한 가지, RDBMS의 설계 방식과 맞지 않습니다. 이 기능은 빠른 개발에는 무척 유용하나 근본적으로 설계를 숨기기 딱 좋고, 명확한 관계를 형성하지도 않을 뿐더러 외래키 제약 조건을 쓸 수 없습니다. 이런 경우 Super table 등을 사용하여 RDBMS에 맞는 형식으로도 구현할 수 있습니다. 물론 엄청나게 귀찮은 일이겠지만요. 


라라벨의 근본적 한계는 대부분 언어(PHP)의 한계이기도 합니다. 마법같은 Magic methods는 PHP의 구세주 같은 존재지만, 이게 과연 좋은 개념일까요. IDE는 제대로 찾아주지도 못합니다. Annotation을 적어가면서 코딩하기에는 너무나 아쉬운 부분이죠. 

지금은 Kotlin + Spring 을 사용해서 개발하고 있는데, 전 PHP가 가지는 한계가 너무 아쉽습니다. 7.4 버전이었나요? JIT 환경이 지금 나오긴 했죠. 발전하는 모습은 꽤 괜찮아 보이긴 해도, 이런 마법같은 기능을 없애고 속도와 안정성에 좀 더 가치를 두었음 하는 바램이 있습니다.

다음 내용이 궁금하세요? 이 포스트를 구매하시면 아래에 이어지는 내용을 감상할 수 있습니다.

  • 텍스트1

댓글

SNS 계정으로 간편하게 로그인하고 댓글을 남겨주세요.