1## 1. 🏷️DaLabel (데이터 라벨링 플랫폼)

DaLabel은 AI 학습 데이터셋 구축을 위한 협업 플랫폼입니다. AI 모델 개발의 핵심은 잘 정제된 대량의 ‘라벨링된 데이터’이며, 이 프로젝트의 목표는 데이터 라벨링을 필요로 하는 ‘의뢰자’와 라벨링 작업을 수행하는 ‘작업자’를 연결하고, 전 과정을 효율적으로 관리할 수 있는 웹 기반 솔루션을 제공하는 것이었습니다.
프로젝트 상태
본 프로젝트는 교육 과정의 일환으로 개발되었으며, 현재는 서비스되고 있지 않습니다. 이 문서는 향후 업데이트 계획이 없는 기술 아카이브 및 회고 자료입니다.
2. 🔗Links
- GitHub Repository: https://github.com/ericnakor/dalabel
- 프로젝트 발표 자료: Google Slides Link
3. 👨👩👧👦 HiddenLayer 팀 (Team & Roles)
본 프로젝트는 5인의 팀으로 구성되었으며, 각 팀원의 담당 역할은 다음과 같습니다.
| 이름 | 역할 | 주요 담당 기능 |
|---|---|---|
| 신용대 | 팀장 / 백엔드 | 라벨링 의뢰 유저(Requestor) 시스템 구현, 프로젝트 총괄 관리 |
| 이미주 | 프론트엔드 | 게시글 댓글/대댓글 기능, 다중 이미지 업로드 게시글 작성 기능 구현 |
| 나준호 | 백엔드 / 프론트엔드 | 커뮤니티 게시판, 라벨링 데이터 신고 기능 구현 |
| 박아멘 | 백엔드 | 데이터 분배 시스템, 유저 권한 관리, 라벨링 작업자(Worker) 시스템 구축 |
| 유성훈 | 백엔드 / AI | 정산 서버 구축, 라벨링 신뢰도 평가 AI 모델 구축 (FastAPI, Keras) |
| 공통 | - | 데이터베이스(ERD) 설계, 화면 및 기능 설계, 로그인/회원가입 등 공통 모듈 |
4. 🏗️ 아키텍처 및 설계
4-1. 시스템 아키텍처 (3-Tier MVC)
본 프로젝트는 레거시 Spring MVC(3.1.1) 와 JSP 템플릿 엔진을 기반으로 하는 전통적인 3-Tier, N-Layered 아키텍처를 따릅니다.
graph RL subgraph "User's Browser" U["User<br>(JSP View in Browser)"] end subgraph "Web Application Server (Tomcat)" subgraph "Presentation Layer (servlet-context.xml)" C["<b>@Controller</b><br>(MemberController, BoardController...)"] I["<b>Interceptor</b><br>(AuthLoginInterceptor)"] JSP["<b>ViewResolver</b><br>(Renders JSP to HTML)"] end subgraph "Business Logic Layer (root-context.xml)" S["<b>@Service / DAO</b><br>(MemberDAO, BoardDAO...)"] end subgraph "Data Access Layer (root-context.xml)" D["<b>@Repository (MyBatis)</b><br>(MyBatis SqlSession)"] M["<b>MyBatis Mapper</b><br>(*.xml)"] end end subgraph "Database Server" DB[("<b>OracleDB</b>")] end U -- HTTP Request --> I I -- Auth Success --> C C -- Logic Request --> S S -- DB Request --> D D -- SQL Call --> M M -- SQL Query --> DB DB -- Result --> M M -- Result --> D D -- Result --> S S -- Model --> C C -- View Name & Model --> JSP JSP -- Rendered HTML --> U
-
Presentation Layer: 사용자의 HTTP 요청을 받아
@Controller가 처리하고, 뷰(JSP)를 서버 사이드에서 렌더링하여 완전한 HTML 페이지로 응답합니다. -
Business Logic Layer:
@Service및DAO로 구성되어 비즈니스 로직(e.g., 데이터 분배)을 수행합니다. -
Data Access Layer:
MyBatis와Mapper.xml을 통해OracleDB와 통신하며 SQL 쿼리를 실행합니다.
4-2. 데이터베이스 스키마 (ERD)
erDiagram DL_MEMBER { string USER_ID PK int USER_TYPE "역할 (1:작업자, 2:의뢰자, 99:관리자)" string USER_NAME } DL_PROJECT { int PROJECT_NO PK string REQUESTOR_ID FK "의뢰자 ID" string TITLE int BUNDLE_NO FK "사용할 데이터 번들" } DL_DATA_BUNDLE { int BUNDLE_NO PK string UPLOADER_ID FK "업로더 ID (의뢰자)" string FILENAME } DL_DATA { string DATA_NO PK int BUNDLE_NO FK string FILE_PATH } DL_LABELING { int LABELING_NO PK string DATA_NO FK "라벨링 대상 데이터" string WORKER_ID FK "작업자 ID" string LABEL_VALUE "라벨링 결과값" int LABEL_STATUS "0:작업중, 1:제출, 2:승인, 3:반려" } DL_BOARD { int BOARD_NO PK string WRITER_ID FK "작성자 ID" string TITLE } DL_BOARD_COMMENT { int COMMENT_NO PK int BOARD_NO FK string WRITER_ID FK int COMMENT_REF FK "대댓글 (Self-ref)" } DL_REPORT { int REPORT_NO PK string REPORTER_ID FK "신고자 ID" string REPORT_TYPE "신고 대상 타입" string TARGET_PK "신고 대상 PK" } DL_MEMBER ||--o{ DL_PROJECT : "의뢰 (1:N)" DL_MEMBER ||--o{ DL_DATA_BUNDLE : "업로드 (1:N)" DL_MEMBER ||--o{ DL_LABELING : "작업 (1:N)" DL_MEMBER ||--o{ DL_BOARD : "작성 (1:N)" DL_MEMBER ||--o{ DL_BOARD_COMMENT : "작성 (1:N)" DL_MEMBER ||--o{ DL_REPORT : "신고 (1:N)" DL_PROJECT }o--|| DL_DATA_BUNDLE : "사용 (1:1)" DL_DATA_BUNDLE ||--o{ DL_DATA : "포함 (1:N)" DL_DATA ||--o{ DL_LABELING : "수행 (1:N)" DL_BOARD ||--o{ DL_BOARD_COMMENT : "포함 (1:N)" DL_BOARD_COMMENT }o--o{ DL_BOARD_COMMENT : "답글 (1:N)"
5. 🛠️ 핵심 기술 스택 (Tech Stack)
| 구분 | Backend (Main) | Backend (AI/Settlement) | Frontend | Database |
|---|---|---|---|---|
| Language | Java 1.8 | Python | JavaScript (ES5), CSS | SQL |
| Framework | Spring MVC 3.1.1 | FastAPI, Keras | jQuery, AJAX | - |
| Persistence | MyBatis 3 | - | - | OracleDB 11g |
| Server/Build | Apache Tomcat | - | - | - |
| Tools | Git, GitHub, Eclipse | VS Code | - | - |
6. 💡 주요 기능 및 기술적 포인트
6-1. 🛡️ 인증/인가 및 접근 제어
(담당: 박아멘, 공통)
‘의뢰자(Requestor)’, ‘작업자(Worker)’, ‘관리자(Admin)‘라는 3가지 사용자 유형에 따라 접근 가능한 페이지를 제어해야 했습니다.
-
Interceptor 활용: Spring의
HandlerInterceptorAdapter를 상속받은AuthLoginInterceptor를 구현했습니다. -
역할 기반 접근 제어(RBAC):
preHandle메소드에서HttpSession의user_type을 확인하여, 요청 URI에 대한 접근 권한이 있는지 검사했습니다. (e.g.,user_type이 ‘작업자’일 경우/manage_labeling.go접근 차단) -
중복 로그인 방지: 세션에 로그인 정보를 저장하여 중복 로그인을 제어했습니다.
flowchart LR A["User Request (/manage/project)"] --> I["AuthLoginInterceptor.preHandle()"] I --> C1{"Is Logged In? (Session exists?)"} C1 -- No --> R1["Redirect to /login.go"] C1 -- Yes --> C2{"Has Correct Role? (user_type == 2)"} C2 -- No --> R2["Redirect to Home (/)"] C2 -- Yes --> GC["return true (pass to Controller)"] GC --> CTRL["Controller executes (manage_labeling.jsp)"]
6-2. 🗂️ 데이터 관리 (ZIP 비동기 처리)
(담당: 신용대)
의뢰자는 수백 개의 이미지가 담긴 .zip 파일을 업로드해야 했습니다. HTTP 요청 시간 내에 이 파일들의 압축 해제 및 DB 삽입을 완료하는 것은 불가능했습니다.
-
비동기 스레드 처리:
ManageLabelingController는 파일 업로드(MultipartFile) 요청을 받으면, 파일을 서버의 임시 저장소에 저장한 뒤 즉시 사용자에게 “업로드 접수” 응답을 반환했습니다. -
백그라운드 작업: 이후
UnZipperThread.java라는 별도의 스레드를 생성하여, 실제.zip파일 압축 해제, 파일 이동,DL_DATA테이블에 메타데이터 삽입 작업을 백그라운드에서 수행하도록 위임했습니다.
sequenceDiagram participant U as User (Requestor) participant C as Controller participant FS as Server (File System) participant T as UnZipperThread participant DB as OracleDB U->>C: POST /upload (with .zip file) C->>FS: 1. Save .zip to temp storage C-->>U: 2. Return HTTP 200 (Upload 접수) C->>T: 3. Start new Thread(zipFile) loop Asynchronous Processing T->>FS: 4. Read .zip file T->>FS: 5. Unzip individual files T->>DB: 6. Insert file metadata (DL_DATA) end T-->>C: (Thread completes)
6-3. 👨💻 라벨링 수행 및 동시성 제어
(담당: 박아멘)
여러 작업자가 동시에 동일한 프로젝트에 접근할 때, 데이터가 중복으로 분배되거나 작업 중인 데이터가 다른 사용자에게 노출되는 문제를 방지해야 했습니다.
-
데이터 분배 로직: 작업자가 ‘라벨링 시작’을 누르면,
DoLabelingController는LABELING_DONE테이블을 참조하여 해당 사용자가 아직 작업하지 않았고, 다른 사용자가 현재 작업 중(STATUS=0)이지 않은 데이터를 1건 조회하여 분배했습니다. -
작업 상태 관리: 데이터가 분배되면
LABELING_DONE테이블에STATUS를 0(작업중)으로 즉시 업데이트하여 다른 작업자에게 분배되지 않도록 Lock을 걸었습니다. -
시연 확인: (슬라이드 시연) 두 개의 다른 브라우저에서 동일 계정으로 동시 접속 시, 각기 다른 이미지가 노출되는 것을 확인했습니다.
6-4. 🗣️ 커뮤니티 및 신고 기능 (AJAX)
(담당: 나준호, 이미주)
-
커뮤니티 (CRUD):
BoardController를 통해 게시글 CRUD 기능을 구현했습니다. -
AJAX 댓글/대댓글: 페이지 새로고침 없이 동적으로 댓글과 대댓글을 처리하기 위해
jQuery와AJAX를 사용했습니다.BoardMapper.xml에서 댓글(COMMENT_REF가 null)과 대댓글(COMMENT_REF가 상위 댓글 ID)을 구분하여 등록 및 조회했습니다. -
데이터 신고: 라벨링 작업 중 부적합한 데이터 발견 시, 작업자가 ‘신고’ 버튼을 누르면
ReportController가 이를DL_REPORT테이블에 저장합니다. 의뢰자는 관리 페이지에서 신고 내역을 확인하고 해당 데이터를 비활성화할 수 있습니다.
6-5. 🤖 AI 정산 서버 (FastAPI)
(담당: 유성훈)
작업자에 대한 신뢰도 평가 및 정산을 위해 별도의 AI 서버를 구축했습니다.
-
기술 스택: 메인 Spring 서버와 별개로, Python 기반의
FastAPI로 API 서버를 구축하고Keras를 활용해 신뢰도 평가 모델을 학습시켰습니다. -
신뢰도 평가: (슬라이드 시연) 의뢰자가 ‘정산’ 버튼을 누르면, 작업 완료된 데이터를 AI 서버로 전송합니다. AI 서버는 작업자의 라벨링 결과와 실제 정답을 비교하여 작업자별 신뢰도(정확도)를 평가합니다.
-
결과 반환: 정산 결과(작업 건수, 신뢰도, 총 보상)는 통계 페이지에 표시되며
CSV파일로 다운로드할 수 있습니다.
7. 🎯 프로젝트 회고 및 교훈
본 프로젝트는 성공적으로 완료되었으나, 팀 자체 평가에서 논의된 몇 가지 아쉬운 점과 교훈이 있습니다.
-
[설계] 초기 설계의 중요성 (아쉬웠던 점 - 나준호, 신용대):
프로젝트 사전 설계가 미흡하여 개발 중 DB 스키마와 기능 구조가 자주 변경되었습니다. 이로 인해 불필요한 재작업이 발생했으며, 개발 착수 전 명확한 ERD와 API 명세를 확정하는 것이 전체 개발 효율성을 높인다는 교훈을 얻었습니다.
-
[보안] 데이터 접근 취약점 (아쉬웠던 점 - 박아멘):
현재 구조는 DL_DATA 테이블의 파일 경로가 외부에 노출될 경우, 인증되지 않은 사용자가 원본 데이터에 직접 접근할 수 있는 잠재적 보안 취약점(IDOR)이 존재했습니다.
- 개선 방향: 실제 파일 경로를 숨기고, 별도의
DataController를 두어 사용자의 작업 참여 권한을 확인한 뒤 파일 스트림(Stream)을 응답으로 전송하는 방식으로 개선해야 합니다.
- 개선 방향: 실제 파일 경로를 숨기고, 별도의
-
[기술 스택] DB 호환성 문제 (아쉬웠던 점 - 유성훈):
초기에는 정산 서버를 Django로 구축하려 했으나, OracleDB 11g 버전과 호환성 이슈가 발생했습니다. Django를 다운그레이드하는 대신 FastAPI로 신속하게 기술 스택을 변경하여 문제를 해결하며 대처 능력을 길렀습니다.
-
[소감] 협업과 소통 (공통):
팀원 모두가 ‘개발’ 자체보다 ‘협업’의 중요성을 가장 큰 배움으로 꼽았습니다. Git 충돌 해결, 코드 스타일 통일, 명확한 의사소통이 없었다면 레거시 Spring 환경에서의 복잡한 프로젝트를 완성하기 어려웠을 것입니다.