TrendShift 딥다이브 · 2026-07-13 · Daily #19

Leantime/leantime 딥다이브
— "프로젝트 매니저가 아닌 사람들"을 위한 오픈소스 PM 시스템

Leantime전략·기획·실행을 한곳에 모은 셀프호스팅 프로젝트 관리 도구다. 슬로건이 곧 정체성 — "프로젝트 매니저가 아닌 사람들을 위한(for non-project managers)" PM 시스템이다. Jira처럼 기능은 풍부하되 Trello처럼 쓰기 쉽고, 무엇보다 ADHD·난독증·자폐를 염두에 두고 설계했다는 점이 독특하다. 기술적으로는 Laravel 11 프레임워크를 통째로 상속·개조한 대형 PHP 애플리케이션으로, 기능마다 폴더가 하나씩인 43개 도메인(domain) 모듈 구조를 쓴다. 최근엔 AI 에이전트가 직접 태스크를 만들 수 있는 MCP 서버(55개 AI 툴)로 진화하며 다시 트렌딩에 올랐다. (저장소: Leantime/leantime · AGPL-3.0 · PHP 8.2+ / Laravel 11 · 앱 v3.9.8 · 43개 도메인 · 최신 커밋 2026-07-09 · TrendShift 오늘 Daily #19 · repo id 2264)
목차
  1. 프로젝트 한 줄 요약
  2. 왜 지금 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 · 파일 구조 해부
  6. 학습 포인트
  7. 시스템 · 설치 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한 줄 요약

이름부터 뜯어보기 — "Lean(린 스타트업의 린) + time(시간)" = 낭비 없이, 전략부터 실행까지 시간을 관리한다

Leantime"아이디어(전략) → 계획 → 실행"의 전 과정을 하나의 웹앱 안에서 다루는 오픈소스 프로젝트 관리 시스템이다. 대부분의 PM 도구가 "이미 정해진 할 일을 칸반에 늘어놓는" 실행 단계에만 집중하는 데 비해, Leantime은 그 앞 단계 — 왜 이 프로젝트를 하는지(목표·전략)부터 붙잡는다. 그래서 Lean Canvas·SWOT·목표(OKR) 같은 전략 수립 도구가 태스크·마일스톤·타임시트 같은 실행 도구와 한 지붕 아래 들어 있다.

가장 큰 차별점은 타깃 사용자다. README 첫 줄이 "for non-project managers(프로젝트 매니저가 아닌 사람들을 위한)" — 즉 PM 전문가가 아니어도, 프리랜서·소규모 팀·스타트업 창업자·비영리 단체가 부담 없이 쓰도록 만들었다. 여기에 "ADHD·난독증·자폐를 염두에 두고 만들었다(Built with ADHD, dyslexia and autism in mind 🧠)"는 뉴로다이버시티(신경다양성) 지향이 더해져, 산만해지기 쉬운 사람도 집중을 유지하도록 UI·동기부여 장치를 설계했다.

핵심 용어
셀프호스팅 (Self-hosted)
SaaS(월 구독으로 남의 서버를 빌려 쓰는 방식)와 달리, 내 서버·내 PC에 소프트웨어를 직접 설치해 데이터를 내 손에 두는 방식. Leantime은 AGPL-3.0 오픈소스라 Docker 한 줄이나 PHP 호스팅에 올려 회사 데이터를 외부에 넘기지 않고 운영할 수 있다. Jira·Asana·Monday 같은 클라우드 전용 SaaS와 근본적으로 다른 지점.
핵심 용어
뉴로다이버시티 (Neurodiversity, 신경다양성)
ADHD·자폐·난독증 등을 "결함"이 아니라 인간 두뇌의 다양한 변이로 보는 관점. Leantime은 이 철학을 제품에 새겼다 — 한 화면에 정보를 몰아넣지 않고, 할 일을 잘게 쪼개고(서브태스크), 진행을 시각적으로 보여주고, 게임처럼 성취를 보상(Gamecenter 도메인)하는 식으로 "집중 유지가 어려운 사람"을 배려한 설계를 곳곳에 넣었다.
한 문장 비유

"할 일 목록(Trello)이 아니라, '왜·무엇을·어떻게'를 한 권에 적는 회사용 통합 노트"

보통의 칸반 보드가 "오늘 뭘 할까"만 적는 메모지라면, Leantime은 맨 앞에 "우리는 왜 이걸 하는가(전략 캔버스)", 가운데에 "그래서 목표는(OKR·마일스톤)", 뒤에 "이번 주 할 일(태스크·타임시트)"이 순서대로 엮인 두꺼운 업무 노트에 가깝다.

게다가 그 노트는 내 책상(내 서버)에 두고, 산만한 사람도 길을 잃지 않게 페이지마다 이정표를 붙여 놓은 형태다. "전략~실행을 하나로 + 셀프호스팅 + 접근성"이라는 세 가지가 Leantime을 다른 PM 도구와 구분 짓는다.

2왜 지금 주목받는가

TrendShift Daily #19 · "비-PM 타깃 + 전략 도구 내장 + 뉴로다이버시티 설계 + AI 네이티브(MCP) + 셀프호스팅"

Leantime은 2019년부터 이어온 성숙한 프로젝트지만, 최근 다시 트렌딩에 오른 데는 이유가 있다. 셀프호스팅·데이터 주권에 대한 관심이 커지는 흐름과, AI 에이전트가 앱을 직접 조작하는 MCP(Model Context Protocol) 통합이라는 신규 기능이 겹쳤다. (TrendShift의 굵은 숫자는 별 수가 아니라 사회적 언급 모멘텀이다.) 매력 포인트를 넷으로 정리한다.

주목 포인트 1 — "비-PM"이라는 뾰족한 포지셔닝

PM 도구 시장은 포화 상태지만, 대부분 PM 전문가나 개발팀을 겨냥한다(Jira가 대표). Leantime은 반대로 "프로젝트 관리를 배운 적 없는 사람"을 노린다. README의 표현 그대로 "Trello만큼 단순하지만 Jira만큼 기능이 풍부한(as simple as Trello but as feature-rich as Jira)" 절충점을 표방한다. 이 뾰족함이 프리랜서·1인 창업자·비영리·연구실 같은 틈새에서 강한 지지를 얻는다.

주목 포인트 2 — 전략 수립 도구를 앱 안에 내장

실행(태스크)만 있는 경쟁 도구와 달리, Leantime은 Lean Canvas·Business Model Canvas·SWOT·리스크 분석·목표(Goal/OKR)·아이디어 보드·회고(Retrospective)를 정식 기능으로 넣었다(각각 Canvas·Goalcanvas·Ideas 도메인). "먼저 전략을 세우고, 그 전략에서 목표가 나오고, 목표에서 태스크가 나온다"는 린 스타트업 사고방식을 제품 구조로 구현한 것이 핵심 차별점이다.

주목 포인트 3 — AI 네이티브: 앱 자체가 MCP 서버

가장 최신이자 트렌딩의 직접적 동력. Leantime은 laravel/mcp 위에서 자기 자신을 MCP 서버로 노출해, Claude 같은 AI 에이전트가 태스크 생성·수정, 마일스톤 추가, 목표 관리, 타임시트 기록을 직접 호출할 수 있게 했다(6개 도메인에 걸쳐 55개 AI 툴). 여기에 멀티 LLM 추상화(Prism), AI 에이전트 프레임워크(neuron-ai), 벡터 데이터베이스(Qdrant)까지 얹어 임베딩·시맨틱 검색 기반을 깔았다. "PM 도구에 AI를 붙인" 게 아니라 "AI가 조작하도록 설계된 PM 도구"라는 점이 신선하다.

주목 포인트 4 — 셀프호스팅 + 강력한 기업 인증

Docker·Helm으로 손쉽게 자체 서버에 올려 데이터를 내부에 두고, LDAP·OIDC·SAML2 + 15종 소셜 로그인·2FA·Sanctum API 토큰까지 지원해 기업 환경 요구를 충족한다. Slack·Mattermost·Discord 알림, S3 파일 저장, CalDAV 캘린더, 20개+ 언어(i18n 48개 파일)도 완비. "무료·오픈소스인데 기업용 기능이 다 있다"는 완성도가 재방문을 부른다.

경쟁 도구와의 비교

도구성격 · Leantime과의 차이
Jira강력하지만 복잡하고 학습 곡선이 가파름, 실행/이슈 트래킹 중심. Leantime은 전략 도구를 앞단에 두고 비전문가도 쓰도록 단순화 + 셀프호스팅.
ClickUp · Monday · Asana세련된 클라우드 SaaS(유료 구독). 데이터는 그들 서버에. Leantime은 AGPL 오픈소스 + 셀프호스팅이라 데이터 주권·무료가 강점.
Trello극도로 단순한 칸반. 전략·리포트·타임트래킹이 약함. Leantime은 "Trello의 쉬움 + Jira의 깊이"를 노림.
OpenProject · Redmine같은 오픈소스 셀프호스팅 PM. 다만 전략 캔버스·뉴로다이버시티·AI(MCP) 지향은 Leantime의 독자 색깔.

3기술 스택 전체 지도

"Laravel 11을 통째로 상속·개조한 대형 PHP 앱 + jQuery·HTMX 혼합 프런트 + MySQL 커스텀 스키마 + Docker/Helm" — 백엔드가 무거운 풀스택

LinkSwift 같은 단일 파일 유틸과 정반대로, Leantime은 백엔드·프런트엔드·인프라가 모두 두꺼운 정통 웹 애플리케이션이다(app/ 아래 PHP 파일만 915개). 스택을 세 계층으로 나눠 본다.

계층 1 — 백엔드 (PHP 8.2 · Laravel 11 기반)

핵심은 Laravel 11 프레임워크를 부분 패키지로 쓰는 게 아니라 통째로 가져와 상속·개조했다는 점이다. illuminate/*를 조각조각 쓰지 않고 laravel/framework 전체를 require한 뒤, app/Core/Application.phpIlluminate\Foundation\Application을 상속해 폴더 구조를 Leantime 방식으로 재매핑한다.

항목내용
언어 · 프레임워크PHP ^8.2(플랫폼 8.2.0 고정) · Laravel ^11.44(전체 프레임워크)
인증 · 로그인laravel/sanctum ^4.0(API 토큰), laravel/socialite ^5.16 + 15종 소셜 프로바이더(authentik·auth0·github·gitlab·google·keycloak·microsoft·okta·saml2…), LDAP·OIDC·2FA(robthree/twofactorauth + endroid/qr-code)
AI 스택 (주목)laravel/mcp ^0.1(MCP 서버), prism-php/prism(멀티 LLM 추상화 — OpenAI·Anthropic 등), inspector-apm/neuron-ai(AI 에이전트 프레임워크), hkulekci/qdrant(벡터 DB 클라이언트 → 임베딩·RAG)
저장 · 파일league/flysystem-aws-s3-v3 + aws/aws-sdk-php(S3 파일 저장), 로컬 파일시스템 대체 가능
기타 라이브러리guzzlehttp/guzzle(HTTP), doctrine/dbal, htmlawed/htmlawed(HTML 새니타이즈), sabre/dav(CalDAV), spatie/icalendar-generator(ICS), stripe/stripe-php(결제), phpmailer/phpmailer(메일), sentry/sentry-laravel(에러 추적)

계층 2 — 프런트엔드 (jQuery 레거시 + HTMX 하이퍼미디어의 이중구조)

프런트엔드는 React·Vue 같은 SPA가 아니다. 서버가 HTML을 그리는 전통 방식을 유지하되, 오래된 jQuery 기반 위에 현대적 HTMX(부분 렌더링)를 얹은 하이브리드다. 빌드는 Laravel Mix(webpack 래퍼)가 담당한다.

빌드 도구Laravel Mix ^6.0(webpack 5 래퍼) · makefilemake build로 구동 · Babel · ESLint
CSSTailwind CSS ^3.4 + LESS ^4.2(레거시 스타일 병존). Bootstrap 없음
JS 코어jquery 3.7.1 + jquery-ui(무거운 레거시 기반) · htmx.org ^1.9(서버 부분 렌더링, 백엔드 Hxcontrollers/와 짝) · Vue/React 런타임 없음
에디터 · 위젯TipTap ^2.11(ProseMirror 리치텍스트, 30여 확장) · chart.js(차트) · fullcalendar(캘린더) · gridstack(대시보드 드래그 위젯) · mermaid(다이어그램) · katex(수식) · uppy(파일 업로드) · shepherd.js(온보딩 투어) · leader-line(의존성 화살표)

계층 3 — 데이터 · 인프라 (MySQL 커스텀 스키마 + Docker/nginx + Helm)

데이터베이스MySQL 8.0+ / MariaDB 10.6+ 기본(utf8mb4), PostgreSQL도 지원(LtPostgresConnection). 모든 테이블 접두사 zp_
DB 접근Laravel 연결 위에 원시 PDO를 얹은 하이브리드(app/Core/Db/). Eloquent 대신 직접 SQL이 주력, 일부만 쿼리 빌더
스키마 관리Laravel 마이그레이션 대신 커스텀 인스톨러Install.php 2,845줄에 41개 CREATE TABLE, 번호 붙은 패치 메서드로 업그레이드(독립 dbVersion 3.5.20)
컨테이너프로덕션 php:8.3-fpm-alpine + nginx + supervisord(멀티스테이지, 비루트 www-data, EXPOSE 8080, Redis PECL). 개발환경은 Apache + Xdebug + MailDev
배포Docker · Kubernetes Helm 차트(helm/) · 수동 PHP 호스팅(public/를 웹루트로)
비유 — "완성 가구(Laravel)를 사와서 벽을 다시 튼 집"

보통의 Laravel 앱이 이케아 가구 배치도(프레임워크 기본 폴더 구조)를 그대로 따르는 아파트라면, Leantime은 같은 가구를 쓰되 벽을 헐고 방 배치를 자기 식(도메인별 폴더)으로 다시 짠 집이다. 그래서 Application 클래스가 "우리 폴더 구조는 다르다"며 Laravel의 모든 경로를 재정의한다(§4). 남의 프레임워크를 깊이 이해해야만 할 수 있는 개조라, Laravel 내부를 공부하려는 사람에게 훌륭한 교재가 된다.

4아키텍처 심화 분석

Laravel 11 + 도메인 주도 설계(DDD) · 부트로더 · 43개 도메인 · WordPress식 이벤트/필터 훅 · PDO 레이어 · MCP 서버

Leantime의 뼈대는 두 축이다 — ① 상속·개조한 Laravel 커널(app/Core/)② 기능마다 하나씩인 43개 도메인 모듈(app/Domain/). 그 위에 확장성을 책임지는 이벤트/필터 훅 시스템이 관통한다. 하나씩 해부한다.

4-1. 부팅 흐름 — 요청이 들어오면 벌어지는 일

app/Core/Bootloader.php의 싱글턴이 진입점이다. 요청을 잡아 웹이면 HttpKernel, CLI면 ConsoleKernel을 컨테이너에서 꺼내 실행한다. 그 전에 Application이 Laravel의 표준 경로를 Leantime 구조로 갈아끼운다.

// app/Core/Application.php — Laravel Application 을 상속해 경로 재매핑
class Application extends \Illuminate\Foundation\Application {
    // "우리 폴더 구조는 다르며, 부르주아에게 굴복하지 않는다" (실제 주석)
    $this->useAppPath($this->basePath . '/app');
    $this->useLangPath($this->basePath . '/app/Language');
    $this->registerLeantimeAliases();
}

// app/Core/Bootloader.php — 커널 선택 후 실행
Bootloader::getInstance()->boot($app);
$request = IncomingRequest::capture();
$kernel  = $isConsole ? $app[ConsoleKernel::class] : $app[HttpKernel::class];
$kernel->handle($request);   // → leantime.core.* 이벤트 디스패치

DI 컨테이너는 Laravel의 Illuminate 컨테이너를 그대로 쓴다(PHP-DI 아님). 즉 "폴더 배치와 부팅 절차는 개조했지만, 심장(컨테이너·커널·서비스 프로바이더)은 Laravel 그대로"라는 절충이다.

4-2. 도메인 주도 설계(DDD) — 기능 하나 = 폴더 하나

Leantime의 정수는 app/Domain/ 아래 43개의 자기완결 모듈이다. 각 도메인은 컨트롤러·서비스·리포지토리·모델·이벤트·권한·템플릿을 자기 폴더 안에 다 갖는다. 공통 베이스 클래스는 app/Core/Domains/에 있다(BaseService·DomainRepository·DomainModel·DTO). 대표 도메인 Tickets(태스크)의 내부를 보면 구조가 한눈에 들어온다.

app/Domain/Tickets/ ← "태스크" 기능 하나가 통째로 이 폴더 안에 ├── Controllers/ 전체 페이지 컨트롤러 (풀 HTML 렌더) ├── Hxcontrollers/ ┐ │ └── Htmx/ ┴ HTMX 부분 렌더 컨트롤러 (조각 HTML: 카드·타이머·서브태스크) ├── Services/ 비즈니스 로직 (class Tickets extends BaseService) ├── Repositories/ 데이터 접근 (원시 PDO SQL) ├── Models/ 도메인 모델 / DTO ├── Events/ 이벤트 클래스 (TicketCreated, TicketUpdated, MilestoneCreated…) ├── Permissions/ 권한 정의 (TicketsPermissions) ├── Templates/ Blade 뷰 (*.blade.php) ├── Tools/ ★ MCP AI 툴 (AddTaskTool, FindTasksTool, BulkEditTasksTool…) └── Support/ 포매터 등 (TicketFormatter)

서비스는 #[RequiresPermission] 애트리뷰트로 권한을 선언하고, DispatchesEvents 트레이트로 이벤트를 쏘며, 다른 도메인의 서비스·리포지토리를 생성자 주입으로 조합한다. "기능 간 결합을 도메인 경계로 가두는" DDD의 교과서적 적용이다.

4-3. 라우팅 — 규약 기반 + 명시적 라우트의 하이브리드

라우팅도 절충형이다. 대부분의 도메인은 Domain.Controller 이름을 URL로 자동 매핑하는 프론트컨트롤러 규약을 따른다(예: Dashboard는 라우트 파일이 없어도 Controllers/만으로 동작). 반면 단 5개 도메인만 명시적 routes.php를 둔다. 모든 라우트는 CheckPermissions 미들웨어로 감싸져, 앞서 본 #[RequiresPermission] 애트리뷰트가 자동으로 강제된다.

4-4. 확장성의 심장 — WordPress식 이벤트 + 필터 훅

Leantime을 가장 특별하게 만드는 설계. app/Core/Events/EventDispatcher.php(28KB)가 두 종류의 훅을 제공한다 — 이벤트(무언가 일어났음을 알림)필터(값을 통과시키며 변형). WordPress의 do_action/apply_filters와 똑 닮았다.

// 이벤트 — "이 일이 일어나면 이 함수를 불러라" (알림형)
add_event_listener('leantime.core.middleware.loadplugins.plugins', function($p){ ... });
dispatch_event('ticket.created', $ticketData);

// 필터 — 값을 가로채 바꿔서 되돌린다 (변형형)
$menu = dispatch_filter('sidebar.menu', $defaultMenu);

// ★ 압권: SQL 문자열조차 필터를 통과한다 → 플러그인이 쿼리를 다시 쓸 수 있다
$sql = dispatch_filter('sql', $sql, ['entity' => 'ticket']);

훅 이름은 leantime.core.middleware.loadplugins...처럼 계층적이고, 와일드카드/정규식 매칭에 컴파일된 패턴 캐시까지 있다. 심지어 리포지토리가 실행하기 직전의 SQL도 필터를 거쳐, 플러그인이 코어를 건드리지 않고 쿼리를 바꿀 수 있다. 이 훅 시스템이 곧 플러그인·마켓플레이스·엔터프라이즈 확장의 토대다.

4-5. 데이터 레이어 — Laravel 위의 원시 PDO

ORM(Eloquent)을 전면에 쓰지 않는 점이 독특하다. app/Core/Db/Db.php는 스스로를 "PDO 연결을 위한 아주 단순한 추상화 계층"이라 부르며, Laravel의 DatabaseManager에서 연결을 얻은 뒤 원시 PDO 객체를 꺼내 직접 prepare/execute한다. 리포지토리 베이스(Repository.php)의 dbcall()이 이 패턴을 감싼다. SQL 인젝션 방지 헬퍼(arrayToPdoBindingString·sanitizeToColumnString)를 직접 구현했고, 앞서 본 dispatch_filter('sql', ...) 훅이 여기에 걸려 있다.

4-6. AI 네이티브 — 앱이 곧 MCP 서버

laravel/mcp 위에서, 6개 도메인의 Tools/ 폴더에 흩어진 55개의 LLM 호출용 "툴"을 노출한다. 각 툴은 Laravel\Mcp\Server\Tool을 상속해 name()·description()·schema()를 정의한다 — AI가 이 스키마를 읽고 함수처럼 호출한다.

// app/Domain/Tickets/Tools/AddTaskTool.php (요지)
class AddTaskTool extends \Laravel\Mcp\Server\Tool {
    public function name()        { return 'addTask'; }
    public function description() { return 'Create a new task/ticket in a project'; }
    public function schema()      { /* 타입 있는 입력 스키마 (제목·프로젝트·담당자…) */ }
}
// 이런 툴이 addTask · addMilestone · findTasks · bulkEditTasks · createSubtasks …로 55개

즉 Claude 같은 에이전트가 "이 프로젝트에 마일스톤 3개 만들고 태스크를 분배해줘"라고 지시받으면, Leantime의 MCP 툴을 직접 호출해 실행한다. 뒤에서 Prism(멀티 LLM)·neuron-ai(에이전트)·Qdrant(벡터 검색)가 받친다.

┌──────────────────────────────────────────────────────────────────┐ │ 브라우저 요청 / AI 에이전트(MCP) / CLI(bin/leantime) │ │ │ │ │ ① Bootloader → HttpKernel / ConsoleKernel (Laravel 커널) │ │ │ │ │ ② 미들웨어 파이프라인 (CheckPermissions · loadplugins 이벤트) │ │ │ │ │ ③ 라우팅: 규약(Frontcontroller) 또는 명시 routes.php │ │ │ │ │ ④ Domain/{기능}/Controllers 또는 Hxcontrollers(HTMX 조각) │ │ │ │ │ │ ▼ ▼ │ │ Services (BaseService) Tools/ (MCP AI 툴 55개) │ │ │ #[RequiresPermission] · DispatchesEvents │ │ ▼ │ │ Repositories → Core/Db (원시 PDO) ──dispatch_filter('sql')──▶ │ │ │ (플러그인이 쿼리 변형) │ │ ▼ │ │ MySQL / MariaDB / PostgreSQL (zp_ 접두사 41 테이블) │ │ │ │ │ ▼ │ │ Blade 템플릿(Domain/*/Templates) → HTML ◀── 이벤트/필터 훅 관통│ └──────────────────────────────────────────────────────────────────┘

5디렉토리 · 파일 구조 해부

"app/Core(개조한 커널) + app/Domain(43개 기능 모듈)"의 이분 구조 — 나머지는 Laravel 관례

루트는 Laravel 앱과 비슷하지만, app/ 내부가 완전히 다르다. 프레임워크 개조 부분(Core)과 기능 부분(Domain)이 명확히 갈린다.

leantime/ ├── app/ ★ 애플리케이션 코드 (PSR-4 네임스페이스 Leantime\) │ ├── Core/ 개조한 프레임워크 커널 (26개 하위폴더) │ │ ├── Application.php Laravel Application 상속 · 경로 재매핑 │ │ ├── Bootloader.php 부팅 싱글턴 · 커널 선택 │ │ ├── Events/ ★ 이벤트+필터 훅 엔진 (EventDispatcher 28KB) │ │ ├── Db/ 원시 PDO 추상화 (Db.php · Repository.php) │ │ ├── Domains/ 도메인 베이스클래스 (BaseService · DomainRepository) │ │ ├── Routing/ RouteLoader · 규약 기반 매핑 │ │ ├── Http/ Middleware/ 커널·미들웨어(CheckPermissions) │ │ ├── UI/ Template · Theme · Composer (Blade 배선) │ │ ├── Plugins/ 플러그인 매니저 │ │ └── Auth/ Cache/ Console/ Configuration/ … │ ├── Domain/ ★ 43개 기능 모듈 (기능 하나 = 폴더 하나) │ │ ├── Tickets/ Sprints/ Timesheets/ Calendar/ Tags/ (실행) │ │ ├── Canvas/ Goalcanvas/ Logicmodelcanvas/ Ideas/ Blueprints/ (전략) │ │ ├── Projects/ Clients/ Reports/ Dashboard/ Widgets/ (관리) │ │ ├── Wiki/ Comments/ Reactions/ Files/ ContentTemplates/ (지식) │ │ ├── Auth/ Users/ TwoFA/ Ldap/ Oidc/ Setting/ (인증·설정) │ │ ├── Gamecenter/ ★ 게이미피케이션(성취·보상 → 뉴로다이버시티) │ │ └── Install/ Cron/ Queue/ Api/ Plugins/ Menu/ … │ ├── Views/ 전역 Blade (Templates/{components,layouts,sections}) │ ├── Command/ 콘솔 명령 (Artisan 스타일) │ ├── Language/ i18n .ini 파일 48개 (ko-KR·ja-JP·ar-SA…) │ ├── Plugins/ (배포 시 비어 있음 — 런타임/마켓플레이스 설치) │ └── helpers.php 전역 헬퍼 함수 ├── config/ sample.env · configuration.sample.php (런타임은 .env) ├── public/ 웹루트 (여기로 도메인 연결) · public/dist = 컴파일 자산 ├── bootstrap/ storage/ Laravel 부트스트랩 · 로그/캐시/세션/뷰 ├── database/ (비어 있음 — 스키마는 app/Domain/Install 에) ├── helm/ Kubernetes Helm 차트 ├── bin/leantime CLI 진입점 ├── tests/ Codeception 스위트 ├── .docker/ .dev/ 프로덕션(nginx+fpm) · 개발(Apache+Xdebug) 환경 ├── makefile 빌드·테스트·패키징 오케스트레이션 ├── webpack.mix.js Laravel Mix 설정 ├── composer.json PHP 의존성 · PSR-4 · 플러그인 병합 └── package.json 프런트 의존성 (v3.9.8)
경로역할
app/Core/개조한 프레임워크층. Laravel을 상속·확장한 부분이 전부 여기. 이벤트/필터 엔진·PDO 레이어·라우팅·플러그인 매니저·Blade 배선. "Leantime이 Laravel을 어떻게 비틀었나"가 궁금하면 여기부터.
app/Domain/43개 기능 모듈. 각 폴더가 컨트롤러~리포지토리~템플릿~MCP툴을 자기 안에 갖는 자기완결 단위. 새 기능은 새 폴더로 추가. Leantime 학습의 본진.
app/Language/48개 언어 .ini. Crowdin으로 번역 협업. 한국어(ko-KR) 포함. "번역 추가"가 첫 기여로 좋음(§8).
app/Domain/Install/Laravel 마이그레이션 대신 커스텀 스키마 인스톨러(Install.php 2,845줄·41 CREATE TABLE). /install·/update UI가 이걸 실행.
.docker/ · helm/배포 자산. Dockerfile(멀티스테이지 nginx+fpm+supervisord)과 K8s Helm 차트. "어떻게 운영하나"의 답.
핵심 관찰
"Core vs Domain" 이분법의 힘
Leantime 코드베이스를 빠르게 파악하는 열쇠는 "프레임워크(Core)와 기능(Domain)을 물리적으로 분리"했다는 점이다. 기능을 추가·수정할 땐 app/Domain/ 보면 되고, "왜 이렇게 동작하지?"라는 프레임워크 수준 의문은 app/Core/에서 풀린다. 1,000개 넘는 파일이 겁나 보여도, 이 두 폴더의 관계만 잡으면 길을 잃지 않는다.

6학습 포인트

이 저장소에서 진짜로 배울 것 — "대형 Laravel 앱을 도메인으로 조직하고, 훅으로 확장하고, AI에 여는 법"

Leantime은 "PM 도구"라는 겉모습을 넘어, 실전 규모의 PHP/Laravel 애플리케이션을 어떻게 설계·조직·확장하는가에 대한 살아있는 교재다. 기술별로 배울 거리를 정리한다.

배울 것 1 — Laravel 프레임워크를 상속·개조하는 법

대부분의 튜토리얼은 Laravel의 기본 구조를 "그대로 따르라"고 가르친다. Leantime은 반대로 Illuminate\Foundation\Application상속해 경로·부팅을 재정의한다. 프레임워크를 사용자가 아니라 개조자의 눈으로 보게 해준다 — 서비스 컨테이너·커널·서비스 프로바이더가 실제로 어떻게 맞물리는지 배우는 최고의 실물.

배울 것 2 — 도메인 주도 설계(DDD)로 대형 앱 나누기

기능이 수십 개인 앱을 "컨트롤러 폴더, 모델 폴더"처럼 기술별로 쌓으면 금세 무너진다. Leantime의 "기능 = 폴더" 도메인 구조는 코드가 커져도 길을 잃지 않는 조직법을 보여준다. 베이스 클래스(BaseService·DomainRepository)로 공통을 뽑고, 도메인 간엔 생성자 주입으로만 소통하는 경계 설계를 관찰하라.

배울 것 3 — WordPress식 이벤트/필터 훅 아키텍처

플러그인이 코어를 수정하지 않고 동작을 바꾸게 하는 훅(hook) 시스템은 확장 가능한 소프트웨어의 핵심 패턴이다. Leantime의 dispatch_event/dispatch_filter(특히 SQL조차 필터로 가로채는 대담함)는 "값을 통과시키며 변형하는 필터"와 "알림형 이벤트"의 차이를 코드로 익히게 해준다. WordPress·Drupal의 훅 철학을 Laravel 위에 구현한 사례.

배울 것 4 — HTMX 하이퍼미디어 UI (SPA 없이 인터랙티브)

React/Vue 없이도 현대적인 UX를 만드는 HTMX의 실전 예다. 백엔드의 Hxcontrollers/조각 HTML을 반환하고 브라우저가 그 부분만 교체한다. "무거운 프런트 빌드 없이 서버 렌더로 인터랙션을 주는" 요즘 대안 접근법을, 레거시 jQuery와 공존시키는 현실적 마이그레이션과 함께 볼 수 있다.

배울 것 5 — 앱을 AI에 여는 법 (MCP 서버 구현)

지금 가장 뜨거운 주제. 기존 앱에 MCP 서버를 붙여 AI 에이전트가 기능을 호출하게 하는 실제 구현을 통째로 볼 수 있다. Tool을 상속해 name/description/schema를 정의하는 패턴, 그리고 그 뒤를 받치는 멀티 LLM 추상화(Prism)·벡터 DB(Qdrant) 배선까지 — "AI 네이티브 앱"의 실전 청사진.

배울 것 6 — ORM 없이 원시 PDO로 안전하게 DB 다루기

Eloquent 같은 ORM에 의존하지 않고 원시 PDO + 직접 만든 인젝션 방지 헬퍼로 데이터를 다루는 접근. ORM이 감춰버린 "prepared statement·바인딩·SQL 새니타이즈"의 원리를 눈으로 확인하게 해준다. 성능·제어를 위해 ORM을 걷어낸 트레이드오프의 사례.

실습 아이디어 (가볍게)
"도메인 하나 정독" 1시간 코스

app/Domain/Comments/(비교적 단순한 도메인)를 골라 Controller → Service → Repository → Template 순으로 한 기능(댓글 작성)의 전체 흐름을 따라가 보라. 그다음 같은 기능을 Tickets에서 찾아 대조하면, "도메인마다 같은 골격이 반복된다"는 DDD의 일관성이 몸에 익는다.

7시스템 · 설치 요구사항

"PHP 8.2 + MySQL + 웹서버" 정통 LAMP/LEMP 스택 — 가장 쉬운 길은 Docker

단일 파일 유틸과 달리 Leantime은 서버·PHP·DB가 갖춰진 환경이 필요하다. 다만 Docker 이미지가 잘 정리돼 있어, 명령 몇 줄이면 뜬다.

항목요구
PHP8.2 이상. 확장 다수 필요: bcmath·ctype·curl·dom·exif·gd·ldap·mbstring·mysqli/pdo_mysql·opcache·openssl·pcntl·zip·simplexml
데이터베이스MySQL 8.0+ 또는 MariaDB 10.6+(기본). PostgreSQL도 지원
웹서버Apache 또는 Nginx(public/를 웹루트로). Docker 이미지는 nginx + PHP-FPM 내장
런타임(선택)Redis(캐시·세션), S3 호환 스토리지(파일), SMTP(메일), AI 기능용 LLM API 키·Qdrant
빌드(개발 시)Node.js + Composer. 프로덕션 릴리스 tarball은 자산이 이미 컴파일돼 있어 빌드 불필요

설치 흐름 (세 갈래)

① Docker (가장 쉬움) ───────────────────────────────────────── docker run 또는 docker-compose 로 leantime 이미지 + MySQL 컨테이너 → 브라우저로 접속 → /install 마법사에서 관리자·DB 설정 (이미지: nginx+php-fpm+supervisord, 8080 포트, LEAN_* 환경변수) ② Kubernetes ───────────────────────────────────────────────── helm/ 차트로 클러스터에 배포 (프로덕션 규모) ③ 수동(전통 호스팅) ────────────────────────────────────────── 릴리스 tarball(Leantime-vX.X.X.tar.gz) 다운로드 → 웹서버 public/ 연결 → DB 생성 → /install 접속 → 스키마 자동 생성(Install.php 41 테이블)
핵심 용어
/install · /update 마법사와 독립 dbVersion
Leantime은 앱 버전(appVersion 3.9.8)과 DB 스키마 버전(dbVersion 3.5.20)을 따로 관리한다. 코드를 새 버전으로 올리면, 접속 시 /update현재 dbVersion과 목표 버전 사이의 번호 붙은 패치 메서드(예: 30503, 30504)만 순서대로 실행한다. Laravel 마이그레이션 파일 대신 이 "번호 패치" 방식으로 스키마를 진화시킨다.

8직접 해볼 수 있는 실습 과제

읽기만 하면 안 남는다 — Leantime을 띄우고, 뜯고, 확장하는 과제 5개(난이도별)
난이도 ★☆☆ · 입문

1. Docker로 내 Leantime 띄우기

공식 Docker 이미지 + MySQL을 docker-compose로 올려 5분 만에 셀프호스팅 PM 서버를 띄운다. /install 마법사로 관리자 계정을 만들고, 프로젝트 하나에 태스크·마일스톤·타임시트를 넣어 보며 "전략→실행" 흐름을 체감. DB 컨테이너의 zp_ 테이블을 직접 들여다보면 §4-5의 스키마가 손에 잡힌다.

난이도 ★☆☆ · 입문

2. 새 언어 번역 추가 / 문구 고치기 (첫 기여)

app/Language/.ini 파일 구조를 파악하고, 한국어(ko-KR.ini)의 어색한 번역을 다듬거나 빠진 키를 채워 본다. i18n이 어떻게 코드와 연결되는지 배우고, 오픈소스 첫 PR로도 안성맞춤(번역은 진입장벽이 낮다).

난이도 ★★☆ · 중급

3. 이벤트/필터 훅 리스너 붙여 보기

add_event_listener('ticket.created', ...)태스크가 생성될 때마다 로그를 남기거나 외부 웹훅을 쏘는 리스너를 등록해 본다. 이어서 add_filter_listener로 사이드바 메뉴(dispatch_filter('sidebar.menu', ...))에 항목을 하나 끼워 넣어, "코어를 안 건드리고 동작을 바꾸는" 훅의 힘을 체감(§4-4).

난이도 ★★☆ · 중급

4. 미니 플러그인 만들기

app/Plugins/ 규약에 맞춰 자체 composer.jsonroutes.php를 가진 작은 플러그인을 만들어, 새 페이지 하나를 추가해 본다. Leantime의 플러그인 매니저·라우트 병합·훅 등록 흐름을 관통하는 과제. "확장 가능한 앱은 어떻게 열려 있는가"를 배운다.

난이도 ★★★ · 심화

5. 나만의 MCP 툴 추가 → AI로 조작

app/Domain/*/Tools/의 기존 툴(AddTaskTool 등)을 본떠 새 MCP 툴(예: "이번 주 완료 태스크 요약")을 하나 정의하고, Claude 같은 MCP 클라이언트를 붙여 자연어로 Leantime을 조작해 본다. Tool 상속·schema() 설계·권한 연동까지 — §4-6의 "AI 네이티브"를 내 손으로 재현하는 최종 보스.

9관련 기술 심화 학습 로드맵

"PHP/Laravel 기초 → 대형 앱 아키텍트"까지, 4주 코스
주차목표 · 학습 내용
1주차
PHP · Laravel 기본
PHP 8.2 문법(타입·애트리뷰트·enum), Composer·PSR-4 오토로딩, Laravel의 서비스 컨테이너·서비스 프로바이더·파사드·미들웨어. → Leantime app/Core/Application.php가 무엇을 개조했는지 읽을 준비.
2주차
도메인 구조 해부
app/Domain/에서 도메인 하나(CommentsTickets)를 Controller→Service→Repository→Blade로 정독. BaseService·DomainRepository 베이스 클래스, #[RequiresPermission], 생성자 주입. → 과제 1·2.
3주차
확장성: 훅 · 플러그인
이벤트 vs 필터의 차이, EventDispatcher의 계층적 훅·와일드카드, 플러그인 매니저·composer-merge-plugin, 원시 PDO 레이어와 dispatch_filter('sql'). → 과제 3·4.
4주차
프런트(HTMX) · AI(MCP)
HTMX 하이퍼미디어(Hxcontrollers/ 조각 렌더), TipTap 에디터, 그리고 MCP 서버·Tool·Prism·Qdrant 벡터 검색. Leantime을 AI로 조작. → 과제 5.
학습 순서 팁

Leantime은 "쓰기는 클릭, 이해는 여러 겹"인 대형 앱이다. 1,000개 넘는 파일에 겁먹지 말고, 가장 먼저 "Core(프레임워크) vs Domain(기능)" 이분법만 머리에 넣어라(§5). 그다음 도메인 딱 하나를 끝까지 따라가면 나머지 42개도 같은 골격이라 술술 읽힌다. 프레임워크 수준 의문이 생길 때만 app/Core/로 내려가면 된다 — 전체를 통독하려는 시도가 가장 흔한 실패다.

10핵심 키워드 사전

이 문서에 나온 용어를 한 번에 — Laravel·PHP·PM 도구 코드를 읽을 때 계속 마주칠 단어들
용어
LaravelPHP의 대표 웹 프레임워크. Leantime은 illuminate/* 조각이 아니라 전체 프레임워크를 상속·개조해 씀.
DDD (도메인 주도 설계)소프트웨어를 "기능(도메인)" 단위로 나누는 설계. Leantime은 app/Domain/기능마다 폴더 하나(43개).
도메인 (Domain)Tickets·Canvas·Goalcanvas처럼 하나의 기능을 이루는 자기완결 모듈(컨트롤러~리포지토리~템플릿~MCP툴 포함).
이벤트 vs 필터 훅이벤트=일어난 일을 알림(dispatch_event). 필터=값을 통과시키며 변형(dispatch_filter). WordPress식 확장 패턴. SQL도 필터 가능.
MCP (Model Context Protocol)AI 에이전트가 외부 앱의 기능을 "툴"로 호출하는 표준. Leantime은 자기 자신을 MCP 서버로 노출(55개 툴).
HTMXSPA 없이 서버가 조각 HTML을 반환해 페이지 일부만 교체하는 하이퍼미디어 라이브러리. Hxcontrollers/와 짝.
BladeLaravel의 템플릿 엔진(*.blade.php). Leantime 뷰는 도메인별 Templates/에.
PDOPHP의 표준 DB 접근 인터페이스. Leantime은 ORM 대신 원시 PDO + 직접 만든 인젝션 방지로 SQL 실행.
Sanctum · SocialiteLaravel 인증 패키지. Sanctum=API 토큰, Socialite=소셜 로그인(+15 프로바이더·SAML2).
Prism · QdrantPrism=여러 LLM을 한 인터페이스로 쓰는 추상화. Qdrant=벡터 데이터베이스(임베딩·시맨틱 검색).
Lean Canvas · OKR린 스타트업의 전략 수립 도구(1장 비즈니스 모델) · 목표관리 프레임(Objectives & Key Results). Leantime에 내장.
뉴로다이버시티ADHD·자폐·난독을 두뇌의 다양성으로 보는 관점. Leantime 설계 철학(Gamecenter·시각적 진행·작은 태스크).
셀프호스팅SaaS와 달리 내 서버에 직접 설치해 데이터 주권을 확보하는 운영 방식. AGPL 오픈소스라 가능.
AGPL-3.0강한 카피레프트 라이선스. 네트워크 서비스로 제공해도 소스 공개 의무. 단, app/Plugins는 별도 라이선스(엔터프라이즈) 예외.
zp_ 접두사 · dbVersion모든 DB 테이블 이름 앞의 zp_. 앱 버전과 분리된 독립 스키마 버전으로 /update가 번호 패치를 적용.

11참고 링크

공식 소스부터 학습 자료까지
구분링크
GitHubgithub.com/Leantime/leantime — 이 저장소(소스·Docker·Helm·문서)
공식 사이트leantime.io — 소개·클라우드 호스팅·마켓플레이스
공식 문서docs.leantime.io — 설치·설정·플러그인 개발 가이드
Docker Hubhub.docker.com/r/leantime/leantime — 공식 이미지(셀프호스팅의 지름길)
Laravel 문서laravel.com/docs — 컨테이너·프로바이더·미들웨어(코어 이해의 전제)
MCP 규격modelcontextprotocol.io · github.com/laravel/mcp — AI 툴(§4-6)의 표준·구현
HTMXhtmx.org — 하이퍼미디어 UI(프런트 절반의 근거)
이슈 · 기여github.com/Leantime/leantime/issues · Crowdin(번역) — 첫 기여의 출발점(§8)