이슈 배경
Chrome/Edge 익스텐션에서 사용자의 브라우저 북마크를 Linkiving으로 가져오는 기능을 제공하려면 한 번에 수십~수백 개의 링크를 저장할 수 있어야 합니다.
현재는 POST /v1/links로 링크를 한 건씩 저장하므로 클라이언트가 가져올 링크 수만큼 요청을 보내야 합니다. 이 방식은 대량 가져오기 시 다음 문제가 있습니다.
다수의 HTTP 요청과 중복 조회가 동시에 발생함
일부 요청만 성공했을 때 클라이언트가 결과를 취합하기 어려움
메타데이터 수집 및 요약 생성 후속 작업이 한꺼번에 몰릴 수 있음
재시도 시 이미 저장된 항목과 미저장 항목을 구분하기 어려움
브라우저 북마크 가져오기뿐 아니라 향후 파일 가져오기 등에서도 재사용할 수 있는 링크 일괄 저장 API를 추가합니다.
이슈 내용
API
링크 목록을 한 요청으로 전달받는 일괄 저장 엔드포인트를 추가합니다.
예시: POST /v1/links/imports 또는 POST /v1/links/bulk
요청 항목은 최소 url, title을 포함하고 기존 링크 생성에서 지원하는 선택 필드의 재사용 여부를 검토합니다.
요청 가능한 최대 항목 수와 요청 크기 제한을 정의합니다.
인증된 사용자 본인의 링크로만 저장합니다.
요청 예시:
{
"source" : " BROWSER_BOOKMARK" ,
"items" : [
{
"clientReferenceId" : " bookmark-1" ,
"url" : " https://react.dev" ,
"title" : " React"
}
]
}
정규화 및 중복 처리
모든 URL에 단건 저장과 동일한 서버 공통 정규화·검증 규칙을 적용합니다.
요청 내부의 중복 URL과 사용자가 이미 저장한 URL을 구분해 처리합니다.
중복 항목은 새 링크로 저장하지 않습니다.
클라이언트의 사전 중복 검사는 보조 수단으로만 사용하고 서버가 최종 정합성을 보장합니다.
관련 URL 정규화 작업인 #298의 규칙 및 구현을 재사용합니다.
부분 성공 및 응답
한 항목의 중복 또는 검증 실패 때문에 전체 요청이 실패하지 않도록 부분 성공을 지원합니다.
전체 개수와 상태별 개수를 응답합니다.
각 입력 항목을 식별할 수 있도록 clientReferenceId 또는 입력 순서를 결과에 포함합니다.
개별 결과에서 최소 CREATED, DUPLICATE, INVALID, FAILED를 구분하고, 생성된 링크 ID 또는 오류 코드를 제공합니다.
응답 예시:
{
"success" : true ,
"data" : {
"totalCount" : 3 ,
"createdCount" : 1 ,
"duplicateCount" : 1 ,
"invalidCount" : 1 ,
"failedCount" : 0 ,
"results" : [
{
"clientReferenceId" : " bookmark-1" ,
"status" : " CREATED" ,
"linkId" : 123
}
]
}
}
후속 작업 부하 제어
HTTP 요청 안에서 각 URL의 메타데이터를 동기적으로 수집하지 않습니다.
링크 저장 후 실행되는 메타데이터·요약·RAG 동기화 작업이 대량 요청에서도 유실되지 않도록 기존 이벤트/비동기 처리 흐름을 점검합니다.
일괄 요청이 비동기 executor와 외부 연동에 순간적인 과부하를 만들지 않도록 큐잉 또는 제한된 동시성 정책을 적용합니다.
처리 시간이 HTTP 타임아웃 범위를 넘을 수 있다면 import job을 생성하고 상태를 조회하는 비동기 방식도 검토합니다.
테스트 범위
여러 유효 링크의 일괄 저장
요청 내부 중복 처리
기존 저장 링크와의 중복 처리
유효 링크와 잘못된 링크가 섞인 요청의 부분 성공
사용자별 링크 중복 범위 검증
최대 항목 수 및 요청 크기 제한
인증되지 않은 요청 거부
후속 비동기 작업 발행 및 과부하 방지 정책 검증
단건 저장과 일괄 저장의 URL 정규화 결과 일치
완료 조건
참고 자료
URL 정규화 및 검증: 링크 저장 URL 정규화 및 검증 적용 #298
익스텐션 연동 이슈: Chrome/Edge 브라우저 북마크 일괄 가져오기 linkiving-extension#5
관련 코드
src/main/java/com/sofa/linkiving/domain/link/controller/LinkController.java
src/main/java/com/sofa/linkiving/domain/link/controller/LinkApi.java
src/main/java/com/sofa/linkiving/domain/link/facade/LinkFacade.java
src/main/java/com/sofa/linkiving/domain/link/service/LinkCommandService.java
src/main/java/com/sofa/linkiving/domain/link/repository/LinkRepository.java
이슈 배경
Chrome/Edge 익스텐션에서 사용자의 브라우저 북마크를 Linkiving으로 가져오는 기능을 제공하려면 한 번에 수십~수백 개의 링크를 저장할 수 있어야 합니다.
현재는
POST /v1/links로 링크를 한 건씩 저장하므로 클라이언트가 가져올 링크 수만큼 요청을 보내야 합니다. 이 방식은 대량 가져오기 시 다음 문제가 있습니다.브라우저 북마크 가져오기뿐 아니라 향후 파일 가져오기 등에서도 재사용할 수 있는 링크 일괄 저장 API를 추가합니다.
이슈 내용
API
POST /v1/links/imports또는POST /v1/links/bulkurl,title을 포함하고 기존 링크 생성에서 지원하는 선택 필드의 재사용 여부를 검토합니다.요청 예시:
{ "source": "BROWSER_BOOKMARK", "items": [ { "clientReferenceId": "bookmark-1", "url": "https://react.dev", "title": "React" } ] }정규화 및 중복 처리
부분 성공 및 응답
clientReferenceId또는 입력 순서를 결과에 포함합니다.CREATED,DUPLICATE,INVALID,FAILED를 구분하고, 생성된 링크 ID 또는 오류 코드를 제공합니다.응답 예시:
{ "success": true, "data": { "totalCount": 3, "createdCount": 1, "duplicateCount": 1, "invalidCount": 1, "failedCount": 0, "results": [ { "clientReferenceId": "bookmark-1", "status": "CREATED", "linkId": 123 } ] } }후속 작업 부하 제어
테스트 범위
완료 조건
참고 자료
src/main/java/com/sofa/linkiving/domain/link/controller/LinkController.javasrc/main/java/com/sofa/linkiving/domain/link/controller/LinkApi.javasrc/main/java/com/sofa/linkiving/domain/link/facade/LinkFacade.javasrc/main/java/com/sofa/linkiving/domain/link/service/LinkCommandService.javasrc/main/java/com/sofa/linkiving/domain/link/repository/LinkRepository.java