도메인별 스키마(company·place·fact·local·site·job)를 걷어내고 public 한 벌로 폈다.
스키마 한정자가 붙은 순간부터 ORM·raw SQL·테스트 픽스처가 각자 그 이름을 들고 다녀야 했다.
- 공용 콘텐츠를 한 테이블로 되돌린다. spots·region_stories 를 따로 파 놓고 보니
같은 성격이 세 곳으로 갈라져 있었다 — `area_contents` 가 처음부터 content_type 으로
종류를 가르는 설계였고 그걸 쓰면 됐다. 관계(거리·숨김)만 `place_area_refs` 로 남긴다.
- migrations/ + scripts/migrate.py: `init.sql` 은 **DB 를 처음 만들 때만** 돈다. 파일에
컬럼을 더해도 이미 데이터가 든 DB 에는 반영되지 않는다 — 실제로 TourAPI 가 주변 정보를
받아 와도 저장할 곳이 없어 축제·맛집이 0건이었고, 화면에는 "그냥 안 나오는 것" 으로만 보였다.
DECISIONS.md 가 예고한 그대로다("운영 DB 가 생기는 순간 다시 필요해진다").
Alembic 을 쓰지 않는 이유는 스키마 정의가 이미 두 곳(ORM·init.sql)이라 세 번째를
더하면 어긋날 자리가 하나 더 생기기 때문이다.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
77 lines
2.2 KiB
CSS
77 lines
2.2 KiB
CSS
/*
|
|
* 두 앱(admin / site)이 공유하는 최소 기본 스타일.
|
|
* 폰트 로딩 · 스크롤바 · 접근성 유틸만 둔다. 색은 각 앱의 토큰이 정한다.
|
|
*/
|
|
|
|
/* Pretendard 가변폰트 self-host (public/fonts). 한국어 본문 기본 서체.
|
|
파일이 없으면 @font-face 가 조용히 실패하고 다음 폴백으로 넘어간다 — 빌드는 깨지지 않는다. */
|
|
@font-face {
|
|
font-family: 'Pretendard Variable';
|
|
font-weight: 45 920;
|
|
font-style: normal;
|
|
font-display: swap;
|
|
src: url('/fonts/PretendardVariable.woff2') format('woff2');
|
|
}
|
|
|
|
html {
|
|
-webkit-text-size-adjust: 100%;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
-webkit-font-smoothing: antialiased;
|
|
-moz-osx-font-smoothing: grayscale;
|
|
/* 한글은 단어 중간에서 끊기면 읽기 나빠진다. 어절 단위로 줄바꿈. */
|
|
word-break: keep-all;
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
/* 가로 스냅 슬라이더용 — 스크롤바를 숨긴다. */
|
|
.no-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
.no-scrollbar {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
/*
|
|
* 스크롤바.
|
|
*
|
|
* ★ `::-webkit-scrollbar` 로 폭을 주면 **macOS 의 오버레이 스크롤바가 꺼진다.**
|
|
* 그러면 스크롤바가 자리를 차지하는 옛날 방식으로 바뀌어, 맥에서 화면 오른쪽에
|
|
* 6px 짜리 빈 띠가 늘 생긴다(실측: innerWidth 1440 ↔ clientWidth 1434).
|
|
* 표준 속성만 쓰면 맥은 오버레이를 유지하고(자리 차지 0), 윈도우·리눅스에서는
|
|
* 가는 스크롤바가 된다.
|
|
*/
|
|
html {
|
|
scrollbar-width: thin;
|
|
}
|
|
|
|
/* 스크린리더 전용 — 화면에서 감추되 접근성 트리에는 남긴다.
|
|
AI 크롤러도 이 텍스트를 읽는다(display:none 이면 안 읽는다). */
|
|
.sr-only {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
padding: 0;
|
|
margin: -1px;
|
|
overflow: hidden;
|
|
clip: rect(0, 0, 0, 0);
|
|
white-space: nowrap;
|
|
border-width: 0;
|
|
}
|
|
|
|
/* 모션 민감 사용자 — 장식 애니메이션을 끈다. */
|
|
@media (prefers-reduced-motion: reduce) {
|
|
*,
|
|
*::before,
|
|
*::after {
|
|
animation-duration: 0.01ms !important;
|
|
animation-iteration-count: 1 !important;
|
|
transition-duration: 0.01ms !important;
|
|
scroll-behavior: auto !important;
|
|
}
|
|
}
|