# Five의 가독성 — AI 시대의 진짜 강점 ## AI가 코딩하는 시대, 왜 가독성이 중요한가 AI가 코드를 자동 생성하는 시대입니다. 하지만 문제가 있습니다: 1. **AI가 복잡한 코드를 만들어냄** — 정상 동작하지만 사람이 이해 못 함 2. **AI 없이 유지보수 불가** — AI 서비스 중단 시 코드가 블랙박스가 됨 3. **버그 발견이 어려움** — 코드를 읽을 수 없으면 버그도 못 찾음 4. **팀 협업 불가** — 작성자 외에 누구도 코드를 이해 못 함 **Five는 이 문제를 근본적으로 해결합니다.** ## 같은 일, 다른 가독성 ### 고객 목록 조회 ```prg // Five (PRG) USE customers NEW SET FILTER TO balance > 10000 GO TOP DO WHILE !Eof() ? name, city, balance SKIP ENDDO ``` ```go // Go func listCustomers() { db, err := sql.Open("sqlite3", "customers.db") if err != nil { log.Fatal(err) } defer db.Close() rows, err := db.Query( "SELECT name, city, balance FROM customers WHERE balance > $1", 10000, ) if err != nil { log.Fatal(err) } defer rows.Close() for rows.Next() { var name, city string var balance float64 if err := rows.Scan(&name, &city, &balance); err != nil { log.Fatal(err) } fmt.Println(name, city, balance) } if err := rows.Err(); err != nil { log.Fatal(err) } } ``` ```python # Python import sqlite3 def list_customers(): conn = sqlite3.connect('customers.db') cursor = conn.cursor() cursor.execute( 'SELECT name, city, balance FROM customers WHERE balance > ?', (10000,) ) for row in cursor.fetchall(): print(row[0], row[1], row[2]) conn.close() ``` ```java // Java public void listCustomers() throws SQLException { try (Connection conn = DriverManager.getConnection("jdbc:sqlite:customers.db"); PreparedStatement stmt = conn.prepareStatement( "SELECT name, city, balance FROM customers WHERE balance > ?")) { stmt.setDouble(1, 10000); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { System.out.println( rs.getString("name") + " " + rs.getString("city") + " " + rs.getDouble("balance") ); } } } } ``` | 언어 | 줄 수 | 에러 처리 | 비개발자 이해 | |------|------|----------|:---:| | **Five (PRG)** | **8** | 내장 | **✅ 가능** | | Python | 12 | 수동 | △ | | Go | 27 | 필수 | ❌ | | Java | 15 | 필수 | ❌ | ## PRG가 읽기 쉬운 이유 ### 1. 영어 문장처럼 읽힌다 ```prg USE customers NEW // 고객 파일 열어 GO TOP // 처음으로 가 DO WHILE !Eof() // 끝까지 반복해 IF balance > 10000 // 잔액이 만 넘으면 ? name, balance // 이름이랑 잔액 출력해 ENDIF // 조건 끝 SKIP // 다음으로 ENDDO // 반복 끝 ``` 프로그래밍을 모르는 사람도 흐름이 보입니다. `{`, `}`, `:=`, `->`, `func`, `defer` 같은 기호가 없습니다. ### 2. 모든 것이 명시적이다 ```prg // Five — 끝이 명확함 IF condition ... ENDIF // IF가 여기서 끝남 FOR i := 1 TO 10 ... NEXT // FOR가 여기서 끝남 DO WHILE condition ... ENDDO // WHILE이 여기서 끝남 ``` ```go // Go — } 가 뭘 닫는 건지 세어야 함 if condition { for i := 0; i < 10; i++ { if another { // ... } // ← 이 } 는 inner if } // ← 이 } 는 for } // ← 이 } 는 outer if ``` ### 3. 변수명이 길어도 자연스럽다 ```prg LOCAL cCustomerName, nTotalBalance, dLastPurchase, lIsActive cCustomerName := "Charles Kwon" nTotalBalance := 15000.50 dLastPurchase := Date() lIsActive := .T. ``` 헝가리안 표기법으로 변수 타입이 이름에 보입니다: - `c` = Character (문자열) - `n` = Numeric (숫자) - `d` = Date (날짜) - `l` = Logical (논리값) - `a` = Array (배열) - `o` = Object (객체) AI가 코드를 작성해도, 변수명만 보면 타입을 알 수 있습니다. ### 4. DEFER로 안전하면서도 깔끔하다 ```go // Go — defer는 있지만 err 체크가 코드를 오염 db, err := sql.Open("sqlite3", dsn) if err != nil { return fmt.Errorf("open failed: %w", err) } defer db.Close() result, err := db.Query("SELECT ...") if err != nil { return fmt.Errorf("query failed: %w", err) } defer result.Close() ``` ```prg // Five — DEFER + 깔끔한 비즈니스 로직 db := sql.Open("sqlite", dsn) DEFER db:Close() // Go의 defer와 동일! result := SqlScan(db, "SELECT ...") // 에러는 BEGIN SEQUENCE로 한 곳에서 처리 // 그런데 코드는 읽기 쉬움 ``` Five는 Go의 `defer`를 `DEFER`로 그대로 지원합니다. Go의 좋은 점은 가져오되, `if err != nil` 반복은 없앱니다. ## AI 시대 시나리오 ### 시나리오 1: AI 서비스가 중단됨 **Go/Python/Java 프로젝트:** - 10만 줄 코드 — 구조 파악에 수일 - 복잡한 타입 시스템, 제네릭, 인터페이스 - 프레임워크 의존성 파악 필요 - 신규 개발자가 인수하려면 수주일 **Five 프로젝트:** - 같은 기능이 3만 줄 — 코드량 자체가 적음 - `USE`, `SKIP`, `SEEK` — 명령어가 의미 그대로 - 경험 없는 개발자도 하루 만에 코드 읽기 가능 ### 시나리오 2: 긴급 버그 수정 ```prg // 버그가 여기 있다고 가정 USE orders NEW SET FILTER TO date >= Date() - 30 GO TOP DO WHILE !Eof() IF amount > 0 nTotal += amount // ← 여기가 문제: += 대신 = 써야 함? ENDIF SKIP ENDDO ``` 비개발자(영업팀, 관리자)도 코드를 읽고 "nTotal이 누적되는 것 같다"를 이해합니다. Go 코드에서는 이 수준의 이해가 불가능합니다. ### 시나리오 3: AI가 만든 코드 검증 ```prg // AI가 생성한 Five 코드 — 사람이 검증 가능 FUNCTION CalcDiscount(nPrice, nQuantity) LOCAL nDiscount IF nQuantity >= 100 nDiscount := nPrice * 0.15 // 100개 이상 15% 할인 ELSEIF nQuantity >= 50 nDiscount := nPrice * 0.10 // 50개 이상 10% 할인 ELSE nDiscount := 0 // 할인 없음 ENDIF RETURN nDiscount ``` 비즈니스 담당자가 이 코드를 보고 "100개 이상이면 15% 맞아?"라고 확인할 수 있습니다. ## Five + Go = 최적의 조합 Five가 쉬운 것만으로 충분한 게 아닙니다. **쉬운 코드로 강력한 기능**을 쓸 수 있어야 합니다. ```prg IMPORT "database/sql" IMPORT _ "modernc.org/sqlite" PROCEDURE Main() LOCAL db, aRows, i // SQL — 쉬운 PRG 문법으로 db := sql.Open("sqlite", ":memory:") DEFER db:Close() db:Exec("CREATE TABLE orders (id INTEGER, amount REAL)") db:Exec("INSERT INTO orders VALUES (1, 15000)") // 결과를 Harbour 배열로 받아서 xBase 스타일로 처리 aRows := SqlScan(db, "SELECT * FROM orders") FOR i := 1 TO Len(aRows) ? aRows[i]["id"], aRows[i]["amount"] NEXT RETURN ``` PRG 문법으로 SQL 데이터베이스를 씁니다. Go의 `database/sql` 패키지가 뒤에서 동작하지만, 코드를 읽는 사람은 **Go를 몰라도** 됩니다. ## 한 줄 요약 > **AI가 코드를 만들어주는 시대에, > 사람이 읽을 수 있는 코드가 진짜 자산입니다. > Five는 AI가 만들어도 사람이 검증할 수 있는 유일한 시스템 언어입니다.**