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

AI 드리븐

이 페이지에 묻기

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

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

AI · DEVELOPMENT

AI 드리븐

생성 수정

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

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

10차시 · 백엔드 역할: 서버 로직

지도 위치 : 2일차 · 구현과 검증 · 구현 | 이전: 9차시 서비스 뼈대 세우기 | 다음: 11차시 프론트엔드 역할: 화면과 경계 키워드 : 설계 기반 구현, 서버의 판정·검증 원칙, 인터페이스 시험

이 차시를 다 읽으면

  1. 서버 판정 원칙 을 유와 종차로 말하고, 요청에 담겨 와도 믿으면 안 되는 값 네 가지 를 댈 수 있다.
  2. 인증과 인가 를 구별하고, 각각이 빠졌을 때의 응답 숫자(401 · 403)와 사고 모양을 클래스온 예로 설명할 수 있다.
  3. 구현 중에 명세가 이상할 때 명세를 고치지 않고 보고하게 하는 이유를 추상 ↔ 구상 축으로 설명할 수 있다.
  4. 서버 안의 세 계층(라우터 · 서비스 · 저장소) 이 각각 무엇을 맡는지 말하고, 그것이 "어디서?" 질문을 쉽게 만드는 이유를 설명할 수 있다.
  5. 인터페이스 시험 을 정상 1개 + 실패 여러 개로 설계하고, 결과를 표로 받아 판정할 수 있다.

0. 이 차시의 판별 축

#축왼쪽 (0)오른쪽 (1)이 축으로 갈리는 것큰 축 (README 5장)
1누가 판정하는가화면 — 사용자 기기 (조작 가능)서버 — 신뢰할 수 있는 곳금액 · 남은 자리 · 권한을 어디서 정하는가화면이 판정 ↔ 서버가 판정 (②의 파생)
2무엇을 묻는가인증 — 누구인가인가 — 이걸 해도 되는가401 ↔ 403, 로그인 ↔ "본인 것인가"이 차시의 축
3약속인가, 구현인가API 명세 (docs/api.md)서버 코드구현이 따라야 할 것 ↔ 고쳐도 되는 것② 추상 ↔ 구상
4지난 요청을 기억하는가무상태 — 요청마다 로그인 증표를 다시 확인상태 — "아까 로그인했으니"매 요청마다 인증 · 인가를 하는가⑦ 무상태 ↔ 상태

이 차시가 답하는 질문은 "서버는 무엇을 믿고, 무엇을 의심해야 하는가" 입니다. 앞에서 배운 API 명세(4차시)가 약속(축 3의 왼쪽)이라면, 이 차시는 그 약속을 지키는 실제 부품을 만듭니다. 그리고 그 부품이 지킬 가장 중요한 원칙이 축 1의 오른쪽, 판정은 서버가 한다 입니다.


1. 설계 기반 구현 — 명세가 먼저

1.1 백엔드 역할의 맥락

docs/api.md (약속) ─▶ 시험 목록 먼저 또는 함께 ─▶ 구현 ─▶ 명세와 대조 (5절)
       ▲
docs/requirements.md의 인수 기준 (3차시) · docs/adr/ (8차시)

앞에서 배운 역할 정의(5차시)대로, 백엔드 에이전트가 읽을 맥락은 명세 · 인수 기준 · 결정 기록 세 가지입니다. 이 셋이 없으면 에이전트는 "그럴듯한 예약 서버"를 상상해서 만듭니다.

1.2 명세가 이상하면 — 고치지 말고 보고

구현하다 보면 "이 응답에 필드 하나가 더 있으면 좋겠다" 같은 생각이 듭니다. 이때 백엔드 에이전트가 명세를 직접 고치지 않고 보고하게 합니다.

명세를 직접 고침보고하고 사람이 결정
프론트엔드 역할모르는 채로 옛 명세대로 만든다바뀐 명세를 함께 받는다
0절 축 3구현이 약속을 끌고 간다약속이 구현을 끌고 간다

명세는 화면과 서버가 함께 보는 약속 이기 때문입니다(⑤ 여럿으로 나눈 대가). 한쪽이 혼자 바꾸면 9차시의 "데이터 모양" 이음매가 깨집니다.


2. ⭐ 서버 판정 원칙

2.1 왜 화면은 판정할 수 없는가

클라이언트 — [요청을 보내는 프로그램]인데, [ 사용자 기기에서 돌아가서 사용자가 마음대로 조작할 수 있다 ]는 점에서 우리가 통제하는 서버와 구별된다. 브라우저 화면이 대표적입니다.

화면을 거치지 않고도 서버에 요청을 보낼 방법은 많습니다.

방법누가 할 수 있나
브라우저 개발자 도구로 보낼 내용을 바꿔서 다시 보내기브라우저가 있는 누구나
curl 같은 명령으로 화면 없이 직접 호출주소를 아는 누구나
화면 코드를 고쳐 버튼 숨김 · 입력 제한을 풀기브라우저가 있는 누구나

서버 판정 원칙 — [보안 설계 원칙]인데, [ 금액 · 남은 자리 · 권한처럼 결과를 바꾸는 판단을 서버가 자기 데이터로만 내리고, 요청에 담긴 판단 결과는 무시한다 ]는 점에서 화면에서 하는 입력 검사(편의용, 11차시)와 구별된다.

2.2 원칙 다섯 가지

원칙의미클래스온 예
클라이언트를 믿지 않는다받은 값은 모두 다시 검사headcount가 1~4 사이 정수인지
판정은 서버가 한다가격 · 재고 · 권한은 서버의 데이터로 계산금액 = DB의 클래스 가격 × 인원. 요청에 들어 있는 금액은 무시
인증과 인가를 구분한다3절로그인했어도 남의 예약 은 취소 불가
실패는 명확하게명세의 상태 코드와 에러 형식대로자리 없음 → 409 SOLD_OUT
함께 성공하거나 함께 실패여러 변경을 트랜잭션 (모두 성공 또는 모두 취소로 묶는 단위, 12차시에서 정의)으로자리 차감 + 예약 생성

상태 코드 는 서버가 응답과 함께 돌려주는 세 자리 숫자입니다(4차시). 이 노트에서는 200 · 201(성공), 400(입력이 잘못됨), 401(누구인지 모름), 403(알지만 권한 없음), 404(없음), 409(현재 상태와 충돌), 500(서버 내부 오류)만 알면 됩니다.

2.3 ⭐ 요청에 담겨 와도 믿지 않는 값

값요청에 들어오면서버는 어디서 가져오나
금액무시DB의 클래스 가격 × 인원
사용자 ID무시요청 본문이 아니라 로그인 증표(토큰) 에서
역할 (role: "admin")무시DB의 사용자 정보에서
상태 (status: "CONFIRMED")무시서버의 처리 결과로만 바뀜 (16차시)

⚠️ AI는 "화면에서 이미 검사했으니까" 서버 검사를 생략한 코드를 자주 만듭니다. 그래서 이 원칙은 백엔드 역할 정의와 지침 파일에 문장으로 적어 둡니다.

2.4 반례 — 이건 서버 판정이 아닙니다

대상왜 아닌가
화면이 금액을 계산해 보내고, 서버는 "0보다 큰지"만 확인형식만 검사했을 뿐 판정은 화면이 했다
화면에서 "취소" 버튼을 남의 예약에는 숨김버튼을 숨겨도 주소를 알면 호출할 수 있다. 화면 편의일 뿐
서버가 요청 본문의 userId로 "본인 것인가"를 확인그 userId를 바꿔 보내면 된다. 비교 기준 자체가 조작 가능

💡 비유는 마지막에 — 서버는 경기의 심판 입니다. 선수(화면)가 "골인입니다"라고 외쳐도 점수는 심판이 자기 눈으로 본 것으로만 올라갑니다.


3. 인증과 인가

3.1 정의와 경계

인증 (Authentication) — [접근 통제 단계]인데, [ 요청을 보낸 사람이 누구인지 확인한다 ]는 점에서 그 사람이 무엇을 해도 되는지 판단하는 인가와 구별된다.

인가 (Authorization) — [접근 통제 단계]인데, [ 확인된 사람이 이 대상에 이 행동을 해도 되는지 판단한다 ]는 점에서 신원만 확인하는 인증과 구별된다.

인증인가
묻는 것누구인가?이 예약을 이 사람이 취소해도 되는가?
판단 재료로그인 증표(토큰)증표에서 꺼낸 사용자 + DB의 대상 데이터
실패 응답401403 (또는 남의 것이 있다는 사실도 숨기려면 404)
빠지면아무나 예약 생성로그인한 누구나 남의 예약 을 보거나 취소
클래스온 예로그인 안 하고 예약 → 거부수강생 A가 B의 예약 취소 → 거부

⚠️ 인증은 인가의 전제 이지 대체물이 아닙니다. "로그인한 사람만 들어올 수 있으니 안전하다"는 인가가 빠진 서버의 전형적인 변명입니다.

3.2 인가 누락 — 가장 흔한 보안 사고

GET /reservations/345   ← 내 예약
GET /reservations/346   ← 주소의 숫자만 1 바꿈 → 남의 예약이 보인다면 인가 누락

🔍 읽는 포인트 : 주소의 숫자 하나 만 바꿔 보는 시험입니다. 코드를 몰라도 브라우저 주소창에서 할 수 있습니다.

3.3 서버는 매번 다시 확인한다 — 무상태

0절 축 4입니다. 서버는 "아까 이 사람이 로그인했으니"를 기억하지 않습니다. 요청마다 로그인 증표를 다시 확인하고(인증), 대상이 그 사람 것인지 다시 확인합니다(인가). 그래서 예약 조회 · 수정 · 취소 모든 경로 에 인가가 들어가야 합니다. 하나라도 빠지면 그 경로가 3.2의 구멍이 됩니다.

앞으로 다시 만납니다 — 14차시에서 인가 누락을 흔한 보안 사고 목록의 맨 앞에 놓고, 계정 두 개로 하는 행동 시험을 정식 점검 항목으로 만듭니다.

💡 비유는 마지막에 — 인증은 건물 출입증 , 인가는 방마다 다른 열쇠 권한 입니다. 출입증이 있다고 사장실에 들어갈 수 있는 것은 아닙니다.


4. 코드 계층 — 판정이 한 곳에 있게

계층 (Layer) — [코드 구조화 방식]인데, [ 책임별로 코드를 나누고 위층이 바로 아래층만 부르게 한다 ]는 점에서 기능별로 파일을 나누는 방식과 구별된다.

라우터 (경로 · 입력 모양 검사) ─▶ 서비스 (규칙 · 판정) ─▶ 저장소 (DB 읽기·쓰기)

🔍 읽는 포인트 : 판정은 가운데(서비스)에만 있어야 합니다. 금액 계산이 라우터나 저장소에도 있으면 판정이 여러 곳에 흩어진 것입니다.

계층맡는 것맡지 않는 것
라우터요청 모양 검사(필수 필드, 타입), 응답 형식 변환"자리가 있는가" 같은 판단
서비스"자리가 있는가?", "취소 기한 안인가?", 금액 계산SQL 직접 작성
저장소DB 질의 실행만규칙 판단

이 구조가 코드를 읽지 않는 사람에게 특히 중요한 이유 가 있습니다. "금액은 어디서 계산돼?"라고 물었을 때 답이 서비스 계층의 한 곳 으로 나와야 정상입니다. 답이 모호하거나 "여러 곳에서"가 나오면 그 자체가 위험 신호입니다. 이 구조는 지침 파일에 적어 두어 모든 에이전트가 같은 모양으로 만들게 합니다.


5. 인터페이스 시험 — 실제로 호출해 본다

구현이 명세와 맞는지는 읽어서가 아니라 호출해서 확인합니다.

# 정상
curl -X POST localhost:4000/reservations \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"classId":12,"date":"2026-11-01","headcount":1}'
# 기대: 201 {"id":..., "status":"PENDING_PAYMENT", "amount":55000}

# 금액 위조 시도 → 서버가 무시해야 함
  -d '{"classId":12,"date":"2026-11-01","headcount":1,"amount":100}'
# 기대: 201, amount는 여전히 55000

# 잘못된 입력
  -d '{"classId":12,"headcount":-1}'
# 기대: 400 {"error":{"code":"INVALID_INPUT",...}}

# 로그인 없이 (Authorization 줄을 빼고)
# 기대: 401

🔍 읽는 포인트 : 주소(/reservations)와 # 기대: 뒤의 숫자(201 · 400 · 401) , 그리고 위조 시도에서 amount가 55000으로 남는지 만 보면 됩니다.

시험기대확인하는 원칙
정상 예약201, 서버가 계산한 금액명세 일치
금액 100원으로 위조201, 금액은 55000판정은 서버가
인원 -1, 0, 5400클라이언트를 믿지 않는다
로그인 없이401인증
남의 예약 ID로 조회403 또는 404인가

⚠️ 정상 경우만 호출해 보고 "완료"라고 보고하는 것 이 AI 보고의 가장 흔한 빈틈입니다. 백엔드 역할의 완료 조건에 "정상 1개 + 실패 3개 이상의 호출 결과 원문" 을 넣어 둡니다.

앞으로 다시 만납니다 — 이 표는 그대로 17차시의 자동 테스트 목록이 됩니다. 사람이 한 번 손으로 확인한 것을 기계가 매번 확인하게 바꾸는 것입니다.


6. 클래스온에 적용하면

백엔드 에이전트에게 맡기는 순서입니다. 쉬운 것에서 판정이 많은 것으로 갑니다.

순서대상이 단계에서 새로 생기는 것
1GET /classes, GET /classes/{id}읽기만. 9차시 뼈대 위의 첫 기능
2인증 (간단한 방식 또는 외부 인증 서비스)로그인 증표
3POST /reservations판정 · 트랜잭션 — 이 차시의 핵심
4GET /me/reservations, 예약 취소인가
5결제 승인16차시

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

서버 코드를 읽는 대신 공격자처럼 시험 합니다. 이 차시의 원칙은 모두 행동으로 확인할 수 있습니다.

지시

docs/api.md의 POST /reservations와 GET /reservations/{id}에 대해 아래 시험을 하는 스크립트를
scripts/attack-test.sh로 만들고 실행해줘.
결과는 [시험 | 기대 | 실제 응답 숫자 | 실제 금액 | 통과?] 표로 보고하고, 실행 출력 원문을 붙여줘.
1. 정상 예약  2. 금액을 100원으로 바꿔 보내기  3. 인원 -1, 0, 5
4. 로그인 없이  5. 사용자 B의 토큰으로 사용자 A의 예약 조회
그리고 아래 두 질문에 [파일 | 줄 | 그 줄이 하는 일 한 문장]으로 답해줘.
- 금액은 어디서 계산돼? 화면에서 보낸 값이 그 계산에 들어가는 경로가 하나라도 있어?
- 사용자 ID는 어디서 가져와? 요청 본문에서 가져오는 곳이 하나라도 있어?

받을 증거

  • 시험 결과 표와 스크립트 실행 출력 원문
  • 금액 계산 · 사용자 ID 출처의 위치(파일 · 줄)

내가 직접 확인할 것

볼 것이걸로 아는 것 / 왜 내가 보는가
결과 표의 금액 위조 줄 : 실제 금액이 55000인가판정이 서버에 있는지. 100이 보이면 즉시 멈춤
계정 두 개를 만들고, A로 예약한 뒤 B로 로그인해 그 예약 주소를 연다 . 주소의 숫자도 1씩 바꿔 본다인가 누락. AI의 표가 아니라 내 눈으로 보는 행동 시험
"어디서?" 답이 서비스 계층의 한 곳 인가모호하거나 여러 곳이면, 13차시의 리뷰 역할에게 같은 질문을 따로 해서 답을 비교 (README 9.1의 교차 검증)
보고에 "아마", "~해야 합니다"가 있는가실행하지 않았다는 신호 (README 9.4)

💡 curl이 낯설다면 API 시험 도구(Postman, Bruno 등)로 화면을 클릭하는 방식으로 같은 요청을 직접 보내 볼 수도 있습니다.


부록 A. 스스로 확인하기

#질문답이 있는 곳
1구현 중 명세가 이상할 때 고치지 말고 보고하게 하는 이유는?1.2
2클라이언트를 믿을 수 없는 이유를 세 가지 방법으로 말하면?2.1
3서버 판정 원칙을 유와 종차로 정의하면?2.1
4요청에 담겨 와도 믿지 않는 값 네 가지와 각각의 출처는?2.3
5인증과 인가가 빠지면 각각 어떤 사고가 나고, 응답 숫자는?3.1
6주소의 숫자 하나로 인가 누락을 시험하는 방법은?3.2
7서버가 요청마다 다시 확인하는 것이 어느 축과 관련되는가?0, 3.3
8판정이 서비스 계층 한 곳에 있어야 하는 이유는?4
9인터페이스 시험에서 정상 외에 넣을 경우는?5

부록 B. 자주 하는 실수

실수바로잡기
요청의 금액 · 사용자 ID · 역할을 그대로 쓴다❌ 금액은 DB, 사용자 ID는 로그인 증표에서 (2.3)
"로그인한 사람만 들어오니 안전하다"❌ 인증은 인가를 대신하지 않습니다 (3.1)
에러를 전부 500으로 돌려준다⚠️ 명세의 상태 코드와 에러 형식대로 (2.2)
에러 메시지에 SQL이나 내부 경로를 노출한다❌ 일반 메시지만 (14차시)
정상 경우만 호출해 보고 완료 처리❌ 정상 1 + 실패 3 이상 (5)
백엔드 에이전트가 명세를 직접 고친다⚠️ 보고하고 사람이 결정 (1.2)
금액 계산이 여러 파일에 있다⭕ 서비스 계층 한 곳으로 모으게 합니다 (4)

부록 C. NotebookLM 복습 프롬프트

이 10차시 노트만 근거로 5문제를 내줘. 비전공자 기준으로.
"서버 판정 원칙과 믿지 않는 값", "인증과 인가의 구별(401/403)", "인터페이스 시험 설계"는 반드시 포함해줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.