[API] 에이전트 엠디 수정
This commit is contained in:
@@ -1,37 +1,16 @@
|
|||||||
# AGENTS.md - alist API 프로젝트
|
# AGENTS.md
|
||||||
|
|
||||||
## Claude 작업 규칙 (중요!)
|
## 목적
|
||||||
|
- 이 저장소에서 작업하는 사람과 코딩 에이전트가 같은 기준으로 개발하도록 돕는 운영 가이드다.
|
||||||
### 코드 수정 시 반드시 따를 것
|
- 불필요한 구조 변경보다 작은 단위의 안전한 수정, 빠른 검증, 명확한 보고를 우선한다.
|
||||||
1. **절대로 바로 파일을 수정하지 말 것**
|
|
||||||
2. **먼저 수정 방향과 계획을 설명**
|
|
||||||
3. **긴 소스 코드를 보여주기 전에 먼저 물어보기**
|
|
||||||
- "코드 보여드릴까요?" 또는 "직접 수정하시겠어요?"
|
|
||||||
- 사용자가 원하면 코드 보여주기 (사용자가 직접 수정할 수도 있도록)
|
|
||||||
4. **파일 작성/수정은 사용자가 요청할 때만**
|
|
||||||
|
|
||||||
### 작업 순서 예시
|
|
||||||
```
|
|
||||||
1. "CORS 설정을 yml로 분리하겠습니다."
|
|
||||||
2. "수정 내용:"
|
|
||||||
- CorsProperties.java 생성 필요
|
|
||||||
- CorsConfig.java 수정 필요
|
|
||||||
- application-local.yaml 수정 필요
|
|
||||||
3. "코드 보여드릴까요? 아니면 직접 수정하시겠어요?"
|
|
||||||
4. (사용자가 "보여줘"라고 하면) 코드 보여주기
|
|
||||||
5. (사용자가 "작성해줘"라고 하면) 파일 수정 진행
|
|
||||||
```
|
|
||||||
|
|
||||||
### 주의사항
|
|
||||||
- **짧은 설명(수정 위치, 수정 방향)은 바로 보여줘도 됨**
|
|
||||||
- **전체 메서드/클래스 같은 긴 코드는 반드시 물어본 후 보여주기**
|
|
||||||
- **화면이 너무 길어지는 것 방지**
|
|
||||||
|
|
||||||
## 프로젝트 개요
|
## 프로젝트 개요
|
||||||
- **프로젝트명**: alist API
|
- 프로젝트 유형: Gradle 기반 Spring Boot 애플리케이션
|
||||||
- **그룹**: com.alist
|
- Java 버전: 21
|
||||||
- **포트**: 8106
|
- Spring Boot 버전: 3.5.10
|
||||||
- **빌드 결과물**: `api.jar`
|
- 기본 애플리케이션 이름: `api`
|
||||||
|
- 기본 포트: `8106`
|
||||||
|
- 실행 진입점: `src/main/java/com/alist/api/ApiApplication.java`
|
||||||
|
|
||||||
## 기술 스택
|
## 기술 스택
|
||||||
- **Java**: 21
|
- **Java**: 21
|
||||||
@@ -40,24 +19,120 @@
|
|||||||
- **DB**: MariaDB
|
- **DB**: MariaDB
|
||||||
- **ORM**: MyBatis (mapper XML: `classpath:mapper/**/*.xml`)
|
- **ORM**: MyBatis (mapper XML: `classpath:mapper/**/*.xml`)
|
||||||
- **인증**: JWT (jjwt 0.11.5) + Spring Security
|
- **인증**: JWT (jjwt 0.11.5) + Spring Security
|
||||||
- **API 문서**: Swagger (springdoc-openapi 2.6.0)
|
- **API 문서**: Swagger (springdoc-openapi 2.8.0)
|
||||||
- **기타**: Lombok, Validation, Actuator, log4jdbc
|
- **기타**: Lombok, Validation, Actuator, log4jdbc
|
||||||
|
|
||||||
## 패키지 구조
|
## 디렉터리 가이드
|
||||||
```
|
- `src/main/java/com/alist/api`: 애플리케이션 시작점과 업무 코드를 둔다.
|
||||||
com.alist.api
|
- `src/main/java/com/alist/api/modules`: 기능별 모듈 패키지를 둔다.
|
||||||
├── common
|
- `src/main/resources`: 설정 파일과 로깅 설정을 관리한다.
|
||||||
│ ├── response/ # ApiResponse, ApiResponseCode
|
- `src/test/java`: 테스트 코드를 둔다.
|
||||||
│ └── utils/ # 공통 유틸리티
|
- `deploy`: 배포 관련 리소스가 있으면 이 경로를 우선 확인한다.
|
||||||
├── config
|
|
||||||
│ ├── jwt/ # JWT 필터, 핸들러, Provider
|
## 현재 확인된 구조
|
||||||
│ ├── exception/ # GlobalExceptionHandler
|
- 현재 기준 메인 흐름은 `Controller -> Form -> Dto -> Service -> Mapper(XML) -> vo -> Service -> Controller` 순서로 연결된다.
|
||||||
│ ├── properties/ # JwtProperties 등
|
- API 에서 request 받을 때 POST 는 주로 JSON을 사용한다. Controller 는 `form` 객체로 요청을 받은 뒤 DTO 로 변환해서 Service 에 전달한다.
|
||||||
│ ├── SecurityConfig.java
|
- MyBatis는 인터페이스와 XML을 함께 사용한다.
|
||||||
│ └── OpenApiConfig.java
|
- Mapper 인터페이스는 `src/main/java/.../mapper`, SQL XML은 `src/main/resources/mapper/...` 경로를 짝으로 맞춘다.
|
||||||
└── modules
|
- 공통 응답은 `common/response`, 보안은 `config/security, jwt`, 전역 예외 처리는 `config/exception` 아래에 둔다.
|
||||||
└── {도메인}/ # Controller, Service, Mapper, DTO
|
- 모듈 패키지는 현재 `auth`, `file`, `main`, `testUser` 형태로 구성되어 있고, 필요한 모듈만 `dto`, `form`, `mapper`, `service`, `vo`를 둔다.
|
||||||
```
|
|
||||||
|
## 파일 생성 규칙
|
||||||
|
- 새 기능은 가능하면 `modules/{도메인명}Controller` 단위로 패키지를 만들고 그 아래에 `service`, `mapper`, `dto`, `vo`를 필요한 만큼만 추가한다.
|
||||||
|
- 요청 검증이나 JSON 바인딩이 필요하면 `form` 패키지를 함께 만든다.
|
||||||
|
- 클래스명은 역할이 바로 드러나게 `도메인명 + 역할` 형식을 유지한다. 예: `ApiService`, `ApiMapper`, `ApiVo`
|
||||||
|
- Mapper 인터페이스를 추가하면 같은 이름의 XML을 `src/main/resources/mapper/{도메인경로}` 아래 함께 만든다.
|
||||||
|
- 단순 예시 코드와 운영 코드는 섞지 말고 패키지로 분리한다.
|
||||||
|
- 설정성 클래스는 `config` 하위 역할별 패키지에 둔다. 예: `config.jwt`, `config.exception`, `config.properties`
|
||||||
|
|
||||||
|
## DTO/VO/Mapper 규칙
|
||||||
|
- `Dto`는 저장, 수정, 로그 적재처럼 내부 상태 변경이나 DB update/insert에 사용하는 값 객체로 본다.
|
||||||
|
- `Vo`는 조회 결과나 스케줄 실행 판단에 필요한 읽기 전용 성격의 값으로 본다.
|
||||||
|
- `Form`은 Controller 입력 검증과 요청 바인딩 전용으로 두고, `@Valid` 와 Jakarta Validation 어노테이션을 우선 사용한다.
|
||||||
|
- 현재 코드처럼 DTO/VO는 Lombok `@Getter`, 필요한 경우에만 `@Setter`를 사용한다.
|
||||||
|
- Form 안에는 DTO 변환 메서드를 둘 수 있다. 예: `testUserDto()`, `fileUploadDto()`
|
||||||
|
- DTO 안에 연관된 다른 DTO 변환이 꼭 필요할 때만 최소한의 보조 메서드를 둔다.
|
||||||
|
- 외부 응답에 노출되면 안 되는 내부 필드는 DTO 에 `@JsonIgnore`로 숨긴다.
|
||||||
|
- Mapper 메서드명은 SQL 동작이 드러나도록 `select`, `insert`, `update` 접두어를 사용한다.
|
||||||
|
- 삭제가 물리 삭제가 아니라 상태 변경이면 `delete` 대신 목적이 드러나는 `update...Canceled`, `update...DelYn` 같은 이름을 우선한다.
|
||||||
|
- Mapper XML `namespace`는 인터페이스의 전체 경로와 정확히 일치시킨다.
|
||||||
|
- XML의 `id`는 Mapper 메서드명과 동일하게 맞춘다.
|
||||||
|
- 조회 결과 타입은 `resultType`, 저장/수정 파라미터는 DTO/VO 필드명과 매핑되는 프로퍼티명을 그대로 사용한다.
|
||||||
|
- Mapper XML 안 SQL 블록 시작부 주석은 현재 코드처럼 `/*Mapper.method*/` 형식을 유지한다.
|
||||||
|
|
||||||
|
## 작업 원칙
|
||||||
|
- 기존 구조와 네이밍을 우선 존중한다.
|
||||||
|
- 한 번에 큰 리팩터링을 하지 말고, 요청 범위 안에서 필요한 만큼만 수정한다.
|
||||||
|
- 인코딩 문제가 보이는 문자열은 무심코 대량 수정하지 말고 원인과 영향 범위를 먼저 확인한다.
|
||||||
|
- 설정 파일 수정 시 `local`, `pjt`, 공통 설정 간 차이를 함께 확인한다.
|
||||||
|
- 스케줄러 코드는 실행 주기, 중복 실행 가능성, 로그량을 반드시 점검한다.
|
||||||
|
- 인증 방식이 섞여 있으므로 세션 기반 처리와 JWT `SecurityContext` 사용 위치를 먼저 구분하고 수정한다.
|
||||||
|
- 파일 경로를 다루는 기능은 상대경로 탈출, 루트 이탈 방지 같은 검증을 같이 본다.
|
||||||
|
|
||||||
|
## 코드 스타일
|
||||||
|
- Java 코드는 현재 프로젝트 스타일에 맞춰 탭/들여쓰기와 import 정렬을 유지한다.
|
||||||
|
- Lombok은 반복 보일러플레이트 제거에만 절제해서 사용한다.
|
||||||
|
- 로그는 `Slf4j`를 사용하고 반복문 내부 대량 출력은 지양한다.
|
||||||
|
- 새로운 기능은 가능하면 역할이 드러나는 패키지로 분리한다.
|
||||||
|
- 생성자 주입을 기본으로 하고 필드 주입은 추가하지 않는다.
|
||||||
|
- Service 에서 DB 상태를 바꾸는 메서드는 필요한 범위에서 `@Transactional`을 사용하고, 조회 전용은 `readOnly = true`를 우선 검토한다.
|
||||||
|
- 문자열 입력값은 현재 코드처럼 필요한 지점에서 `trim()` 처리하고, null 가능성 여부를 먼저 확인한다.
|
||||||
|
|
||||||
|
## Controller/Service 규칙
|
||||||
|
- Controller 는 요청/응답 조립과 인증 주체 확인에 집중하고, DB 처리나 복잡한 계산은 Service 로 넘긴다.
|
||||||
|
- Controller 응답은 `ResponseEntity<ApiResponse<T>>` 를 기본으로 사용한다. 파일 다운로드처럼 바이너리 응답이 필요한 경우만 예외로 둔다.
|
||||||
|
- Controller 에서는 `@RequestBody`, `@PathVariable`, `@RequestHeader`, `@CookieValue` 를 명시적으로 선언해 요청 출처를 드러낸다.
|
||||||
|
- Service 는 resultCode 를 DTO 에 담아 반환하는 패턴이 일부 있으므로, 기존 모듈 흐름에 맞춰 유지한다.
|
||||||
|
- 인증 사용자 확인은 모듈 구현에 따라 `HttpSession` 또는 `SecurityContextHolder` 를 사용하므로 기존 방식을 먼저 맞춘다.
|
||||||
|
|
||||||
|
## 예외/응답 규칙
|
||||||
|
- 공통 예외 응답은 `GlobalExceptionHandler` 에서 처리하므로 Controller 별 개별 예외 처리를 중복해서 늘리지 않는다.
|
||||||
|
- `@Valid`, 바인딩 실패, JSON 파싱 실패, 타입 오류는 `CODE_4001` 로 통일하고 필드 오류가 있으면 `Map<String, String>` 형태로 반환한다.
|
||||||
|
- 단순 성공/실패 문자열을 직접 내려주기보다 `ApiResponse.entity(...)` 와 `ApiResponseCode` 조합을 우선 사용한다.
|
||||||
|
- 404/405/500 같은 공통 HTTP 오류도 가능하면 `ApiResponseCode` enum 으로 맞춘다.
|
||||||
|
|
||||||
|
## 설정 규칙
|
||||||
|
- 공통 설정은 `application.yaml`, 환경별 차이는 `application-local.yaml`, `application-pjt.yaml` 에 둔다.
|
||||||
|
- `pjt` 프로파일은 DB/Redis/JWT/Swagger 계정을 환경변수 치환으로 받으므로 새 민감정보는 하드코딩하지 않는다.
|
||||||
|
- 로깅 설정은 프로파일별 `logback-local.xml`, `logback-pjt.xml` 을 사용하므로 로그 정책 변경 시 함께 본다.
|
||||||
|
- MyBatis 설정은 `application.yaml` 기준으로 관리하므로 mapper location, alias package, camel case 옵션을 중복 정의하지 않는다.
|
||||||
|
- Redis 는 세션 저장소와 업로드 상태 캐시 용도를 함께 가지므로 키 prefix 충돌 여부를 확인한다.
|
||||||
|
|
||||||
|
## 실행 및 검증
|
||||||
|
- 로컬 실행: `./gradlew bootRun`
|
||||||
|
- 테스트 실행: `./gradlew test`
|
||||||
|
- jar 생성: `./gradlew bootJar`
|
||||||
|
- Windows 명령: `.\gradlew.bat bootRun`, `.\gradlew.bat test`, `.\gradlew.bat bootJar`
|
||||||
|
- 현재 테스트 코드는 최소 수준이므로 기능 수정 시 단위 테스트 또는 최소 통합 검증 범위를 직접 보강하는 쪽을 우선한다.
|
||||||
|
|
||||||
|
## 변경 시 체크리스트
|
||||||
|
- 변경한 코드와 직접 관련된 파일만 수정했는지 확인한다.
|
||||||
|
- 새 API, 스케줄러, 설정 추가 시 관련 설정 파일과 테스트를 함께 검토한다.
|
||||||
|
- 로그 레벨과 로그량이 운영 환경에서 감당 가능한지 확인한다.
|
||||||
|
- 기동 실패 가능성이 있는 설정 변경은 실행 또는 테스트로 검증한다.
|
||||||
|
- Mapper 인터페이스 추가/변경 시 XML namespace, id, parameter/result 매핑이 같이 맞는지 확인한다.
|
||||||
|
- 공개 경로나 권한 정책을 바꿨다면 SecurityConfig 와 Swagger 노출 범위를 같이 확인한다.
|
||||||
|
- 파일 업로드/다운로드 기능 수정 시 DB 상태, Redis 상태, 실제 파일 시스템 경로가 같이 맞는지 확인한다.
|
||||||
|
|
||||||
|
## 에이전트 응답 원칙
|
||||||
|
- 무엇을 바꿨는지보다 왜 그렇게 바꿨는지를 짧고 분명하게 설명한다.
|
||||||
|
- 파일 수정 후 가능하면 테스트 또는 최소 실행 검증 결과를 함께 남긴다.
|
||||||
|
- 검증하지 못한 내용은 추정으로 말하지 않고 미실행 사유를 적는다.
|
||||||
|
- 요청 범위를 벗어나는 개선점은 강제로 반영하지 말고 제안으로 분리한다.
|
||||||
|
|
||||||
|
## 사용자 선호 규칙
|
||||||
|
- 소스코드 변경이 필요한 요청에서는 바로 구현하지 말고 먼저 다음 중 무엇을 원하는지 확인한다.
|
||||||
|
- `코드로 보여주기`: 사용자가 직접 프로젝트에 반영할 수 있도록 예시 코드나 패치를 제공한다.
|
||||||
|
- `직접 작성하기`: 에이전트가 저장소에 직접 수정한다.
|
||||||
|
- 사용자는 코드 흐름을 먼저 파악하고 코드 컨벤션에 맞게 직접 반영하는 방식을 선호하므로, 선택이 명시되지 않았다면 기본적으로 `코드로 보여주기`를 우선 제안한다.
|
||||||
|
- 이 규칙은 이후 작업에서도 반복 확인 대상이며, 에이전트는 이를 임의로 생략하지 않는다.
|
||||||
|
|
||||||
|
## 현재 코드베이스에서 특히 주의할 점
|
||||||
|
- `README.md`는 아직 템플릿 상태이므로 실제 동작 방식은 코드와 설정 파일을 기준으로 판단한다.
|
||||||
|
- 예시 스케줄러 코드에는 깨진 문자열과 과도한 반복 로그가 보일 수 있으니 관련 수정 시 인코딩과 로그 정책을 함께 점검한다.
|
||||||
|
- 테스트 코드가 충분하지 않을 수 있으므로 기능 변경 시 필요한 테스트를 보강한다.
|
||||||
|
- 일부 Java 소스와 주석, Swagger 설명에 인코딩이 깨진 문자열이 있으므로 표시 문자열 수정은 영향 범위를 보고 묶어서 처리한다.
|
||||||
|
- `application-local.yaml` 은 로컬 실행값이 직접 들어가 있으므로 공유하거나 커밋할 때 민감정보 노출 여부를 한 번 더 확인한다.
|
||||||
|
|
||||||
## 프로파일
|
## 프로파일
|
||||||
| 프로파일 | 설명 |
|
| 프로파일 | 설명 |
|
||||||
@@ -66,9 +141,11 @@ com.alist.api
|
|||||||
| `pjt` | 프로젝트(개발) 환경 |
|
| `pjt` | 프로젝트(개발) 환경 |
|
||||||
|
|
||||||
## 보안 구조
|
## 보안 구조
|
||||||
- **Swagger**: `/v3/api-docs/**`, `/swagger-ui/**` → HTTP Basic 인증 (InMemory)
|
- Swagger: `/v3/api-docs/**`, `/swagger-ui/**` → HTTP Basic 인증 (InMemory)
|
||||||
- **API**: JWT Bearer 토큰 인증 (Stateless)
|
- API: JWT Bearer 토큰 인증 (Stateless)
|
||||||
- **공개 경로**: `/`, `/actuator/health`, `/auth/**`, `/api/user/signup`
|
- 세션/쿠키: Redis Session 저장소 사용, 쿠키 속성은 프로파일별 `cookie.*` 설정으로 제어
|
||||||
|
- 공개 경로: `/`, `/actuator/health`, `/auth/**`, `/test/**`, `/files/tusHook`
|
||||||
|
- Swagger 인증과 API 인증은 `SecurityFilterChain` 을 분리해서 관리한다.
|
||||||
|
|
||||||
## 응답 코드 규칙
|
## 응답 코드 규칙
|
||||||
|
|
||||||
@@ -92,18 +169,6 @@ com.alist.api
|
|||||||
|
|
||||||
- `{0}` 자리에 대상명 삽입 (예: `CODE_2001` → "회원 정보 조회에 성공하였습니다.")
|
- `{0}` 자리에 대상명 삽입 (예: `CODE_2001` → "회원 정보 조회에 성공하였습니다.")
|
||||||
|
|
||||||
## 빌드 및 실행
|
|
||||||
```bash
|
|
||||||
# 빌드
|
|
||||||
./gradlew bootJar
|
|
||||||
|
|
||||||
# 로컬 실행
|
|
||||||
./gradlew bootRun --args='--spring.profiles.active=local'
|
|
||||||
|
|
||||||
# JAR 실행
|
|
||||||
java -jar build/libs/api.jar --spring.profiles.active=local
|
|
||||||
```
|
|
||||||
|
|
||||||
## Swagger 접속
|
## Swagger 접속
|
||||||
- URL: `http://localhost:8106/swagger-ui.html`
|
- URL: `http://localhost:8106/swagger-ui.html`
|
||||||
- 인증: `swagger.login.id` / `swagger.login.password` (환경별 yaml에 설정)
|
- 인증: `swagger.login.id` / `swagger.login.password` (환경별 yaml에 설정)
|
||||||
@@ -113,79 +178,15 @@ java -jar build/libs/api.jar --spring.profiles.active=local
|
|||||||
- 응답 코드는 `ApiResponseCode` enum 사용
|
- 응답 코드는 `ApiResponseCode` enum 사용
|
||||||
- MyBatis Mapper XML은 `src/main/resources/mapper/` 하위에 작성
|
- MyBatis Mapper XML은 `src/main/resources/mapper/` 하위에 작성
|
||||||
- 카멜케이스 자동 변환 활성화 (`map-underscore-to-camel-case: true`)
|
- 카멜케이스 자동 변환 활성화 (`map-underscore-to-camel-case: true`)
|
||||||
- 새 모듈 추가 시: `modules/{moduleName}/` 하위에 Controller, Service, Mapper, dto/, vo/ 구조로 생성
|
- 새 모듈 추가 시: `modules/{moduleName}/` 하위에 Controller, Service, Mapper, dto/, vo/, 필요 시 form/ 구조로 생성
|
||||||
- Mapper XML은 `resources/mapper/{moduleName}/` 에 위치
|
- Mapper XML은 `resources/mapper/{moduleName}/` 에 위치
|
||||||
|
- Form 에서 DTO 로 변환할 때는 검증과 trim, 기본값 치환까지 같이 처리하는 현재 패턴을 우선 따른다.
|
||||||
|
- 파일/인증처럼 상태값을 내려주는 DTO 는 `resultCode` 필드를 활용하는 기존 흐름을 해치지 않도록 한다.
|
||||||
|
|
||||||
## MyBatis 규칙
|
## MyBatis 규칙
|
||||||
- Mapper XML 위치: `src/main/resources/mapper/**/*.xml`
|
- Mapper XML 위치: `src/main/resources/mapper/**/*.xml`
|
||||||
- `map-underscore-to-camel-case: true` 설정 → DB 컬럼 `user_idx` → Java 필드 `userIdx` 자동 매핑
|
- `map-underscore-to-camel-case: true` 설정 → DB 컬럼 `user_idx` → Java 필드 `userIdx` 자동 매핑
|
||||||
- Mapper 인터페이스와 XML의 namespace, id 반드시 일치시킬 것
|
- Mapper 인터페이스와 XML의 namespace, id 반드시 일치시킬 것
|
||||||
- VO: DB 조회 결과 매핑용 / DTO: 서비스 레이어 간 데이터 전달용 / Form: 컨트롤러 입력 검증용
|
- VO: DB 조회 결과 매핑용 / DTO: 서비스 레이어 간 데이터 전달용 / Form: 컨트롤러 입력 검증용
|
||||||
|
- `useGeneratedKeys`, `keyProperty` 를 사용하는 insert 가 있으므로 신규 PK 생성 테이블은 현재 패턴을 먼저 확인한다.
|
||||||
## CI/CD
|
- 상태 집계나 이력성 데이터는 단건 update 외에 이벤트 로그 insert 가 같이 필요한지 확인한다.
|
||||||
- **Jenkins**: `Jenkinsfile.pjt`
|
|
||||||
- **Docker**: `Dockerfile`
|
|
||||||
- **배포 스크립트**: `deploy/` 디렉토리
|
|
||||||
|
|
||||||
## 개발 서버 (pjt)
|
|
||||||
|
|
||||||
### 도메인
|
|
||||||
- **API**: `api-alist.pjt.kr`
|
|
||||||
- **파일(업로드)**: `file-alist.pjt.kr`
|
|
||||||
- **Swagger**: `https://api-alist.pjt.kr/swagger-ui/index.html`
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
- **레지스트리**: `registry.pjt.kr`
|
|
||||||
- **이미지**: `registry.pjt.kr/alist/api`
|
|
||||||
- **컨테이너명**: `alist-api`
|
|
||||||
- **포트**: `127.0.0.1:8106->8106/tcp`
|
|
||||||
|
|
||||||
### 서버 디렉토리 (`/srv/project/alist/`)
|
|
||||||
```
|
|
||||||
/srv/project/alist/
|
|
||||||
├── compose/ # docker-compose 파일
|
|
||||||
├── data/ # 데이터
|
|
||||||
├── env/ # 환경변수 파일
|
|
||||||
├── logs/ # 로그
|
|
||||||
├── scripts/ # 배포/운영 스크립트
|
|
||||||
└── uploads/ # 업로드 파일 (file-alist.pjt.kr 루트)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Nginx
|
|
||||||
- `file-alist.pjt.kr` → `/srv/project/alist/uploads` (정적 파일 서빙)
|
|
||||||
- HTTP(80) → HTTPS(301) 리다이렉트
|
|
||||||
- SSL: Let's Encrypt
|
|
||||||
- 직접 접근 차단 (`allow 127.0.0.1; deny all;`)
|
|
||||||
|
|
||||||
### 파일 업로드
|
|
||||||
- 업로드 저장 경로: `/srv/project/alist/uploads/`
|
|
||||||
- 업로드 파일 접근 URL: `https://file-alist.pjt.kr/{파일경로}`
|
|
||||||
|
|
||||||
## TUS 업로드 운영 메모 (alist)
|
|
||||||
- `tusd`는 API 내 라이브러리가 아니라 별도 실행형 업로드 서버(Go 바이너리)로 운영
|
|
||||||
- 내부 바인딩: `127.0.0.1:8110`
|
|
||||||
- base path: `/tus/files/`
|
|
||||||
- 임시 업로드 경로: `/srv/project/alist/uploads/tmp`
|
|
||||||
- 실행 파일 경로: `/srv/project/alist/tusd/tusd`
|
|
||||||
|
|
||||||
### Nginx 라우팅
|
|
||||||
- `https://file-alist.pjt.kr/tus/files/` -> `http://127.0.0.1:8110/tus/files/` 프록시
|
|
||||||
- `location /tus/files/`는 `location /` 보다 구체적이므로 우선 매칭됨
|
|
||||||
- `location /`가 차단(`deny all`)이어도 `/tus/files/`는 별도 허용 가능
|
|
||||||
|
|
||||||
### systemd
|
|
||||||
- 서비스 파일: `/etc/systemd/system/tusd-alist.service`
|
|
||||||
- `User`/`Group`은 실제 서버 계정으로 맞춰야 함 (예: `bigfuntnp`)
|
|
||||||
- 계정 불일치 시 `status=217/USER`, `Failed to determine user credentials` 발생
|
|
||||||
|
|
||||||
### 자주 쓰는 점검
|
|
||||||
```bash
|
|
||||||
sudo ss -ltnp | grep 8110
|
|
||||||
curl --http1.1 -i -X OPTIONS http://127.0.0.1:8110/tus/files/
|
|
||||||
curl --http1.1 -i -X OPTIONS https://file-alist.pjt.kr/tus/files/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 운영 메모
|
|
||||||
- `-max-size`는 청크 크기가 아니라 최종 업로드 파일 전체 크기 제한
|
|
||||||
- `bind: address already in use` 발생 시 포트 점유 프로세스 확인 후 정리
|
|
||||||
- 인증/권한은 API(`init/complete`)에서 관리하고, 실제 업로드 전송은 TUS 경로로 처리
|
|
||||||
|
|||||||
Reference in New Issue
Block a user