Laravel 컨트롤러 라우팅 시 "Class ... does not exist" 에러 발생 원인과 해결

2021. 10. 15. 17:42·Computer/PHP

상황 (Laravel 8 경험 사례)

오랜만에 새로운 프로젝트를 Laravel 8로 시작.

테스트 코드를 먼저 작성하는 방식으로 개발해보려 했는데, 시작부터 막혔다.

라우트에 다음과 같이 컨트롤러를 연결하고 테스트를 실행했다.

Route::get('/', 'BaseController@index')->name('site-index');

 

그랬더니:

Expected response status code [200] but received 500.

The following exception occurred during the request:

ReflectionException: Class "BaseController" does not exist in ...

 

컨트롤러를 못 찾는다는 게 이해가 안 됐다.

Laravel 5.x를 쓸 때는 문자열 컨트롤러 지정('BaseController@index')이 아무 문제 없이 동작했기 때문이다.

원인

Laravel 8부터 RouteServiceProvider에 하드코딩되어 있던 컨트롤러 네임스페이스 자동 prefix 처리($namespace = 'App\Http\Controllers')가 기본적으로 빠졌다.

그래서 'BaseController@index'처럼 짧은 이름만 써주면, Laravel이 App\Http\Controllers 네임스페이스를 자동으로 붙여주지 못한다.

결국 BaseController라는 클래스를 최상위 네임스페이스에서 찾다가 실패하는 것이다.

구글링해보니 해외 커뮤니티(Stack Overflow)에 이미 잘 정리되어 있었다.

해결 방법 3가지

1. 컨트롤러 클래스 이름 앞에 네임스페이스 전체 경로를 포함한다.

Route::get('/', 'App\Http\Controllers\BaseController@index')->name('site-index');

2. use 키워드로 클래스를 임포트하고 배열(튜플) 문법을 사용한다.

use App\Http\Controllers\BaseController;

Route::get('/main', [BaseController::class, 'index'])->name('site-index');

3. RouteServiceProvider에 컨트롤러 네임스페이스를 다시 설정한다. (가장 간편했던 방법)

// app/Providers/RouteServiceProvider.php
protected $namespace = 'App\\Http\\Controllers';

컨트롤러 네임스페이스가 기본적으로 설정은 되어 있었지만 주석 처리되어 있었다.

버전별로 이 부분의 변화가 좀 복잡했다.

  • 7.x까지: $namespace 기본 적용
  • 8.0.0: $namespace 변수 자체가 제거됨
  • 8.0.1: $namespace = null로 되돌아옴
  • 8.0.2부터: 기본값 세팅 + 주석 처리 상태로 유지

IDE에서 컨트롤러 클래스로 코드 추적(점프)이 되는지를 생각하면, 2번 방법(임포트 + 배열 문법)에 익숙해지는 게 장기적으로 나을 것 같다.


업데이트: Laravel 9 이후에는 상황이 더 바뀌었다

이 글은 Laravel 8 기준으로 작성된 경험담이다.

이후 버전을 쓰는 분들을 위해 몇 가지 추가로 정리해둔다.

에러 메시지 자체가 바뀌었다

최신 버전에서는 ReflectionException: Class "..." does not exist 대신 아래 형태로 나온다.

Target class [BaseController] does not exist.

원인은 동일(컨트롤러 네임스페이스를 못 찾음)하니 해결 방법도 그대로 적용된다.

3번 방법(RouteServiceProvider의 $namespace 설정)은 Laravel 11부터 아예 불가능해졌다

Laravel 11에서 app/Providers/RouteServiceProvider.php 파일 자체가 삭제되고, 라우팅 관련 설정은 bootstrap/app.php의 withRouting()으로 옮겨갔다.

AuthServiceProvider, EventServiceProvider, Http/Kernel.php도 같은 흐름으로 사라지거나 AppServiceProvider/bootstrap/app.php로 흡수됐다.

즉 지금 최신 버전(9, 10, 11, 12.x)을 쓰고 있다면 3번 방법은 선택지에서 제외해야 한다.

결과적으로 남는 선택지는 1번(풀 네임스페이스 문자열) 또는 2번(임포트 + 배열 문법)이다.

IDE 연동이나 리팩터링 편의성을 생각하면 2번이 사실상 표준으로 굳어졌다.

최신 Laravel 스타터 킷이나 공식 문서 예제들도 대부분 이 방식을 기본으로 사용한다.

정리하면:

  • Laravel 9 이하 & RouteServiceProvider 파일이 남아있는 프로젝트: 위 세 가지 방법 모두 유효
  • Laravel 11 이상: 1번 또는 2번만 가능, 2번을 권장
    Laravel 8 당시 작성한 글을 다시 정리했습니다.
'Computer/PHP' 카테고리의 다른 글
  • Microsoft Translator API 사용하기.
MC02
MC02
  • MC02
    IT개발자의 생활
    MC02
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 세상사는이야기
        • MyStory
        • My K200D
        • 시끄러운거
        • 이것저것
        • 자장구 타기!
      • Computer
        • JAVA
        • JavaScript
        • CSS
        • PHP
        • iReport/Jasper
        • Oracle
        • Server
        • MySQL
  • 블로그 메뉴

    • HOME
    • TAG
    • MEDIA LOG
    • LOCATION LOG
    • GUEST BOOK
    • ADMIN
    • WRITE
  • 링크

    • ▒ 하늘아래 땅위에서 ▒
    • zestor.blog
    • TEARS - 덤벼라 세상아
    • 수공예악세사리-앤스다이아
  • 공지사항

  • 인기 글

  • 태그

    프리스틴밸리
    대장잉어
    선릉
    전남e조은뉴스
    두루미
    소라광장
    k200D
    ReflectionException
    이명박
    토요초급
    의료보험 민영화
    아이디 판매
    도싸
    nginx
    PHP
    개인정보유출
    촛불문화재
    샤방벙말고헬벙
    미국산쇠고기
    laravel
    mariaDB
    RouteServiceProvider
    정보누출
    광나루
    분원리
    한글/로마자변환기 조으다
    오빠...
    진달래
    다락재
    자포
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
MC02
Laravel 컨트롤러 라우팅 시 "Class ... does not exist" 에러 발생 원인과 해결
상단으로

티스토리툴바