[개발]AGENTS 문서 업데이트

This commit is contained in:
2026-04-24 10:58:14 +09:00
parent 88c3a4364b
commit 6cae972c0c
14 changed files with 608 additions and 182 deletions
+46 -182
View File
@@ -1,193 +1,57 @@
# AGENTS.md # AGENTS.md
## 목적 ## 목적
- 이 저장소에서 작업하는 사람과 코딩 에이전트가 같은 기준으로 개발하도록 돕는 운영 가이드다. - 이 저장소에서 작업하는 사람과 코딩 에이전트가 같은 기준으로 개발하도록 돕는 운영 가이드다.
- 불필요한 구조 변경보다 작은 단위의 안전한 수정, 빠른 검증, 명확한 보고를 우선한다. - 불필요한 구조 변경보다 작은 단위의 안전한 수정, 빠른 검증, 명확한 보고를 우선한다.
## 프로젝트 개요 ## 우선 확인할 규칙
- 기존 구조와 네이밍을 우선 존중하고, 요청 범위 안에서 필요한 만큼만 수정한다.
- 소스코드 변경 요청에서는 바로 구현하지 말고 `코드로 보여주기` 또는 `직접 작성하기` 중 원하는 방식을 먼저 확인한다.
- Controller 는 요청/응답 조립과 인증 주체 확인에 집중하고, 복잡한 로직과 DB 처리는 Service 로 넘긴다.
- 응답은 `ApiResponse<T>``ApiResponseCode` 조합을 우선 사용한다.
- 변경 후에는 가능하면 테스트 또는 최소 실행 검증 결과를 남기고, 미실행 항목은 사유를 분명히 적는다.
## 문서 인덱스
| 구분 | 문서 | 경로(URL) |
|------|------|-----------|
| 기본 | [프로젝트 개요](docs/project-overview.md) | `docs/project-overview.md` |
| 기본 | [코드 컨벤션](docs/code-conventions.md) | `docs/code-conventions.md` |
| 기본 | [보안 및 응답 규칙](docs/security-and-response.md) | `docs/security-and-response.md` |
| 기본 | [설정 및 실행 가이드](docs/runtime-config.md) | `docs/runtime-config.md` |
| 기본 | [검증 및 체크리스트](docs/verification-checklist.md) | `docs/verification-checklist.md` |
| 기본 | [Codex 작업 규칙](docs/agent-workflow.md) | `docs/agent-workflow.md` |
| 기본 | [현재 코드베이스 메모](docs/codebase-notes.md) | `docs/codebase-notes.md` |
| 정책 | [정책서 요약 인덱스](docs/policy/index.md) | `docs/policy/index.md` |
| 정책 | [정책서: 서비스 개요](docs/policy/overview.md) | `docs/policy/overview.md` |
| 정책 | [정책서: 회원/권한/인증](docs/policy/membership-and-auth.md) | `docs/policy/membership-and-auth.md` |
| 정책 | [정책서: 캠퍼스/강좌/학습 흐름](docs/policy/campus-and-learning.md) | `docs/policy/campus-and-learning.md` |
| 정책 | [정책서: 콘텐츠/LMS](docs/policy/content-and-lms.md) | `docs/policy/content-and-lms.md` |
| 정책 | [정책서: 인터페이스/도메인/운영](docs/policy/interfaces-and-operations.md) | `docs/policy/interfaces-and-operations.md` |
## 빠른 판단 가이드
- 구조, 네이밍, DTO/VO/Form, Mapper 작성 방식은 `docs/code-conventions.md` 를 우선 본다.
- 인증/인가, 공통 응답, 예외 처리, 응답 코드는 `docs/security-and-response.md` 를 우선 본다.
- 프로파일, 설정 파일, 로깅, Swagger, 실행 명령은 `docs/runtime-config.md` 를 우선 본다.
- 테스트 범위, 배포 전 점검, 파일/권한/설정 변경 확인사항은 `docs/verification-checklist.md` 를 우선 본다.
- Codex 협업 방식과 응답 원칙은 `docs/agent-workflow.md` 를 우선 본다.
- 도메인 정책, 역할, 강좌/콘텐츠/LMS 규칙은 `docs/policy/` 하위 문서를 우선 본다.
## 정책서 핵심 요약
- 서비스는 `alist.co.kr` 메인 서비스, `a-campus.co.kr` 캠퍼스 메인, `class.a-campus.co.kr` 교사용, `student.a-campus.co.kr` 학생용, `admin.alist.co.kr` 백오피스/CMS로 분리 운영한다.
- 회원 유형은 관리자, 교사, 학생, 수강생으로 구분하며, 수강생은 캠퍼스 초대 기반 준회원이고 학생 전환 및 ID 병합 정책이 존재한다.
- 교사만 캠퍼스를 생성할 수 있고 캠퍼스는 `단일 캠퍼스형``복합 캠퍼스형`으로 나뉜다. 복합 캠퍼스형은 관리자 승인 후 운영한다.
- 캠퍼스 계층은 `캠퍼스 -> 클래스 -> 강좌(Lecture)` 구조이며, 강좌는 `교재 1종``1:1 매칭`되고 학생/수강생 초대, 과제/평가, 학습 관리의 기준 단위다.
- 교사 회원은 Live 상태에서 단수 캠퍼스만 소속 가능하고, 수강생도 Live 상태에서 단수 캠퍼스만 소속 가능하다. 본인 인증을 마친 학생은 복수 캠퍼스 소속이 가능하다.
- 강좌 운영 중 학생 중도 초대와 상태 변경이 가능하며, 탈퇴/종료 시 교사 화면에서는 학습 이력과 산출물이 숨김 처리된다.
- 콘텐츠는 교재 자료, 스마트 콘텐츠, 평가 문항, 온라인 학습/과제/평가로 구성되며 접근 권한과 학습 관리 범위가 회원 유형별로 다르다.
- 학습 관리는 진도, 수행 여부, 정오답, 성취도, 변화 추이, 오답 노트, 포트폴리오까지 포함한다. 과제/평가/온라인 학습 데이터가 주요 관리 대상이다.
- 캠퍼스 개인화는 캠퍼스 명칭, 직접 접속 도메인, 로고, GNB 색상 기준으로 제공하며, 정책서상 해외 임대/제휴 확장을 고려한 도메인 구조를 가진다.
- 기존 서비스 회원 DB와 학습 이력은 완전 마이그레이션 대상이 아니므로 최초 로그인 연동, 레거시 병행 운영, 데이터 재구조화 정책을 함께 고려해야 한다.
## 프로젝트 핵심 정보
- 프로젝트 유형: Gradle 기반 Spring Boot 애플리케이션 - 프로젝트 유형: Gradle 기반 Spring Boot 애플리케이션
- Java 버전: 21 - Java 버전: 21
- Spring Boot 버전: 3.5.10 - Spring Boot 버전: 3.5.10
- 기본 애플리케이션 이름: `api` - 기본 애플리케이션 이름: `api`
- 기본 포트: `8106` - 기본 포트: `8106`
- 실행 진입점: `src/main/java/com/alist/api/ApiApplication.java` - 실행 진입점: `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 가 같이 필요한지 확인한다.
+20
View File
@@ -0,0 +1,20 @@
# Codex 작업 규칙
## 작업 원칙
- 기존 구조와 네이밍을 우선 존중한다.
- 한 번에 큰 리팩터링을 하지 말고, 요청 범위 안에서 필요한 만큼만 수정한다.
- 인코딩 문제가 보이는 문자열은 무심코 대량 수정하지 말고 원인과 영향 범위를 먼저 확인한다.
- 요청 범위를 벗어나는 개선점은 강제로 반영하지 말고 제안으로 분리한다.
## 에이전트 응답 원칙
- 무엇을 바꿨는지보다 왜 그렇게 바꿨는지를 짧고 분명하게 설명한다.
- 파일 수정 후 가능하면 테스트 또는 최소 실행 검증 결과를 함께 남긴다.
- 사용자가 IDE 에서 파일을 수정하거나 새 파일을 만든 뒤 질문할 수 있으므로, 관련 답변 전에는 저장된 최신 파일 상태를 다시 확인하는 것을 우선한다.
- 이전에 읽은 세션 문맥만으로 최신 파일 상태를 단정하지 말고, 저장되지 않은 편집 내용은 확인할 수 없음을 전제로 설명한다.
## 사용자 선호 규칙
- 소스코드 변경이 필요한 요청에서는 바로 구현하지 말고 먼저 다음 중 무엇을 원하는지 확인한다.
- `코드로 보여주기`: 사용자가 직접 프로젝트에 반영할 수 있도록 예시 코드나 패치를 제공한다.
- `직접 작성하기`: 에이전트가 저장소에 직접 수정한다.
- 사용자는 코드 흐름을 먼저 파악하고 코드 컨벤션에 맞게 직접 반영하는 방식을 선호하므로, 선택이 명시되지 않았다면 기본적으로 `코드로 보여주기`를 우선 제안한다.
- 이 규칙은 이후 작업에서도 반복 확인 대상이며, 에이전트는 이를 임의로 생략하지 않는다.
+48
View File
@@ -0,0 +1,48 @@
# 코드 컨벤션
## 파일 생성 규칙
- 새 기능은 가능하면 `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/Form 규칙
- `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`로 숨긴다.
- Form 에서 DTO 로 변환할 때는 검증과 `trim()`, 기본값 치환까지 같이 처리하는 현재 패턴을 우선 따른다.
## Mapper/MyBatis 규칙
- Mapper 메서드명은 SQL 동작이 드러나도록 `select`, `insert`, `update` 접두어를 사용한다.
- 삭제가 물리 삭제가 아니라 상태 변경이면 `delete` 대신 목적이 드러나는 `update...Canceled`, `update...DelYn` 같은 이름을 우선한다.
- Mapper XML `namespace`는 인터페이스의 전체 경로와 정확히 일치시킨다.
- XML의 `id`는 Mapper 메서드명과 동일하게 맞춘다.
- 조회 결과 타입은 `resultType`, 저장/수정 파라미터는 DTO 필드명과 매핑되는 프로퍼티명을 그대로 사용한다.
- Mapper XML 안 SQL 블록 시작부 주석은 현재 코드처럼 `/*Mapper.method*/` 형식을 유지한다.
- Mapper XML 위치는 `src/main/resources/mapper/**/*.xml` 이다.
- `map-underscore-to-camel-case: true` 설정으로 DB 컬럼 `user_idx` 는 Java 필드 `userIdx` 로 자동 매핑된다.
- `useGeneratedKeys`, `keyProperty` 를 사용하는 insert 가 있으므로 신규 PK 생성 테이블은 현재 패턴을 먼저 확인한다.
- 상태 집계나 이력성 데이터는 단건 update 외에 이벤트 로그 insert 가 같이 필요한지 확인한다.
## Java/Spring 코드 스타일
- 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` 를 사용하므로 기존 방식을 먼저 맞춘다.
+8
View File
@@ -0,0 +1,8 @@
# 현재 코드베이스 메모
## 현재 특히 주의할 점
- `README.md`는 아직 템플릿 상태이므로 실제 동작 방식은 코드와 설정 파일을 기준으로 판단한다.
- 예시 스케줄러 코드에는 깨진 문자열과 과도한 반복 로그가 보일 수 있으니 관련 수정 시 인코딩과 로그 정책을 함께 점검한다.
- 테스트 코드가 충분하지 않을 수 있으므로 기능 변경 시 필요한 테스트를 보강한다.
- 일부 Java 소스와 주석, Swagger 설명에 인코딩이 깨진 문자열이 있으므로 표시 문자열 수정은 영향 범위를 보고 묶어서 처리한다.
- `application-local.yaml` 은 로컬 실행값이 직접 들어가 있으므로 공유하거나 커밋할 때 민감정보 노출 여부를 한 번 더 확인한다.
+83
View File
@@ -0,0 +1,83 @@
# 정책서: 캠퍼스/강좌/학습 흐름
## 캠퍼스 개요
- A★캠퍼스는 A*List 교재를 활용한 상호 교수·학습 활동을 위한 온라인 공간이다.
- 서비스 대상은 A*List 회원인 교사와 학생이며, 운영자는 캠퍼스 인터페이스와 관련 지원 기능을 제공한다.
- 캠퍼스 개인화 요소는 캠퍼스 명칭, 직접 접속 도메인, 로고, GNB 색상이다.
## 캠퍼스 생성 정책
- 캠퍼스 생성 주체는 교사 회원이다.
- 단일 캠퍼스형은 생성 즉시 운영 가능하다.
- 복합 캠퍼스형은 교사 생성 후 관리자 승인 절차를 거친 뒤 운영 가능하다.
- 관리자(Back Office)도 캠퍼스를 직접 생성할 수 있다.
## 캠퍼스 유형
- 단일 캠퍼스형: 1인 교사 공부방 또는 단일 학원형
- 복합 캠퍼스형: 동일 브랜드 하위 가맹 캠퍼스를 갖는 학원형
## 캠퍼스 계층 구조
- 캠퍼스
- 클래스
- 강좌(Lecture)
## 계층별 의미
- 캠퍼스: 운영 단위, 교재/교사/학생/설정 관리의 상위 개념
- 클래스: 교사 1인 기준의 운영 단위
- 강좌: 교재 + 복수 학생 기준의 실제 교수·학습 수행 단위
## 강좌 정책
- 강좌와 교재는 1:1 관계다
- 교재 1종은 단일 ISBN 한 권이 아니라 학습 연관성을 가진 교재 묶음일 수 있다
- 동일 학생이어도 교재가 바뀌면 새 강좌 생성
- 동일 교재여도 학생 구성이 바뀌면 새 강좌 생성
- 강좌 복사 기능을 제공하며 수업 중 강좌도 복사 가능하다
- Live 상태 강좌 수는 제한될 수 있고 종료 강좌를 포함한 총 강좌 수는 무제한이다
## 강좌 생명주기
- 강의 준비중
- 강의 중
- 강의 종료
- 학생 기준 상태로는 수강 대기중, 수강 중, 수강 종료가 별도로 존재한다
## 강좌 운영 규칙
- 강좌 생성 시 교재 선택, 학생 초대, 수업 코스 설계, 과제/평가 생성이 함께 이뤄진다
- 운영 중 학생 중도 초대가 가능하다
- 운영 중 학생 상태를 이용 중지 또는 수강 종료로 변경할 수 있다
- 학생이 운영 중간에 가입하면 이전 과제/평가도 미수행 상태로 제시한다
- 상태 변경 시 학생과 학부모에게 알림이 발송된다
## 교사 업무 흐름
- 캠퍼스 생성 또는 초대 가입
- 캠퍼스 개인화 설정
- 교재 선택 및 클래스/강좌 생성
- 학생/수강생 초대
- 타임라인 기반 수업 코스 설계
- 과제/평가 출제
- 제출 관리, 채점, 피드백
- 학습 현황 및 보고서 생성
## 학생/수강생 학습 흐름
- 초대 URL/초대 코드 기반 강좌 가입 또는 학생 회원 자기주도학습 시작
- 수업 참여
- 과제 수행 및 제출
- 평가 수행 및 제출
- 복습 및 자기주도학습
- 학습 결과/성취도 확인
## 과제/평가 정책
- 과제/평가는 강좌 단위로 출제한다
- 학생은 온라인 과제 뷰어 또는 온라인 학습 콘텐츠 뷰어에서 수행한다
- 제출 기한과 수행률 관리가 필요하다
- 교사는 채점 및 피드백을 입력한다
- 알림장, 이메일, 앱 푸시, SMS가 보조 수단으로 사용된다
## SMS 정책
- 캠퍼스 초대, 학습 알림, 보고서 발송 등에 SMS를 병행 사용할 수 있다
- SMS 수량은 캠퍼스 마스터가 구매/충전하는 구조다
- 발송 성공 시 수량이 차감된다
- 백오피스에서 수량 충전 기능을 제공한다
## 개발 해석 포인트
- 캠퍼스, 클래스, 강좌는 이름이 비슷하지만 역할이 다르므로 테이블/DTO/응답 모델을 명확히 분리해야 한다
- 강좌는 실제 학습 데이터와 과제/평가의 기준 단위이므로, API 설계 시 강좌 식별자를 중심으로 묶는 것이 자연스럽다
- 초대, 가입, 탈퇴, 종료, 상태 변경은 회원 상태와 강좌 소속 상태를 구분해 처리해야 한다
+75
View File
@@ -0,0 +1,75 @@
# 정책서: 콘텐츠/LMS
## 콘텐츠 범주
- 수업 자료: PPT, Lesson Plan, Syllabus, Scope & Sequence, Teacher Guide, Script, Worksheet, Word Test 등
- 평가 자료: Test Sheet, 단원 평가, 중간/최종 평가, 평가 문항, 내신 수행평가 자료
- 멀티미디어: MP3, MP4, 온라인 PPT, 온라인 클래스, 플래시 카드
- 솔루션형 콘텐츠: 교사용 e-Book, 온라인 평가, 온라인 OMR 평가, Voca*List, 클래스 카드, 레벨 테스트
- 교사 보유 자료: PDF, MP3, MP4 업로드 자료
## 콘텐츠 생산과 활용
- CMS에서 콘텐츠 분류 체계, 메타데이터, 자료 등록, 대량 등록, 미리 보기를 관리한다
- 교사는 수업 뷰어에서 문서형 자료, URL, 온라인 콘텐츠, 과제, 평가를 통합적으로 사용한다
- 학생은 온라인 학습 콘텐츠 뷰어와 과제/평가 뷰어에서 콘텐츠를 수행한다
- 평가지는 별도 생성 솔루션(Test Generator)으로 출제, 편집, 출력한다
## 콘텐츠 메타데이터
- 콘텐츠는 교재, 시리즈, 레벨, 학년, 난이도, CEFR, Lexile, AR 등 학습 레벨 메타데이터를 가진다
- 교재 레벨 메타는 백오피스/CMS에서 별도로 관리한다
- 메타데이터는 검색, 교재 노출, 학습 추천, 보고서 분류에 영향을 줄 수 있다
## 콘텐츠 접근 권한
- 교사: 대부분의 수업 자료와 교사용 자료, 수업 뷰어 기능 접근 가능
- 학생: 제한된 수업 자료와 멀티미디어, 온라인 학습 콘텐츠 접근 가능
- 수강생: 강좌 기반 학습 활동 위주로 제한된 권한을 가진다
- 학생용 I/F에서는 기본 권한 자료와 교사가 추가 허용한 자료를 함께 노출할 수 있다
## 주요 솔루션과 기능
- 교수자용 수업 뷰어
- E-Book, PDF, PPSX, Audio, Video, URL, 온라인 콘텐츠 연동
- 확대/축소, 그리기, 북마크, 메모, 타이머, 주사위, 스포트라이트 등 보조 기능
- 온라인 학습 콘텐츠 뷰어
- 문제 풀이, 게임형 활동, Audio/Video 재생, Drawing, Recording, 타이머
- 학습자용 온라인 과제 뷰어
- 답안 입력, 자동 채점, 제출
- 입력, 그림, 녹음, 이미지/음원/영상 업로드
- OMR/온라인 평가 수행
- 평가지 생성 솔루션
- 문항 검색, 문항 수/유형 설정, 사용자 문항 추가, PDF 생성, 출력
- 학습 분석 보고서
- 레벨테스트, 교재별, Unit별 보고서 생성
## 학습 관리 대상
- 레벨테스트
- 온라인 학습 콘텐츠
- 온라인 평가
- 온라인 과제
- 클래스 과제
## 학습 관리 영역
- 정량 관리
- 학습 횟수
- 회차별 학습 시간
- 전체/평균 학습 시간
- 단위 학습 수행 여부
- 성취 관리
- 정오답
- 학습 진도
- 전체 성취도
- SKILL별 성취도
- 성취도 변화 추이
- 산출물 관리
- 오답 노트
- 학습 산출물 데이터
- 유사 문항 학습
- 포트폴리오
## 시각화 및 보고
- 대시보드 I/F와 학습 분석 보고서가 주요 표현 수단이다
- 학생별/강좌별 현황, 성취도, 수행률, 레벨테스트 결과 시각화가 중요하다
- 교사 화면에서는 강좌별 관리와 학생별 관리가 모두 필요하다
## 개발 해석 포인트
- 콘텐츠 자체 메타데이터와 학습 수행 데이터는 분리 저장하는 편이 좋다
- 학습 관리 영역은 단순 진도율이 아니라 성취도·산출물·포트폴리오까지 포함하므로 조회 API가 넓어질 가능성이 높다
- 학생용 권한은 `회원 유형`, `강좌 소속 여부`, `교사 공유 여부`의 조합으로 판단해야 한다
+22
View File
@@ -0,0 +1,22 @@
# 정책서 요약 인덱스
원본 정책서: `D:/work/project/202601_alist/document/00_정책서/이퍼블릭_AList 교수학습지원 통합 플랫폼 구축_정책 설계_Ver 0.29.pdf`
## 문서 구성
- [서비스 개요](overview.md)
- [회원/권한/인증](membership-and-auth.md)
- [캠퍼스/강좌/학습 흐름](campus-and-learning.md)
- [콘텐츠/LMS](content-and-lms.md)
- [인터페이스/도메인/운영](interfaces-and-operations.md)
## 빠른 요약
- 플랫폼은 메인 서비스, 캠퍼스 메인, 교사용 캠퍼스, 학생용 캠퍼스, 백오피스/CMS로 분리된다.
- 핵심 도메인은 회원, 캠퍼스, 클래스, 강좌, 콘텐츠, 과제/평가, 학습 관리다.
- 정책서상 주요 제약은 회원 유형별 권한 차등, 캠퍼스 소속 제한, 강좌-교재 1:1 관계, 캠퍼스 개인화 도메인, 레거시 병행 운영이다.
- 실제 개발 판단에서는 이 문서 묶음을 기능 정의서보다 `도메인 정책서`로 취급하는 것이 적합하다.
## 개발 시 우선 참고 포인트
- 회원 가입, 초대, 상태값, 로그인, 권한 분기는 `membership-and-auth.md`
- 캠퍼스 생성, 계층 구조, 강좌 정책, 과제/평가 흐름은 `campus-and-learning.md`
- 콘텐츠 유형, 접근 권한, 뷰어/솔루션, LMS 지표는 `content-and-lms.md`
- 화면 경계, 도메인 구조, 메뉴 범위, 서버/이관 정책은 `interfaces-and-operations.md`
+82
View File
@@ -0,0 +1,82 @@
# 정책서: 인터페이스/도메인/운영
## 인터페이스별 역할
- 메인 서비스(`alist.co.kr`)
- 교재/자료, 스마트 콘텐츠, 지원 센터, 마이페이지, 교사 지원 서비스 중심
- 캠퍼스 메인(`a-campus.co.kr`)
- 서비스 소개, 이용 방법, 체험하기, 캠퍼스 진입
- 캠퍼스 교사용(`class.a-campus.co.kr`)
- 강좌/학생/학습/알림/수업준비/캠퍼스 관리 중심
- 캠퍼스 학생용(`student.a-campus.co.kr`)
- 오늘 학습, 셀프 스터디, 나의 학습, 알림방 중심
- 백오피스/CMS(`admin.alist.co.kr`)
- 운영 관리, 교재/콘텐츠/CMS, 파트너, 홍보, 문의, 통계 관리
## 교사용 I/F 핵심 메뉴
- 강좌 관리
- 학생 관리
- 학습 관리
- 소통방
- 수업 준비
- 마이페이지
- 역할에 따라 가맹 캠퍼스 관리, 캠퍼스 관리, 공지 관리 등 추가 메뉴 노출
## 학생용 I/F 핵심 메뉴
- 오늘 학습
- 셀프 스터디
- 나의 학습
- 알림방
- 마이페이지
- 학생만 `학습 교재 추가`, `교재 추가` 같은 자기주도학습 확장 기능 사용 가능
## 백오피스/CMS 핵심 메뉴
- 관리자/권한 관리
- 메뉴 관리
- 파트너/유통업체 관리
- A*List/A★캠퍼스 메인 관리
- 팝업, 이벤트, FAQ, 세미나, 게시판, 1:1 문의
- 교재 분류/레벨 메타 관리
- 교재 관리, 캠퍼스 서비스 교재 관리
- 콘텐츠 저작/관리, 온라인 콘텐츠 관리, 제휴사 콘텐츠 관리
- 학습 관리, 통계 관리
## 도메인 정책
- 메인 서비스와 캠퍼스 서비스 도메인을 분리한다
- 캠퍼스 생성 시 개인화 도메인을 제공한다
- 기본 URL 구조는 `/home/...`, 임대/개인화 URL 구조는 `/{campusId}/...` 이다
- 학생용 기본 자기주도학습 화면은 `student.a-campus.co.kr/home` 이다
- 개인화 도메인은 서버 부하 분산, 확장성, 운영 편의성을 고려한 정책이다
## 캠퍼스 개인화 도메인 개발 정책
- 정책서에는 Next.js 자동 라우팅 + 미들웨어 + 템플릿 파일 자동 생성 방식이 예시로 제시된다
- 핵심 요구사항은 다음과 같다
- 관리자에서 캠퍼스 ID 등록 시 개인화 경로가 반영될 것
- 캠퍼스 ID별 로고/헤더/GNB 스타일을 동적으로 적용할 것
- 허용된 캠퍼스 ID만 접근 가능하도록 제어할 것
- 기본 사용자와 임대/브랜드 사용자의 URL 흐름을 분리할 것
## 서버/소프트웨어 구성
- Web / WAS / DB / File Storage / Legacy / 관리 서버를 분리한 구성을 기본으로 본다
- 정책서 권장 스택
- Web: Linux, Apache 2.4, Node.js / Next.js
- WAS: Linux, Apache/Tomcat 9.x, JDK/OpenJDK, Spring Boot, Gradle, MyBatis, Swagger
- DB: Linux, MariaDB 10.6 이상
- Legacy 서버는 기존 회원 로그인 연계와 앱 유지 목적상 일정 기간 병행 운영한다
## 데이터 이관 정책
- 교재 정보, 수업 자료, e-Book, 온라인 PPT, 레벨테스트, 문항, 내신 수행평가, 세미나, 교재 소개 등은 재구조화 후 이관 대상이다
- 기존 회원 DB는 품질 이슈와 암호화 방식 차이로 직접 이관이 어렵다
- 기존 앱 화면, 일부 ASP 기반 화면, 구 LMS 학습 이력은 신규 구조와 차이가 커서 병행 운영 또는 별도 연계가 필요하다
- 온라인 PPT는 변환기(PPT to HTML)를 거쳐 탑재한다
## 서비스 오픈 정책
- 개발
- 알파 테스트
- 베타 테스트
- 서비스 오픈 및 운영
- 일정 기간 기존 서비스 시스템 병행 운영
## 개발 해석 포인트
- 정책서의 화면 메뉴는 단순 네비게이션이 아니라 권한/역할/도메인 경계 정의에 가깝다
- 도메인과 URL 구조는 운영 정책과 강하게 연결돼 있으므로 하드코딩보다 설정/데이터 기반 관리가 적합하다
- 레거시 병행 운영과 최초 로그인 연동은 회원 기능 수정 시 항상 영향 범위를 같이 봐야 한다
+74
View File
@@ -0,0 +1,74 @@
# 정책서: 회원/권한/인증
## 회원 유형
- 관리자
- 일반 관리자
- 마스터 관리자
- 교사
- 학생
- 수강생
## 회원 유형 정의
- 교사: 정회원 사용자. 본인 인증과 이메일 인증을 거치며 메인 서비스와 교사용 캠퍼스 I/F 사용
- 학생: 정회원 사용자. 본인 인증 또는 부모 동의 인증과 이메일 인증을 거치며 메인 서비스와 학생용 캠퍼스 I/F 사용
- 수강생: 준회원 사용자. 캠퍼스 초대 기반 가입이며 본인 인증 없이 학생용 캠퍼스 I/F 중심으로 사용
- 학부모: 독립 회원이 아니라 학생/수강생의 부가 정보 항목이다
## 인증 및 가입 정책
- 교사 가입: 서비스 직접 방문, 휴대폰 본인 인증, 이메일 인증
- 학생 가입: 서비스 직접 방문, 부모 동의 인증 포함 휴대폰 인증, 이메일 인증
- 수강생 가입: 캠퍼스 초대 URL + 초대 코드 기반 가입, 학생용 I/F 접근 계정 생성
- 관리자 계정: 개발 또는 마스터 관리자 등록 방식
## 인터페이스 접근 권한
- 관리자: 백오피스/CMS 접근, 메뉴별 권한 차등
- 교사: 메인 서비스 + 캠퍼스 교사용 I/F 접근
- 학생: 메인 서비스 + 학생용 I/F 접근, 일부 메뉴 제한
- 수강생: 학생용 I/F 중심 접근, 메인 서비스 권한 없음 또는 제한
- 학생/수강생은 같은 학생용 I/F를 사용하지만 권한 범위는 다르다
## 캠퍼스 소속 정책
- 교사 회원은 온라인 캠퍼스 역할과 무관하게 Live 상태에서 단수의 캠퍼스에만 소속 가능
- 수강생은 Live 상태에서 단수의 캠퍼스에만 소속 가능
- 본인 인증을 마친 학생은 복수 캠퍼스 소속 가능
- 교사 비회원은 캠퍼스 생성 또는 선생님 역할 소속이 불가하며, 초대 가입 시에도 A*List 회원 가입이 필요하다
## 캠퍼스 내 역할
- 캠퍼스 마스터: 캠퍼스 생성자, 운영/관리 권한 보유
- 가맹 캠퍼스장: 복합 캠퍼스 하위 지점 운영 역할
- 선생님: 클래스 및 강좌 운영 주체
- 학생: 학습 수행 주체
## 회원 상태값
- 정상(Live)
- 휴면
- 병합
- 탈퇴 요청
- 탈퇴
## 상태 변경 정책
- 1년 이상 접속 이력 없으면 휴면 전환
- 휴면 후 2년간 해제 없으면 탈퇴 처리
- 탈퇴 요청 후 30일 경과 시 데이터 삭제
- 병합 상태는 ID 통합 후 미사용 계정 처리 상태
## 탈퇴/복구 정책
- 교사는 하위 강좌가 모두 종료 상태일 때만 탈퇴 요청 가능
- 학생/수강생은 수강 중 강좌가 있어도 탈퇴 가능하지만 안내가 필요하다
- 탈퇴 시 강좌 가입 상태는 종료(탈퇴)로 바뀌고 교사 화면에서는 학습 이력/산출물이 숨김 처리된다
- 휴면 해제와 탈퇴 번복은 로그인 후 이메일/휴대폰 인증으로 복구한다
## 회원 전환 및 ID 병합
- 수강생은 모바일 본인 인증 또는 부모 인증 후 학생으로 전환 가능
- 전환 시 클래스/강좌 정보와 학습 이력은 유지한다
- 학생/수강생은 ID 병합 기능 제공 대상이다
- 교사는 ID 병합 대상이 아니다
## 레거시 회원 정책
- 기존 A*List, eLearning Town 회원은 최초 로그인 시 레거시 DB 조회 후 신규 시스템 기준으로 보완 입력 및 저장한다
- 레거시 비밀번호 체계상 DB 직접 마이그레이션이 어려워 최초 로그인 연동이 중요하다
## 개발 해석 포인트
- `회원 유형`, `인증 여부`, `캠퍼스 역할`, `캠퍼스 소속 상태`는 분리된 개념으로 모델링하는 편이 안전하다
- 학생과 수강생은 UI는 유사하지만 권한과 소속 정책이 다르므로 같은 enum 하나로 단순화하면 후속 정책 충돌 가능성이 높다
- 탈퇴와 캠퍼스 소속 종료, 강좌 종료는 별도 상태 전이로 다뤄야 한다
+38
View File
@@ -0,0 +1,38 @@
# 정책서: 서비스 개요
## 서비스 목적
- A*List는 교재 기반 교수·학습 지원 통합 플랫폼이다.
- 핵심 제공 가치는 교사용 수업 자료 제공, 스마트 콘텐츠/솔루션 제공, 교사 지원 서비스, 온라인 캠퍼스 기반 교수·학습 활동 지원이다.
- 운영 주체는 A*List 서비스 운영자이며, 실사용자는 교사와 학생이다.
## 서비스 구성 축
- 메인 서비스: 교재/자료 소개, 스마트 콘텐츠, 교사 지원 서비스 제공
- A★캠퍼스: 교사·학생이 실제 교수·학습 활동을 수행하는 온라인 캠퍼스
- 백오피스/CMS: 플랫폼 운영, 콘텐츠 관리, 파트너/교재/회원/통계 관리
- 해외 확장: 영어 홍보 사이트, 해외 임대(이식) 서비스, 제휴/유통업체 운영
## 주요 인터페이스
- `www.alist.co.kr`: 메인 서비스
- `www.a-campus.co.kr`: 캠퍼스 서비스 메인
- `class.a-campus.co.kr/{campusId}`: 캠퍼스 교사용 I/F
- `student.a-campus.co.kr/{campusId}`: 캠퍼스 학생용 I/F
- `student.a-campus.co.kr/home`: 캠퍼스 미소속 학생의 자기주도학습 I/F
- `admin.alist.co.kr`: 관리자(Back Office / CMS) I/F
- `eng.alist.co.kr`: 영어 홍보 I/F
## 역할별 큰 흐름
- 교사: 회원 가입 후 캠퍼스 생성 또는 캠퍼스 초대 가입, 교재 선택, 수업 설계, 학생 초대, 과제/평가 관리, 학습 관리 수행
- 학생: 본인 인증 기반 정회원으로 가입 가능, 자기주도학습과 캠퍼스 강좌 활동 수행
- 수강생: 캠퍼스 초대 기반 준회원으로 가입하며 강좌 기반 학습 활동 위주로 이용
- 관리자/유통업체: 캠퍼스 생성 승인, 교재/콘텐츠 관리, 파트너 및 운영 정책 관리
## 서비스 환경 정책
- 메인 서비스와 캠퍼스 메인은 PC Web 중심이며 태블릿/모바일은 보기 위주로 제한되는 화면이 있다.
- 캠퍼스 교사용 I/F는 PC 중심, 캠퍼스 학생용 I/F는 Web + Hybrid App 배포를 전제한다.
- 학생용 앱은 국내 기준 Google Play, Apple Store 배포를 고려한다.
- 해외 임대 서비스는 국가별 서비스 환경에 따라 App 배포 여부를 별도 판단한다.
## 개발 해석 포인트
- 이 플랫폼은 단순 콘텐츠 사이트가 아니라 `회원 + 캠퍼스 + 강좌 + 학습 데이터`를 중심으로 동작하는 LMS 성격이 강하다.
- 교사용과 학생용 인터페이스가 명확히 분리되어 있으므로 메뉴, 권한, 응답 데이터도 같은 기준으로 나눠 설계해야 한다.
- 해외 임대/제휴 확장을 전제로 하므로 도메인, 캠퍼스 개인화, 메뉴 노출, 권한 모델에 고정값을 박아 넣지 않는 편이 안전하다.
+33
View File
@@ -0,0 +1,33 @@
# 프로젝트 개요
## 프로젝트 기본 정보
- 프로젝트 유형: 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`를 둔다.
+24
View File
@@ -0,0 +1,24 @@
# 설정 및 실행 가이드
## 설정 규칙
- 공통 설정은 `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 충돌 여부를 확인한다.
## 프로파일
| 프로파일 | 설명 |
|---------|------|
| `local` | 로컬 개발 환경 |
| `pjt` | 프로젝트(개발) 환경 |
## Swagger 접속
- URL: `http://localhost:8106/swagger-ui.html`
- 인증: `swagger.login.id` / `swagger.login.password` (환경별 yaml에 설정)
## 실행 명령
- 로컬 실행: `./gradlew bootRun`
- 테스트 실행: `./gradlew test`
- jar 생성: `./gradlew bootJar`
- Windows 명령: `.\gradlew.bat bootRun`, `.\gradlew.bat test`, `.\gradlew.bat bootJar`
+35
View File
@@ -0,0 +1,35 @@
# 보안 및 응답 규칙
## 예외/응답 규칙
- 공통 예외 응답은 `GlobalExceptionHandler` 에서 처리하므로 Controller 별 개별 예외 처리를 중복해서 늘리지 않는다.
- `@Valid`, 바인딩 실패, JSON 파싱 실패, 타입 오류는 `CODE_4001` 로 통일하고 필드 오류가 있으면 `Map<String, String>` 형태로 반환한다.
- 단순 성공/실패 문자열을 직접 내려주기보다 `ApiResponse.entity(...)``ApiResponseCode` 조합을 우선 사용한다.
- 404/405/500 같은 공통 HTTP 오류도 가능하면 `ApiResponseCode` enum 으로 맞춘다.
## 보안 구조
- 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` → "회원 정보 조회에 성공하였습니다.")
+20
View File
@@ -0,0 +1,20 @@
# 검증 및 체크리스트
## 기본 검증 원칙
- 현재 테스트 코드는 최소 수준이므로 기능 수정 시 단위 테스트 또는 최소 통합 검증 범위를 직접 보강하는 쪽을 우선한다.
- 기동 실패 가능성이 있는 설정 변경은 실행 또는 테스트로 검증한다.
- 검증하지 못한 내용은 추정으로 말하지 않고 미실행 사유를 적는다.
## 변경 시 체크리스트
- 변경한 코드와 직접 관련된 파일만 수정했는지 확인한다.
- 새 API, 스케줄러, 설정 추가 시 관련 설정 파일과 테스트를 함께 검토한다.
- 로그 레벨과 로그량이 운영 환경에서 감당 가능한지 확인한다.
- Mapper 인터페이스 추가/변경 시 XML namespace, id, parameter/result 매핑이 같이 맞는지 확인한다.
- 공개 경로나 권한 정책을 바꿨다면 SecurityConfig 와 Swagger 노출 범위를 같이 확인한다.
- 파일 업로드/다운로드 기능 수정 시 DB 상태, Redis 상태, 실제 파일 시스템 경로가 같이 맞는지 확인한다.
## 기능 특성별 점검 포인트
- 스케줄러 코드는 실행 주기, 중복 실행 가능성, 로그량을 반드시 점검한다.
- 인증 방식이 섞여 있으므로 세션 기반 처리와 JWT `SecurityContext` 사용 위치를 먼저 구분하고 수정한다.
- 파일 경로를 다루는 기능은 상대경로 탈출, 루트 이탈 방지 같은 검증을 같이 본다.
- 설정 파일 수정 시 `local`, `pjt`, 공통 설정 간 차이를 함께 확인한다.