본문으로 건너뛰기
페이지 목차
이 페이지에서 검색

AI 드리븐

이 페이지에 묻기

AI 드리븐 · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.

생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.

AI · DEVELOPMENT

AI 드리븐

생성 수정

요구사항과 역할 정의부터 구현·검증·배포·운영까지, AI와 함께 개발하며 사람이 판단할 기준을 정리합니다.

26개 문서 · 2일차 · 12 / 26

11차시 · 프론트엔드 역할: 화면과 경계

지도 위치 : 2일차 · 구현과 검증 · 구현 | 이전: 10차시 백엔드 역할: 서버 로직 | 다음: 12차시 데이터 관리 역할 키워드 : 화면과 서버의 역할 경계, 데이터 연동, 연동 시 주의점

이 차시를 다 읽으면

  1. 화면과 서버가 맡는 일을 표로 가르고, "화면의 검사는 편의를 위한 것" 이라는 말을 예로 설명할 수 있다.
  2. 공개 환경변수 를 유와 종차로 정의하고, 환경변수 이름만 보고 비밀값 노출을 판별할 수 있다.
  3. CORS 가 무엇을 막고 무엇을 막지 않는지 말할 수 있다.
  4. API 호출을 한 곳에 모으기 · 요청과 응답 모양 공유 · 네 가지 화면 상태가 각각 어떤 문제를 막는지 말할 수 있다.
  5. 브라우저 개발자 도구의 Network 탭 으로 화면이 서버에 보낸 것과 받은 것을 직접 확인할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1누가 판정하는가화면 — 보여 주고 입력받고 전달서버 — 금액 · 자리 · 권한 판정같은 규칙이 두 군데 생기는가화면이 판정 ↔ 서버가 판정 (②의 파생)
2사용자 브라우저로 전달되는가공개 — 화면 코드에 박혀 누구나 봄비밀 — 서버 안에만 있음공개 키 ↔ 비밀 키, 공개 환경변수 ↔ 일반 환경변수이 차시의 축
3어디서 돌아가는가로컬 — localhost원격 — 배포된 주소서버 주소 · 허용 출처가 환경마다 달라짐④ 로컬 ↔ 원격
4응답을 기다려서 표시하는가기다린다 — 서버 응답 후 "예약 완료"기다리지 않는다 — 누르자마자 "예약 완료"실패했는데 성공으로 보이는 사고⑥ 동기 ↔ 비동기

이 차시가 답하는 질문은 "화면은 어디까지 하고, 어디서 멈춰야 하는가" 입니다. 10차시에서 판정을 서버에 두었으니, 이번에는 그 반대편에서 같은 경계를 봅니다. 입력은 앞에서 배운 디자인 규칙과 검증을 통과한 시안(6 · 7차시), 그리고 API 명세(4차시)입니다.


1. ⭐ 화면과 서버의 경계

1.1 정의와 경계표

프론트엔드 (화면) — [서비스의 한 층]인데, [ 사용자 기기에서 돌아가며 보여 주고, 입력받고, 서버의 판정을 전달한다 ]는 점에서 판정을 내리는 서버(백엔드)와 구별된다.

일화면서버
입력 형식 검사 (빈칸, 숫자)⭕ 사용자 편의용⭕ 진짜 검사
금액 계산표시만 (서버가 준 값)⭕
남은 자리 판단표시만⭕
권한 판단버튼 숨김 정도 (편의용)⭕ 진짜 차단
로딩 · 에러 표시⭕—
비밀값 사용❌ 절대 안 됨⭕

화면의 검사는 편의를 위한 것이고, 보안을 위한 것이 아니다.

화면에서 버튼을 숨겨도 API는 직접 호출할 수 있습니다(10차시). 화면의 검사는 사용자가 실수를 서버에 보내기 전에 알려 주는 친절일 뿐입니다.

1.2 경계가 흐려지면 — 같은 규칙이 두 군데

상황결과
취소 가능 기한을 화면은 "3일 전까지", 서버는 "2일 전까지"로 판단화면엔 "취소" 버튼이 보이는데 누르면 거절당함
⭕ 서버가 응답에 "cancellable": true를 담아 주고 화면은 그 값만 따름규칙은 서버 한 곳에만 있음

규칙이 두 군데 있으면 언젠가 반드시 달라집니다. 한쪽만 고쳐지기 때문입니다. 그래서 화면은 판정 결과를 받아서 보여 주기만 합니다.

1.3 반례 — 이건 화면의 일이 아닙니다

대상왜 아닌가
화면이 "가격 × 인원"을 계산해 서버로 보냄판정입니다. 화면은 서버가 준 금액을 표시만
남은 자리 0이면 화면이 예약 요청을 아예 안 보냄 (그리고 서버는 검사 안 함)편의로는 좋지만, 서버 검사를 대신할 수 없음
서버가 아직 없어서 화면에 가짜 데이터를 박아 둠 → 잊음연동이 됐는지 안 됐는지 화면만 봐서는 모름. 연동 뒤 반드시 제거

2. 데이터 연동

2.1 API 호출을 한 곳에 모으기

apps/web/src/api/
├── client.ts         # 서버 주소, 로그인 증표 붙이기, 에러 형식 처리를 한 곳에서
├── classes.ts        # getClasses(), getClass(id)
└── reservations.ts   # createReservation(), getMyReservations()

🔍 읽는 포인트 : 서버와 통신하는 코드가 api/ 폴더 한 곳 에 있는지만 보면 됩니다. 화면 조각마다 서버 호출이 흩어져 있으면 에러 처리가 제각각이 됩니다.

2.2 요청 · 응답 모양을 공유하기

9차시 뼈대에서 만든 packages/shared에 요청 · 응답의 모양(필드 이름과 타입)을 두고 화면과 서버가 함께 씁니다. 한쪽이 모양을 바꾸면 다른 쪽에서 타입 오류로 바로 드러납니다. 9차시의 "데이터 모양" 이음매를 기계가 지켜 주는 장치입니다.

2.3 네 가지 화면 상태

앞에서 배운 디자인 규칙(6차시)의 네 상태를 실제 데이터와 연결합니다.

상태화면빠지면
로딩 중스켈레톤(회색 자리 표시)빈 화면에서 사용자가 버튼을 여러 번 누름
성공 · 데이터 있음목록—
성공 · 데이터 없음"아직 클래스가 없어요" 안내고장 난 것처럼 보임
실패에러 코드별 안내 (SOLD_OUT → "방금 마감됐어요")alert("에러 발생") 하나로 끝남

3. ⭐ 공개 환경변수와 비밀값

3.1 정의

앞에서 배운 환경변수(9차시)에는 두 종류가 있습니다.

공개 환경변수 — [환경변수]인데, [ 화면을 만들(빌드할) 때 코드 속에 그대로 박혀 사용자 브라우저로 전달된다 ]는 점에서 서버 안에서만 읽히는 일반 환경변수와 구별된다.

화면 도구들은 이름 앞에 정해진 접두사 가 붙은 환경변수만 화면 코드에 넣어 줍니다.

NEXT_PUBLIC_...   VITE_...   REACT_APP_...   PUBLIC_...

🔍 읽는 포인트 : 이 접두사가 붙은 이름은 "누구나 볼 수 있음" 표시입니다. 뒤에 SECRET, PRIVATE, PASSWORD, DATABASE_URL이 붙어 있으면 코드를 몰라도 즉시 사고 라고 판단할 수 있습니다.

3.2 경계 — 공개해도 되는 것과 안 되는 것

공개 (화면에 둬도 됨)비밀 (서버에만)
예서버 주소, 결제 대행사의 공개 키 (클라이언트 키)결제 비밀 키 , DB 비밀번호, 로그인 증표 서명 키
노출되면문제없음 — 원래 보이라고 만든 값남이 내 권한으로 결제 승인 · 취소, DB 접속
0절 축 2왼쪽오른쪽

⚠️ "화면 코드는 난독화(읽기 어렵게 압축)되니까 괜찮다"는 틀린 말입니다. 브라우저에 도착한 것은 전부 사용자 손에 있습니다.

앞으로 다시 만납니다 — 14차시에서 비밀값을 정식으로 정의하고 "두지 않을 곳"을 정리합니다. 16차시 결제에서는 공개 키(결제창 띄우기)와 비밀 키(승인)가 실제로 나뉘어 쓰이는 모습을 봅니다.


4. CORS — 브라우저가 지키는 규칙

4.1 정의

출처 (Origin) — 주소의 앞부분(https://classon.kr처럼 방식 + 도메인 + 포트)입니다. 화면이 localhost:3000, 서버가 localhost:4000이면 포트가 달라서 다른 출처 입니다.

CORS (교차 출처 리소스 공유) — [브라우저 보안 규칙]인데, [ 다른 출처의 서버 응답을 화면 코드가 읽으려면 그 서버가 "이 출처는 허락한다"는 표시를 응답에 담아야 한다 ]는 점에서 서버가 요청자를 확인하는 인증 · 인가와 구별된다.

4.2 경계 — 무엇을 막고 무엇을 막지 않는가

CORS인증 · 인가 (10차시)
누가 검사하나브라우저서버
막는 것남의 사이트 화면이 사용자 브라우저를 통해 우리 서버 응답을 읽는 것권한 없는 요청 자체
curl · 서버끼리 호출❌ 막지 않음⭕ 막음

⚠️ CORS는 서버를 지키는 장치가 아닙니다. CORS 설정이 아무리 엄격해도 curl로 직접 부르는 요청은 그대로 서버에 도착합니다. 서버의 보호는 여전히 10차시의 인증 · 인가가 합니다.

증상대응
브라우저 콘솔에 빨간 CORS 에러, 그런데 curl로는 잘 됨서버의 허용 출처 목록 에 화면 주소를 추가
AI가 "CORS 에러를 고쳤습니다" → 허용 목록이 *(전부 허용)⚠️ 피합니다. 화면 주소를 명시
로컬에선 되는데 배포 후 CORS 에러0절 축 3. 허용 출처를 환경변수 로 두고 환경마다 값을 바꿈 (15차시)

💡 비유는 마지막에 — CORS는 건물 입구가 아니라 방문객 휴대폰에 깔린 규칙 입니다. 휴대폰(브라우저)이 "이 건물이 허락한 앱에만 내용을 보여 준다"고 지킬 뿐, 휴대폰 없이 걸어 들어오는 사람은 막지 못합니다.


5. 연동 시 주의점

문제증상대응
환경별 주소로컬에선 되는데 배포하면 안 됨서버 주소를 공개 환경변수로 (VITE_API_URL 등)
중복 요청결제 버튼 두 번 클릭 → 예약 두 개요청 중 버튼 비활성화 + 서버 측 방지 (16차시) — 화면만으로는 부족
낙관적 표시응답 전에 "예약 완료" → 실제론 실패0절 축 4. 예약 · 결제처럼 중요한 동작은 서버 응답 후 표시
모양 불일치화면에 undefined공유 타입(2.2), 명세 대조
비밀값 노출비밀 키가 화면 코드에3절. 공개 환경변수에는 공개 키만

6. 클래스온에 적용하면

프론트엔드 에이전트 정의의 핵심 줄입니다.

## 맥락
- 시안: design/*.html (디자인 검증 역할을 통과한 것만)
- 규칙: docs/design.md
- 약속: docs/api.md, packages/shared의 타입

## 하지 않는 일
- 금액 · 남은 자리 · 권한 · 취소 가능 여부를 화면에서 계산하거나 판단하지 않는다
- 서버 코드와 API 명세를 수정하지 않는다
- 비밀 키를 화면 코드나 공개 환경변수에 넣지 않는다

## 완료 조건
- 각 화면에서 로딩 / 빈 / 에러 상태가 동작한다
- 로컬 서버와 실제로 연동해 예약 흐름을 끝까지 눌러 봤다 (가짜 데이터 없음)

🔍 읽는 포인트 : "하지 않는 일"의 첫 줄이 0절 축 1, 셋째 줄이 축 2입니다. 이 두 줄이 이 차시 전체입니다.


7. 실습 — 맡기고 검수하기

지시

예약 흐름(목록 → 상세 → 예약하기)을 로컬 서버와 연동해서 완성해줘. 6절의 에이전트 정의를 따른다.
끝나면 아래를 보고해줘.
1. [화면 | 부르는 API | 로딩/빈/에러 처리 여부] 표
2. 화면 코드 전체에서 금액·인원·자리 계산을 하는 곳 [파일 | 줄 | 하는 일] — 없으면 "없음"
3. 공개 환경변수 목록 전체 [이름 | 값의 종류]. 값 자체는 쓰지 말고 종류만.
4. 서버의 CORS 허용 출처 설정값
가짜(하드코딩) 데이터가 남아 있는지 검색한 명령과 출력 원문도 붙여줘.

받을 증거

  • 화면별 연동 표, 계산 위치 목록( "없음"이어야 정상 ), 공개 환경변수 이름 목록, CORS 허용 출처 값
  • 가짜 데이터 검색 명령과 출력 원문

내가 직접 확인할 것

브라우저 개발자 도구의 Network 탭 하나만 익혀 두면, 코드를 읽지 않고도 화면과 서버 사이에서 실제로 무엇이 오가는지 볼 수 있습니다. 열기: F12(Mac은 Cmd+Option+I) → Network 탭 → 화면에서 "예약하기" → 목록에 생긴 요청을 클릭.

볼 것이걸로 아는 것 / 왜 내가 보는가
Network 탭 요청의 Payload (화면이 보낸 것 )에 금액이 있는가있으면 화면이 판정하려는 신호. 서버가 무시하는지 10차시 시험으로 재확인
Response (서버가 돌려준 것 )의 숫자와 내용연동이 실제로 됐는지. 빨간 줄은 실패한 요청 — 캡처해서 AI에게 주면 원인 찾기가 빨라짐
보고받은 공개 환경변수 이름에 SECRET · PRIVATE · PASSWORD · DATABASE_URL이 붙은 것이 있는가코드 없이 잡는 비밀값 노출 (3.1)
CORS 허용 출처가 *인가4.2의 ⚠️
결제 · 예약 버튼을 빠르게 두 번 누른다 → 내 예약 목록에 몇 건?중복 요청 방지 (5절, 16차시)
와이파이를 끄고 버튼을 누른다에러 상태 화면이 나오는가, 아니면 멈추는가 (2.3)
예약 직후 브라우저 뒤로 가기 · 새로고침같은 예약이 다시 만들어지지 않는가

부록 A. 스스로 확인하기

#질문답이 있는 곳
1"화면의 검사는 편의용"이라는 말을 예로 설명하면?1.1
2같은 규칙이 화면과 서버 두 군데 있으면 무슨 일이 생기는가?1.2
3API 호출을 한 곳에 모으고 모양을 공유하면 각각 무엇이 좋은가?2.1, 2.2
4네 가지 화면 상태와, 빠졌을 때의 증상은?2.3
5공개 환경변수를 유와 종차로 정의하면? 대표 접두사는?3.1
6공개 키와 비밀 키는 노출되면 각각 어떻게 되는가?3.2
7CORS는 누가 검사하고, curl 요청을 막는가?4.1, 4.2
8CORS 에러를 *로 고치면 왜 안 되는가?4.2
9낙관적 표시가 예약 · 결제에서 위험한 이유는?0, 5

부록 B. 자주 하는 실수

실수바로잡기
화면에서 금액을 계산해 서버로 보낸다❌ 화면은 서버가 준 금액을 표시만 (1.1)
공개 환경변수에 비밀 키를 넣는다❌ 사용자 브라우저로 그대로 전달됩니다 (3.1)
"CORS를 설정했으니 서버는 안전하다"❌ CORS는 브라우저 규칙. curl은 막지 않습니다 (4.2)
CORS 에러를 * 전체 허용으로 해결⚠️ 화면 주소를 명시 (4.2)
가짜 데이터를 박아 두고 잊는다⚠️ 연동 후 검색해서 제거 확인 (1.3)
에러를 alert("에러 발생") 하나로 처리⭕ 에러 코드별 안내 (2.3)
버튼 비활성화로 중복 결제를 막았다고 끝냄⚠️ 서버 측 방지가 함께 있어야 합니다 (5, 16차시)

부록 C. NotebookLM 복습 프롬프트

이 11차시 노트만 근거로 5문제를 내줘. 비전공자 기준으로.
"화면의 검사는 편의용", "공개 환경변수와 비밀값", "CORS가 막는 것과 막지 않는 것"은 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.