Остання активність 1761878715

Версія 39f8f61846ab891998d0fdc75dbc029410de0630

nti설계.md Неформатований

지금 구조는 1:N 관계 (알림 1건 ↔ 처리내역 여러 건) 이므로, 이건 단순 “속성”이 아니라 하위 리소스(sub-resource) 로 취급해야 합니다.

즉, “NTI(알림)”가 상위 도메인, “처리내역”은 NTI 하위에 종속된 도메인으로 보아야 합니다. 아래는 REST 설계, DTO 분리, 서비스 구조 모두를 기준으로 한 권장 설계안입니다.


1. 도메인 관계 요약

개체 설명 관계
Nti 알림 (상위 도메인) 1
NtiProcess 알림의 처리내역 N (하위)

예시:

Nti(id=100, title="재난 문자")
 ├── NtiProcess(id=1, status="발송대기", updatedAt="2025-10-31")
 ├── NtiProcess(id=2, status="발송완료", updatedAt="2025-10-31")
 └── ...

2. REST API 설계

(1) 상위 도메인: 알림

기능 Method URI 설명
알림 목록 조회 GET /api/v1/nti 알림 전체 목록
알림 상세 조회 GET /api/v1/nti/{ntiId} 알림 단건 조회
알림 생성 POST /api/v1/nti 새 알림 생성

(2) 하위 리소스: 알림의 처리내역

기능 Method URI 설명
특정 알림의 처리내역 목록 조회 GET /api/v1/nti/{ntiId}/processes 특정 알림의 처리내역 리스트
특정 처리내역 조회 GET /api/v1/nti/{ntiId}/processes/{processId} 특정 내역 상세
처리내역 추가 POST /api/v1/nti/{ntiId}/processes 해당 알림에 내역 추가

3. Controller 구조

@RestController
@RequestMapping("/api/v1/nti")
@RequiredArgsConstructor
@Slf4j
public class NtiController {

    private final NtiService ntiService;

    @GetMapping
    public ResponseEntity<List<NtiListResponse>> getAllNti() {
        return ResponseEntity.ok(ntiService.getAll());
    }

    @GetMapping("/{ntiId}")
    public ResponseEntity<NtiDetailDto> getNti(@PathVariable Long ntiId) {
        return ResponseEntity.ok(ntiService.getById(ntiId));
    }
}
@RestController
@RequestMapping("/api/v1/nti/{ntiId}/processes")
@RequiredArgsConstructor
@Slf4j
public class NtiProcessController {

    private final NtiProcessService ntiProcessService;

    @GetMapping
    public ResponseEntity<List<NtiProcessDto>> getProcesses(@PathVariable Long ntiId) {
        return ResponseEntity.ok(ntiProcessService.getProcessesByNtiId(ntiId));
    }

    @GetMapping("/{processId}")
    public ResponseEntity<NtiProcessDto> getProcess(
            @PathVariable Long ntiId,
            @PathVariable Long processId
    ) {
        return ResponseEntity.ok(ntiProcessService.getProcessDetail(ntiId, processId));
    }

    @PostMapping
    public ResponseEntity<Void> addProcess(
            @PathVariable Long ntiId,
            @RequestBody NtiProcessRequest request
    ) {
        ntiProcessService.addProcess(ntiId, request);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }
}

4. DTO 구조

Nti (상위)

public class NtiDetailDto {
    private Long id;
    private String title;
    private String classification;
    private LocalDateTime createdAt;
    private List<NtiProcessDto> processes; // 옵션: 포함 조회용
}

NtiProcess (하위)

public class NtiProcessDto {
    private Long id;
    private String status;
    private String handler;
    private String comment;
    private LocalDateTime updatedAt;
}

요청용 DTO

public class NtiProcessRequest {
    private String status;
    private String handler;
    private String comment;
}

5. 서비스 및 패키지 구조

com.example.nti
 ├── controller
 │    ├── NtiController.java
 │    └── NtiProcessController.java
 ├── service
 │    ├── NtiService.java
 │    └── NtiProcessService.java
 ├── dto
 │    ├── NtiListResponse.java
 │    ├── NtiDetailDto.java
 │    ├── NtiProcessDto.java
 │    └── NtiProcessRequest.java
 ├── repository
 │    ├── NtiRepository.java
 │    └── NtiProcessRepository.java
 └── entity
      ├── Nti.java
      └── NtiProcess.java

6. 데이터 모델 예시 (JPA)

@Entity
public class Nti {
    @Id @GeneratedValue
    private Long id;

    private String title;
    private String classification;

    @OneToMany(mappedBy = "nti", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<NtiProcess> processes = new ArrayList<>();
}
@Entity
public class NtiProcess {
    @Id @GeneratedValue
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "nti_id")
    private Nti nti;

    private String status;
    private String handler;
    private String comment;
    private LocalDateTime updatedAt;
}

7. 설계 요약

구분 설계 방식 URI 예시
상위 리소스 NTI (알림) /api/v1/nti/{ntiId}
하위 리소스 처리내역 /api/v1/nti/{ntiId}/processes
단건 처리내역 조회 ID 기반 /api/v1/nti/{ntiId}/processes/{processId}
DTO NtiProcessDto, NtiProcessRequest 속성 분리

8. 핵심 요약 문장

알림 하위의 처리내역은 Nti의 속성이 아니라 NtiProcess라는 독립된 하위 리소스(Sub-resource) 로 분리해야 하며, /api/v1/nti/{ntiId}/processes 형태로 접근하도록 설계하는 것이 RESTful하고 확장성에 유리합니다.


원하신다면 “처리내역이 단순 로그 형태인지, 상태 전이(예: 진행중→완료)인지” 알려주시면 그 흐름에 맞는 상태 기반 도메인 설계(state transition model) 까지 구체화해드릴 수 있습니다. 그 부분 포함해서 볼까요?