Eloquent 직렬화
번역일: 2026년 6월 20일
Eloquent 직렬화
소개
Laravel로 API를 개발할 때는 모델과 관계(relationship)를 배열이나 JSON 형태로 변환해야 하는 경우가 자주 있습니다. Eloquent는 이런 변환을 간편하게 처리할 수 있는 메서드를 제공하며, 직렬화 결과에 포함할 속성을 세밀하게 제어할 수 있습니다.
NOTE
Eloquent 모델과 컬렉션의 JSON 직렬화를 더욱 강력하게 제어하고 싶다면, Eloquent API 리소스 문서를 참고하세요.
모델과 컬렉션 직렬화
배열로 직렬화
모델과 로드된 관계를 배열로 변환하려면 toArray 메서드를 사용합니다. 이 메서드는 재귀적으로 동작하므로, 모든 속성과 관계(관계의 관계 포함)가 모두 배열로 변환됩니다.
use App\Models\User;
$user = User::with('roles')->first();
return $user->toArray();관계는 제외하고 모델의 속성만 배열로 변환하려면 attributesToArray 메서드를 사용합니다.
$user = User::first();
return $user->attributesToArray();모델 컬렉션 전체를 배열로 변환할 때도 컬렉션 인스턴스에 toArray를 호출하면 됩니다.
$users = User::all();
return $users->toArray();JSON으로 직렬화
모델을 JSON으로 변환하려면 toJson 메서드를 사용합니다. toArray와 마찬가지로 재귀적으로 동작하여 모든 속성과 관계가 JSON으로 변환됩니다. PHP가 지원하는 JSON 인코딩 옵션도 인수로 전달할 수 있습니다.
use App\Models\User;
$user = User::find(1);
return $user->toJson();
return $user->toJson(JSON_PRETTY_PRINT);모델이나 컬렉션을 문자열로 캐스팅하면 toJson 메서드가 자동으로 호출됩니다.
return (string) User::find(1);모델과 컬렉션은 문자열로 캐스팅될 때 자동으로 JSON으로 변환되므로, 라우트나 컨트롤러에서 Eloquent 객체를 직접 반환해도 됩니다. Laravel은 라우트나 컨트롤러에서 반환된 Eloquent 모델과 컬렉션을 자동으로 JSON으로 직렬화합니다.
Route::get('users', function () {
return User::all();
});관계 직렬화
Eloquent 모델을 JSON으로 변환할 때, 이미 로드된 관계는 JSON 객체의 속성으로 자동 포함됩니다. 관계 메서드는 카멜 케이스(camelCase)로 정의되지만, JSON 속성명은 스네이크 케이스(snake_case)로 변환된다는 점에 주의하세요.
예를 들어 rolesList() 관계 메서드는 JSON에서 roles_list 키로 표현됩니다.
JSON에서 특정 속성 숨기기
비밀번호처럼 외부에 노출되어서는 안 되는 속성은 배열이나 JSON 변환 결과에서 제외할 수 있습니다. 모델에 $hidden 프로퍼티를 추가하고, 숨길 속성명을 배열로 지정하면 됩니다.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 배열/JSON 직렬화 시 숨길 속성 목록
*
* @var array
*/
protected $hidden = ['password'];
}NOTE
관계를 숨기려면 관계 메서드명을 $hidden 배열에 추가하면 됩니다.
반대로, 노출할 속성만 명시적으로 허용하고 싶다면 $visible 프로퍼티를 사용합니다. $visible 배열에 없는 속성은 모두 숨겨집니다.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 배열/JSON 직렬화 시 노출할 속성 목록
*
* @var array
*/
protected $visible = ['first_name', 'last_name'];
}일시적으로 속성 공개 범위 변경하기
특정 모델 인스턴스에 한해 숨겨진 속성을 임시로 노출하려면 makeVisible 메서드를 사용합니다. 이 메서드는 모델 인스턴스를 반환하므로 메서드 체이닝이 가능합니다.
return $user->makeVisible('attribute')->toArray();반대로, 평소에는 노출되는 속성을 특정 인스턴스에서만 임시로 숨기려면 makeHidden 메서드를 사용합니다.
return $user->makeHidden('attribute')->toArray();$visible이나 $hidden 설정 전체를 임시로 덮어쓰고 싶다면 setVisible과 setHidden 메서드를 각각 사용합니다.
return $user->setVisible(['id', 'name'])->toArray();
return $user->setHidden(['email', 'password', 'remember_token'])->toArray();JSON에 값 추가하기
데이터베이스 컬럼에는 존재하지 않지만, 배열이나 JSON 변환 결과에 포함시키고 싶은 값이 있을 수 있습니다. 이럴 때는 먼저 해당 값에 대한 접근자(accessor)를 정의합니다.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 사용자가 관리자인지 여부를 반환합니다.
*/
protected function isAdmin(): Attribute
{
return new Attribute(
get: fn () => 'yes',
);
}
}이 접근자를 항상 직렬화 결과에 포함시키려면 모델의 $appends 프로퍼티에 속성명을 추가합니다. 접근자 메서드는 카멜 케이스로 정의하지만, $appends에는 스네이크 케이스로 지정하는 것에 주의하세요.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* 모델의 배열 형태에 항상 포함할 접근자 목록
*
* @var array
*/
protected $appends = ['is_admin'];
}$appends에 추가된 속성은 배열과 JSON 표현 모두에 포함되며, 모델에 설정된 $visible / $hidden 규칙도 동일하게 적용됩니다.
런타임에 동적으로 속성 추가하기
특정 모델 인스턴스에 한해 런타임에 속성을 추가하려면 append 메서드를 사용합니다. 추가 속성 목록 전체를 교체하려면 setAppends 메서드를 사용합니다.
return $user->append('is_admin')->toArray();
return $user->setAppends(['is_admin'])->toArray();날짜 직렬화
기본 날짜 형식 커스터마이징
serializeDate 메서드를 오버라이드하면 날짜 직렬화 시 사용할 기본 형식을 변경할 수 있습니다. 이 메서드는 배열이나 JSON으로 변환할 때의 출력 형식에만 영향을 미치며, 데이터베이스에 저장되는 형식에는 영향을 주지 않습니다.
/**
* 배열/JSON 직렬화를 위한 날짜 형식을 지정합니다.
*/
protected function serializeDate(DateTimeInterface $date): string
{
return $date->format('Y-m-d');
}속성별 날짜 형식 커스터마이징
모델의 캐스트 선언에서 날짜 형식을 직접 지정하면, 속성별로 개별적인 직렬화 형식을 설정할 수 있습니다.
protected $casts = [
'birthday' => 'date:Y-m-d',
'joined_at' => 'datetime:Y-m-d H:00',
];