Die Suche verändert sich auch in der Schweiz. Nutzer verwenden längst nicht mehr nur Google, sondern zunehmend auch ChatGPT, Perplexity, Gemini und andere KI-Systeme, um Unternehmen zu finden, Produkte zu vergleichen und Entscheidungen vorzubereiten. Für Schweizer Unternehmen entsteht dadurch eine neue Aufgabe: SearchGPT SEO beziehungsweise die Optimierung für ChatGPT Search . Dabei geht es nicht darum, klassische SEO zu ersetzen. Entscheidend ist vielmehr die Frage: Wie schaffen Sie es, dass Ihr Unternehmen von ChatGPT gefunden, verstanden und bei relevanten Fragen berücksichtigt wird? Genau hier setzen Generative Engine Optimization, kurz GEO, und moderne AI-Search-Optimierung an. Was ist SearchGPT SEO? SearchGPT war ursprünglich die Bezeichnung für OpenAIs KI-basierte Suchtechnologie. Heute wird in der Praxis häufiger von ChatGPT Search gesprochen. Der Begriff SearchGPT SEO wird dennoch weiterhin genutzt, wenn es darum geht, Websites und Marken für die Suche innerhalb von ChatGPT zu optimieren. Das Ziel unterscheidet sich teilweise von klassischer Google-SEO. Bei Google möchten Unternehmen möglichst weit oben in den Suchergebnissen erscheinen. Bei ChatGPT lautet das Ziel häufiger: Teil der eigentlichen Antwort zu werden. Eine Schweizer Treuhandfirma möchte beispielsweise nicht nur für „Treuhänder Zürich“ ranken. Sie möchte auch bei Fragen berücksichtigt werden wie: „Welche Treuhandfirma in Zürich eignet sich für ein wachsendes SaaS-Unternehmen?“ Oder: „Welche Schweizer Treuhänder haben Erfahrung mit internationalen Firmen?“ Solche Fragen sind länger, spezifischer und häufig näher an einer Kaufentscheidung. Warum ChatGPT Search für Schweizer Unternehmen wichtig wird Google bleibt auch 2026 ein zentraler Bestandteil der Online-Suche. Gleichzeitig verändert sich das Verhalten der Nutzer. Statt mehrere Websites zu öffnen und Informationen selbst zusammenzutragen, können Menschen ihre Situation direkt in ChatGPT beschreiben und eine zusammengefasste Antwort erhalten. Typische Fragen sind zum Beispiel: Welche Software eignet sich für Schweizer KMU? Welche Agentur kann bei GEO und AI Visibility helfen? Welche Anbieter gibt es in Zürich? Welches Produkt passt zu einem bestimmten Anwendungsfall? Was sind gute Alternativen zu einem bekannten Anbieter? Welche Lösung ist für ein kleines Schweizer Unternehmen geeignet? Diese Art von Suchanfragen kann besonders wertvoll sein, weil sie oft deutlich näher an einer Entscheidung liegt als ein allgemeines Informationskeyword. Jemand, der nach „SEO Erklärung“ sucht, hat eine andere Absicht als jemand, der fragt: „Welche GEO-Agentur in der Schweiz kann unseren Shopify-Shop für ChatGPT optimieren?“ SearchGPT SEO ist nicht dasselbe wie klassische SEO Klassische SEO konzentriert sich stark auf Rankings in Suchmaschinen. SearchGPT SEO und GEO konzentrieren sich zusätzlich darauf, ob eine Marke in KI-generierten Antworten verstanden, erwähnt oder als Quelle verwendet wird. Bei klassischer SEO spielen unter anderem Keywords, interne Verlinkung, Backlinks, technische Optimierung und Content-Qualität eine wichtige Rolle. Bei GEO kommen weitere Fragen hinzu: Ist klar, wofür Ihre Marke steht? Wird Ihr Unternehmen auch ausserhalb der eigenen Website erwähnt? Beantworten Ihre Inhalte konkrete Nutzerfragen? Sind Informationen einfach zu extrahieren? Sind Unternehmensdaten konsistent? Kann ein KI-System Ihre Produkte, Leistungen und Zielgruppen eindeutig einordnen? Beide Disziplinen ergänzen sich. Eine technisch saubere Website mit hochwertigen Inhalten bleibt die Grundlage. Wie ChatGPT Informationen über Schweizer Unternehmen versteht ChatGPT bewertet ein Unternehmen nicht nur anhand einer einzelnen Seite. Vielmehr entsteht ein Gesamtbild aus verschiedenen öffentlich zugänglichen Signalen. Dazu können gehören: Informationen auf der eigenen Website Produkt- und Leistungsseiten Fachartikel Unternehmensprofile Rezensionen Erwähnungen in Fachmedien Vergleichsseiten Branchenportale Podcasts Interviews Community-Diskussionen Je konsistenter diese Informationen sind, desto leichter kann eine Marke eingeordnet werden. Wenn ein Unternehmen sich selbst als führenden Anbieter bezeichnet, reicht das allein nicht aus. Wenn jedoch mehrere unabhängige Quellen dieselbe Marke mit einem bestimmten Thema, Produkt oder Anwendungsfall verbinden, entsteht ein stärkeres Signal. Optimieren Sie Inhalte für echte Fragen Viele Websites arbeiten weiterhin hauptsächlich mit einzelnen Keywords. Für ChatGPT Search sollten Unternehmen stärker in vollständigen Fragen denken. Ein Schweizer Anbieter für Photovoltaik könnte beispielsweise nicht nur für: „Solaranlage Schweiz“ optimieren. Interessanter sind Fragen wie: „Lohnt sich eine Solaranlage für ein Einfamilienhaus in der Schweiz?“ „Was kostet eine Photovoltaikanlage in Zürich?“ „Welche Solaranlage eignet sich für wenig Dachfläche?“ „Welche Solaranbieter gibt es in der Schweiz?“ „Welche Fördermöglichkeiten gibt es für Solaranlagen in der Schweiz?“ Diese Suchanfragen spiegeln besser wider, wie Menschen mit KI-Assistenten kommunizieren. Geben Sie die Antwort möglichst früh Ein häufiger Fehler bei SEO-Texten ist eine zu lange Einleitung. Die eigentliche Antwort kommt erst nach mehreren Absätzen. Für ChatGPT Search ist eine direkte Struktur meist sinnvoller. Wenn eine Überschrift lautet: Was kostet SEO in der Schweiz? Dann sollte der erste Absatz direkt erklären, wovon die Kosten abhängen. Danach können zusätzliche Details, Beispiele und Ausnahmen folgen. Diese Struktur hilft nicht nur KI-Systemen. Auch menschliche Leser finden schneller die Information, die sie suchen. Erstellen Sie thematische Content-Cluster Eine einzelne Seite reicht selten aus, um ein Thema vollständig abzudecken. Unternehmen sollten wichtige Themen in mehreren miteinander verbundenen Artikeln behandeln. Eine Schweizer Digitalagentur könnte beispielsweise Inhalte zu folgenden Themen veröffentlichen: Generative Engine Optimization Wie funktioniert GEO? ChatGPT Sichtbarkeit Wie erscheint ein Unternehmen in ChatGPT? AI Visibility Wie lässt sich die Sichtbarkeit in KI-Suchmaschinen messen? E-Commerce Wie können Shopify-Shops in ChatGPT gefunden werden? Lokale Suche Wie optimiert man ein Schweizer Unternehmen für lokale KI-Suchen? Gemeinsam ergeben diese Inhalte ein viel klareres thematisches Profil als ein einzelner allgemeiner Artikel über AI SEO. Machen Sie Ihre Marke eindeutig verständlich ChatGPT sollte möglichst einfach erkennen können: Wer sind Sie? Was bieten Sie an? Für wen ist Ihr Angebot gedacht? In welcher Region arbeiten Sie? Welche Probleme lösen Sie? Was unterscheidet Sie von Alternativen? Viele Unternehmen verwenden sehr kreative Marketingformulierungen, ohne konkret zu erklären, was sie eigentlich tun. Eine Aussage wie: „Wir gestalten gemeinsam die digitale Zukunft“ klingt gut, ist aber unpräzise. Eine Formulierung wie: „Wir entwickeln B2B-SaaS-Plattformen für Schweizer Finanzunternehmen“ ist deutlich eindeutiger. Für AI Search ist Klarheit oft wichtiger als Marketing-Sprache. Lokalisieren Sie Ihre Inhalte für die Schweiz Eine deutschsprachige Website ist nicht automatisch optimal auf die Schweiz ausgerichtet. Schweizer Unternehmen sollten regionale Unterschiede berücksichtigen. Dazu gehören beispielsweise: Schweizer Franken statt Euro Schweizer Begriffe und Schreibweisen Lokale Städte und Kantone Regionale Beispiele Schweizer Gesetze oder Vorschriften, wenn sie relevant sind Schweizer Anbieter und Wettbewerber Lokale Kaufgewohnheiten Ein Nutzer aus Zürich erwartet bei bestimmten Fragen andere Antworten als ein Nutzer aus Berlin. Berücksichtigen Sie die Mehrsprachigkeit der Schweiz Die Schweiz besteht nicht nur aus einem deutschsprachigen Markt. Je nach Zielgruppe können deutsche, französische, italienische und teilweise englische Inhalte relevant sein. Unternehmen, die in mehreren Sprachregionen aktiv sind, sollten nicht einfach alle Inhalte automatisch übersetzen. Besser ist es, pro Markt zu prüfen: Welche Fragen stellen Nutzer? Welche Begriffe verwenden sie? Welche Anbieter kennen sie? Welche lokalen Unterschiede sind wichtig? Die zentrale Positionierung der Marke sollte dabei über alle Sprachversionen hinweg konsistent bleiben. Erhöhen Sie Ihre externe Markenpräsenz GEO endet nicht auf der eigenen Website. Externe Erwähnungen können entscheidend dafür sein, wie eindeutig eine Marke im Web wahrgenommen wird. Hilfreich können sein: Fachmedien Branchenportale Interviews Gastbeiträge Podcasts Events Unternehmensverzeichnisse Kundenreferenzen Vergleichsseiten Community-Diskussionen Dabei geht es nicht darum, möglichst viele beliebige Erwähnungen zu sammeln. Wichtiger sind relevante Erwähnungen im richtigen thematischen Kontext. Veröffentlichen Sie konkrete Fakten KI-Systeme können strukturierte und eindeutige Informationen leichter verarbeiten. Unternehmen sollten deshalb konkrete Angaben bereitstellen. Dazu können gehören: Leistungsumfang Standorte Zielgruppen Branchen Produktfunktionen Integrationen Preise Sprachen Liefergebiete Zertifizierungen Anwendungsfälle Je weniger ein KI-System über Ihr Angebot erraten muss, desto besser. Welche Inhalte funktionieren für ChatGPT Search besonders gut? Besonders hilfreich sind Inhalte, die konkrete Fragen beantworten. Dazu gehören ausführliche Ratgeber, Vergleichsartikel, FAQ-Seiten, Produktseiten, Leistungsseiten, Fallstudien, Glossare und lokale Landingpages. Entscheidend ist jedoch nicht allein das Format. Ein oberflächlicher 2.000-Wörter-Artikel ist nicht automatisch besser als ein präziser Text mit 800 Wörtern. Der Inhalt muss eine echte Nutzerfrage zuverlässig beantworten. Schreiben Sie für Themen statt nur für Keywords Keyword-Recherche bleibt wichtig. Für AI Search sollten Unternehmen zusätzlich komplette Themenwelten abdecken. Ein Schweizer ERP-Anbieter könnte beispielsweise nicht nur auf: „ERP Schweiz“ optimieren. Weitere relevante Fragen wären: „Welches ERP eignet sich für Schweizer KMU?“ „Welche ERP-Software ist für Produktionsunternehmen
오늘은 최근에 알게된 프로젝트에 대해서 분석해보는 글을 작성해 보려고 한다. 다만 프로젝트의 익명성을 위하여 프로젝트에 관한 내용은 일절 다루지 않고, 오로지 프로젝트의 구조와 규칙에 대해서 조사해봤다. 즉, 이번 보고서의 분석 대상은 서비스가 무엇을 하는가 가 아니라, 프로젝트를 어떤 구조로 나누고 어떤 규칙으로 개발하는가 이다. 이 구조를 무엇이라고 부를 수 있을까? 내가 참고한 이 프로젝트는 크게 두 구조가 결합되어 있다. 1. 기능 중심 레이어드 모놀리스 Feature-first Layered Monolith 2. 문서·테스트·AI를 이용한 개발 하네스 Documentation-driven AI Development Harness 첫 번째 구조는 코드를 정리한다. 기능 └── Controller └── Service └── Repository └── Database / External API 두 번째 구조는 개발 과정을 정리한다. 작업 규칙 ├── 문서 ├── AI 역할 ├── 테스트 ├── Git Hook └── CI 즉, 하나는 코드가 엉키지 않게 하는 구조 이고, 다른 하나는 개발 과정이 엉키지 않게 하는 구조 다. 질문 1. 우리가 공부하려는 것은 서비스일까, 구조일까? 프로젝트를 분석할 때 다음 두 가지를 혼동하기 쉽다. 서비스 분석 └── 어떤 기능을 제공하는가? 구조 분석 └── 기능이 늘어나도 어떻게 정리하고 관리하는가? 예를 들어 주문 기능 , 회원 기능 , 검색 기능 이 있다는 사실은 서비스 분석이다. 반면 다음은 구조 분석이다. 기능별로 패키지를 나누는가? Controller와 Service의 책임은 무엇인가? 공통 규칙은 어디에 기록하는가? AI가 코드를 수정할 수 있는가? 변경이 안전한지 어떻게 검증하는가? 누가 최종 책임을 가지는가? 해결 방법 서비스 이름과 도메인 용어를 제거하고도 남는 규칙을 본다. order member catalog 위 이름을 다른 것으로 바꿔도 구조가 유지된다면 재사용 가능한 구조다. payment reservation notification 이 문서에서는 기능 이름이 아니라 다음 요소를 중심으로 본다. 코드 경계 의존 방향 문서 체계 개발 순서 검증 방식 AI 역할 전체 구조에서 담당하는 부분 이 구분은 앞으로 분석의 기준점이다. 기능은 프로젝트마다 바뀌지만, 안전하게 기능을 추가하는 구조는 다른 프로젝트에도 재사용할 수 있다. 질문 2. 처음부터 안전한 프로젝트를 만들려면 거대한 구조를 먼저 만들어야 할까? 안전한 프로젝트를 만들고 싶으면 처음부터 다음을 모두 준비해야 할 것처럼 느껴진다. 멀티모듈 클린 아키텍처 포트와 어댑터 이벤트 시스템 공통 라이브러리 여러 AI 에이전트 복잡한 CI 하지만 분석 대상 프로젝트는 그렇게 시작하지 않았다. 해결 방법 가장 작은 실행 가능한 프로젝트에서 출발했다. backend/ ├── build.gradle ├── BackendApplication.java ├── application.properties └── BackendApplicationTests.java 그 뒤 실제 필요가 생긴 순서대로 추가했다. 최소 Spring Boot 프로젝트 ↓ Docker 실행 환경 ↓ Git·코드 컨벤션 ↓ 개발 하네스 ↓ 도메인 모델 ↓ 외부 데이터 연동 ↓ PostgreSQL 통합 테스트 ↓ API·인증·검색 왜 필요한가? 초기부터 완성형 구조를 만들면 아직 존재하지 않는 문제를 예상해 코드를 작성하게 된다. 그 결과 다음 문제가 생긴다. 구현체가 하나뿐인 인터페이스 사용하지 않는 공통 모듈 필요하지 않은 이벤트 시스템 실제 변경보다 구조 유지 비용이 더 큰 프로젝트 팀원이 이해하지 못하는 추상화 실제 적용 방법 처음에는 다음 정도면 충분하다. my-project/ ├── backend/ │ ├── build.gradle │ └── src/ │ ├── main/ │ └── test/ ├── README.md └── compose.yaml 첫 번째 기능이 생겼을 때 해당 기능 패키지를 추가한다. src/main/java/com/example/ └── order/ ├── controller/ ├── service/ ├── repository/ └── domain/ 전체 구조에서 담당하는 부분 이 단계는 프로젝트의 기술적 출발점 을 담당한다. 유의 사항 빈 계층을 미리 만들지 않는다. 실제 코드가 생길 때 패키지를 만든다. 미래 확장을 위한 인터페이스를 먼저 만들지 않는다. 단일 모듈로 해결되는 동안에는 멀티모듈로 나누지 않는다. 질문 3. 코드는 기술별로 나눠야 할까, 기능별로 나눠야 할까? 가장 단순한 레이어드 구조는 다음과 같다. controller/ ├── OrderController ├── MemberController └── CatalogController service/ ├── OrderService ├── MemberService └── CatalogService 처음에는 깔끔해 보이지만 기능이 늘어나면 하나의 기능을 이해하기 위해 여러 디렉터리를 이동해야 한다. 해결 방법 최상위는 기능으로 나누고, 기능 내부를 계층으로 나눈다. order/ ├── controller/ ├── service/ ├── repository/ ├── domain/ ├── dto/ └── exception/ member/ ├── controller/ ├── service/ ├── repository/ ├── domain/ └── dto/ 이를 기능 중심 패키지 구조 라고 볼 수 있다. 어디서 어떻게 사용되는가? 새로운 주문 요구사항을 조사한다면 order 안에서 대부분의 흐름을 찾을 수 있다. OrderController ↓ OrderService ↓ OrderRepository ↓ Order 기능의 API, 유스케이스, 데이터 접근, 도메인 규칙이 가까운 위치에 모인다. 왜 필요한가? 프로젝트의 실제 변경은 대개 기술 단위가 아니라 기능 단위로 발생한다. “Service를 변경한다” 보다는 다음과 같은 요청이 많다. “주문 취소 기능을 변경한다” “회원 탈퇴 규칙을 수정한다” 따라서 변경 이유가 같은 코드를 가까이 두는 편이 이해하기 쉽다. 실제 적용 방법 com.example.backend/ ├── order/ ├── member/ ├── catalog/ ├── notification/ └── global/ 각 기능 안에는 필요한 계층만 둔다. notification/ ├── service/ └── repository/ Controller나 Domain이 없다면 빈 디렉터리를 만들 필요도 없다. 전체 구조에서 담당하는 부분 이 구조는 기능 간 경계와 코드 탐색 범위 를 담당한다. 유의 사항 기능 패키지를 너무 잘게 나누지 않는다. 단순 클래스 종류를 기능으로 착각하지 않는다. common , util , shared 에 코드를 성급히 모으지 않는다. 두 기능에서 실제로 안정적으로 공유될 때만 공통 영역으로 이동한다. 질문 4. 각 계층은 무엇을 담당해야 안전할까? 기능별 패키지를 만들었더라도 모든 로직을 Service에 넣으면 결국 거대한 Service가 된다. 그러면 각 계층이 맡아야 하는 책임을 정해야 한다. 해결 방법 의존 방향을 한 방향으로 제한한다. Controller ↓ Service ↓ Repository ↓ Database / External API Service ↓ Domain Controller는 무엇을 하는가? Controller는 외부 요청과 애플리케이션 사이의 경계다. 담당 ├── HTTP 요청 수신 ├── 요청 값 검증 ├── DTO 변환 ├── Service 호출 └── HTTP 응답 생성 Controller가 직접 Repository를 호출하지 않는다. // 피해야 하는 형태 orderRepository.findById(id); Controller는 유스케이스를 Service에 요청한다. orderService.findOrder(id); Service는 무엇을 하는가? Service는 하나의 사용자 작업을 완성하는 흐름을 담당한다. 담당 ├── 유스케이스 순서 ├── 트랜잭션 범위 ├── 여러 Repository 협력 ├── Domain 객체 호출 └── 실패 전파 Service가 모든 비즈니스 규칙을 계산할 필요는 없다. 상태와 직접 관련된 규칙은 Domain 객체가 소유하는 편이 좋다. Repository는 무엇을 하는가? Repository는 데이터가 어디서 오는지 숨긴다. 담당 ├── 데이터베이스 조회·저장 ├── 쿼리 ├── 외부 API 접근 └── 영속성 변환 분석 대상 구조에서는 DB와 외부 API 접근 모두 Repository 계층에 포함한다. 이것은 실용적인 레이어드 구조이며, 엄격한 포트·어댑터 구조는 아니다. Domain은 무엇을 하는가? Domain은 상태와 그 상태를 지키는 규칙을 담당한다. 담당 ├── 상태 ├── 상태 변경 행위 ├── 불변식 ├── 값 검증 └── 도메인 계산 Domain은 다음을 알지 못해야 한다. HTTP Controller DTO JSON 응답 형식 Service 화면 구조 전체 구조에서 담당하는 부분 계층 규칙은 책임 혼합과 순환 의존을 방지 한다. 유의 사항 Controller에서 Repository를 직접 호출하지 않는다. Repository가 Service를 호출하지 않는다. Domain이 DTO나 Web 기술에 의존하지 않는다. JPA Entity를 API 응답으로 직접 반환하지 않는다. Service가 단순 전달만 한다면 정말 필요한 계층인지 검토한다. 질문 5. 모든 Controller 옆에 지침 문서를 두면 관리하기 쉬울까? 다음처럼 파일마다 설명서를 두고 싶을 수 있다. OrderController.java OrderController.md MemberController.java MemberController.md 하지만 코드가 바뀔 때 문서가 함께 수정되지 않으면 서로 다른 설명이 남는다. 해결 방법 문서는 클래스별이 아니라 질문과 규칙별로 중앙화 한다. docs/ ├── README.md ├── architecture.md ├── layer-boundaries.md ├── development-cycle.md ├── api-conventions.md ├── persistence.md ├── testing.md ├── security.md └── quality-gates.md 어디서 어떻게 사용되는가? docs/README.md 가 문서 지도 역할을 한다. API를 변경한다 └── api-conventions.md DB를 변경한다 └── persistence.md 구조를 변경한다 ├── architecture.md └── layer-boundaries.md 작업을 완료한다 └── quality-gates.md 왜 필요한가? 동일 규칙이 여러 문서에 복제되면 서로 다른 내용으로 변한다. 예를 들어 모든 Controller 문서에 오류 응답 규칙이 들어 있으면, 규칙을 변경할 때 모든 문서를 수정해야 한다. 대신 다음처럼 하나의 원본만 둔다. 오류 응답 규칙의 원본 └── exception-handling.md 실제 적용 방법 문서를 세 단계로 구성할 수 있다. 루트 AGENTS.md └── 프로젝트 전체 작업 지도 backend/AGENTS.md └── 백엔드 작업 규칙 backend/docs/README.md └── 상황별 상세 문서 라우터 전체 구조에서 담당하는 부분 이 문서 구조는 사람과 AI가 어떤 규칙을 읽어야 하는지 안내하는 내비게이션 이다. 유의 사항 같은 규칙을 여러 문서에 복사하지 않는다. 문서의 원본 위치를 명확히 한다. 코드만 보면 알 수 있는 내용을 문서로 반복하지 않는다. 클래스의 실제 동작은 테스트로 설명한다. 복잡한 업무 흐름만 별도 문서로 승격한다. 질문 6. 개발 하네스란 무엇이고 왜 필요한가? 문서에 규칙을 적어도 아무도 읽지 않으면 규칙은 지켜지지 않는다. 그렇다면 문서를 실제 개발 과정과 어떻게 연결할 수 있을까? 해결 방법 문서, AI 역할, 자동 검사를 하나의 흐름으로 연결한다. 개발 하네스 ├── AGENTS.md ├── 작업별 문서 ├── AI 역할 정의 ├── 검증 스크립트 ├── Git Hook ├── 테스트 └── CI 하네스는 특정 프레임워크가 아니다. 개발자가 안전한 순서에서 벗어나지 않도록 둘러싼 작업 환경 전체다. 어디서 어떻게 사용되는가? 작업 시작 └── AGENTS.md가 읽을 문서를 안내 코드 작성 전 └── 개발 절차와 계층 경계 확인 커밋 전 └── Git Hook으로 규칙 검사 PR 생성 후 └── CI에서 테스트와 문서 구조 검사 완료 전 └── Quality Gate 확인 왜 필요한가? 문서만 있으면 권고 사항에 머문다. 자동 검사를 연결하면 일부 규칙이 실행 가능한 계약이 된다. “필수 문서가 있어야 한다” → 스크립트로 파일 존재 검사 “에이전트는 읽기 전용이어야 한다” → 설정 파일 검사 “커밋 제목은 일정한 형식이어야 한다” → commit-msg hook 검사 “백엔드는 DB 통합 테스트를 통과해야 한다” → CI에서 PostgreSQL 실행 후 Gradle check 전체 구조에서 담당하는 부분 하네스는 코드 구조 자체가 아니라 코드를 변경하는 과정을 보호 한다. 유의 사항 모든 규칙을 문서 검사로 해결할 수는 없다. 예를 들어 다음 규칙은 별도의 구조 테스트가 없다면 문서와 리뷰에 의존한다. Controller가 Repository를 직접 호출하지 않는다. 이 규칙이 자주 깨진다면 ArchUnit 같은 자동 검사를 추가할 수 있다. 한 번도 깨지지 않았다면 미리 추가할 필요는 없다. 질문 7. 여러 AI가 동시에 코드를 작성하면 더 빠르지 않을까? AI가 여러 대라면 기능을 나눠 동시에 구현하는 것이 빠르게 보인다. 하지만 같은 코드베이스를 여러 AI가 수정하면 다음 문제가 생길 수 있다. 동일 파일 충돌 서로 다른 설계 도입 중복 구현 최종 책임 불명확 한 AI의 전제를 다른 AI가 모름 해결 방법 Single Writer, Multiple Readers 구조를 사용한다. 메인 작업자 ├── 요구사항 판단 ├── 코드 작성 ├── 결과 통합 └── 최종 검증 책임 읽기 전용 보조 AI ├── Explorer ├── Architect └── Reviewer 메인 작업자는 사람일 수도 있고 AI일 수도 있다. Explorer는 무엇을 하는가? Controller ↓ Service ↓ Repository ↓ Domain 이 흐름을 추적해 변경 영향 범위를 조사한다. 직접 수정하지 않고 다음을 보고한다. 관련 파일 호출 흐름 데이터 흐름 기존 테스트 미확인 사항 Architect는 무엇을 하는가? 다음을 검토한다. 기능 경계 계층 의존 API 계약 트랜잭션 범위 데이터 일관성 마이그레이션 영향 Architect도 코드를 수정하지 않는다. Reviewer는 무엇을 하는가? 구현이 끝난 뒤 독립적인 관점에서 다음을 본다. 정확성 회귀 인증·인가 입력 검증 동시성 성능 테스트 누락 비밀 노출 왜 필요한가? 구현한 주체는 자신의 전제를 당연하다고 생각하기 쉽다. 읽기 전용 Reviewer는 구현 과정에 참여하지 않았기 때문에 다른 관점에서 볼 수 있다. 전체 구조에서 담당하는 부분 AI 역할 분리는 병렬 구현 보다 독립적인 조사와 검증 을 담당한다. 유의 사항 모든 변경에 여러 AI를 사용하지 않는다. 단순 변경은 메인 작업자 하나로 충분하다. 구조·보안·DB 변경처럼 위험한 작업에만 보조 역할을 추가한다. AI 리뷰를 테스트 통과로 간주하지 않는다. 최종 책임은 항상 메인 작업자에게 둔다. 질문 8. 기능 하나를 실제로 어떤 순서로 개발해야 할까? 바로 코드를 작성하면 빠르지만, 중간에 요구사항이나 영향 범위를 잘못 이해했다는 사실을 발견할 수 있다. 해결 방법 작업을 다음 흐름으로 고정한다. 계약 → 탐색 → 설계 → Red → Green → Refactor → Verify → Review 1단계: 작업 계약 코드를 작성하기 전에 네 가지를 적는다. Goal 사용자가 얻을 결과는 무엇인가? Context 관련 코드와 테스트는 어디에 있는가? Constraints 기술·범위·안전 제한은 무엇인가? Done 무엇을 실행해 완료를 증명할 것인가? 2단계: 탐색 Controller ↓ Service ↓ Repository ↓ Domain 운영 코드만 보지 않고 가까운 테스트를 함께 읽는다. 또한 다음을 찾는다. 공개 API 계약 트랜잭션 경계 외부 시스템 실패 경로 기존 사용자 영향 3단계: 설계 게이트 변경할 객체마다 한 문장으로 책임을 설명한다. OrderController → 주문 취소 HTTP 요청을 검증하고 Service에 전달한다. OrderService → 주문 취소 유스케이스와 트랜잭션을 관리한다. Order → 현재 상태에서 취소 가능한지 판단한다. 설명이 어렵다면 책임이 섞였을 가능성이 있다. 4단계: Red → Green → Refactor Red └── 필요한 행동을 보여주는 실패 테스트 Green └── 테스트를 통과하는 최소 구현 Refactor └── 행동을 유지하면서 이름·책임·중복 개선 5단계: Verify → Review 가장 가까운 테스트 ↓ 기능 전체 테스트 ↓ DB 통합 테스트 ↓ 전체 검사 ↓ 최종 diff 리뷰 전체 구조에서 담당하는 부분 이 순서는 잘못된 요구사항을 큰 코드로 확장하기 전에 멈추게 하는 역할 을 한다. 유의 사항 컴파일 오류를 Red 단계의 성공으로 보지 않는다. 테스트만 통과하도록 값을 하드코딩하지 않는다. 하나의 작업에서 여러 행동을 한꺼번에 변경하지 않는다. 실행하지 못한 검사는 통과했다고 기록하지 않는다. 질문 9. 테스트는 어느 계층에 얼마나 작성해야 할까? 모든 클래스를 단위 테스트하면 테스트 수는 많아지지만 실제 서비스 동작을 보장하지 못할 수 있다. 반대로 통합 테스트만 작성하면 느리고 실패 원인을 찾기 어렵다. 해결 방법 계층별 위험에 맞는 테스트를 둔다. Domain └── 빠른 단위 테스트 행위, 불변식, 경계값 Service └── 유스케이스 테스트 흐름, 협력, 실패 전파 Controller └── HTTP 계약 테스트 검증, 상태 코드, 오류 응답 Repository └── DB 통합 테스트 매핑, 쿼리, 제약조건 External API └── 계약·통합 테스트 요청, 응답, timeout, 변환 왜 필요한가? 각 계층에서 발생하는 문제의 성격이 다르기 때문이다. Domain 오류 → 잘못된 비즈니스 판단 Controller 오류 → 잘못된 HTTP 계약 Repository 오류 → 실제 DB와 다른 동작 외부 API 오류 → timeout이나 응답 형식 변화 실제 적용 방법 테스트 디렉터리가 운영 코드 구조를 따라가도록 한다. src/main/java/com/example/order/ ├── controller/ ├── service/ ├── repository/ └── domain/ src/test/java/com/example/order/ ├── controller/ ├── service/ ├── repository/ └── domain/ 전체 구조에서 담당하는 부분 테스트는 문서보다 더 정확하게 현재 코드가 실제로 보장하는 동작 을 설명한다. 유의 사항 구현 세부사항보다 외부 행동을 검증한다. 테스트 하나는 행동 하나를 검증한다. 실제 DB 경계가 중요하면 mock으로 대체하지 않는다. 버그 수정은 실제 증상을 재현하는 테스트에서 시작한다. flaky 테스트는 재실행 성공만으로 통과시키지 않는다. 질문 10. 언제 별도의 업무 문서를 만들어야 할까? 모든 기능에 상세 설계 문서를 만들면 관리 비용이 커진다. 반대로 아무 문서도 없으면 복잡한 업무 흐름을 코드만 보고 이해해야 한다. 해결 방법 코드만으로 파악하기 어려운 흐름에만 별도 문서를 둔다. 별도 문서가 유용한 경우는 다음과 같다. 여러 단계로 이어지는 데이터 파이프라인 중단과 재시작이 있는 작업 외부 데이터 동기화 데이터 수명주기 마이그레이션 순서 장애 복구 절차 운영자가 직접 실행하는 작업 예시 docs/ ├── data-pipeline-execution.md ├── source-data-lifecycle.md └── address-reference-import.md 이 문서들은 클래스 설명서가 아니다. 어떤 순서로 실행되는가? 중간에 실패하면 어떻게 되는가? 재실행해
Z Yuan et al, AET5: A transcriptome-guided molecular generation framework with contrastive selfsupervised learning, PLOS Computational Biology Introduction 초기 de novo molecular generation 연구 는 방대한 chemical space를 효율적으로 탐색하기 위해 시작되었다. 기존의 high-throughput screening은 비용이 높고 탐색 가능한 화학 공간이 제한적이기 때문에, VAE, GAN, RNN, graph-based model과 같은 딥러닝 기반 생성 모델이 등장하였다. 이후 Transformer와 molecular language model 이 도입되면서 MolT5, MolGPT, Chemformer와 같이 분자의 SMILES 표현이나 구조적 패턴을 학습하여 보다 효과적으로 새로운 분자를 생성하는 방향으로 발전하였다. 그러나 이러한 초기 생성 모델의 주된 목표는 화학적으로 유효한 분자를 생성 하거나 특정 physicochemical property를 만족 시키는 것이었으며, 생성된 분자가 실제 세포에서 어떤 생물학적 반응을 유도하는지는 직접적으로 고려하지 않는 경우가 많았다. 이러한 한계를 보완하기 위해 최근에는 단순한 화학적 특성을 넘어 생물학적 정보를 조건으로 사용하는 molecular generation이 연구되기 시작했다. 특히 gene expression profile 은 세포의 전체적인 상태를 나타내며, 질병 상태와 약물 처리 이후의 세포 반응을 직접적으로 연결할 수 있다는 장점이 있다. 따라서 disease-associated expression state를 정상 상태로 되돌릴 수 있는 분자를 생성한다는 관점에서 transcriptomic information은 유용한 conditioning signal 이 될 수 있다. 하지만 기존 연구에는 두 가지 중요한 문제가 남아 있다. 첫째, 많은 방법들이 여전히 chemical syntax, molecular property , 또는 기존 약물의 prioritization과 repurposing 에 집중하고 있으며, 생성 과정에서 gene regulatory response와 같은 downstream biological effect를 명시적인 생성 제약으로 충분히 활용하지 못하고 있다 . 기존의 biological modeling 역시 protein target이나 protein–ligand interaction과 같은 비교적 직접적인 분자 수준의 관계에 집중 해 왔기 때문에, 특정 분자가 세포 전체의 regulatory state를 어떻게 변화시키는지를 고려한 생성은 상대적으로 부족 하다. 즉, “어떤 target에 결합하는가”를 넘어 “세포 상태를 원하는 방향으로 변화시키는가”라는 biological-effect-oriented generation이 충분히 다뤄지지 않았다는 것이다. 둘째, 기존 expression-conditioned generation에서 gene expression을 표현하는 방법 자체에도 한계가 있다. 많은 연구가 raw expression vector를 직접 molecular representation과 concatenate하거나, linear projection을 적용하거나, VAE를 통해 저차원 latent representation으로 변환한다. 그러나 transcriptomic data는 본질적으로 high-dimensional하고 noisy하며 gene–gene dependency가 복잡 하기 때문에 단순한 linear transformation만으로는 중요한 biological pattern을 충분히 포착하기 어렵다. 또한 VAE는 smooth하고 continuous한 latent space를 만드는 데 최적화되어 있기 때문에, expression encoder로 사용할 경우 disease-specific 또는 perturbation-specific signal이 지나치게 smoothing되거나 distributional regularization에 의해 약화 될 가능성이 있다. 결과적으로 기존 embedding 방식은 gene expression이 포함하고 있는 세포 상태의 biological semantics를 충분히 보존하지 못하고, molecular generation의 biological controllability를 제한 할 수 있다. 이 문제는 질병에 따라 더욱 복잡해진다. 예를 들어 바이러스 감염은 데이터가 적고 noise가 크며 빠르게 변화하는 cellular background를 갖는 반면, cancer는 매우 높은 cellular heterogeneity와 강한 gene–gene correlation을 가진다. 따라서 서로 다른 disease context에 동일한 단순 conditioning mechanism을 적용하면 중요한 질병 특이적 biological signal을 안정적으로 추출하기 어렵다 . 결국 expression-conditioned molecular generation의 핵심 문제는 단순히 gene expression을 generator에 입력하는 것이 아니라, noise를 억제하면서도 disease와 cellular context에 관련된 정보를 보존 하고, 이를 molecular representation과 효과적으로 연결할 수 있는 transcriptomic representation을 학습 하는 것이라고 볼 수 있다. Method Transcriptome conditional encoder 다양한 교란 하에서도 일관성을 유지하는 강건한 잠재 표현을 추출하기 위해 sef-supervised contrastive learning을 통해 사전학습된다. 유전자 간의 맥락적 의존성을 명시적으로 모델링하기 위해 각 유전자를 하나의 토큰으로 간주하고, 각 샘플 내의 모든 유전자에 대해 특징별 어텐션을 적용한다. 유전자들은 의존 관계를 가지지만 본질적인 순차적 순서가 존재하지 않는다. transformer는 고차원 embedding을 입력으로 받기 때문에 scalar를 FNN으로 projection한다. 각 유전자의 두 개의 증강 뷰는 네 가지 증강 연산자, feature dropout $D$, random scaling $S$, adaptive Gaussian noise $G_{adap}$, structured Gaussian noise $G_{struct}$의 확률적 조합을 사용하여 생성된다. $$ \tilde{x}^{(i)} = A_i(x) = D_i \circ S_i \circ G_{adap,i} \circ G_{struct,i}(x) $$ 각 연산자는 다양한 교란을 생성하도록 무작위로 파라미터화되며, 연산자의 조합 순서는 특정한 모델링 의미를 갖지 않는다. feature dropout : 유전자 특징을 무작위로 마스킹 random scaling : 유전자 수준에서 발현값을 교란 adaptive Gaussian noise : 학습 세트에서 추정된 분산을 사용하여 특징별 노이즈 주입 structured Gaussian noise : 다변량 가우시안 분포 $N(0,\sum)$에서 샘플링 각 증강 뷰는 이후 유전자 수준 transformer $f_{\theta}(\cdot)$에 의해 인코딩되어 문맥화된 유전자 표현을 생성하고, projection head에 의해 샘플 수준 잠재 벡터로 압축 $$ h_1 = f_{\theta}(\tilde{x}^{(1)}), h_2 = f_{\theta}(\tilde{x}^{(2)}) $$ $$ c_1 = g(h_1), c_2 = g(h_2) $$ 모델은 InfoNCE loss를 사용하여 샘플 수준에서 최적화된다. 동일한 발현 프로파일의 두 증강 뷰는 positive pair, 동일한 배치 내 다른 샘플의 표현은 negative pair로 사용된다. $$ \mathcal{L} {InfoNCE} = -\frac{1}{B}\sum^B {i=1}log\frac{exp(\frac{sim(c^i_1,c^i_2)}{\tau})}{\sum^B_{j=1}exp(\frac{sim(c^i_1,c^i_2)}{\tau})} $$ 사전학습 이후 전사체 조건 인코더는 동결되어, 입력 약물 유도 발현 프로파일 $x$를 잠재 조건 벡터 $c = g(f_{\theta}(x))$로 매핑하는 데 사용된다. Molecule generation module Transcriptome conditional encoder가 생성한 $c$를 MolT5의 hidden state에 호환되도록 하기 위해, feed-forward condition-mapping network를 통해 고정 길이의 조건 토큰 시퀀스로 변환된다. $$ C = Reshape(FFN_{cond}(c)) \in \mathbb{R}^{K_C \times d_T} $$ $K_C$ : 조건 토큰의 수 $d_T$ : MolT5의 hidden state 생성되 조건 토큰 $C$는 MolT5 인코더의 입력으로 사용된다. 인코더에서는 self-attention을 통해 각 condition token 사이의 관계를 학습하고, 최종적으로 transcriptomic condition을 표현하는 contextualized representation $H_{enc}$를 생성한다. 이 과정을 통해 원래의 gene expression 기반 조건 정보가 MolT5가 활용할 수 있는 latent representation으로 변환된다. $$ H^l_{enc} = FFN^l_{enc}(SelfAttn(H^{l-1} {enc})) \ H^l {enc} = Adapter^l_{enc}(H^l_{enc}) $$ 반면 decoder는 이전까지 생성된 SMILES token을 입력으로 받아 다음 token을 순차적으로 예측한다. 먼저 masked self-attention을 통해 기존에 생성된 SMIELS sequence의 문맥을 반영하고, 이후 cross-attention을 통해 encoder가 생성한 transcriptomic condition representation $H_{enc}$를 참조한다. 따라서 다음 SMILES token을 결정할 때 단순히 앞선 molecular sequence만 고려하는 것이 아니라, 입력으로 주어진 biological condition도 함께 반영하게 된다. $$ H^l_{dec} = SelfAttn^l_{dec}(H^{l-1} {dec}) \ E^l = CrossAttn^l {dec}(H^l_{dec},H_{enc}) \ H^l_{dec} = Adapter^l_{dec}(FFN^l_{dec}(E^l)) $$ 이 과정에서 MolT5 전체를 처음부터 학습하지 않고, pretrained MolT5가 이미 가지고 있는 molecular language knowledge를 최대한 유지하기 위해 parameter-efficient fine-tuning 전략을 사용한다. 대부분의 pretrained parameter는 freeze하고, Transformer block 내부에 lightweight adapter를 추가하여 해당 adapter와 condition-mapping network, 그리고 일부 상위 layer만 학습한다. 이를 통해 제한된 transcriptomic-molecule pair 데이터에서도 전체 모델을 fine-tuning하는 것보다 적은 수의 parameter만 업데이트하면서 새로운 biological condition에 적응할 수 있다. 학습 단계에서는 teacher forcing을 사용한다. 즉, $n$번째 SMILES token을 예측할 때 모델이 이전에 생성한 token을 다시 입력하는 것이 아니라 실제 정답 sequence인 ($s_1,\ldots,s_{n-1}$)를 decoder의 입력으로 제공한다. 모델은 주어진 transcriptomic condition $C$와 이전 SMILES token들을 바탕으로 다음 token의 확률을 최대화하도록 학습된다. $$ -\sum_{n=1}^{N} \log p_{\psi} \left( s_n \mid s_1,\ldots,s_{n-1},C \right) $$ 추론 과정에서는 분자 다양성을 향상시키기 위해 stochastic decoding을 사용하여 전사체 조건하에서 후보 SMILES 시퀀스를 자기회귀적으로 생성한다. 결국 molecular generation module의 핵심은 transcriptome-derived embedding을 MolT5의 condition token으로 변환한 뒤, 이를 encoder에 입력하고 decoder가 cross-attention을 통해 해당 biological condition을 지속적으로 참조하면서 SMILES를 autoregressive하게 생성하는 것 Results 저자들은 실제 질병 transcriptome에서도 AET5가 작동하는지 살펴보았다. SARS-CoV-2 infection : 데이터가 제한적이고 noisy하며, 서로 다른 source에서 수집되어 heterogeneous한 transcriptome 환경 Prostate cancer(PC) : 데이터는 비교적 풍부하지만 disease mechanism이 복잡한 환경 이 실험의 목적은 크게 3개이다. noisy하고 heterogeneous한 transcriptome에서도 AET5가 안정적으로 작동하는지 모델이 학습한 disease-conditional signal이 실제 disease-related gene/target과 연결되는지 서로 다른 질환에서도 하나의 expression-conditioned generation framework가 유효한 후보 분자를 생성할 수 있는지 SARS-CoV-2 서로 다른 출처의 transcriptome을 사용하였다. 한쪽은 collective sample, 다른 쪽은 individual-level sample이었으며 두 source 사이에는 상당한 expression pattern 차이가 있었다. 저자들은 이를 그대로 하나의 조건으로 쓰기보다 mixed-sample strategy를 사용해 여러 개의 potential disease expression profile을 구성하고, 각각을 조건으로 AET5가 candidate molecule을 생성하도록 하였다. 생성된 molecule은 다음 순서로 필터링 되었다. AET5-generated molecules ↓ RDKit validity check ↓ Canonical SMILES 기반 duplicate 제거 ↓ SA score < 4인 molecule만 유지 ↓ DeepCE 기반 disease-reversal 평가 DeepCE를 통해 각 generated molecule이 유도할 것으로 예측되는 transcriptomic perturbation을 계산하고, 이를 실제 SARS-CoV-2 disease expression signature와 비교하였다. 핵심 아이디어는 다음과 같다 Disease expression Gene A ↑ Gene B ↓ Gene C ↑ Drug-induced expression Gene A ↓ Gene B ↑ Gene C ↓ 이 처럼 두 profile이 반대 방향일수록 negative correlation이 강해진다. 따라서 저자들은 disease-specific expression과 가장 강한 negative correlation을 보이는 molecule을 우선 후보로 선택했다. 선정된 후보에 대해 SwissADME, QED, BOILED-Egg 등을 사용해 drug-likeness와 pharmacokinetic property를 평가했다. 대부분의 SARS-CoV-2-conditioned molecule은: SA score < 4 QED > 0.5 BOILED-Egg의 absorbable region 또는 그 주변 에 위치했다. 또한 일부 molecule은 known compound와 TPSA–WLOGP 공간에서는 가까우면서도 구조적 유사도는 낮아, 기존 compound를 단순히 복제하지 않고 유사한 pharmacokinetic property를 가진 새로운 구조를 생성할 수 있음을 보여주었다. Prostate cancer 이전과 달리 여기서는 AET5가 molecule을 생성할 때 실제 PC-related gene signal을 참고하고 있는지를 확인하려 한다. 저자들은 molecular generator의 attention score를 이용해 각 gene locus가 token-level molecular decision에 얼마나 기여했는지 계산했다. 그 다음 attention score가 높은 gene들을 Open Targets와 비교했다. 그 결과 978개 loci 중 25개가 confidence score > 0.5인 PC-related target과 연결되었다. 이는 AET5가 transcriptome condition을 단순한 numerical control signal로 사용하는 것이 아니라, disease-relevant biological signal을 어느 정도 포착하고 있을 가능성을 보여주는 결과로 해석된다. Attention ranking 상위 50개 gene 중에서 다음 조건을 만족하는 target을 선정했다. complete protein structure가 존재 known binding pocket이 존재 reference molecule이 존재 그 결과: CHEK2 — PDB ID: 2YCF TUBB6 — PDB ID: 6AB2 가 PC-related candidate target으로 선택되었다 동시에 PC-conditioned generated molecule에 대해서도 ADME, SA, QED를 평가했다. 대부분의 molecule은 낮은 SA score 범위에 있었고, QED는 약 0.5를 중심으로 비교적 넓게 분포했다. 마지막으로 generated molecule의 target-binding potential을 평가했다. 사용한 target은 총 4개였다. Disease Target PDB ID SARS-CoV-2 Nsp3 7LMD SARS-CoV-2 RdRp 9I1S Prostate cancer CHEK2 2YCF Prostate cancer TUBB6 6AB2 SARS-CoV-2의 Nsp3와 RdRp는 각각 viral polyprotein processing/immune evasion과 viral RNA replication에 중요한 protein이다. Molecular Docking Generated molecule이 target protein의 binding pocket에 실제로 들어갈 수 있는지를 AutoDock Vina를 이용해 평가했다. 특히 SARS-CoV-2의 Nsp3 target인 7LMD에서 generated molecule은 control molecule과 유사한 binding pocket을 차지하면서도 구조적으로는 분명한 차이를 보였다. 또한 docking score 기준으로 generated molecule이 control보다 favorable한 binding profile을 보였다. Molecular dynamics simulation Docking은 정적인 binding pose만 보여주기 때문에, 저자들은 추가로 molecular dynamics simulation을 수행했다. 주요 평가 지표는: RMSD hydrogen bond number radius of gyration 이다. 7LMD에 대해 generated ligand–protein complex는 simulation 동안 비교적 안정적인 conformational behavior를 보였다. 저자들은 두 case study를 종합해 AET5가: 서로 다른 disease context에서 적용 가능하고 disease-conditioned biological signal을 반영할 가능성이 있으며 generated molecule이 favorable한 predicted pharmacokinetic property와 target-binding potential을 가질 수 있다고 주장한다 Limitations 실험적 검증 부족 현재 검증은 molecular similarity, ADME prediction, dockin
들어가기에 앞서 정보 엔트로피(information entropy) step1. 정보량 어떤 사건이 자주 일어나면 별로 놀랍지 않고, 거의 안 일어나는 사건이 발생하면 놀라움 정보이론에서는 이 “놀라움의 정도”를 정보량이라고 봄 어떤 사건의 확률이 0.5라면 정보량은 비교적 작고, 확률이 0.01이라면 정보량은 훨씬 큼 그러면 아래와 같이 step2. 왜 -(log P(x))를 사용할까? 확룰이 작을수록 정보량이 커져야함 100% 일어나는 사건은 새로운 정보가 없음을 의미 하지만 드문 사건일수록 정보량이 커짐 step3. 왜 로그를 쓰는가? 로그 성질때문에 이렇게 진행이 됨 step4. 그러면 엔트로피는 무엇인가? -> 정보량의 평균값 각 사건마다 정보량이 다르기 때문에 전체 시스템이 평균적으로 얼마나 많은 정보를 가지는지를 계산함 발생 확률 × 그 사건의 정보량 step5. 주사위로 보면 해당 부분에서 머신러닝을 진행할때 softmax가 확률을 출력함 모델이 얼마나 확신하고 있는지 판단하는 데 사용할 수 있음 bit를 사용한 것은 log_{2}를 사용했을 떄의 정보량 단위임 크로스 엔트로피(cross entropy) 실제 분포 (P)를 기준으로 봤을 때, 모델이 예측한 분포 (Q)가 얼마나 잘못되었는지를 나타내는 값 -> 예측과 달라서 생기는 깜놀도(즉 정보량)을 의미함 핵심은 정답이 실제로 발생했는데, 모델이 그 정답에 낮은 확률을 줬다면 큰 손실을 준다는 것 정답이 0 또는 1인 이진 분류에서는 다음과 같이 씀 여기서 보이듯이 정답이 높은 확률을 부여하면 -> cross entropy가 작음 정답에 낮은 확률을 부여하면 -> cross entropy 큼 Entropy와 Cross Entropy의 차이 -> 실제 분포 (P) 자체가 얼마나 불확실한가 = entropy -> 실제는 (P)인데 모델이 (Q)라고 생각했을 때 필요한 평균 정보량 = Cross Entropy KL Divergence는? KL Divergence는 두 확률분포 (P)와 (Q)가 얼마나 다른지를 정보량 관점에서 나타낸 값 즉 해당 것은 모델 떄문에 추가로 발생한 차이임
이번 주차에서는 1주차에 설계했던 ERD를 MySQL 테이블과 더미 데이터로 구현하고, SELECT , WHERE , JOIN , ORDER BY , LIMIT 등을 사용해 화면에 필요한 데이터를 직접 조회해보았다. 그중 가장 궁금했던 부분은 JOIN 이었다. 미션 3에서 특정 책의 태그 목록을 조회하기 위해 book , book_tag , tag 테이블을 JOIN했는데, 책은 하나인데 같은 책 제목이 여러 줄 나타났다. 처음에는 JOIN을 잘못해서 데이터가 중복된 건가? 라고 생각했다. 하지만 ERD의 관계를 다시 확인해보니, 이 결과는 오류가 아니라 1:N 관계가 JOIN 결과에 그대로 펼쳐진 것 이었다. 그래서 이번 글에서는 단순히 JOIN 문법을 정리하기보다, JOIN하면 왜 행의 개수가 늘어날 수 있는지 1:N, N:M 관계가 결과 행 수에 어떤 영향을 주는지 정상적인 반복과 잘못된 중복은 어떻게 다른지 DISTINCT 로 중복을 제거하면 항상 해결되는지 단순한 존재 여부를 확인할 때는 왜 EXISTS 를 사용할 수 있는지 를 중심으로 정리해보려고 한다. 1. JOIN은 단순히 테이블을 옆으로 붙이는 걸까? JOIN은 서로 다른 테이블에 나누어 저장된 데이터를 관계를 기준으로 하나의 결과로 조회할 때 사용한다. 이번 실습의 도서 상세 화면에서는 다음과 같은 정보가 필요했다. 책 제목 태그 이름 현재 사용자의 좋아요 여부 하지만 이 값들은 하나의 테이블에 모두 들어 있지 않았다. book → 책 정보 tag → 태그 정보 book_tag → 책과 태그의 관계 book_like → 사용자와 책의 좋아요 관계 특히 책과 태그는 다음과 같이 연결되어 있다. book ↓ book_tag ↓ tag book_tag 는 책과 태그 사이의 관계를 저장하는 중간 테이블이다. 예를 들어 book_id = 1 인 책에 tag_id = 1 , tag_id = 2 가 연결되어 있다면 book_tag 에는 다음과 같은 데이터가 존재할 수 있다. book_id | tag_id --------|------- 1 | 1 1 | 2 즉 책 한 권에 여러 태그가 연결될 수 있다. 이 관계가 JOIN 결과의 행 수를 결정하는 중요한 요소가 된다. 2. 책은 하나인데 왜 JOIN 결과는 두 줄일까? 미션 3에서 태그 정보를 조회하기 위해 다음과 같은 SQL을 작성했다. SELECT b.title, t.name AS tag_name FROM book b JOIN book_tag bt ON b.book_id = bt.book_id JOIN tag t ON bt.tag_id = t.tag_id WHERE b.book_id = 1; 실행 결과는 다음과 같이 나타났다. 달빛 도서관 | 소설 달빛 도서관 | 추천 달빛 도서관 이라는 책은 한 권인데 결과에서는 두 번 등장한다. 하지만 실제 관계를 보면 이유는 단순하다. 달빛 도서관 ├─ 소설 └─ 추천 책 자체는 하나지만 책과 태그 사이의 관계가 두 개 존재한다. JOIN은 이 두 관계를 각각 하나의 행으로 표현한다. 따라서 책 1개 + 연결된 태그 2개 = JOIN 결과 2행 이 된다. 즉 JOIN 결과에서 기준 테이블의 데이터가 반복되는 것은 항상 중복 오류를 의미하지 않는다. 하나의 데이터가 여러 데이터와 관계를 맺고 있다면 그 관계의 수만큼 기준 데이터가 반복될 수 있다. 3. 카디널리티에 따라 JOIN 결과는 어떻게 달라질까? ERD에서 자주 보는 1:1 , 1:N , N:M 은 단순히 다이어그램에 표시하는 관계가 아니다. 이 관계는 실제 JOIN 결과의 형태에도 영향을 준다. 1:1 관계 한 행이 상대 테이블의 한 행과만 연결된다. A 1 : 1 B A의 한 행에 B의 한 행만 연결된다면 JOIN 이후에도 일반적으로 한 관계가 한 행으로 표현된다. 1:N 관계 한 행이 상대 테이블의 여러 행과 연결된다. book 1 : N book_tag 예를 들어 책 한 권에 태그 연결 정보가 세 개 있다면 JOIN 결과에서는 같은 책 정보가 세 번 나타날 수 있다. 책 A | 태그 1 책 A | 태그 2 책 A | 태그 3 N:M 관계 양쪽 데이터가 모두 여러 개의 상대 데이터와 연결될 수 있다. 관계형 데이터베이스에서는 보통 중간 테이블을 이용해 두 개의 1:N 관계로 풀어서 표현한다. 이번 실습의 책과 태그도 사실상 다음 구조다. book 1 : N book_tag tag 1 : N book_tag 이를 전체적으로 보면 book N : M tag 관계가 된다. 이처럼 N:M 관계에서는 하나의 데이터에 여러 관계가 연결되기 때문에 JOIN 결과의 행 수가 더 쉽게 늘어날 수 있다. 결국 JOIN 결과의 행 수를 이해하려면 단순히 테이블에 몇 행이 있는지만 볼 것이 아니라, 각 행이 상대 테이블에서 몇 개의 행과 매칭되는지 를 함께 봐야 한다. 4. 같은 값이 반복되면 무조건 중복일까? JOIN 결과에서 같은 값이 여러 번 보이면 가장 먼저 중복 이라는 생각이 들기 쉽다. 하지만 다음 두 결과를 비교해보면 차이를 알 수 있다. 달빛 도서관 | 소설 달빛 도서관 | 추천 책 제목은 반복되지만 태그가 다르다. 각 행은 서로 다른 관계를 표현하기 때문에 두 행 모두 의미가 있다. 이것은 정상적인 반복 이다. 반대로 JOIN의 ON 조건을 잘못 작성하면 실제 관계와 맞지 않는 데이터까지 연결될 수 있다. JOIN에서 중요한 것은 다음과 같이 ERD의 PK·FK 관계에 맞는 조건을 사용하는 것이다. JOIN book_tag bt ON b.book_id = bt.book_id 그리고 다시 tag 와 연결할 때도 실제 FK 관계를 따른다. JOIN tag t ON bt.tag_id = t.tag_id 만약 이러한 관계를 무시하고 잘못된 조건으로 JOIN하면 의도하지 않은 행 조합이 생성되고, 결과 행 수가 예상보다 크게 증가할 수 있다. 따라서 JOIN 결과가 예상보다 많다면 바로 데이터를 지우거나 중복 제거부터 하기보다 다음 순서로 확인하는 것이 좋다. ERD 관계 확인 ↓ PK / FK 확인 ↓ ON 조건 확인 ↓ 각 결과 행이 어떤 관계를 표현하는지 확인 5. 중복처럼 보인다고 DISTINCT부터 쓰면 될까? 여기부터는 이번 실습에서 더 궁금해져 추가로 정리한 내용이다. SQL에는 중복 행을 제거할 수 있는 DISTINCT 가 있다. 예를 들어 다음처럼 작성할 수 있다. SELECT DISTINCT b.title FROM book b JOIN book_tag bt ON b.book_id = bt.book_id JOIN tag t ON bt.tag_id = t.tag_id WHERE b.book_id = 1; 이렇게 하면 결과는 책 제목 하나만 남는다. 달빛 도서관 겉으로 보면 깔끔해 보인다. 하지만 원래 알고 싶었던 것이 책의 태그 목록이라면 문제가 생긴다. 기존 결과는 달빛 도서관 | 소설 달빛 도서관 | 추천 처럼 각각의 태그 관계를 표현하고 있었다. 그런데 단순히 중복처럼 보인다는 이유로 필요한 컬럼을 빼거나 DISTINCT 를 사용해 결과를 줄여버리면, 실제로 필요한 관계 정보까지 사라질 수 있다. 따라서 DISTINCT 는 중복이 보이니까 일단 제거하는 도구 로 사용하기보다, 최종 결과에서 정말 동일한 행을 하나만 남기는 것이 요구사항에 맞는가? 를 먼저 판단한 뒤 사용하는 것이 중요하다. 즉 JOIN 결과가 많다고 해서 항상 DISTINCT 가 해결책인 것은 아니다. 6. 좋아요 여부를 JOIN하지 않고 EXISTS로 확인한 이유 이번 미션 3에서는 태그뿐만 아니라 현재 사용자가 해당 책에 좋아요를 눌렀는지도 함께 조회했다. 실제 쿼리는 다음과 같이 작성했다. SELECT b.title, t.name AS tag_name, EXISTS ( SELECT 1 FROM book_like bl WHERE bl.book_id = b.book_id AND bl.user_id = 1 ) AS is_liked FROM book b JOIN book_tag bt ON b.book_id = bt.book_id JOIN tag t ON bt.tag_id = t.tag_id WHERE b.book_id = 1; 여기서 태그 정보는 JOIN을 사용했지만 좋아요 여부는 EXISTS 를 사용했다. EXISTS 는 조건을 만족하는 행이 존재하는지를 확인한다. 이번 요구사항에서 필요한 것은 좋아요 데이터 자체를 여러 건 조회하는 것 이 아니라 현재 사용자가 이 책을 좋아요 했는가? 라는 존재 여부다. 따라서 book_like 의 행 자체를 결과에 펼치기보다 해당 관계가 존재하는지만 확인하는 방식이 자연스럽다. 좋아요 기록 존재 → 1 좋아요 기록 없음 → 0 실제 결과는 다음과 같이 나타났다. 달빛 도서관 | 소설 | 1 달빛 도서관 | 추천 | 1 여기서 좋아요 여부가 두 번 보이는 이유 역시 태그 관계가 두 개이기 때문이다. EXISTS 가 두 개의 좋아요 데이터를 만든 것이 아니라, 이미 태그 JOIN으로 두 행이 만들어졌고 각 행에서 같은 좋아요 존재 여부를 확인한 것이다. 이 부분을 통해 JOIN을 사용할지 다른 방식으로 관계를 확인할지는 최종적으로 어떤 데이터를 결과 행으로 펼치고 싶은가 에 따라 달라질 수 있다는 점도 알게 되었다. 7. JOIN을 볼 때는 결과보다 관계를 먼저 보자 1주차에서는 ERD를 설계하며 테이블 사이의 관계를 정리했다. 2주차에는 그 관계를 실제 SQL로 조회하면서 ERD의 카디널리티가 실제 SQL 결과의 형태로 나타난다. 는 것을 확인할 수 있었다. 처음에는 다음 결과만 보고 달빛 도서관 | 소설 달빛 도서관 | 추천 책 제목이 중복되었다고 생각했다. 하지만 ERD를 함께 보면 book 1 : N book_tag 관계이기 때문에 같은 책이 여러 행에 나타나는 것이 자연스럽다는 것을 바로 이해할 수 있다. 그래서 앞으로 JOIN 쿼리를 작성하거나 결과를 확인할 때는 쿼리만 보지 않고 다음을 먼저 확인하려고 한다. 기준 테이블은 무엇인가? 어떤 PK와 FK가 연결되어 있는가? 관계가 1:1, 1:N, N:M 중 무엇인가? 기준 행 하나에 몇 개의 상대 행이 매칭될 수 있는가? 현재 결과의 한 행은 어떤 관계를 의미하는가? 이 과정을 먼저 생각하면 결과 행이 예상보다 많을 때도 단순히 중복 오류 라고 판단하지 않고 원인을 더 정확하게 찾을 수 있다. 마무리 이번 주차에서 JOIN을 직접 사용하기 전에는 JOIN을 단순히 여러 테이블을 하나로 연결하는 SQL 문법 정도로 생각했다. 하지만 실제로 조회 결과를 확인하면서 JOIN은 단순히 테이블을 옆으로 붙이는 것이 아니라, 테이블 사이에 존재하는 관계를 결과 행으로 펼쳐 보여주는 과정 에 더 가깝다고 느꼈다. 특히 1:N 관계에서는 하나의 기준 데이터가 여러 데이터와 연결되어 있기 때문에 같은 값이 여러 행에 반복될 수 있다. 이 반복은 항상 잘못된 중복이 아니다. 중요한 것은 각 행이 실제로 서로 다른 관계를 나타내고 있는지를 확인하는 것이다. 또한 결과가 많다고 바로 DISTINCT 로 제거하기보다, ERD의 관계와 ON 조건을 먼저 확인해야 한다는 점도 알게 되었다. 이번 실습을 통해 가장 기억에 남은 내용을 한 문장으로 정리하면 다음과 같다. JOIN 결과의 행 수는 단순히 원본 테이블의 행 수가 아니라, 데이터 사이에 존재하는 관계의 수와 카디널리티에 의해 결정될 수 있다. 앞으로 JOIN 결과가 예상과 다르게 나온다면 ERD 관계 → PK/FK → 카디널리티 → ON 조건 → 결과 행의 의미 순서로 확인해보려고 한다.
Durante años, medir la visibilidad online significaba abrir una herramienta SEO y comprobar en qué posición aparecía una página para una palabra clave concreta. En 2026, eso ya no es suficiente. Cada vez más personas utilizan ChatGPT, Perplexity y Gemini para descubrir productos, empresas, servicios y soluciones. En lugar de revisar una lista tradicional de resultados en Google, pueden hacer una pregunta completa y recibir directamente una selección de recomendaciones. Esto crea una nueva pregunta para cualquier empresa: ¿Aparece mi marca cuando alguien pregunta a una inteligencia artificial por productos o servicios como los míos? Un AI Rank Tracker permite responder precisamente a esa pregunta. Y no necesitas empezar utilizando una herramienta costosa. Es posible crear un sistema gratuito para monitorizar tu presencia en ChatGPT, Perplexity y Gemini y entender cómo evoluciona tu visibilidad dentro de los motores de inteligencia artificial. ¿Qué es un AI Rank Tracker? Un AI Rank Tracker es un sistema utilizado para comprobar si una empresa, producto o marca aparece en las respuestas generadas por motores de inteligencia artificial. Un rank tracker SEO tradicional analiza posiciones en Google. Puede mostrar, por ejemplo, que una página aparece en la posición 3 para una keyword concreta. El seguimiento de visibilidad en IA funciona de manera diferente. Aquí no siempre existe una posición exacta del 1 al 10. Lo importante es saber si la marca aparece, con qué frecuencia es mencionada, en qué contexto aparece, qué competidores son recomendados y qué tipos de preguntas generan esas menciones. Imagina que tienes un software de facturación para autónomos. En Google, una persona podría buscar: software de facturación para autónomos En ChatGPT, la misma persona podría preguntar: ¿Cuál es el mejor software de facturación para un autónomo en España? También podría escribir: Necesito un programa sencillo para crear facturas y gestionar mi negocio. ¿Qué opciones me recomiendas? La intención es muy similar, pero la forma de buscar es completamente diferente. Por eso el AI Rank Tracking debe analizar preguntas completas, contexto e intención, no solamente keywords. ¿Por qué monitorizar ChatGPT, Perplexity y Gemini? La forma en que las personas descubren empresas está cambiando. Google sigue siendo un canal fundamental, pero cada vez más usuarios utilizan asistentes de IA para investigar productos, comparar empresas y decidir qué soluciones considerar. Una persona que antes buscaba: mejores agencias SEO España ahora puede preguntar: Tengo una tienda Shopify y quiero mejorar mi visibilidad tanto en Google como en ChatGPT. ¿Qué agencias debería considerar? La segunda pregunta proporciona mucho más contexto. La IA puede interpretar la necesidad del usuario y seleccionar directamente varias empresas que considera relevantes. Si tu marca aparece regularmente en este tipo de respuestas, estás obteniendo una nueva forma de visibilidad digital. Si tus competidores aparecen y tú no, existe un gap que merece ser investigado. AI ranking y SEO ranking no son lo mismo Es importante no tratar las posiciones en IA exactamente igual que las posiciones en Google. En Google puedes hablar con bastante claridad de una posición 1, posición 2 o posición 10. En ChatGPT, Gemini o Perplexity, una respuesta puede ser mucho más flexible. Una IA puede recomendar tres empresas sin asignarles una posición clara. Puede mencionar una marca al principio de la respuesta, citar otra en un ejemplo y añadir una tercera como alternativa. Además, la respuesta puede cambiar dependiendo del idioma, del contexto de la conversación, de la ubicación del usuario, del modelo utilizado y de la información disponible en ese momento. Por eso, en muchos casos es más útil hablar de AI Visibility que de una posición fija. Lo que realmente quieres saber es con qué frecuencia tu marca forma parte de las respuestas relevantes. Cómo crear un AI Rank Tracker gratis No necesitas desarrollar una plataforma completa para empezar. Una hoja de cálculo y una lista bien diseñada de preguntas pueden ser suficientes para construir una primera versión. El objetivo inicial es crear una metodología consistente que puedas repetir con el tiempo. Primero necesitas identificar las categorías comerciales más importantes para tu negocio. Una tienda de colchones, por ejemplo, podría querer monitorizar preguntas relacionadas con colchones para dolor de espalda, colchones para parejas, colchones económicos o mejores marcas de colchones. Una empresa SaaS podría centrarse en preguntas relacionadas con mejores herramientas, comparaciones, alternativas a competidores, software por sector o soluciones para problemas específicos. Estas categorías se convierten en la base de tu sistema de seguimiento. Convierte tus keywords en preguntas naturales Uno de los errores más frecuentes consiste en utilizar exactamente las mismas keywords que se utilizan para SEO tradicional. Las personas suelen interactuar con una IA de una manera más conversacional. En lugar de comprobar únicamente: agencia GEO España puedes utilizar una pregunta como: ¿Cuáles son las mejores agencias GEO en España? Después puedes probar una versión más específica: ¿Qué agencia puede ayudar a una tienda Shopify a mejorar su visibilidad en ChatGPT? También puedes analizar una pregunta comparativa: ¿Qué empresas ayudan a mejorar la visibilidad en motores de inteligencia artificial además del SEO tradicional? Cada pregunta representa una variación de la misma intención. Esto permite construir una imagen mucho más realista de cómo tu marca aparece durante el proceso de descubrimiento. Utiliza los mismos prompts en varias plataformas Para obtener datos comparables, intenta utilizar el mismo conjunto principal de preguntas en ChatGPT, Perplexity y Gemini. No esperes recibir exactamente la misma respuesta. De hecho, esa diferencia es precisamente lo que hace interesante el análisis. Una empresa puede tener una visibilidad fuerte en Perplexity y aparecer muy poco en Gemini. Otra puede aparecer frecuentemente en ChatGPT cuando alguien pregunta por alternativas, pero no cuando la consulta es más general. Al utilizar los mismos prompts, puedes detectar estas diferencias con mucha más claridad. Registra los resultados de manera consistente Puedes hacerlo inicialmente con una hoja de cálculo sencilla. Cada vez que ejecutes una pregunta, registra la fecha, el prompt utilizado, la plataforma, si tu marca aparece, qué competidores son mencionados y cualquier detalle relevante sobre la respuesta. También puedes registrar la posición aproximada cuando la IA ofrece una lista claramente ordenada. No necesitas un sistema extremadamente sofisticado. La consistencia es mucho más importante. Si analizas las mismas preguntas cada mes, podrás empezar a detectar patrones y cambios reales. Cómo calcular tu AI Share of Voice Una de las métricas más sencillas consiste en calcular en qué porcentaje de las preguntas analizadas aparece tu marca. Imagina que compruebas 100 prompts relacionados con tu mercado. Tu empresa aparece en 28 respuestas. En ese caso, tu AI Visibility sería del 28 %. También puedes calcular este porcentaje por plataforma. Quizás aparezcas en el 35 % de las preguntas de ChatGPT, en el 42 % de las respuestas de Perplexity y solamente en el 18 % de Gemini. Esto te permite identificar rápidamente dónde existe mayor visibilidad y dónde todavía hay margen de mejora. Qué deberías medir además de las menciones El número de menciones es un buen punto de partida, pero no cuenta toda la historia. También importa saber si la IA simplemente menciona tu empresa o realmente la recomienda. No es lo mismo aparecer en una frase secundaria que formar parte de las principales opciones sugeridas al usuario. También deberías prestar atención a los competidores que aparecen junto a tu marca. Si determinados competidores aparecen en muchas más consultas que tú, eso puede indicar que poseen una presencia temática, una autoridad externa o una cobertura de contenido más fuerte en determinadas áreas. Otra métrica interesante es el llamado Topic Ownership . Se refiere a los temas donde una marca aparece de forma especialmente consistente. Por ejemplo, quizás una empresa tenga una visibilidad general moderada, pero aparezca casi siempre cuando alguien pregunta por una categoría muy concreta. Eso puede indicar que la IA relaciona esa marca fuertemente con ese tema. Cómo monitorizar posiciones en ChatGPT Para ChatGPT puedes crear un conjunto estable de preguntas comerciales importantes y ejecutarlas periódicamente. Cuando analices las respuestas, no te limites a comprobar si aparece el nombre de tu empresa. Observa también cómo ChatGPT describe tu marca. Esto puede revelar problemas importantes. Una empresa puede aparecer frecuentemente, pero estar asociada con una categoría antigua. Por ejemplo, una compañía que actualmente se posiciona como plataforma GEO podría seguir siendo descrita principalmente como una herramienta SEO. Eso significa que la IA conoce la marca, pero no necesariamente entiende correctamente su posicionamiento actual. Cómo monitorizar visibilidad en Perplexity Perplexity resulta especialmente útil porque muchas de sus respuestas incluyen fuentes. Esto permite analizar no solamente si una empresa aparece, sino también qué páginas parecen estar contribuyendo a esa visibilidad. Si un competidor aparece repetidamente, puedes estudiar qué tipos de fuentes lo mencionan. Quizás esté presente en artículos comparativos. Tal vez aparezca en publicaciones especializadas. Puede que tenga páginas específicas respondiendo a preguntas comerciales muy concretas. Estos patrones pueden ayudarte a entender por qué una marca obtiene más visibilidad que otra. Cómo monitorizar visibilidad en Gemini Gemini debe analizarse como una plataforma independiente. No deberías asumir que una buena presencia en ChatGPT significa automáticamente una buena presencia en Gemini. Utiliza el mismo conjun
1. 다이어그램 작성 이번 커머스 과제를 구현하면서 클래스 간 관계를 파악하기 위해 draw.io로 구조를 정리했다. 현재 구현한 구조는 대략 다음과 같다. [클래스 다이어그램] - draw.io [흐름도] - draw.io Main ↓ CommerceSystem ↓ Category ↓ Product CommerceSystem ↓ Customer CommerceSystem은 전체적인 흐름과 사용자 입력을 담당하고, Category는 상품 목록을 관리하며, Product는 개별 상품 정보를 관리하도록 역할을 나누었다. 또한 실무에서 다이어그램을 어떻게 활용하는지, 다양한 다이어그램 중 상황에 따라 어떤 것을 선택하는지 궁금해졌다. 특히 이전 국비 과정에서도 아키텍처와 DFD의 차이를 명확하게 구분하기 어려웠기 때문에 이에 대해 질문했다. 2. 트러블슈팅 — 상품 목록이 출력되지 않는 문제 처음 실행했을 때 카테고리를 선택해도 상품이 정상적으로 출력되지 않고 다음과 같이 나타났다. [ [] ] 확인해보니 Category의 addProduct()가 실제 products 리스트에 상품을 추가하지 않고 있었고, getName()도 카테고리의 이름이 아닌 다른 값을 반환하도록 잘못 구현되어 있었다. 또한 getProducts()에서 상품 리스트를 정상적으로 반환하지 않아 이후에는 다음과 같은 NullPointerException도 발생했다. Cannot invoke "java.util.List.size()" because "products" is null 원인을 확인한 후 Category의 상품 추가 및 조회 로직을 수정했다. public void addProduct(Product product) { products.add(product); } public String getName() { return name; } public List getProducts() { return products; } 수정 후 카테고리를 선택하면 해당 카테고리에 등록된 상품들이 정상적으로 출력되는 것을 확인했다. 3. 배운 점 이번 과제를 통해 단순히 클래스를 만드는 것뿐만 아니라 각 클래스가 어떤 역할과 책임을 가져야 하는지 분리하는 것이 중요하다는 것을 다시 확인했다. 특히 CommerceSystem에서 모든 상품 데이터를 직접 관리하는 대신 Category가 자신의 상품 목록을 관리하도록 분리하면서 객체 간 역할을 구분할 수 있었다. 그리고 오류가 발생했을 때 무작정 코드를 수정하기보다 실제 데이터가 어디에서 생성되고, 어디에 저장되며, 어디에서 조회되는지를 따라가면서 원인을 찾는 것이 중요하다는 것을 배웠다.
Krizhevsky, Sutskever, Hinton. ImageNet Classification with Deep Convolutional Neural Networks . NeurIPS 2012. 1. 왜 나왔나? (Problem) 2012년 이전의 이미지 분류는 사람이 특징을 설계 하는 방식이었다. SIFT, HOG 같은 특징 추출기로 이미지를 벡터로 바꾸고, 그 위에 SVM 같은 분류기를 얹었다. 이 방식은 두 가지 벽에 부딪혀 있었다. 성능 정체 : 특징을 사람이 만들다 보니 복잡한 이미지에서 한계가 뚜렷했다. ImageNet 대회 top-5 오류율은 25% 근처에서 맴돌았다. 신경망은 "이론상 좋지만 실제로는 안 되는" 기술 : CNN은 LeNet(1998)부터 있었지만 손글씨 숫자 같은 작은 문제에서만 통했다. 네트워크를 깊고 크게 만들면 학습이 너무 느리고 (sigmoid/tanh의 기울기 포화, CPU 연산 한계) 데이터 대비 파라미터가 많아 과적합 이 심했다. 즉 풀어야 할 문제는 이것이었다. "120만 장, 1000개 클래스짜리 대규모 데이터에서, 거대한 CNN을 현실적인 시간 안에, 과적합 없이 학습시킬 수 있는가?" 2. 다른 방법과 뭐가 다른가? 비교 대상 그쪽 방식 AlexNet 전통 방식 (SIFT + SVM) 특징을 사람이 설계 특징을 데이터로부터 학습 (end-to-end) LeNet-5 (1998) 작은 입력(32×32), 층 얕음, 파라미터 약 6만, CPU, tanh 224×224 컬러, Conv 5 + FC 3, 파라미터 약 6,000만 , GPU, ReLU 좌측은 LeNet-5, 우측은 AlexNet입니다. 이미지 출처: daeun-computer-uneasy.tistory.com 핵심 차이는 "새로운 층을 발명했다"가 아니라, 규모를 키웠을 때 생기는 문제들을 실전적으로 해결해서 깊은 CNN이 실제로 동작함을 증명했다 는 점이다. 3. 그래서 어떻게 풀었나? (Solve) 구조: Conv 5층 + FC 3층 층 구성 비고 Conv1 96개, 11×11, stride 4 ReLU → LRN → MaxPool Conv2 256개, 5×5 ReLU → LRN → MaxPool Conv3 384개, 3×3 ReLU Conv4 384개, 3×3 ReLU Conv5 256개, 3×3 ReLU → MaxPool FC6 4096 ReLU + Dropout FC7 4096 ReLU + Dropout FC8 1000 Softmax 문제별 해결책 학습이 느리다 → ReLU + GPU max(0, x) 는 양수 구간에서 기울기가 1로 유지돼 포화가 없다. 논문 실험에서 tanh 대비 같은 오류율 도달이 약 6배 빨랐다. GTX 580(3GB) 한 장에 모델이 안 들어가서 네트워크를 절반씩 두 GPU에 나눠 학습했다. 특정 층에서만 GPU끼리 통신한다. (구조도가 위아래 두 갈래인 이유) 과적합이 심하다 → Dropout + Data Augmentation Dropout (p=0.5) : FC6, FC7에서 뉴런을 무작위로 끈다. 파라미터가 몰린 FC층의 과적합을 직접 겨냥했다. Data Augmentation : 256×256에서 무작위 224×224 크롭 + 좌우 반전, PCA 기반 색상 변형으로 데이터를 사실상 크게 늘렸다. 일반화 성능을 조금 더 → Overlapping Pooling, LRN 3×3 풀링을 stride 2로 겹쳐서 적용. LRN으로 인접 채널 간 정규화. (단, 이후 효과가 미미하다고 밝혀져 BatchNorm에 자리를 내줌) LRN(Local Response Normalization)이란? LRN은 AlexNet에서 사용한 정규화 기법이다. 같은 공간 위치에 있는 인접 채널들의 활성값을 이용해 각 값을 조정한다. 주변 채널의 활성값이 클수록 더 큰 값으로 나누기 때문에, 해당 채널의 출력이 작아진다. 여기서 값을 ‘누른다’ 는 것은 0으로 만든다는 뜻이 아니라 크기를 줄인다는 뜻이다. 큰 활성값도 LRN을 거치면 작아질 수 있으며, 채널 사이의 반응을 상대적으로 비교하는 효과가 있다. AlexNet에서는 일부 합성곱 층의 ReLU 뒤, Max Pooling 앞에 LRN을 적용했다. 오늘날에는 LRN보다 Batch Normalization 같은 정규화 방법이 주로 사용된다. Overlapping Pooling이란? 풀링 창을 이동할 때 인접한 창이 서로 겹치도록 하는 방식이다. 풀링 창의 크기보다 이동 간격(stride)이 작으면 겹침이 생긴다. 예를 들어 AlexNet은 3×3 Max Pooling에 stride 2를 사용했다. 첫 번째 창이 가로 방향의 1 3번째 값을 보면, 다음 창은 3 5번째 값을 본다. 3번째 값이 두 창에 모두 포함되는 것이다. 반대로 2×2 창을 stride 2로 이동하면 창끼리 겹치지 않는다. AlexNet 논문에서는 overlapping pooling을 사용했을 때 오류율이 소폭 낮아졌다고 보고했다. 학습 설정 : SGD + momentum 0.9, weight decay 0.0005, batch 128, lr 0.01에서 시작해 정체 시 1/10, 약 90 epoch, 5~6일. 결과 ILSVRC 2012 top-5 오류율 15.3% . 2위는 26.2%. 이 격차로 컴퓨터 비전의 주류가 하루아침에 딥러닝으로 넘어갔다. 4. 코드로는 어떻게 쓰나? 실무에서 AlexNet을 처음부터 학습시킬 일은 거의 없다. 주로 구조를 직접 구현하며 CNN을 이해하는 용도 나, 사전학습 모델로 전이학습을 연습하는 용도 로 쓴다. 참고: torchvision 의 AlexNet은 원 논문이 아니라 단일 GPU 버전이다. Conv1 채널이 64개이고, LRN이 없다. (1) 직접 구현 (PyTorch) import torch import torch.nn as nn class AlexNet(nn.Module): def __init__(self, num_classes=1000): super().__init__() self.features = nn.Sequential( nn.Conv2d(3, 96, kernel_size=11, stride=4, padding=2), nn.ReLU(inplace=True), nn.LocalResponseNorm(size=5), nn.MaxPool2d(kernel_size=3, stride=2), # overlapping pooling nn.Conv2d(96, 256, kernel_size=5, padding=2), nn.ReLU(inplace=True), nn.LocalResponseNorm(size=5), nn.MaxPool2d(kernel_size=3, stride=2), nn.Conv2d(256, 384, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.Conv2d(384, 384, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.Conv2d(384, 256, kernel_size=3, padding=1), nn.ReLU(inplace=True), nn.MaxPool2d(kernel_size=3, stride=2), ) self.classifier = nn.Sequential( nn.Dropout(0.5), nn.Linear(256 * 6 * 6, 4096), nn.ReLU(inplace=True), nn.Dropout(0.5), nn.Linear(4096, 4096), nn.ReLU(inplace=True), nn.Linear(4096, num_classes), ) def forward(self, x): x = self.features(x) x = torch.flatten(x, 1) return self.classifier(x) model = AlexNet() print(model(torch.randn(1, 3, 224, 224)).shape) # torch.Size([1, 1000]) (2) 사전학습 모델로 추론 from torchvision.models import alexnet, AlexNet_Weights from PIL import Image weights = AlexNet_Weights.IMAGENET1K_V1 model = alexnet(weights=weights).eval() preprocess = weights.transforms() # 리사이즈·크롭·정규화를 한 번에 img = preprocess(Image.open("dog.jpg")).unsqueeze(0) with torch.no_grad(): pred = model(img).softmax(dim=1) idx = pred.argmax().item() print(weights.meta["categories"][idx], pred[0, idx].item()) (3) 전이학습: 내 데이터(예: 5개 클래스)에 맞추기 model = alexnet(weights=AlexNet_Weights.IMAGENET1K_V1) # 특징 추출부는 고정 for p in model.features.parameters(): p.requires_grad = False # 마지막 FC층만 내 클래스 수로 교체 model.classifier[6] = nn.Linear(4096, 5) optimizer = torch.optim.SGD( filter(lambda p: p.requires_grad, model.parameters()), lr=1e-3, momentum=0.9, weight_decay=5e-4, # 논문 설정과 같은 계열 )
Je hoeft in 2026 niet te betalen voor goede zoekwoorddata. Er zijn meerdere gratis alternatieven voor Google Keyword Planner, maar de beste keuze hangt af van wat je precies wilt onderzoeken. Ja, Google Keyword Planner heeft verschillende gratis alternatieven. Voor snelle zoekwoordideeën zijn tools zoals Semrush Free Keyword Tool en Ahrefs Keyword Generator interessant. Voor trends kun je Google Trends gebruiken en voor zoekwoorden waarop jouw eigen website al zichtbaar is, blijft Google Search Console een van de nuttigste gratis bronnen. Er bestaat alleen geen gratis tool die Google Keyword Planner op elk onderdeel volledig vervangt. Keyword Planner combineert zoekwoordsuggesties, geschatte maandelijkse zoekvolumes en advertentiedata binnen het ecosysteem van Google Ads. Andere gratis tools zijn vaak sterker op één specifiek onderdeel. De slimste aanpak is daarom meestal niet om één vervanger te zoeken, maar om verschillende gratis databronnen te combineren. Is Google Keyword Planner zelf eigenlijk gratis? Google Keyword Planner wordt vaak een gratis zoekwoordtool genoemd, en technisch gezien hoef je geen betaald SEO-abonnement af te sluiten om de tool te gebruiken. Je hebt wel een Google Ads-account nodig. Google vraagt gebruikers bovendien om de accountconfiguratie af te ronden, waaronder het invoeren van factureringsgegevens, voordat bepaalde functies van Keyword Planner beschikbaar worden. Dat maakt Keyword Planner minder toegankelijk dan sommige SEO-tools waarbij je direct een zoekwoord kunt invoeren zonder advertentieaccount. Binnen Keyword Planner kun je onder andere: zoekwoordideeën ontdekken op basis van een term of website; geschatte maandelijkse zoekvolumes bekijken; advertentiekosten en CPC-indicaties onderzoeken; zoekwoorden groeperen; prognoses voor Google Ads-campagnes bekijken. Voor pure SEO is een deel van die informatie nuttig, maar niet alles is noodzakelijk. Wanneer je vooral onderwerpen, long-tail zoekwoorden en contentkansen wilt vinden, zijn er eenvoudigere gratis opties. Wat is het beste gratis alternatief voor Google Keyword Planner? Er bestaat geen universeel beste alternatief. De juiste tool hangt af van je doel. Wil je snel nieuwe zoekwoorden vinden, dan zijn Ahrefs Keyword Generator en de gratis zoekwoordtool van Semrush praktische opties. Wil je onderzoeken of een onderwerp populairder of minder populair wordt, dan is Google Trends nuttiger. Wil je zien via welke zoekopdrachten jouw website daadwerkelijk in Google verschijnt, gebruik dan Google Search Console. Voor serieus zoekwoordonderzoek kun je deze databronnen juist samen gebruiken. Begin bijvoorbeeld met een breed onderwerp. Verzamel daarna varianten en vragen via een keyword generator. Controleer de ontwikkeling van het onderwerp in Google Trends en gebruik Search Console om te kijken waar jouw website al vertoningen krijgt. Dat geeft vaak een realistischer beeld dan blind vertrouwen op één zoekvolume. 1. Semrush Free Keyword Tool Semrush biedt in 2026 een gratis zoekwoordtool waarmee je zonder volledig betaald SEO-abonnement zoekwoordideeën kunt onderzoeken. Je krijgt onder andere informatie over zoekvolume, zoekwoordmoeilijkheid, CPC en zoekintentie. Dat laatste is vooral interessant voor SEO. Google Keyword Planner is in eerste instantie gebouwd rond Google Ads. Daardoor is commerciële advertentiedata belangrijk in de interface. SEO-tools proberen vaker antwoord te geven op een andere vraag: Hoe moeilijk is het om organisch zichtbaar te worden voor dit zoekwoord? Semrush voegt daarvoor een keyword difficulty-indicatie toe en categoriseert zoektermen op basis van zoekintentie. De gratis versie is uiteraard beperkter dan de betaalde Keyword Magic Tool. Je krijgt minder resultaten en minder geavanceerde filters. Voor een kleine website, eerste contentplanning of snelle zoekwoordcheck kan dat echter voldoende zijn. Wanneer is Semrush interessant? Gebruik Semrush vooral wanneer je niet alleen zoekvolume wilt zien, maar ook wilt begrijpen waarom iemand zoekt. Een zoekopdracht kan bijvoorbeeld informatief, commercieel of transactioneel zijn. Dat verschil is belangrijk. Iemand die zoekt naar “wat is GEO” bevindt zich in een andere fase dan iemand die zoekt naar “beste GEO bureau Nederland”. Het zoekvolume alleen vertelt je dat niet. 2. Ahrefs Keyword Generator Ahrefs heeft eveneens gratis tools voor keyword research. Met de Keyword Generator kun je vanuit een basiszoekwoord gerelateerde termen, vragen en andere zoekwoordvarianten ontdekken. Een voordeel is dat je snel van één breed onderwerp naar veel specifiekere zoekvragen kunt gaan. Stel dat je begint met: “AI SEO” Daaruit kunnen vervolgens varianten ontstaan rond kosten, tools, strategie, voorbeelden en implementatie. Juist die specifieke zoekopdrachten zijn interessant wanneer je content maakt. Een breed zoekwoord kan veel concurrentie hebben, terwijl een specifiekere vraag veel beter aansluit op wat iemand daadwerkelijk probeert te weten. De gratis tools van Ahrefs zijn wel bewust beperkt ten opzichte van de volledige betaalde suite. Zie ze daarom vooral als onderzoeksinstrument en niet als volledige vervanging van een professionele SEO-database. 3. Google Trends Google Trends is een van de meest onderschatte gratis hulpmiddelen voor zoekwoordonderzoek. De tool geeft je niet simpelweg een traditioneel absoluut zoekvolume. In plaats daarvan laat Google Trends zien hoe de relatieve zoekinteresse zich ontwikkelt. Dat is waardevol omdat een gemiddeld maandelijks zoekvolume soms een verkeerd beeld kan geven. Stel dat twee onderwerpen ongeveer even interessant lijken op basis van historische volumes. Het eerste onderwerp daalt al maanden. Het tweede onderwerp groeit snel. Als je alleen naar een gemiddelde kijkt, zie je dat verschil nauwelijks. Google Trends maakt die ontwikkeling zichtbaar. Je kunt de tool daarom gebruiken om: seizoenspatronen te herkennen; groeiende onderwerpen te ontdekken; verschillende termen met elkaar te vergelijken; regionale verschillen te onderzoeken; te controleren of interesse in een onderwerp structureel groeit of slechts tijdelijk piekt. Voor onderwerpen rond AI en nieuwe zoektechnologie is dit extra relevant. Terminologie verandert snel. Een zoekwoord dat vorig jaar nauwelijks werd gebruikt, kan binnen korte tijd belangrijk worden. 4. Google Search Console Heb je al een website met organische zichtbaarheid? Dan is Google Search Console vaak waardevoller dan een traditionele keyword planner. Search Console laat zien voor welke zoekopdrachten jouw eigen pagina’s daadwerkelijk in Google zijn verschenen. Je kunt onder andere klikken, vertoningen, gemiddelde positie en doorklikratio onderzoeken. Dat maakt Search Console bijzonder interessant voor het vinden van bestaande kansen. Een pagina kan bijvoorbeeld gemiddeld op positie 11 staan voor een zoekopdracht waar je nog nauwelijks aandacht aan hebt besteed. Dat is meestal veel interessanter dan een volledig nieuw zoekwoord waarop jouw website nog geen enkele relevantie heeft opgebouwd. Zoek naar zoekwoorden met veel vertoningen maar weinig klikken Dit is een eenvoudige manier om kansen te ontdekken. Filter binnen Search Console op zoekopdrachten met relatief veel vertoningen. Controleer vervolgens welke termen weinig klikken krijgen. Daar kunnen verschillende redenen voor zijn. Je positie is nog te laag. De titel sluit niet goed aan. De pagina behandelt het onderwerp slechts gedeeltelijk. Of Google ziet jouw pagina als enigszins relevant, maar niet als het beste antwoord. Juist deze zoekopdrachten kunnen goede optimalisatiekansen vormen. 5. Google autocomplete en gerelateerde zoekopdrachten Je hoeft niet altijd een speciale SEO-tool te gebruiken. Google zelf kan al veel informatie geven over hoe mensen zoeken. Wanneer je een onderwerp invoert, verschijnen vaak aanvullende zoekopdrachten en suggesties. Deze suggesties kunnen helpen bij het vinden van specifieke vragen en formuleringen. Zoek je bijvoorbeeld op een brede term, dan kun je varianten ontdekken rond: kosten; alternatieven; reviews; voorbeelden; problemen; handleidingen; vergelijkingen. Deze woorden zeggen iets over de intentie achter een zoekopdracht. Voor contentplanning zijn ze daarom vaak minstens zo interessant als een exact zoekvolume. Waarom zoekvolume niet het enige criterium moet zijn Een veelgemaakte fout bij keyword research is het kiezen van zoekwoorden puur op basis van zoekvolume. Een zoekwoord met 10.000 maandelijkse zoekopdrachten is niet automatisch waardevoller dan een term met 200 zoekopdrachten. De kleinere zoekterm kan veel specifieker zijn. Daardoor kan de bezoeker dichter bij een beslissing zitten. Vergelijk bijvoorbeeld: “SEO” met: “SEO bureau voor Shopify Nederland” Het eerste zoekwoord heeft een veel bredere betekenis. Iemand kan op zoek zijn naar een definitie, opleiding, vacature, softwaretool of marketingbureau. Het tweede zoekwoord geeft veel duidelijker aan wat de gebruiker zoekt. Voor bedrijven kan zo’n kleiner maar specifieker zoekwoord daarom commercieel veel relevanter zijn. Gratis keyword research in 2026: gebruik meerdere databronnen Een sterke gratis workflow hoeft niet ingewikkeld te zijn. Begin met het hoofdonderwerp waarvoor je zichtbaar wilt worden. Gebruik vervolgens een gratis keyword generator om varianten te verzamelen. Controleer daarna in Google Trends welke onderwerpen groeien en welke juist dalen. Heb je al organisch verkeer, voeg dan Search Console-data toe. Daarna kun je de zoekwoorden ordenen op basis van intentie. Welke zoekvragen vragen om uitleg? Welke zoekvragen vergelijken oplossingen? Welke zoekvragen laten zien dat iemand een product, dienst of tool zoekt? Op die manier verandert keyword research van een lijst met termen in een contentstrategie. Verandert AI de manier waarop je zoekwoorden onderzoekt? Ja. Traditioneel SEO-onderzoek draaide sterk om individuele zoekwoorden. Voor AI-zoekmachines en generatieve zoekervaringen wordt het belangrijker om complete onderwerpen en echte gebrui