diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f3dcdd1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,209 @@
+
+
+# ๐งน LinClean API
+
+**๋งํฌ ์ ์ฅ ยท AI ๋ถ์ ๋ชจ๋ฐ์ผ ์๋น์ค์ ๋ฐฑ์๋ REST API ์๋ฒ**
+
+[](https://openjdk.org/projects/jdk/21/)
+[](https://spring.io/projects/spring-boot)
+[](https://www.postgresql.org/)
+[-DC382D?style=flat-square&logo=redis&logoColor=white)](https://valkey.io/)
+[](https://gradle.org/)
+[](https://www.docker.com/)
+
+[](https://github.com/403-Forb2dden/LinClean-BE-spring/actions/workflows/CI.yml)
+[](https://github.com/403-Forb2dden/LinClean-BE-spring/actions/workflows/CD.yml)
+
+
+
+---
+
+## ๐ ํ๋ก์ ํธ ์๊ฐ
+
+**LinClean**์ ์ฌ์ฉ์๊ฐ ์ ์ฅํ ๋งํฌ(URL)๋ฅผ ์นดํ
๊ณ ๋ฆฌ๋ณ๋ก ๊ด๋ฆฌํ๊ณ , AI ๋ถ์ ์์ง์ ํตํด ๋งํฌ๋ฅผ ๋ถ์ยท๋ถ๋ฅํด ์ฃผ๋ ๋ชจ๋ฐ์ผ ์๋น์ค์
๋๋ค.
+
+์ด ๋ ํฌ์งํ ๋ฆฌ(`linclean-api`)๋ ๊ทธ์ค **๋ฐฑ์๋ REST API ์๋ฒ**๋ก, ๋ชจ๋ฐ์ผ ์ฑ(Expo)์ ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ํ์ยท๋งํฌยท๋ถ์ยท์ฝ๊ดยท๊ณต์ง ๋๋ฉ์ธ์ ๊ด๋ฆฌํฉ๋๋ค. ์ธ์ฆ์ **Clerk(OAuth2 JWT)** ๋ก ์์ํ๊ณ , ๋งํฌ ๋ถ์์ ๋ณ๋์ **FastAPI ๋ถ์ ์์ง**๊ณผ ๋น๋๊ธฐ๋ก ์ฐ๋ํฉ๋๋ค.
+
+## โจ ์ฃผ์ ๊ธฐ๋ฅ
+
+- **๐ ๋งํฌ ๊ด๋ฆฌ** โ ๋งํฌ ์ ์ฅ/์กฐํ/์ญ์ , ๋ถ๋งํฌยท์นดํ
๊ณ ๋ฆฌยท์ ๋ชฉ ์์ , ์ค๋ณต ํ์ธ
+- **๐๏ธ ์นดํ
๊ณ ๋ฆฌ ๊ด๋ฆฌ** โ ์นดํ
๊ณ ๋ฆฌ ์์ฑ/์กฐํ/์์ /์ญ์
+- **๐ค AI ๋ถ์** โ ๋ถ์ ์์ฒญ, ๋ถ์ ๊ฒฐ๊ณผ ์กฐํ, ๋ถ์ ํต๊ณ ์ง๊ณ (FastAPI ๋ถ์ ์์ง๊ณผ ๋น๋๊ธฐ ์ฐ๋ + ๋ด๋ถ ์ฝ๋ฐฑ ์์ )
+- **๐ค ํ์ ๊ด๋ฆฌ** โ Clerk ๊ธฐ๋ฐ ํ์ ๋๊ธฐํ, ํ์ ํํด ์ *Soft Delete โ ๋ณด์กด ๊ธฐ๊ฐ ๊ฒฝ๊ณผ ํ Hard Delete* ์ค์ผ์ค๋ง
+- **๐ ์ด์ฉ์ฝ๊ด / ๐ข ๊ณต์ง์ฌํญ** โ ์ฝ๊ด ํ์
๋ณ ์กฐํ, ๊ณต์ง ๋ชฉ๋กยท์์ธ ์กฐํ
+- **๐ ์ธ์ฆยท๋ณด์** โ Clerk OAuth2 JWT ๊ฒ์ฆ, ๋ด๋ถ ํต์ ์ฉ API Key ํํฐ(`InternalApiKeyFilter`)
+- **๐ ๋ก๊น
ยท๋ชจ๋ํฐ๋ง** โ Logback + Logstash JSON ํ์ผ ๋ก๊น
, ์๋ฌ ๋ฐ์ ์ **Discord ์นํ
์๋ฆผ**, Actuator ํฌ์ค ์ฒดํฌ
+
+## ๐ ๏ธ ๊ธฐ์ ์คํ
+
+| ๊ตฌ๋ถ | ๊ธฐ์ |
+| --- | --- |
+| **Language** | Java 21 (LTS) |
+| **Framework** | Spring Boot 3.5.13, Spring MVC (Spring Web), Spring Security |
+| **HTTP Client** | Spring WebClient (์ธ๋ถ ๋ถ์ ์์งยทClerk API ํธ์ถ์ฉ) |
+| **Auth** | OAuth2 Resource Server (JWT) ยท Clerk |
+| **Database** | PostgreSQL, Spring Data JPA (Hibernate), Flyway (๋ง์ด๊ทธ๋ ์ด์
) |
+| **Cache** | Redis (Valkey ํธํ), Spring Data Redis |
+| **API Docs** | SpringDoc OpenAPI 2.8.6 (Swagger UI) |
+| **Logging** | Logback + Logstash Logback Encoder (JSON), Discord Webhook |
+| **Build** | Gradle 8.14.4 |
+| **Test** | JUnit 5, Spring Boot Test, Testcontainers (PostgreSQL), OkHttp MockWebServer |
+| **Infra** | Docker (๋ฉํฐ์คํ
์ด์ง ๋น๋), GitHub Actions (CI/CD), AWS EC2 + SSM |
+
+## ๐๏ธ ์์คํ
์ํคํ
์ฒ
+
+```mermaid
+flowchart LR
+ App["๐ฑ ๋ชจ๋ฐ์ผ ์ฑ
(Expo)"]
+
+ subgraph LinClean API["๐งน LinClean API (Spring Boot)"]
+ direction TB
+ Sec["Security
(Clerk JWT ๊ฒ์ฆ / Internal API Key)"]
+ Domain["Domain Layer
analysis ยท link ยท member
notice ยท terms"]
+ Sec --> Domain
+ end
+
+ PG[("๐ PostgreSQL")]
+ Redis[("๐ด Redis
(Valkey)")]
+ Clerk["๐ Clerk
(JWKS / ์ธ์ฆ)"]
+ Engine["๐ค FastAPI
๋ถ์ ์์ง"]
+
+ App -->|REST API + JWT| LinClean
+ Domain --> PG
+ Domain --> Redis
+ Sec -.JWKS ๊ฒ์ฆ.-> Clerk
+ Domain -.๋ถ์ ์์ฒญ (๋น๋๊ธฐ).-> Engine
+ Engine -.๋ถ์ ๊ฒฐ๊ณผ ์ฝ๋ฐฑ.-> Sec
+```
+
+## ๐ ํ๋ก์ ํธ ๊ตฌ์กฐ
+
+```
+src/main/java/com/linclean
+โโโ LincleanApiApplication.java # ์ ํ๋ฆฌ์ผ์ด์
์ง์
์
+โโโ domain # ๋น์ฆ๋์ค ๋๋ฉ์ธ (controllerยทserviceยทentityยทdtoยทrepository)
+โ โโโ analysis # ๋งํฌ ๋ถ์ ์์ฒญยท๊ฒฐ๊ณผยทํต๊ณ
+โ โโโ link # ์ ์ฅ ๋งํฌ & ์นดํ
๊ณ ๋ฆฌ
+โ โโโ member # ํ์ ๊ด๋ฆฌยทํํด ์ค์ผ์ค๋ง
+โ โโโ notice # ๊ณต์ง์ฌํญ
+โ โโโ terms # ์ด์ฉ์ฝ๊ด
+โ โโโ device # ๊ธฐ๊ธฐ ์ ๋ณด
+โ โโโ notification # ์๋ฆผ
+โโโ security # ์ธ์ฆ ์ฃผ์ฒด(MemberPrincipal) / ์ธ์ฆ ์๋ํฌ์ธํธ
+โโโ global # ๊ณตํต ๊ธฐ๋ฅ
+ โโโ config # SecurityยทRedisยทSwaggerยทAsyncยทWebClient ๋ฑ ์ค์
+ โโโ entity # BaseEntity (Auditing)
+ โโโ web # ๊ณตํต ์๋ต ํฌ๋งท(ApiResponse)
+ โโโ exception # ์ ์ญ ์์ธ ์ฒ๋ฆฌ(GlobalExceptionHandlerยทErrorCode)
+ โโโ log # JSON ๋ก๊ทธ / Discord ์นํ
Appender
+ โโโ security # InternalApiKeyFilter (๋ด๋ถ ํต์ ์ธ์ฆ)
+
+src/main/resources
+โโโ application.yml # ๋ฉ์ธ ์ค์ (+ dev / prod / test ํ๋กํ)
+โโโ logback-spring.xml # ๋ก๊น
์ค์
+โโโ db/migration # Flyway ๋ง์ด๊ทธ๋ ์ด์
์คํฌ๋ฆฝํธ
+```
+
+## ๐ ์์ํ๊ธฐ
+
+### ์ฌ์ ์๊ตฌ์ฌํญ
+
+- **JDK 21**
+- **PostgreSQL**, **Redis(Valkey)** โ ๋ก์ปฌ ์ค์น ๋๋ Docker
+- **Clerk** ์ธ์ฆ ํค, **FastAPI ๋ถ์ ์์ง** ์๋ํฌ์ธํธ (์ธ๋ถ ์ฐ๋)
+
+### ํ๊ฒฝ ๋ณ์
+
+๋ฃจํธ์ `.env` ํ์ผ์ ์์ฑํฉ๋๋ค (`application.yml`์ด `optional:file:.env`๋ก ๋ก๋).
+
+| ํค | ์ค๋ช
|
+| --- | --- |
+| `SPRING_PROFILES_ACTIVE` | ํ์ฑ ํ๋กํ (`dev` / `prod` / `test`) |
+| `API_PORT` | ์๋ฒ ํฌํธ |
+| `POSTGRES_HOST` ยท `POSTGRES_PORT` ยท `POSTGRES_DATABASE` ยท `POSTGRES_USER` ยท `POSTGRES_PASSWORD` | PostgreSQL ์ฐ๊ฒฐ ์ ๋ณด |
+| `REDIS_HOST` ยท `REDIS_PORT` ยท `REDIS_PASSWORD` | Redis(Valkey) ์ฐ๊ฒฐ ์ ๋ณด |
+| `CLERK_JWKS_URI` ยท `CLERK_ISSUER` ยท `CLERK_SECRET_KEY` | Clerk OAuth2 JWT ์ค์ |
+| `ANALYSIS_ENGINE_URL` | FastAPI ๋ถ์ ์์ง Base URL |
+| `ANALYSIS_ENGINE_CONNECT_TIMEOUT_MS` ยท `ANALYSIS_ENGINE_READ_TIMEOUT_S` | ๋ถ์ ์์ง ํต์ ํ์์์ (๊ธฐ๋ณธ 3000ms / 5s) |
+| `INTERNAL_API_KEY` | ๋ด๋ถ ํต์ (๋ถ์ ์์ง โ Spring) ์ธ์ฆ ํค |
+| `MEMBER_WITHDRAWAL_RETENTION_DAYS` | ํํด ํ์ ๋ณด์กด ๊ธฐ๊ฐ (๊ธฐ๋ณธ 30์ผ) |
+| `MEMBER_WITHDRAWAL_HARD_DELETE_CRON` | Hard Delete ์ค์ผ์ค cron (๊ธฐ๋ณธ ๋งค์ผ 03:00) |
+| `DISCORD_WEBHOOK_URL` | ์๋ฌ ๋ก๊ทธ Discord ์๋ฆผ ์นํ
URL |
+
+### ๋น๋ & ์คํ
+
+```bash
+# ๋น๋
+./gradlew build
+
+# ๋ก์ปฌ ์คํ
+./gradlew bootRun
+
+# ๋๋ JAR ์ง์ ์คํ
+java -jar build/libs/linclean-api-0.0.1-SNAPSHOT.jar
+```
+
+### Docker ์คํ
+
+```bash
+docker build -t linclean-api .
+docker run -p 8080:8080 --env-file .env linclean-api
+```
+
+### Spring ํ๋กํ
+
+| ํ๋กํ | ์ฉ๋ |
+| --- | --- |
+| `dev` | ๋ก์ปฌ ๊ฐ๋ฐ (SQL ๋ก๊น
ยทSwagger ํ์ฑ, ๊ธฐ๋ณธ๊ฐ) |
+| `prod` | ์ด์ (Graceful shutdown ๋ฑ) |
+| `test` | ํ
์คํธ (Testcontainers ๊ธฐ๋ฐ) |
+
+## ๐ API ๋ฌธ์
+
+์ ํ๋ฆฌ์ผ์ด์
์คํ ํ Swagger UI์์ ์ ์ฒด API ๋ช
์ธ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
+
+- **Swagger UI**: `http://localhost:{API_PORT}/swagger-ui.html`
+- **OpenAPI Docs**: `http://localhost:{API_PORT}/v3/api-docs`
+
+### ์ฃผ์ ์๋ํฌ์ธํธ
+
+| ๋๋ฉ์ธ | Method & Path | ์ค๋ช
|
+| --- | --- | --- |
+| ์ธ์ฆ | `GET /api/v1/auth/me` | ๋ด ์ธ์ฆ ์ ๋ณด ์กฐํ |
+| ๋ถ์ | `POST /api/v1/analyses` | ๋งํฌ ๋ถ์ ์์ฒญ |
+| ๋ถ์ | `GET /api/v1/analyses/statistics` | ๋ถ์ ํต๊ณ ์กฐํ |
+| ๋ถ์ | `GET /api/v1/analyses/{analysisId}` | ๋ถ์ ๊ฒฐ๊ณผ ์กฐํ |
+| ๋งํฌ | `POSTยทGET /api/v1/saved-links` | ๋งํฌ ์ ์ฅ / ๋ชฉ๋ก ์กฐํ |
+| ๋งํฌ | `GET /api/v1/saved-links/check` | ๋งํฌ ์ค๋ณต ํ์ธ |
+| ๋งํฌ | `PATCH /api/v1/saved-links/{id}/{bookmark\|category\|title}` | ๋ถ๋งํฌยท์นดํ
๊ณ ๋ฆฌยท์ ๋ชฉ ์์ |
+| ๋งํฌ | `DELETE /api/v1/saved-links/{id}` | ๋งํฌ ์ญ์ |
+| ์นดํ
๊ณ ๋ฆฌ | `POSTยทGET /api/v1/categories` | ์นดํ
๊ณ ๋ฆฌ ์์ฑ / ๋ชฉ๋ก ์กฐํ |
+| ์นดํ
๊ณ ๋ฆฌ | `PATCHยทDELETE /api/v1/categories/{id}` | ์นดํ
๊ณ ๋ฆฌ ์์ / ์ญ์ |
+| ํ์ | `DELETE /api/v1/members/me` | ํ์ ํํด |
+| ์ฝ๊ด | `GET /api/v1/terms/{type}` | ์ฝ๊ด ํ์
๋ณ ์กฐํ |
+| ๊ณต์ง | `GET /api/v1/notices` ยท `GET /api/v1/notices/{id}` | ๊ณต์ง ๋ชฉ๋ก / ์์ธ ์กฐํ |
+| ํฌ์ค | `GET /actuator/health` | ํฌ์ค ์ฒดํฌ |
+
+> `POST /internal/analysis-result` ๋ฑ `/internal/**` ๊ฒฝ๋ก๋ ๋ถ์ ์์ง๊ณผ์ ๋ด๋ถ ํต์ ์ ์ฉ์ผ๋ก, `INTERNAL_API_KEY`๋ก ๋ณดํธ๋ฉ๋๋ค.
+
+## ๐งช ํ
์คํธ
+
+```bash
+./gradlew test
+```
+
+> ํตํฉ ํ
์คํธ๋ **Testcontainers(PostgreSQL)** ๋ฅผ ์ฌ์ฉํ๋ฏ๋ก ์คํ ํ๊ฒฝ์ **Docker**๊ฐ ํ์ํฉ๋๋ค.
+
+## ๐ CI/CD
+
+GitHub Actions๋ก ๋น๋ยท๋ฐฐํฌ๋ฅผ ์๋ํํฉ๋๋ค.
+
+- **CI** (`.github/workflows/CI.yml`) โ `dev`/`main` push ๋ฐ `dev` ๋์ PR์์ Gradle ํ
์คํธ ์คํ
+- **CD** (`.github/workflows/CD.yml`) โ `main` CI ์ฑ๊ณต ์ Docker ์ด๋ฏธ์ง๋ฅผ ๋น๋ํด Docker Hub์ ํธ์ํ๊ณ , **AWS SSM**์ผ๋ก EC2์์ `docker compose`๋ฅผ ํตํด ๋ฌด์ค๋จ ๋ฐฐํฌ
+
+> ๋ฐฐํฌ ์ํคํ
์ฒ ์์ธ๋ [`docs/๋ฐฐํฌ.md`](docs/๋ฐฐํฌ.md)๋ฅผ ์ฐธ๊ณ ํ์ธ์.
+
+## ๐ ์ปจ๋ฒค์
+
+- **์ปค๋ฐ ์ปจ๋ฒค์
**: [`docs/commit.md`](docs/commit.md) ์ฐธ๊ณ
+- **๋ธ๋์น ์ ๋ต**: ๊ธฐ๋ฅ ๋ธ๋์น โ `dev`(PR base) โ `main`(๋ฐฐํฌ)