라라벨 5.8.16 새기능(2)

라라벨 5.8.16에서는 이전에 소개한 마이그레이션 이벤트 이외에 두가지 기능이 더 추가 되었습니다.

하나는 PostgreSQL을 사용하는 사람을 위한 기능으로, migrate:fresh 할 때 type을 지울 수 있는 옵션이 추가된 것입니다. 개발자에 의하면 PostgreSQL 에서는 ENUM에 타입을 사용하는데 migrate:fresh를 하면 테이블은 다 지워지지만 이 타입이 남아서 문제가 생겼었다고 하네요. 데이터베이스 뷰를 지우는 옵션을 사용하는 것과 같은 방법으로 사용하면 된다고 합니다. (데이터베이스 뷰를 지우는 옵션도 있었군요…ㅎㅎ)

php artisan migrate:fresh --drop-types

다른 하나는 MailMessage 클래스에 Renderable 컨트랙트를 추가한 것입니다. 이를 통해 알림(Notification) 메일이 어떻게 보내질 것인지 브라우저로 확인해볼 수 있다고 하네요. 예를 들어, 컨트롤러에서 다음과 같이 하면 된다고 합니다.

return (new FooNotification())->toMail('example@example.com');

브라우저로 메일 내용을 미리보는 건 Mailable 클래스에 이미 있던 기능인데, 같은 기능을 알림 메일에 사용하는 MailMessage 클래스에도 추가했다고 합니다.

그렇지 않아도 이번에 막 알림을 메일로도 받을 수 있게 작업하려는 참이었는데 잘됐네요 ㅎㅎ

라라벨 5.8.16 새기능(1) – 마이그레이션 이벤트 추가

Illuminate\Database\Events 네임스페이스에 아래 이벤트가 추가되었습니다.

  • MigrationEnded
  • MigrationsEnded
  • MigrationStarted
  • MigrationsStarted

이 기능을 제안하고 추가한 알렉스 보워스가 밝힌 용도는 마이그레이션을 시작할 때 캐시를 지우거나, 마이그레이션 시작과 종료를 모니터링하는 것 등 입니다.

참고

라라벨 5.8.11 – Date 파사드에 macro 메소드 추가

하 벌써 5.8.13이 나왔던데 뭔 업데이트가 이리 빠른가요.. 여튼 한 박자 늦긴 했지만 5.8.11 에 변경된 사항을 정리해봅니다.

Date 파사드에 macro 메소드 추가

Date::macro('example', function () {
    return 'hello';
});

Date::example(); // hello

위의 예시에서 보듯이 macro 메소드는 런타임에 인스턴스에 메소드를 추가할 수 있게 해줍니다. macro 메소드는 컬렉션에도 있고 리스폰스에도 있다는데 아직 써보진 못했어요. 왜 이 기능을 추가하기로 했는지 궁금해서 PR을 찾아봤는데 별 내용이 없더군요.

다행히 Carbon에 설명이 있어서 용도를 가늠해볼 수 있었습니다. Carbon 문서에서는 설정이나 유저 선호에 따라 날짜를 출력할 때 쓰기 좋다고 이야기하고 있습니다. 아래는 Carbon 문서에 있는 예시입니다. 파리 시간과 프랑스어로 바꾸고 calendar 메소드를 실행한 결과를 출력하도록 formatForUser 메소드를 추가합니다.

<?php
// Let assume you get user settings from the browser or preferences stored in a database
$userTimezone = 'Europe/Paris';
$userLanguage = 'fr_FR';

Carbon::macro('formatForUser', function () use ($userTimezone, $userLanguage) {
    $date = $this->copy()->tz($userTimezone)->locale($userLanguage);

    return $date->calendar(); // or ->isoFormat($customFormat), ->diffForHumans(), etc.
});

// Then let assume you store all your dates/times in UTC (because you definitely should)
$dateString = '2010-01-23 10:00:00'; // Get this from your database or any input

// Then now you can easily display any date in a page/e-mail using those user settings and the chosen format
echo Carbon::parse($dateString, 'UTC')->formatForUser();   // 23/01/2010

덕분에 이른바 Macroable 이라는 특성에 대해 생각해보는 기회가 됐네요. 현재까지 이해한 바로는 기존 클래스를 확장하기엔 불편하고, 헬퍼보다는 더 체계적이고 싶을 때 쓰면 좋은 것 같습니다. 가령 Collection을 확장해서 MyCollection을 만들면 엘로퀀트 ORM도 Collection 대신 MyCollection을 반환하게 손을 대는 등 프레임워크의 여러 부분에 손을 대야 할 것 같아요. 메소드 하나 추가하자고 일이 너무 커져버리니까 이런 경우에 macro라는 컨셉을 쓰나 봅니다. 이 부분은 잘 몰라서 뇌피셜을 쓴 것이니 바로잡아주실 필요가 있으면 댓글 부탁드려요.

5.8.11에 추가된 게 두 가지 더 있지만 그건 다음에 기회되면 다룰께요.

라라벨 5.8.9 – 이벤트 발견 기능 추가

5.8.8 까지는 어떤 이벤트가 발생하면 어떤 리스너가 작동해야하는지 직접 적어줬어야 했습니다. 아래와 같은 식이죠.

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'App\Events\OrderShipped' => [
        'App\Listeners\SendShipmentNotification',
    ],
];

5.8.9 부터 이벤트 발견 기능이 추가되어 이벤트와 리스너의 관계를 직접 등록하는 수고를 덜게 됐습니다.

이벤트 발견 기능은 기본적으로 비활성화 되어 있습니다. 이벤트 발견 기능을 사용하려면 아래와 같이 EventServiceProvidershouldDiscoverEvents 메소드를 오버라이드해야 합니다.

/**
 * Determine if events and listeners should be automatically discovered.
 *
 * @return bool
 */
public function shouldDiscoverEvents()
{
    return true;
}

이벤트 발견 기능을 활성화하면 이벤트 캐시 파일이 있으면 이를 이용하고, 없으면 실시간으로 이벤트를 찾습니다. 실시간으로 리퀘스트를 찾으면 애플리케이션이 느려지기 때문에 되도록 캐시를 사용하는게 좋습니다. artisan event:cache 명령으로 캐시할 수 있습니다.

Laravel Collection 메소드 중 concat과 push의 차이

라라벨 5.8.8에서 쿼리 빌더에 forPageBeforeId 메소드가 추가되었습니다. 뭔지 알아보려고 PR을 보는데, 예제에서 컬렉션 메소드 중 concatpush를 쓰더군요.

$posts = new Collection;

$posts = $posts->concat(ChatPost::forPageBeforeId(15, $focused->id)->get()->reverse());

$posts = $posts->push($focused);

$posts = $posts->concat(ChatPost::forPageAfterId(15, $focused->id)->get());

둘 다 제가 잘 안쓰던 메소드들이라 메뉴얼을 찾아봤는데, 읭? 둘이 똑같아 보이는 겁니다.

push 메소드는 컬렉션의 마지막에 아이템을 추가합니다:

concat 메소드는 주어진 배열 또는 컬렉션의 마지막에 값을 추가합니다:

그래서 소스를 봤는데, 소스를 보니 차이점을 알겠더라구요.

    /**
     * Push all of the given items onto the collection. 
     *
     * @param  iterable  $source
     * @return static
     */
    public function concat($source)
    {
        $result = new static($this);

        foreach ($source as $item) {
            $result->push($item);   // 주어진 아이템들을 push를 사용해서 추가
        }

        return $result;
    }

push는 하나의 아이템을 컬렉션의 마지막에 추가하는 거고, concatpush 메소드를 이용해서 여러 아이템을 한 번에 추가하는 거였어요.

뭐 별로 중요한 얘기는 아니었습니다 하핫

라라벨 제작자가 추천한 라라벨 코드 깔끔하게 짜는 방법 초간단 요약

얼마전에 테일러 오트웰이 더 깔끔한 코드를 짜고 싶으면 참고하라며 링크 두개를 던져줬습니다.

두 자료를 초간단 요약해봤습니다.

Methods Are Affordances, Not Abilities

첫번째 자료는 Adam Wathan의 블로그 글인데 “메소드는 그 클래스’가’ 무얼 할 수 있는지가 아니라 그 클래스’를 가지고’ 무얼 할 수 있는지로 봐야한다”라는 내용입니다.

Announcement::create(request(['subject', 'message']))->broadcast();

위와 같은 코드를 예로 설명했는데, 메소드를 클래스를 가지고 무얼 할 수 있는지라고 생각하면 매우 자연스럽습니다. ‘Announcement를 broadcast한다’ 자연스럽죠. 반면, 메소드를 클래스가 할 수 있는 것이라고 생각하면 Announcement가 스스로를 broadcast 하는게 어색해서 AnnouncementBroadcaster 같은 클래스를 만들게 됩니다. 이러면 괜히 코드가 복잡해진다고 합니다. 자세한 내용은 원문에서 🙂

Cruddy by Design

두번째 자료는 라라콘 2017의 발표 영상인데, 이 역시 Adam Wathan의 발표입니다.

레일즈를 만든 David Heinemeier Hansson이 “사람들이 레일즈를 쓸 때 컨트롤러를 너무 적게 쓴다”고 지적한 것을 계기로, 어떻게하면 컨트롤러가 많게 코드를 작성할 수 있는지 고민했나봅니다.

이 분이 알려준 비법은 Never Write Custom Action 입니다. CRUD에 사용하는 기본 메소드 7가지(index, create, store, show, edit, update, destroy)만 사용하라는 것입니다. 이외에 메소드를 추가하는 상황이 오면, 메소드를 추가하는 대신 새로운 컨트롤러를 추가합니다. 영상에서는 구체적인 기법 4가지를 소개합니다.

  • Tip1. Nested resource? New Controller
  • Tip2. Edited independently? New Controller
  • Tip3. Touches pivot records? New Controller (and probably a new model)
  • Tip4. Transitions state? New Controller

역시나 자세한 건 원본 영상에서 🙂

소감

영어라 읽고 보기 힘들었지만 ㅠ 그래도 보고나니 괜히 전보다 좀 더 깔끔한 코드를 짤 수 있을 것 같은 느낌적인 느낌이 듭니다. 하핫

힘빼기

자유형을 지도하시던 선생님께서 갑자기 접영 무한 반복을 시키셨다. 강습이 거의 끝날 때 즈음 다시 자유형을 시키셨다. 회원들이 자유형으로 한 바퀴 돌고 오자 칭찬하시면서 말씀하시길.

여러분 너무 잘하셨어요. 힘이 빠지니까 자세가 너무 좋아졌습니다. 지금처럼 리커버리할 때는 손목에 힘을 빼도록 하세요.

체력을 소모시켜서 자연스럽게 힘빠진 동작을 경험할 수 있도록 하신 것이다.

힘빼기를 익힌다는건 머리로는 할 수 없고, 빡쎈 연습을 반복해서 가장 좋은 효율의 동작을 몸에게 자주 경험시켜 줌으로써만 익힐 수 있는게 아닐까?

Mac에서 Docker로 개발환경 구성시, Internet Explorer로 테스트하는 방법

모든 웹브라우저가 다 똑같이 동작하면 참 감사할텐데, 실상은 그렇지 않죠. 특히 IE! 뭐 어쩌겠습니까. 고객님들이 쓰는 주요 브라우저는 다 테스트 해봐야지요.

Mac을 사용하는 개발자들의 문제는 Mac에 IE가 설치되지 않는다는 점입니다. 다행히 모던 PHP 유저 그룹의 a2님으로부터 VirtualBox의 가상 머신으로 도커 머신에 접근하는 방법을 배울 수 있었습니다. 저만 배우고 입 싹 닦을 순 없으니 방법을 정리해서 공유합니다.

Virtualbox 네트워크 만들기

virtualbox를 실행하고 ‘전역도구’에서 호스트 네트워크 관리자를 선택합니다. 만들기를 클릭해서 호스트 네트워크를 하나 만듭니다. 성공하면 위와 같이 네트워크가 하나 만들어집니다.

가상 머신에 네트워크 연결

사용할 윈도우 가상 머신 설정으로 들어가서 네트워크에 ‘호스트 전용 어댑터’로 방금 만든 네트워크를 추가해줍니다.

윈도우 host 설정

virtualbox로 윈도우를 띄웁니다. 윈도우에서 테스트할 도메인을 앞서 만든 네트워크에 연결합니다. 예를 들어, 윈도우10인 경우, c:\windows\system32\drivers\etc\hosts 파일을 열고 아래의 내용을 추가합니다. 아래의 IP주소는 앞서 만든 vboxnet0의 IP입니다. 여러분은 여러분 것을 사용하시면 됩니다.

192.168.56.1 dev.example.com

도커 포트 설정

도커로 개발환경을 띄울 때 포트에 192.168.56.1:80:80을 추가해서 띄워줍니다. 저는 docker-compose를 사용하기 때문에 아래와 같이 docker-compose.yml 파일에서 ports에 한 줄 추가해주면 되었습니다.

이렇게하면 virtualbox로 띄운 윈도우에서 dev.example.com 접속시 호스트 컴퓨터의 도커 머신으로 접속하게 됩니다.

모쪼록 크로스 브라우징 작업에 조금이나마 스트레스가 줄길 바랍니다. 🙂

Chromium으로 스크린 캡쳐를 했는데 한글이 네모로 나오는 경우

자동으로 스크린샷을 저장하기 위해 Browsershot을 사용했다. 그런데, 한글이 제대로 표시되지 않아서 한참 삽질했다. 다행히 포기하기 직전에 기적적으로 해결 방법을 발견했다. 원래는 일본어가 동일한 증상으로 표현이 안되는 문제에 대한 글인데, 답변자가 친절하게도 한글 해결책도 함께 제시해줬다. 결론은 ttf-unfonts-core를 설치해주면된다.

sudo apt-get install ttf-unfonts-core

한 스트로크 더

선생님께 여쭤봤습니다.

“선생님 저는 너무 힘들어서 여러 바퀴를 한 번에 못 돌겠어요”

그러자 선생님이 이렇게 말씀해주시네요.

“호흡을 잘 못 하거나, 몸에 힘이 들어가서 그럴 수 있습니다. 점차 나아질 겁니다. 힘들어도 쉬지 말고 조금씩 더 해서 한계를 조금씩 늘려가셔야 합니다. 힘들다고 중간에 멈춰버릇하면 습관이 돼요. 중급반이시니까, 최소한 네 바퀴는 한 번에 도실 수 있어야 합니다.”

기초체력이 부족한데, 자꾸 기적의 비법만 찾고 있었나 봅니다. 당분간 닥치고 빡수영하는걸로.