Files
api2/AGENTS.md
T
2026-04-09 10:54:53 +09:00

15 KiB

AGENTS.md

목적

  • 이 저장소에서 작업하는 사람과 코딩 에이전트가 같은 기준으로 개발하도록 돕는 운영 가이드다.
  • 불필요한 구조 변경보다 작은 단위의 안전한 수정, 빠른 검증, 명확한 보고를 우선한다.

프로젝트 개요

  • 프로젝트 유형: Gradle 기반 Spring Boot 애플리케이션
  • Java 버전: 21
  • Spring Boot 버전: 3.5.10
  • 기본 애플리케이션 이름: api
  • 기본 포트: 8106
  • 실행 진입점: src/main/java/com/alist/api/ApiApplication.java

기술 스택

  • Java: 21
  • Framework: Spring Boot 3.5.10
  • 빌드 도구: Gradle
  • DB: MariaDB
  • ORM: MyBatis (mapper XML: classpath:mapper/**/*.xml)
  • 인증: JWT (jjwt 0.11.5) + Spring Security
  • API 문서: Swagger (springdoc-openapi 2.8.0)
  • 기타: Lombok, Validation, Actuator, log4jdbc

디렉터리 가이드

  • src/main/java/com/alist/api: 애플리케이션 시작점과 업무 코드를 둔다.
  • src/main/java/com/alist/api/modules: 기능별 모듈 패키지를 둔다.
  • src/main/resources: 설정 파일과 로깅 설정을 관리한다.
  • deploy: 배포 관련 리소스가 있으면 이 경로를 우선 확인한다.

현재 확인된 구조

  • 현재 기준 메인 흐름은 Controller -> Form -> Dto -> Service -> Mapper(XML) -> Vo -> Service -> Controller 순서로 연결된다.
  • API 에서 request 받을 때 POST 는 주로 JSON을 사용한다. Controller 는 form 객체로 요청을 받은 뒤 DTO 로 변환해서 Service 에 전달한다.
  • MyBatis는 인터페이스와 XML을 함께 사용한다.
  • Mapper 인터페이스는 src/main/java/.../mapper, SQL XML은 src/main/resources/mapper/... 경로를 짝으로 맞춘다.
  • 공통 응답은 common/response, 보안은 config/security, jwt, 전역 예외 처리는 config/exception 아래에 둔다.
  • 모듈 패키지는 현재 auth, file, main, user 형태로 구성되어 있고, 필요한 모듈만 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는 각 Controller 에서 Service, Mapper 로 전달하는 파라미터 성격의 값 객체로 정의한다.
  • Dto는 요청 처리에 필요한 저장, 수정, 로그 적재 같은 작업 파라미터를 담는 용도로 우선 사용한다.
  • Vo는 Mapper 에서 Service, Controller 로 반환하는 값 객체로 정의한다.
  • Vo는 Mapper 조회 결과를 담을 수 있고, Service 에서 비즈니스 로직 처리 후 필요한 데이터를 가공해서 Controller 로 반환하는 용도로 사용한다.
  • Form은 Controller 입력 검증과 요청 바인딩 전용으로 두고, @Valid 와 Jakarta Validation 어노테이션을 우선 사용한다.
  • 현재 코드처럼 DTO/VO는 Lombok @Getter, 필요한 경우에만 @Setter를 사용한다.
  • Form 안에는 DTO 변환 메서드를 둘 수 있다. 예: userDto(), fileUploadDto()
  • DTO 안에 연관된 다른 DTO 변환이 꼭 필요할 때만 최소한의 보조 메서드를 둔다.
  • 외부 응답에 노출되면 안 되는 내부 필드는 응답에 사용될 수 있는 객체에서 @JsonIgnore로 숨긴다.
  • Mapper 메서드명은 SQL 동작이 드러나도록 select, insert, update 접두어를 사용한다.
  • 삭제가 물리 삭제가 아니라 상태 변경이면 delete 대신 목적이 드러나는 update...Canceled, update...DelYn 같은 이름을 우선한다.
  • Mapper XML namespace는 인터페이스의 전체 경로와 정확히 일치시킨다.
  • XML의 id는 Mapper 메서드명과 동일하게 맞춘다.
  • 조회 결과 타입은 resultType, 저장/수정 파라미터는 DTO 필드명과 매핑되는 프로퍼티명을 그대로 사용한다.
  • 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 를 명시적으로 선언해 요청 출처를 드러낸다.
  • 인증 사용자 확인은 모듈 구현에 따라 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 상태, 실제 파일 시스템 경로가 같이 맞는지 확인한다.

에이전트 응답 원칙

  • 무엇을 바꿨는지보다 왜 그렇게 바꿨는지를 짧고 분명하게 설명한다.
  • 파일 수정 후 가능하면 테스트 또는 최소 실행 검증 결과를 함께 남긴다.
  • 검증하지 못한 내용은 추정으로 말하지 않고 미실행 사유를 적는다.
  • 사용자가 IDE 에서 파일을 수정하거나 새 파일을 만든 뒤 질문할 수 있으므로, 관련 답변 전에는 저장된 최신 파일 상태를 다시 확인하는 것을 우선한다.
  • 이전에 읽은 세션 문맥만으로 최신 파일 상태를 단정하지 말고, 저장되지 않은 편집 내용은 확인할 수 없음을 전제로 설명한다.
  • 요청 범위를 벗어나는 개선점은 강제로 반영하지 말고 제안으로 분리한다.

사용자 선호 규칙

  • 소스코드 변경이 필요한 요청에서는 바로 구현하지 말고 먼저 다음 중 무엇을 원하는지 확인한다.
  • 코드로 보여주기: 사용자가 직접 프로젝트에 반영할 수 있도록 예시 코드나 패치를 제공한다.
  • 직접 작성하기: 에이전트가 저장소에 직접 수정한다.
  • 사용자는 코드 흐름을 먼저 파악하고 코드 컨벤션에 맞게 직접 반영하는 방식을 선호하므로, 선택이 명시되지 않았다면 기본적으로 코드로 보여주기를 우선 제안한다.
  • 이 규칙은 이후 작업에서도 반복 확인 대상이며, 에이전트는 이를 임의로 생략하지 않는다.

현재 코드베이스에서 특히 주의할 점

  • README.md는 아직 템플릿 상태이므로 실제 동작 방식은 코드와 설정 파일을 기준으로 판단한다.
  • 예시 스케줄러 코드에는 깨진 문자열과 과도한 반복 로그가 보일 수 있으니 관련 수정 시 인코딩과 로그 정책을 함께 점검한다.
  • 테스트 코드가 충분하지 않을 수 있으므로 기능 변경 시 필요한 테스트를 보강한다.
  • 일부 Java 소스와 주석, Swagger 설명에 인코딩이 깨진 문자열이 있으므로 표시 문자열 수정은 영향 범위를 보고 묶어서 처리한다.
  • application-local.yaml 은 로컬 실행값이 직접 들어가 있으므로 공유하거나 커밋할 때 민감정보 노출 여부를 한 번 더 확인한다.

프로파일

프로파일 설명
local 로컬 개발 환경
pjt 프로젝트(개발) 환경

보안 구조

  • Swagger: /v3/api-docs/**, /swagger-ui/** → HTTP Basic 인증 (InMemory)
  • API: JWT Bearer 토큰 인증 (Stateless)
  • 세션/쿠키: Redis Session 저장소 사용, 쿠키 속성은 프로파일별 cookie.* 설정으로 제어
  • 공개 경로: /, /actuator/health, /sso/**, /auth/**, /user/signup, /files/tusHook
  • Swagger 인증과 API 인증은 SecurityFilterChain 을 분리해서 관리한다.

응답 코드 규칙

ApiResponseCode enum으로 관리. 주요 코드:

코드 메시지 HTTP Status 용도
CODE_200 성공 200 OK 일반 성공
CODE_400 잘못된 요청 400 Bad Request 일반 클라이언트 오류
CODE_401 인증 필요 합니다. 401 Unauthorized 인증 없음
CODE_403 접근 권한 필요 합니다. 403 Forbidden 권한 없음
CODE_404 페이지를 찾을 수 없습니다. 404 Not Found 리소스 없음
CODE_405 잘못된 요청입니다. 요청 방식을 확인해 주세요. 405 Method Not Allowed 메서드 불일치
CODE_500 요청을 처리하는 중 오류가 발생했습니다. 500 Internal Server Error 서버 오류
CODE_2001 {0} 정보 조회에 성공하였습니다. 200 OK 단건 조회 성공
CODE_2002 {0} 등록 되었습니다. 201 Created 등록 성공
CODE_2003 조회된 정보가 없습니다. 200 OK 조회 결과 없음
CODE_2004 중복된 {0} 정보 입니다. 409 Conflict 중복 데이터
CODE_4001 입력값을 확인해주세요. 400 Bad Request @Valid / 바인딩 / 타입오류 / JSON 파싱 실패
CODE_4003 필수 요청 파라미터가 누락되었습니다. 400 Bad Request 필수 파라미터 누락
  • {0} 자리에 대상명 삽입 (예: CODE_2001 → "회원 정보 조회에 성공하였습니다.")

Swagger 접속

  • URL: http://localhost:8106/swagger-ui.html
  • 인증: swagger.login.id / swagger.login.password (환경별 yaml에 설정)

코드 작성 규칙

  • 응답은 ApiResponse<T> 래퍼 사용
  • 응답 코드는 ApiResponseCode enum 사용
  • MyBatis Mapper XML은 src/main/resources/mapper/ 하위에 작성
  • 카멜케이스 자동 변환 활성화 (map-underscore-to-camel-case: true)
  • 새 모듈 추가 시: modules/{moduleName}/ 하위에 Controller, Service, Mapper, dto/, vo/, 필요 시 form/ 구조로 생성
  • Mapper XML은 resources/mapper/{moduleName}/ 에 위치
  • Form 에서 DTO 로 변환할 때는 검증과 trim, 기본값 치환까지 같이 처리하는 현재 패턴을 우선 따른다.

MyBatis 규칙

  • Mapper XML 위치: src/main/resources/mapper/**/*.xml
  • map-underscore-to-camel-case: true 설정 → DB 컬럼 user_idx → Java 필드 userIdx 자동 매핑
  • Mapper 인터페이스와 XML의 namespace, id 반드시 일치시킬 것
  • DTO/VO/Form 역할 정의는 DTO/VO/Mapper 규칙 섹션을 기준으로 맞춘다.
  • useGeneratedKeys, keyProperty 를 사용하는 insert 가 있으므로 신규 PK 생성 테이블은 현재 패턴을 먼저 확인한다.
  • 상태 집계나 이력성 데이터는 단건 update 외에 이벤트 로그 insert 가 같이 필요한지 확인한다.