Frontend Engineer

이해람

Introduce

6년차 프론트엔드 엔지니어로 30년의 업력을 가진 UI 프레임워크 개발 기업에서 기본기를 다진 뒤 헬스케어 스타트업에서 의료진 / 환자 / 고령자 대상의 애플리케이션을 개발/유지보수 하였습니다.

아키텍처에 정답은 없다고 생각하며 프로젝트의 목적, 개발팀의 리소스, 개발 기한을 고려하여 가장 적합한 아키텍처를 설계하고 있습니다.

저는 가장 중요한 업무에 가장 큰 에너지를 사용해야 한다는 원칙을 중요하게 생각합니다. 함께 일하는 동료들 역시 그렇게 할 수 있도록, 각자의 성향을 파악해 불필요한 감정 소모나 의사소통 피로감을 최소화하고 갈등을 해결하는 것에 강점이 있습니다.

AI는 사용하는 사람에 따라 생산성이 달라지기 때문에 AI 룰 작성이나 프롬프트 공유 등 AI를 활용한 팀 생산성 높이기에 많은 고민을 합니다.

Skills

Languages

TypeScriptDart

Frameworks & Libraries

ReactNext.jsFlutterTanstack-RouterTailwind

State Management

ZustandBlocTanstack-Query

Tools & Platforms

pnpmgRPCFirebaseGitFigma

Projects

SarcoFit

근감소증 치료를 위한 디지털 치료기기(DTx)

2024.10 - 현재

🚨 Problem: 모노레포 병합 지옥

DDD 기반 개발 전략의 부작용

User Story별로 Fractal Cell을 나누고 브랜치를 분리하여 개발 후 develop 브랜치로 병합

역할 중심 아키텍처의 한계

components/, pages/, hooks/ 등 역할별 폴더 구조로 인해 여러 팀원이 동일한 디렉토리를 수정하며 충돌 발생

10+
2주 스프린트당 브랜치
10+
분(1회 병합 시간)
수십개
스프린트당 Conflict
높음
개발자 인지 부담

💥 실제 Conflict 발생 사례

⚠️
Conflict Scenario
개발자 A와 B가 동시에 같은 파일(components/ExerciseCard.tsx)을 수정하여 merge 시 conflict 발생
components/ExerciseCard.tsx
개발자 A의 브랜치 (feature/exercise-records)
1export function ExerciseCard({ exercise }: Props) {
2 const { data: records } = useExerciseRecords(exercise.id);
3
4 return (
5 <div className="card">
6 <h3>{exercise.name}</h3>
7 <p>{exercise.description}</p>
8
9 {/* 개발자 A가 추가한 코드 */}
10 <div className="records">
11 {records?.map(r => (
12 <RecordItem key={r.id} record={r} />
13 ))}
14 </div>
15 </div>
16 );
17}
❌ Merge 시 발생하는 문제
  • • 두 개발자가 같은 파일의 같은 위치를 수정
  • • Git이 자동으로 merge하지 못해 수동 해결 필요
  • • 해결 과정에서 실수로 코드 누락 가능성
  • • 매 스프린트마다 반복되는 비효율

✨ FSD 아키텍처로 해결

⚠️
Conflict Scenario
각 개발자가 독립적인 feature 폴더에서 작업하여 conflict 없이 개발
features/exercise-records/ui/ExerciseRecordView.tsx
개발자 A의 작업 영역 (격리됨)
1// Feature: 운동 기록 조회
2import { ExerciseCard } from '@/entities/exercise';
3import { useExerciseRecords } from '../api/useExerciseRecords';
4
5export function ExerciseRecordView({ exerciseId }: Props) {
6 const { data: records } = useExerciseRecords(exerciseId);
7
8 return (
9 <div className="space-y-4">
10 <ExerciseCard exerciseId={exerciseId} />
11
12 <div className="records-section">
13 <h4>운동 기록</h4>
14 {records?.map(record => (
15 <RecordItem key={record.id} record={record} />
16 ))}
17 </div>
18 </div>
19 );
20}
✅ FSD 아키텍처의 장점
  • • 각 feature가 독립된 폴더에 격리되어 충돌 없음
  • • ExerciseCard는 entities/에서 공유 컴포넌트로 관리
  • • User Story 1개 = Feature 1개 = 독립적인 개발 영역
  • • 코드 리뷰 시 변경 범위가 명확해짐

🏗️ FSD 레이어 구조

BEFORE: 역할 중심
src/
├── components/
⚠️ 모든 팀원이 수정
├── pages/
⚠️ 충돌 빈발
├── hooks/
⚠️ 충돌 빈발
├── utils/
└── types/
AFTER: FSD (기능 중심)
src/
├── features/
✓ 격리된 기능 개발
├── widgets/
공통 위젯
├── entities/
순수 UI (재사용)
└── shared/

⚙️ Solution: 개발 프로세스 개선

1
스프린트 시작: 설계 우선 개발

Sprint에서 구현 할 User Stroy를 정확하게 정의 후 컴포넌트 설계

2
스프린트 중: 격리된 개발

Rule: 1 User Story = 1 Feature = 1 Branch

개발자 A
feature-1/
개발자 B
feature-2/
개발자 C
feature-3/
3
스프린트 종료: 리팩터링 타임

Feature 성격에 맞지 않는 코드를 적절한 레이어로 이동

→ entities/
순수 UI
→ widgets/
공통 위젯
→ shared/
유틸리티

🤖 AI 활용 생산성 향상

FSD 레이어별로 명확한 규칙을 수립하고 AI 룰을 작성하여 팀 전체가 활용

entities/
  • • 순수 UI 컴포넌트
  • • Props로 데이터 수신
  • • 비즈니스 로직 금지
widgets/page/
  • • Data fetching 허용
  • • useContainer 사용
  • • 비즈니스 로직 포함
useContainer
  • • 1 widget = 1 container
  • • Query/Mutation 관리
  • • 상태 관리

📈 Impact: 정량적 성과

80%↓
Merge Conflict 감소
격리된 feature 개발로 충돌 최소화
3.5x
AI 코드 채택률 향상
20% → 70% (명확한 규칙으로)
100%
개발 프로세스 준수율
팀 전체가 동일한 규칙 적용

화푸리

화병 치료를 위한 디지털 치료기기(DTx)

2024.06 - 2025.08

🚨 Problem: 협업 파트너의 도구 미숙련

리소스 제약 속 협업

사이드 프로젝트로 리소스가 제한된 상황에서 Figma에 익숙하지 않은 영상 디자이너와 앱 개발 진행

디자인 전달의 어려움

초기 디자인이 개발하기 어려운 형태로 전달되어 반복적인 수정 필요

✨ 동료 성장을 돕는 협업 방식

1
심리적 안전감 제공

"어떻게 주셔도 개발할 수 있으니 괜찮아요"라며 디자이너가 도전할 수 있도록 동기부여

2
긍정적 피드백 방식

"이렇게 하면 안 돼요" 대신 "이렇게 해주시면 개발이 더 수월해요"로 구체적 개선 방향 제시

예시:
❌ "컴포넌트가 너무 복잡해서 개발이 어려워요"
✅ "반복되는 요소를 컴포넌트로 만들어주시면 개발이 빨라져요. 이런 식으로요..."
3
UI/UX 공동 토의

디자이너와 활발히 소통하며 함께 앱의 사용자 경험을 개선

📈 Impact: 상호 성장

100%
일정 준수율
매달 정기 회의 일정 모두 달성
50%↓
디자인 피드백 감소
6개월 후 디자이너의 Figma 숙련도 향상
↑↑
UI/UX 역량 향상
개발자의 디자인 감각과 지식 성장

MyVivache

고령자 대상 운동 애플리케이션

2023.01 - 2023.10

🚨 Problem: 불명확한 아키텍처

개발 철학의 부재

명확한 아키텍처 패턴이 없어 개발자마다 비즈니스 로직을 다른 위치에 작성

유지보수의 어려움

코드의 일관성 저하로 동료 간 코드 이해와 유지보수에 불필요한 비용 발생

🏗️ Clean Architecture 도입

BEFORE: 비즈니스 로직 분산
문제점
  • • Widget에 비즈니스 로직 혼재
  • • API 호출이 여러 곳에 분산
  • • 테스트가 어려운 구조
  • • 재사용성 낮음
lib/
├── screens/
⚠️ 로직 혼재
└── widgets/
⚠️ API 직접 호출
AFTER: Clean Architecture
개선점
  • • 도메인 로직과 UI 분리
  • • Repository 패턴으로 데이터 계층 추상화
  • • 테스트 용이한 구조
  • • 높은 재사용성
lib/
├── domain/
✓ 비즈니스 로직
├── data/
✓ Repository
└── presentation/
✓ UI만

💡 Repository Pattern 적용

⚠️
Conflict Scenario
데이터 소스를 추상화하여 비즈니스 로직과 데이터 계층 분리
presentation/screens/exercise_screen.dart
UI Layer - 순수하게 UI만 담당
1class ExerciseScreen extends StatelessWidget {
2 final ExerciseRepository repository;
3
4 @override
5 Widget build(BuildContext context) {
6 return FutureBuilder<List<Exercise>>(
7 future: repository.getExercises(),
8 builder: (context, snapshot) {
9 if (!snapshot.hasData) {
10 return CircularProgressIndicator();
11 }
12
13 return ListView.builder(
14 itemCount: snapshot.data!.length,
15 itemBuilder: (context, index) {
16 return ExerciseCard(
17 exercise: snapshot.data![index],
18 );
19 },
20 );
21 },
22 );
23 }
24}

🔍 주도적인 UX 리서치

어르신 복지관 방문 시 앱 설치 역할에서 더 나아가 직접 사용자 인터뷰 진행

🗣️ 발견한 UX 이슈들
  • • 아이콘의 의미를 해석하지 못함
  • • 붉은 계열의 색상을 무조건 경고로 받아들임
  • • 버튼이 일반적인 형태와 다르면 버튼이라는 인식을 못함
  • • 순서가 있는 리스트에서 순차적으로 해야한다는 사실 인지 못함
  • • 버튼이 2개 이상이면 어떤 버튼을 클릭해야하는지 혼란
✅ 개선 결과

기획팀과 긴밀히 소통하여 고령자 친화적인 UI/UX로 개선

📄 연구 결과가 논문에 기재됨 →

📈 Impact: 개발 문화와 프로덕트 품질 향상

유지보수성 향상
도메인 로직과 UI 분리로 코드 이해도 증가
100%
팀 전체 적용
모든 팀원이 동일한 구조로 개발

MyVivache (MVP)

고령자 대상 운동 애플리케이션 MVP 버전

2022.08 - 2022.12

🚨 Challenge: 미경험 기술 스택

Flutter 경험 전무

React 기반 웹 서비스 유지보수 중, 신규 앱 프로젝트를 Flutter로 개발해야 하는 상황

빠른 MVP 개발 필요

프로덕트 출시를 위해 단기간 내 학습과 개발을 병행해야 함

💡 기술은 프로덕트를 위한 것

"프로덕트의 성공을 위해서는 기술 스택이 장벽이 되어서는 안 된다"

1
빠른 학습

Dart 언어와 Flutter 생태계를 즉시 학습 시작. 기존 모바일 앱 개발 경험과 웹 개발 지식을 활용

2
학습과 개발 병행

이론 학습과 동시에 MVP 개발을 진행하며 실전적인 문제 해결에 집중

3
프로덕트 중심 사고

기술 자체보다 사용자와 프로덕트의 가치를 우선순위로 두고 개발

🚀 Flutter 학습 여정

📚
Week 1-2
  • • Dart 기본 문법
  • • Widget 개념 이해
  • • 상태 관리 기초
🛠️
Week 3-8
  • • MVP 핵심 기능 개발
  • • 실전 문제 해결
  • • 패키지 생태계 학습
🎯
Week 9-12
  • • 기능 완성 및 테스트
  • • 고령자 UX 최적화
  • • 배포 준비 완료

📈 Impact: 빠른 적응과 성공적인 배포

3개월
MVP 개발 완료
Flutter 미경험에서 출시까지
성공적인 배포
고령자 대상 앱 스토어 출시
💪
개발자 가치 증명
기술이 아닌 프로덕트 중심 사고

Contact

사람을 위한 프로덕트를 함께 만들어갈 개발자입니다

<Human />

© 2025 Haeram Lee. Built with React Router 7