IDP(Individual Development Plan)를 만들면서 배운 점

발행: (2025년 12월 18일 오후 07:38 GMT+9)
8 min read
원문: Dev.to

Source: Dev.to

정의

이러한 성찰을 바탕으로 초기 목표를 정의했습니다:

  1. 기술 역량 향상
  2. 전체 프로젝트를 영어로 문서화

주제를 정의하는 것은 간단하지 않았습니다. 왜냐하면 제 개인적인 성장뿐만 아니라 IDP가 회사에 어떤 가치를 더할 수 있는지도 고려하려 했기 때문입니다. 일상 업무에 적용 가능하고 유용하며, 앞으로 더 나은 아키텍처 결정을 내리는 데 도움이 되는 것을 원했습니다.

나는 이렇게 생각했습니다: 풀스택 개발자로 일하면 모든 것을 알 수는 없지만, 아키텍처 원칙을 마스터하면 기술 스택에 관계없이 큰 차이를 만들 수 있다.

그래서 저는 SOLID(단일 책임, 개방‑폐쇄, 리스코프 치환, 인터페이스 분리, 의존성 역전)를 실제로 공부하고 적용하기로 선택했습니다.

이 동기에서 세 번째 목표를 도출했습니다:

  1. 프로젝트 아이디얼라이제이션 단계에서 모범 사례를 적용할 수 있는 개발자 되기

저의 주요 동기는 경험에서 비롯되었습니다. 많은 프로젝트에서 멘토가 없었고, 가능한 한 짧은 시간 안에 최선을 다해 전달하면서 실수를 통해 배우곤 했습니다. SOLID를 더 잘 이해하면 보다 조직적이고 확장 가능한 시스템을 구축할 수 있어, 제 작업의 품질을 직접적으로 향상시킬 수 있습니다.

계획

적용하고 싶었던 스택과 실천 목록을 정리했습니다:

  1. Laravel – Eloquent 사용 (이미 일상에 포함되어 있음). 기존 기능을 재발명하기보다 개념과 아키텍처에 집중할 것입니다.
  2. Vue.js – Composition API 사용.
  3. ESLint & Prettier – 코드가 표준을 따르고 IDE 오류를 일으키지 않도록 보장합니다.
  4. Service Layer – Service Layer를 사용할지 Repository Pattern을 사용할지 고민했지만, Service Layer를 선택했습니다 (아래에 자세히 설명).

처음에 정의한 모든 것이 구현된 것은 아닙니다 (예: 인증, CORS, 배포, git hooks). 나중에 구현할 계획이며, 현재는 베스트 프랙티스와 아키텍처에만 집중할 것입니다.

프로젝트 주제: 도시 전설 지도 – 베스트 프랙티스를 적용하고 Laravel 및 Vue.js 실력을 다듬으며 SOLID 원칙에 대한 이해를 심화시키기 위한 수단입니다.

Practice

Why the Composition API?

I started with Vue.js using the Options API, but in some projects the complexity grew together with file size. Switching to the Composition API on ongoing projects made the experience much smoother, as it facilitates reuse and organisation.

Applying SOLID principles to the front‑end isn’t obvious, but I focused on separating responsibilities and making the code reusable.

UI components should only handle UI

I created a src/api/ folder containing:

src/api/
├─ connect.js   // configures the connection to the API
└─ legend.js    // queries the API endpoints

Each file has a single responsibility.

The components depend only on the functions exported by legend.js, not on Axios directly. If I replace Axios with GraphQL, nothing in the component needs to change.

With this structure, the UrbanLegendMap.vue component only handles UI (Leaflet), consumes domain functions, and does not contain any HTTP logic.

Why the Service Layer?

Changing the ORM in a project is difficult, so implementing a Repository Pattern would add an unnecessary layer and duplicate what Eloquent already provides.

Therefore, the Service Layer is responsible for business decisions, handling approaches, and containing reusable logic – i.e., the business rules.

Each class should have a single reason to change

The controller only receives the request, calls the service interface, and returns an HTTP response, e.g.:

public function store(StoreUrbanLegendRequest $request)
{
    $legend = $this->service->create($request->validated());

    return (new UrbanLegendResource($legend))
        ->response()
        ->setStatusCode(Response::HTTP_CREATED);
}

No validation logic or business rules belong in the controller.

When a new legend is created, a slug is generated for URL access. This responsibility is assigned to the Model.

Thus:

  • Validations → Form Requests
  • Business rules → Service
  • Slug generation, UUIDs, relationships → Model

Each part of the system now has a well‑defined responsibility.

Open for extension, closed for modification

The controller depends only on the service’s interface, not its concrete implementation. If we later migrate the service to an external API, we simply create another class that implements the same interface. The controller remains unchanged, and both the controller and the new service share the same logical contract.

Testing features can be beneficial

I usually test only the service or use‑case layer, but because the project is well‑structured I added both feature tests and unit tests to verify the behaviour of the whole stack.

기능 테스트

전체 흐름 — 라우트, 미들웨어, 요청, 서비스, 모델, 그리고 리소스 — 을 테스트할 수 있습니다 — 예를 들어:

public function test_validates_required_fields_and_returns_422(): void
{
    User::factory()->create();

    $res = $this->withHeaders([
        'Authorization' => 'Bearer ' . $this->token,
    ])->postJson('/api/legend', $this->payload([
        'title' => '',
    ]));

    $res->assertStatus(422)
        ->assertJsonValidationErrors(['title']);
}

이것이 제가 항상 기능을 테스트한다는 의미는 아니지만, 프런트‑엔드가 외부 API에만 의존하기 때문에 응답이 HTTP 원칙을 따르는지 확인하고 문서 작성을 돕는 것이 중요했습니다.

단위 테스트

단위 테스트는 비즈니스 규칙을 격리된 상태에서 검증합니다. 예를 들어:

public function test_list_returns_filtered_legends(): void
{
    $this->service->create($this->payload([
        'title' => 'Lenda - Brasília',
        'city'  => 'Brasília',
    ]));

    $this->service->create($this->payload([
        'title' => 'Lenda - Florianópolis',
        'city'  => 'Florianópolis',
    ]));

    $results = $this->service->list(['city' => 'Brasília']);

    $this->assertCount(1, $results);
    $this->assertEquals('Brasília', $results->first()->city);
}

How the IDP Changed My Thinking

Throughout this Individual Development Project (IDP) my main objective was to improve my technical knowledge. I:

  • Studied each step and implementation, asking why behind every line.
  • Consulted many articles for both theory and practical examples.
  • Built a project applying SOLID principles, discovering that every architectural decision impacts the whole system.

New Daily Questions

Before writing code I now ask myself:

  1. Who is responsible for this?
  2. Does this class have a single reason to change?
  3. Are there any unnecessary methods or functions?
  4. Can it be extended without breaking?
  5. Will I have a headache when maintaining it?

These questions have become part of my routine. Choosing SOLID as my main topic gave me a mindset that will accompany my professional life beyond this IDP.

Although not all planned items were completed (e.g., authentication), I consider the IDP successful. It gave me technical maturity and a solid understanding of how to structure a project from ideation onward—not just learning a technology, but learning to think about architecture intentionally.

요점

  • 좋은 실천은 스택에 의존하지 않고, 의식적인 결정에 따라 달라집니다.
  • 진화는 계속됩니다.

프로젝트 저장소:

References

Back to Blog

관련 글

더 보기 »