Lalabase
Tickets, Doku, Zeiterfassung und Kundengespräche an einem Ort, durchsuchbar per KI. Für Softwarefirmen mit Kundenprojekten. Open Source: auf deinem eigenen Server oder in unserer Cloud in Deutschland.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
요양보호사·간병인·가사도우미와 요양시설을 연결하는 구인구직 매칭 웹 서비스입니다. 로컬 개발 중에는 프론트가 .env.local 의 VITE_API_BASE_URL 로 백엔드를 가리킨다. 배포 환경변수는 각 대시보드(Vercel / Render)에서 관리한다. 🚧 개발 진행 중. 백엔드 API 기준으로 구현된 범위:檢視完整 README ↗
요양보호사·간병인·가사도우미와 요양시설을 연결하는 구인구직 매칭 웹 서비스입니다.
| 대상 | URL | 비고 |
|---|---|---|
| 서비스 (프론트) | https://care-match-lake.vercel.app | Vercel |
| API 서버 (백엔드) | https://carematch-gtke.onrender.com | Render (무료 인스턴스 — 최초 요청 시 콜드스타트 수십 초) |
| 헬스체크 | https://carematch-gtke.onrender.com/actuator/health | {"status":"UP"} |
로컬 개발 중에는 프론트가
.env.local의VITE_API_BASE_URL로 백엔드를 가리킨다. 배포 환경변수는 각 대시보드(Vercel / Render)에서 관리한다.
🚧 개발 진행 중. 백엔드 API 기준으로 구현된 범위:
API 상세는 docs/API.md, 데이터 모델은 docs/ERD.md 참고.
| 구분 | 기술 |
|---|---|
| 프론트엔드 | React 19 · Vite · TypeScript · Tailwind CSS · React Router — Vercel 배포 |
| 백엔드 | Spring Boot 3 · Spring Security(JWT/OAuth2) · Spring Data JPA — Render 배포 (Docker) |
| DB | PostgreSQL — Neon (로컬은 H2 인메모리) |
| 스키마 마이그레이션 | Flyway (prod 자동 적용, local/test 는 H2 create-drop) |
| 파일 스토리지 | Cloudflare R2 (S3 호환, presigned URL) — 로컬은 stub |
| 결제 | 포트원(PortOne) V2 — 포인트 충전. 서버가 결제 결과를 재조회해 검증, 클라이언트가 보낸 값은 신뢰하지 않음 |
| 지도 | 카카오맵 SDK — 내 주변 일자리(반경 검색 + 클러스터링) |
| 이름 | GitHub | 역할 |
|---|---|---|
| 혁 (팀장) | @heo-hyuk | 백엔드 |
| 신영 | @syyu21b | 프론트엔드 |
| 경수 | @HurKyungsoo | 백엔드 |
| 동한 | @Kim-dong-han | 프론트엔드 |
커밋 히스토리(9/7 프로젝트 시작 ~ 9/16) 기준 파트별 주요 작업 요약.
backend/·frontend/ 분리) 전환, CODEOWNERS·PR 자동 리뷰어 지정, GitHub Flow 협업 규칙(CLAUDE.md), CI(GitHub Actions 빌드체크)@Lob→oid 컬럼 문제), Flyway 마이그레이션 도입, Cloudflare R2 파일 스토리지MATCH_SCORE) 추가 — 노출등급과 무관하게 순수 매칭점수로만 정렬ENUM_MAPPING.md 문서화main — 통합 + 배포 브랜치. 직접 push 금지, PR로만 병합feature/* — 기능 브랜치. main에서 분기 → main으로 PR
feature/be-기능명feature/fe-기능명main에 git 태그(vX.Y.Z)로 표시main push 시 Render / Vercel 자동 배포.github/workflows/ci-frontend.yml, ci-backend.yml) — frontend/, backend/ 변경분에 각각 반응자세한 협업 규칙은 CLAUDE.md 참고.
CareMatch/
├── backend/ # Spring Boot API 서버 (Render 배포)
│ └── src/main/resources/db/migration/ # Flyway 마이그레이션 (V1, V2, ...)
├── frontend/ # React 앱 (Vercel 배포)
├── docs/ # API / ERD / 백엔드 / 마이그레이션 문서
├── .github/ # CODEOWNERS, 워크플로우
└── CLAUDE.md # 협업 규칙
git clone https://github.com/SBS-fullstack-A-team/CareMatch.git
cd CareMatch
cd backend
./gradlew bootRun # 로컬은 H2 인메모리 + Flyway 비활성 → 별도 DB 세팅 불필요
backend/ 를 Gradle 프로젝트로 임포트한다 (루트를 열면 인식 안 됨).backend/.env.example.cd frontend
npm install
cp .env.example .env.local # VITE_API_BASE_URL 설정 (로컬 백엔드면 http://localhost:8080)
npm run dev # http://localhost:5173
http://localhost:5173(Vite) / http://localhost:3000 을 허용한다..env.local 의 VITE_API_BASE_URL 을 배포 API 주소로 두면 된다.prod 는 앱 기동 시 Flyway 가 backend/src/main/resources/db/migration/V*.sql 을 자동 적용한다.V{다음번호}__설명.sql 파일을 같은 PR 에 추가하면 배포 때 반영된다. 이미 배포된 V*.sql 은 수정 금지.docs/MIGRATION.md.지금까지 겪고 해결한 이슈 기록. (괄호 안은 관련 커밋)
64f9ada)./gradlew build 실패. wrapper 가 커밋되지 않아 clone 직후 빌드 불가.build.gradle 의 Java toolchain(17 고정) 제거 → options.release = 17 로 전환(17 바이트코드는 유지). Gradle wrapper(jar·스크립트·properties) 커밋. .gitattributes 로 gradlew=LF / gradlew.bat=CRLF 고정(Mac/Linux 팀원 대응).a1b1f0d)SecurityConfig → OAuth2SuccessHandler → AuthService → PasswordEncoder(@Bean, SecurityConfig 내부) 로 자기 자신으로 돌아오는 순환참조. BeanCurrentlyInCreationException 으로 contextLoads 테스트 실패, bootRun 기동 불가.PasswordEncoder 빈을 의존성 없는 별도 클래스 PasswordConfig 로 분리해 고리를 끊음. AuthenticationManager 빈은 순환 경로가 아니라 그대로 유지.8e1f8e9)carematch-*.vercel.app)처럼 서브도메인이 매번 바뀌어 고정 origin 목록으로는 차단됨. 로컬 Vite 포트(5173)도 미허용.setAllowedOrigins → setAllowedOriginPatterns(패턴 허용)로 변경. 로컬 origin 에 http://localhost:5173 추가(3000 유지). .env.example 도 패턴 형식으로 갱신.0246862)backend/ 하위로 이동하면서 배포·IDE 경로가 어긋남.backend 로 변경. IntelliJ 는 backend/ 를 Gradle 프로젝트로 재임포트. .gitignore 의 wrapper jar 예외 경로를 **/ 로 일반화.1c54fc0)No open ports detected 로 배포 실패. Render 는 $PORT 로 동적 포트를 주입하는데 그 포트로 리스닝하는지 확인함.application.yml 에 server.port: ${PORT:8080} 추가(로컬은 8080 유지). Dockerfile ENTRYPOINT 의 중복 -Dserver.port 제거, exec 로 SIGTERM 전달 개선.@Lob → oid (1c54fc0, 1d079dd, 389551f)Schema-validation: missing table [...]. 운영 DB(Neon)가 비어 있는데 prod 는 ddl-auto: validate.Faq.answer 등 @Lob String 필드가 Hibernate 6 + PostgreSQL 에서 text 가 아닌 oid 컬럼으로 생성 → 문자열 insert/조회가 깨짐 (H2 로컬에선 안 드러남).@Lob → @Column(columnDefinition = "TEXT"). 그리고 Flyway 도입 — prod 는 기동 시 db/migration/V*.sql 을 자동 적용(baseline-on-migrate 로 기존 스키마 위에 얹음), local/test 는 비활성. 이후로 수동 ALTER 불필요.VITE_ 공개 접두어 경고VITE_API_BASE_URL 에 대해 "public prefix 는 브라우저에 노출된다, Config 로 바꿔라" 경고 표시.VITE_ 접두어 변수만 클라이언트에 노출하므로 접두어가 필수다. 값이 공개 API URL 이라 노출돼도 안전(시크릿 아님). 시크릿은 애초에 프론트 환경변수에 두지 않는다.2cae4b1)main의 프론트 빌드가 실패. 파일 안에 <<<<<<</=======/>>>>>>> 마커 텍스트와 양쪽 브랜치 코드가 그대로 섞여 커밋돼 있었음(중복 import, 존재하지 않는 변수 참조, JSX 구조 깨짐).main의 리팩터링 이전 시점에서 갈라진 상태로 오래 유지되다 머지되면서, git의 라인 기반 diff가 무관한 섹션에 코드를 잘못 이어붙임. 사람이 병합 충돌 마커를 실수로 안 지우고 그대로 커밋.account_email 동의항목은 사업자등록증이 없어도 "개인 개발자 본인인증"으로 신청 가능하지만 카카오 심사(수일)가 필요해서, 승인 전까지는 profile_nickname만 쓰고 이메일이 없으면 OAuthAttributes.emailOrPlaceholder()가 임시 이메일을 채워주도록 처리(a5c734b).62e83e8)main이 깨진 걸 아무도 몰랐음..github/workflows/ci-frontend.yml(npm ci → lint → tsc -b → build), ci-backend.yml(./gradlew build, 테스트 포함) 추가. pull_request 트리거 + paths 필터로 관련 있는 변경에만 반응해서 평소엔 조용하고, PR에서 빌드가 깨지면 그 자리에서 바로 표시됨.localhost:5173)에서 띄우고 API base URL 을 배포된 Render 백엔드로 잡으면, 회원가입 등 API 호출이 CORS 로 막힘. 프론트 쪽 설정(.env.local 등)은 다 맞아도 재현됨.CORS_ALLOWED_ORIGINS 환경변수가 Vercel 도메인만 화이트리스트로 등록돼 있어서(docs/BACKEND.md 참고 — 와일드카드 금지, 화이트리스트만 허용), localhost 는 배포 백엔드 기준으로 허용 origin 이 아님. 코드나 로컬 설정 문제가 아니라 서버(Render) 쪽 화이트리스트 문제.cd backend && ./gradlew bootRun) 후 프론트가 http://localhost:8080 을 바라보게 설정. 로컬 백엔드 기본 CORS 설정엔 localhost:5173/3000 이 이미 포함돼 있어 바로 동작.CORS_ALLOWED_ORIGINS 에 http://localhost:5173 을 콤마로 추가(Render 대시보드 → 서비스 → Environment). 대시보드 접근 권한이 있는 사람만 가능.UnexpectedRollbackException (4c2779c)complete)·인재 연락처 열람·구인공고 스크랩처럼 "확인(존재 여부/상태) → 부수효과(포인트 차감·적립, DB 저장) → 저장" 순서인 로직에서, 두 번째 저장이 unique 제약 위반으로 실패할 때 그 예외를 catch해서 조용히 넘어가는 방식으로 동시요청을 처리하고 있었음. 동시성 재현 테스트(같은 인재를 8개 스레드로 동시에 열람)를 돌려보니 UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only 발생.UnexpectedRollbackException 을 던진다 — catch 블록이 있어도 실제로는 요청 하나가 처리되지 않은 예외로 끝나는 상태였음.SELECT ... FOR UPDATE, findByIdForUpdate)을 걸어서 "확인 → 부수효과 → 저장" 구간 자체를 애초에 경쟁이 안 생기도록 직렬화. PointChargeService.complete()(같은 결제건 이중 적립 방지), ContactUnlockService.unlock()/grantFreeAccess()(연락처 열람 이중 차감 방지), ScrapService.scrap()(찜하기 중복 클릭) 세 곳 모두 동일 패턴으로 수정. ContactUnlockServiceConcurrencyTest 로 회귀 테스트 추가 — 수정 전 코드로는 이 테스트가 실제로 실패함을 확인.e92e5b5)Member.point 컬럼과 point_charge 테이블을 새로 추가했는데, 같은 PR에 마이그레이션 파일(V*.sql)을 포함하지 않았음. ddl-auto: validate 인 운영에서 스키마가 없으면 기동 자체가 실패해야 하는데, 실제로는 배포가 정상 동작 중이었음 — 어떤 경로로든 운영 DB(Neon)에 스키마가 먼저 반영된 채로 git 에는 그 변경 이력이 없는 상태.V12__point_charge.sql 을 사후 작성 — 운영에 이미 반영돼 있을 가능성을 고려해 ALTER TABLE ... ADD COLUMN IF NOT EXISTS, CREATE TABLE IF NOT EXISTS 로 전부 멱등하게 작성. H2 로 (1) 빈 DB에 V1~V12 순서대로 적용 (2) 컬럼/테이블이 이미 있는 상태에서 재실행 — 둘 다 에러 없이 통과함을 확인.1656b25)paymentId 를 "point-" + UUID.randomUUID() 형태의 긴 문자열로 생성했는데, 일부 PG사는 주문번호(orderId) 길이에 제한을 둠 — 그 제한을 초과.paymentId 길이를 PG사 주문번호 제한 이내로 축소.