· nambak80 Blog 로그인
CodeIgniter4

CodeIgniter 4로 블로그 만들기 #06 — 시더로 더미 데이터 생성

CodeIgniter 4로 블로그 만들기 #06 — 시더로 더미 데이터 생성

지난 회차에서 posts 테이블을 만들었습니다. 하지만 테이블은 비어 있죠. 목록 화면과 상세 화면을 만들려면 보여 줄 데이터가 필요합니다. 매번 손으로 글을 하나하나 입력하는 건 번거롭고, 화면을 새로 갈아엎을 때마다 데이터가 날아가면 곤란합니다.

이번 회차의 목표는 시더(Seeder)로 현실적인 더미 글을 한 번에 채우는 것입니다.

시더란

시더는 개발·테스트 단계에서 미리 정해 둔 데이터를 DB에 밀어 넣는 스크립트입니다. php spark db:seed 한 줄이면 그럴듯한 더미 글이 채워지고, 언제든 같은 상태를 재현할 수 있습니다. 특히 뒤에서 만들 Feature 테스트는 매번 마이그레이션 후 시더를 돌려 깨끗한 데이터로 검증하는데, 그때 이 시더가 그대로 쓰입니다.

한 가지 짚어 둘 점은, 아직 PostModel이 없다는 것입니다. 모델은 다음 회차(ep07)에서 만듭니다. 그래서 이번에는 모델 대신 쿼리 빌더로 직접 insert합니다. 커리큘럼의 회차 순서를 지키기 위해 미래 회차의 코드를 미리 끌어오지 않는 원칙입니다.

이번 회차 목표

  • PostSeeder로 강좌 흐름을 담은 더미 글 6건을 넣는다.
  • 시더를 반복 실행해도 유니크 제약에 걸리지 않게 한다.
  • created_at을 하루씩 벌려 최신순 정렬을 확인할 수 있게 한다.
  • DatabaseSeeder에서 PostSeeder를 호출하도록 연결한다.

PostSeeder 작성

시더는 app/Database/Seeds/에 둡니다. PostSeeder.php를 만들고, run() 메서드 안에서 넣을 글들을 배열로 준비합니다.

<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class PostSeeder extends Seeder
{
    public function run()
    {
        $posts = [
            [
                'title' => 'CodeIgniter 4로 블로그 만들기를 시작하며',
                'slug'  => 'codeigniter4-blog-start',
                'body'  => "이 블로그는 CodeIgniter 4를 한 회차씩 쌓아 올리며 만들어 갑니다.\n\n첫 글에서는 왜 프레임워크를 쓰는지, 그리고 앞으로 어떤 기능을 차례로 붙여 갈지 가볍게 정리해 둡니다. 라우팅과 뷰부터 시작해 모델·인증·댓글까지, 작은 단위로 커밋하며 나아갑니다.",
            ],
            // ... 라우팅, 공통 레이아웃, 첫 테스트, 마이그레이션, 시더 주제의 글 5건 더
        ];

여기서 눈여겨볼 점은 더미 글이 아무 의미 없는 로렘 입숨이 아니라는 것입니다. 각 글은 이 강좌가 실제로 다루는 주제(라우팅, 공통 레이아웃, 테스트, 마이그레이션, 시더)를 담고 있습니다. 이렇게 하면 목록·상세 화면을 만들 때 실제 블로그처럼 자연스럽게 보입니다. body에는 \n\n으로 문단을 나눠 뒀는데, 이건 나중에 상세 화면(ep09)에서 nl2br로 줄바꿈을 살릴 때 요긴합니다.

반복 실행에도 안전하게

시더에서 흔히 겪는 문제가 있습니다. 두 번 실행하면 같은 slug를 또 넣으려다 유니크 제약(ep05에서 걸어 둔)에 걸려 에러가 나는 것이죠. 이걸 막기 위해, 이번에 넣을 slug들만 먼저 지우고 시작합니다.

// 시더를 반복 실행해도 슬러그 유니크 제약에 걸리지 않도록,
// 이번에 넣을 슬러그만 먼저 비운다(실제 글은 건드리지 않음).
$slugs = array_column($posts, 'slug');
$this->db->table('posts')->whereIn('slug', $slugs)->delete();

array_column으로 넣을 글들의 slug만 뽑아, whereIn으로 그 slug들만 지웁니다. 테이블 전체를 비우는 게 아니라는 점이 중요합니다. 나중에 실제로 쓴 글이 있어도 시더가 그걸 건드리지 않습니다.

최신순 정렬이 눈에 보이게

목록 화면은 최신 글이 위로 오도록 정렬할 예정입니다. 그런데 시더가 글 6건을 순식간에 넣으면 created_at이 전부 거의 같은 시각이 되어, 정렬이 제대로 됐는지 눈으로 확인하기 어렵습니다. 그래서 작성 시각을 하루씩 벌려 넣습니다.

foreach ($posts as $i => $post) {
    // 최신 글이 위로 오도록 작성 시각을 하루씩 벌려 둔다
    $createdAt = date('Y-m-d H:i:s', strtotime("-{$i} days"));

    $this->db->table('posts')->insert([
        'user_id'    => null,
        'title'      => $post['title'],
        'slug'       => $post['slug'],
        'body'       => $post['body'],
        'created_at' => $createdAt,
        'updated_at' => $createdAt,
    ]);
}

배열 인덱스 $i를 이용해 첫 글은 오늘, 두 번째는 어제, 세 번째는 그저께… 이렇게 하루씩 과거로 밀어냅니다. 결과적으로 배열 맨 앞의 글이 가장 최신이 됩니다. 이 정렬 규칙은 뒤에서 페이지네이션 테스트(ep08)의 판정 기준으로도 그대로 쓰입니다("1페이지=최신 5건, 2페이지=가장 오래된 1건").

user_id는 아직 null입니다. 작성자 연결은 인증을 도입하는 이후의 일입니다.

DatabaseSeeder에 연결

php spark db:seed DatabaseSeeder로 한 번에 모든 시더를 돌리려면, 대표 시더인 DatabaseSeederPostSeeder를 호출하게 해야 합니다. appstarter에는 이 파일이 기본 포함되어 있지 않으므로 새로 만듭니다.

<?php

namespace App\Database\Seeds;

use CodeIgniter\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->call('PostSeeder');
    }
}

$this->call('PostSeeder') 한 줄로 연결됩니다. 앞으로 시더가 더 생기면(예: 댓글 시더) 여기에 $this->call(...)을 추가하기만 하면 됩니다. DatabaseSeeder는 모든 시더를 한데 묶는 입구 역할을 합니다.

실행과 검증

php spark db:seed DatabaseSeeder

에러 없이 끝나면 성공입니다. 명령을 두 번, 세 번 반복해도 유니크 제약에 걸리지 않고 잘 돌아가는지 확인해 보세요. 앞에서 slug를 먼저 지우도록 해 뒀기 때문에 몇 번을 돌려도 항상 같은 6건으로 유지됩니다.

마무리 — 커밋과 태그

git add .
git commit -m "feat: 글 시더로 더미 데이터"
git tag ep06

다음 회차

이제 테이블과 데이터가 모두 준비됐습니다. 다음 글에서는 드디어 PostModel과 Post 엔티티를 만들고, 글 목록 화면을 그립니다. 모델이 DB를 읽어 엔티티로 감싸 주고, 컨트롤러가 그걸 뷰에 넘기는 CI4의 데이터 흐름을 처음으로 완성합니다. 첫 Feature 테스트도 함께 붙입니다.


이번 회차 요약

  • 다루는 파일: app/Database/Seeds/PostSeeder.php(생성), app/Database/Seeds/DatabaseSeeder.php(생성·연결)
  • 핵심: PostModel이 아직 없어 쿼리 빌더로 직접 insert. slug만 먼저 비워 반복 실행에 안전하게, created_at을 하루씩 벌려 최신순 정렬을 확인 가능하게. DatabaseSeeder가 시더들의 입구.

다음: PostModel/Entity와 글 목록

댓글 0

아직 댓글이 없습니다.

로그인 후 댓글을 남길 수 있습니다.

← 목록으로