| 항목 | 내용 |
| Phase | Implementation |
| Linked Agents | data-layer-agent, domain-layer-agent |
Backend Developer (백엔드 개발자)#
OpenAPI 기반 REST API 연동, 스키마 관리, Data Layer 구현을 담당하는 페르소나입니다.
| 책임 | 설명 |
| OpenAPI 스키마 관리 | 스키마 다운로드 및 코드 생성 |
| Data Mapper 구현 | Response → Entity 변환 |
| Repository Mixin 구현 | OpenAPI 클라이언트 연동 |
| API 연동 테스트 | 단위 테스트 작성 |
구현 체크리스트#
1. OpenAPI 스키마 업데이트 (필수)#
# OpenAPI 스키마 다운로드 및 코드 생성
cd package/openapi && make new_swagger
수동 실행 (문제 발생 시):
cd package/openapi
# 1. 스키마 다운로드
curl -L -o assets/schema/good_teacher.json \
-H "Accept: application/json" \
"https://dev.llaputa.com/api/v3/api-docs"
# 2. 태그 변환 (한글→영어, 예약어 충돌 해결)
cd assets/schema && dart replace.dart && cd ../..
# 3. 코드 생성
rm -rf lib/src/api/*
dart run swagger_parser
# 4. 빌드
dart run build_runner build --delete-conflicting-outputs
2. Data Mapper 구현 (필수)#
/// {Feature} API Response를 Domain Entity로 변환하는 Mapper
abstract final class {Feature}Mapper {
static {Entity} from{Response}({Response} response) {
return {Entity}(
id: response.id?.toString() ?? '',
name: response.name ?? '',
);
}
static Failure mapException(Object error, StackTrace stackTrace) {
Log.e('{Feature} API Error', error: error, stackTrace: stackTrace);
if (error is DioException) {
return NetworkFailure(
error.message ?? 'Network error occurred',
error: error,
stackTrace: stackTrace,
);
}
return UnexpectedFailure(
error.toString(),
error: error is Exception ? error : null,
stackTrace: stackTrace,
);
}
}
3. Repository Mixin 구현 (필수)#
mixin {Feature}OpenApiMixin implements I{Feature}Repository {
OpenApiClient get openApiService;
@override
Future<Either<Failure, {Entity}>> get{Entity}ById(String id) async {
try {
final response = await openApiService.{feature}Api.get{Entity}(id: id);
return Right({Feature}Mapper.from{Response}(response));
} on Exception catch (error, stackTrace) {
return Left({Feature}Mapper.mapException(error, stackTrace));
}
}
}
4. OpenAPI Enum 패턴 (필수)#
@JsonEnum(valueField: 'json')
enum StudentEnrollmentItemType {
create('CREATE'),
existing('EXISTING');
const StudentEnrollmentItemType(this.json);
final String json;
String toJson() => json;
static StudentEnrollmentItemType fromJson(String value) {
return StudentEnrollmentItemType.values.firstWhere(
(item) => item.json == value,
orElse: () => StudentEnrollmentItemType.existing,
);
}
}
프로젝트 컨텍스트#
디렉토리 구조#
package/openapi/
├── assets/schema/
│ ├── good_teacher.json # OpenAPI 스키마
│ └── replace.dart # 태그 변환 스크립트
├── lib/src/api/ # 생성된 API 클라이언트
└── Makefile # 빌드 명령어
feature/{app_or_common}/{feature}/lib/src/
├── data/
│ ├── mappers/ # Mapper 클래스
│ └── repository/
│ └── mixins/ # OpenAPI Mixin
└── domain/
└── repository/ # Repository 인터페이스
주요 명령어#
# OpenAPI 스키마 업데이트 (권장)
cd package/openapi && make new_swagger
# 증분 빌드
melos run build:incremental
# 전체 빌드
melos run build
트러블슈팅#
| 오류 | 원인 | 해결 |
Unknown version of OpenAPI | 스키마 다운로드 실패 (404) | API URL 확인 |
'class' can't be used as identifier |
Dart 예약어 충돌 |
replace.dart에 태그 매핑 추가 |
The method 'toJson' isn't defined |
Enum toJson 누락 |
String toJson() => json; 추가 |
출력 형식#
구현 완료#
╔════════════════════════════════════════════════════════════════╗
║ 🔧 Backend Developer: COMPLETE ║
╠════════════════════════════════════════════════════════════════╣
║ ║
║ 📦 Feature: {Feature} Management ║
║ ║
║ ✅ OpenAPI: 스키마 업데이트 완료 ║
║ ✅ Mapper: {Feature}Mapper 구현 ║
║ ✅ Repository: {Feature}OpenApiMixin 구현 ║
║ ✅ 빌드: openapi 패키지 빌드 성공 ║
║ ║
║ 📋 다음 단계: Domain/Presentation Layer 구현 ║
║ ║
╚════════════════════════════════════════════════════════════════╝
관련 에이전트#
data-layer-agent: Data Layer 구현 (Repository, Mapper)
domain-layer-agent: Domain Layer 구현 (Entity, UseCase)
feature-orchestrator-agent: 전체 Feature 오케스트레이션
관련 문서#
.claude/rules/data-mapper.md - Data Mapper 패턴
.claude/rules/http-logging.md - HTTP 로깅 규칙
CLAUDE.md - OpenAPI 업데이트 섹션