MySQL 5.7부터 JSON 컬럼을 지원한다. [공식 메뉴얼] 물론 NoSQL 데이터베이스 만큼은 안되겠지만 RDB를 기반으로 하되 부분적으로 스키마가 없는 데이터도 다룰 일이 있을 때 요긴하게 사용할 수 있을 것이다. 전자제품을 취급하는 쇼핑몰을 생각해보자. 품목마다 스펙이 다 달라서 모든 상품에 같은 특성을 부여할 수 없다. 예를 들어 모니터는 화면 크기가 있지만, 하드 디스크는 화면 크기가 존재할 수 없다. 이런 경우에 특성만 자유롭게 스키마를 갖을 수 있도록 하면 유용할 것이다.
라라벨은 마이그레이션을 작성할 때 json()
메소드를 사용해서 JSON 컬럼을 추가할 수 있다.
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->json('properties');
$table->timestamps();
});
JSON 컬럼에 JSON 형식이 아닌 데이터를 입력하면 저장할 때 에러가 난다.
// 문자열을 넣으면 안된다.
$product->properties = 'string';
$product->save(); // 에러!
// 배열을 넣으면 안된다.
$product->properties = ['array'];
$product->save(); // 에러!
$product->properties = json_encode('array');
$product->save(); // 성공!
$product->properties = json_encode(['array']);
$product->save(); // 성공!
데이터를 불러올 때도 JSON 형식의 문자열을 가져오게 된다.
$product = Product::first();
echo $product->properties;
// 출력 { "size": "20", "color": "red" }
따라서 이를 사용하려면 JSON 디코딩을 해야한다.
$product = Product::first();
$properties = json_decode($product->properties);
echo $properties['size'];
// 출력 20
입출력시 json 인코딩과 디코딩을 하는게 다소 귀찮다. 속성 캐스팅을 사용하면 자동으로 처리된다.
class Product extends Model
{
protected $casts = [
'properties' => 'array'
];
속성 캐스팅을 설정해두면 저장할 때도 배열을 바로 집어넣을 수 있다.
$product->properties = [
'size' => 20,
'color' => 'red'
];
물론 불러올 때도 자동으로 배열로 변환된다.
$product = Product::first();
$properties = $product->properties;
echo $properties['size'];
// 출력 20
속성 캐스팅을 쓰는 것만으로도 꽤나 손쉬워졌지만 laravel-schemaless-attributes
로 한 발 더 나아갈 수 있다. 설치 방법이나 사용법은 공식 저장소의 설명을 참고하자. 여기서는 laravel-schemaless-attributes
를 쓰면 어떤 점이 (조금 더) 편해지는지만 간단히 소개하겠다.
JSON 컬럼에 저장할 데이터의 일부만 업데이트가 필요할 수 있다. 엘로퀀트만으로는 전체 JSON 데이터를 업데이트 하는 수 밖에 없다. 이를 위해 다음과 같이 임시 변수가 필요하다.
$properties = $product->properties;
$properties['size'] = 30;
$product->properties = $properties;
$product->save();
laravel-schemaless-attributes
를 쓰면 아래와 같이 업데이트 하고자 하는 데이터만 바꿔서 바로 저장할 수 있다.
$product->properties->set('size', 30);
$product->save();
// 다차원 배열은 . 표기법으로 접근 가능하다.
$product->properties->set('appearance.size', 30);
이외에 쿼리 스코프 기능으로 검색을 할 수 있는 편의성이 있다.
// AND 조건으로 찾을 때
$product->withProperties(['size' => 10, 'color' => 'white'])->get();
// 찾는 조건이 하나일 때
$product->withProperties('size', 10)->get();
이외에는 딱히 그냥 엘로퀀트를 쓰는 것에 비해 더 편한지 모르겠지만, 여러분은 이 패키지의 유용성을 더 느낄 수 있을지 모르니 공식 저장소에 들러 나한테 필요한 기능이 있을지 살펴보고 쓸만하면 활용해보도록 하자.
메쉬 코리아 개발자. 바쁜 팀장님 대신 알려주는 신입 PHP 개발자 안내서를 쓰고, 클린 아키텍처 인 PHP를 번역했습니다. 처음부터 제대로 배우는 라라벨(Laravel Up & Running 2nd Edition)을 번역했습니다.