Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
title: "AI는 어떻게 브라우저를 조작할까? 모델·하네스·MCP의 역할"
description: "AI의 도구 호출이 실제 브라우저 동작으로 이어지는 과정과 하네스, MCP 서버, 브라우저 자동화 도구의 역할을 구분합니다."
pubDate: "2026-10-16T20:08:00+09:00"
categories: "Computer Science"
tags: ["AI", "MCP", "브라우저 자동화", "Playwright"]
slug: "cs/ai-browser-tools-harness-mcp"
relatedSlugs: ["programming/playwright-vs-puppeteer", "programming/playwright-java-binding"]
---

## 핵심 요약

- 모델은 다음 행동을 제안하고, 실행 프로그램은 도구 호출을 받아 실제 브라우저를 움직입니다.
- 하네스는 실행 흐름을 관리하고, MCP 서버는 도구를 제공하며, Playwright 같은 라이브러리는 브라우저 조작을 수행합니다.
- 화면이 바뀌었다는 사실과 원하는 기능이 정상 동작한다는 사실은 다르므로, 작업에 맞는 검증이 필요합니다.

## 모델의 판단이 실제 클릭으로 바뀌기까지

AI에게 “페이지를 열고 저장 버튼이 동작하는지 확인해 줘”라고 요청했다고 가정해 보겠습니다. 모델의 추론만으로 운영체제에 클릭이 전달되지는 않습니다. 모델이 선택한 동작을 실제 프로그램이 실행해야 합니다.

예를 들어 실행 환경이 `browser_click`이라는 도구와 입력 형식을 제공하면, 모델은 클릭 대상 등의 인자를 담은 호출을 생성합니다. 이 호출을 받아 처리하는 프로그램이 브라우저를 조작하고 결과를 돌려줍니다. 아래 JSON은 개념을 설명하기 위한 예시이며, 특정 제품의 실제 API 형식은 아닙니다.

```json
{
"tool": "browser_click",
"arguments": {
"element": "저장 버튼",
"ref": "button-12"
}
}
```

실행 결과가 다시 입력으로 들어오면 모델은 “저장 완료 안내가 나타났는가?”, “오류를 더 확인해야 하는가?”를 판단합니다. 이처럼 **관찰 → 행동 선택 → 실행 → 재관찰**을 반복하는 구조입니다. 실제로 사용할 수 있는 행동은 연결된 도구와 권한에 따라 달라집니다.

## 하네스와 MCP 서버는 같은 것일까?

두 역할을 나누면 구조를 이해하기 쉽습니다. MCP는 AI 애플리케이션과 외부 도구를 연결하는 프로토콜이며, 호스트·클라이언트·서버 구조를 사용합니다.[1]

| 구성 요소 | 맡는 일 | 예시 |
| --- | --- | --- |
| 모델 | 관찰 결과를 해석하고 다음 행동 선택 | 저장 버튼 클릭을 요청 |
| 하네스·호스트 애플리케이션 | 모델 호출, 도구 실행 전달, 상태와 권한 관리 | 코딩 에이전트의 실행 환경 |
| MCP 클라이언트 | 호스트에서 MCP 서버와 통신 | 서버의 도구 목록 조회와 호출 |
| MCP 서버 | 정해진 형식으로 도구 제공 | Playwright MCP 서버 |
| 자동화 라이브러리 | 페이지 이동, 입력, 클릭 등을 구현 | Playwright |
| 브라우저 | 페이지와 JavaScript 실행 | Chromium, Firefox, WebKit |

MCP 서버가 모든 판단과 반복 실행을 담당하는 것은 아닙니다. 또한 브라우저 자동화에 MCP가 반드시 필요한 것도 아닙니다. 애플리케이션이 자동화 라이브러리를 직접 호출하는 방식도 가능합니다.

## 브라우저와 연결되는 방법

Chrome DevTools Protocol(CDP)은 Chrome 계열 브라우저의 디버깅·제어 인터페이스입니다. 페이지나 네트워크 상태를 관찰하고 제어하는 기능을 제공합니다.[2]

Playwright와 Puppeteer는 이런 저수준 통신을 직접 다루는 수고를 줄여 주는 자동화 라이브러리입니다. 다만 **두 도구의 모든 브라우저 제어가 CDP로 이루어지는 것은 아닙니다.** Playwright는 Chromium뿐 아니라 Firefox와 WebKit을 지원하고, Puppeteer도 WebDriver BiDi를 통해 Firefox를 지원합니다.[3][4]

브라우저 확장 프로그램을 통해 사용 중인 탭과 연결하는 제품도 있습니다. 이때 기존 로그인 상태를 이용할 수 있는지는 해당 도구의 연결 방식에 달려 있습니다.

## 무엇을 보고 정상 동작을 판단할까?

Playwright MCP는 접근성 정보를 담은 구조화된 스냅샷을 주요 상호작용 수단으로 제공합니다.[5] 스크린샷과 스냅샷은 서로 다른 정보를 줍니다.

| 관찰 결과 | 확인하기 좋은 것 | 그것만으로 부족한 것 |
| --- | --- | --- |
| 스크린샷 | 배치, 겹침, 잘림, 오류 화면 | 데이터가 실제로 저장됐는지 |
| 접근성 스냅샷·DOM | 요소 이름, 역할, 상태 | 시각적인 깨짐 전체 |
| 콘솔 로그 | JavaScript 오류와 경고 | 사용자의 최종 작업 성공 여부 |
| 네트워크 응답 | 요청 결과와 응답 내용 | 올바른 업무 결과인지 |
| 명시적인 단언 | 예상한 텍스트·상태와 실제 결과 비교 | 단언하지 않은 다른 동작 |

저장 기능이라면 버튼 클릭 후 완료 문구만 확인할 수도 있지만, 더 강한 검증은 새로고침 후에도 수정한 값이 유지되는지 보는 것입니다. 필요한 관찰은 검증하려는 목표에서 정해야 합니다.

## 자동화할 때 남는 한계

좌표 클릭은 창 크기나 스크롤 위치가 달라지면 대상이 바뀔 수 있습니다. 요소의 역할·이름이나 스냅샷 참조로 대상을 식별하면 이런 문제를 줄일 수 있지만, 잘못된 대상을 선택할 가능성까지 없어지지는 않습니다.

웹페이지에 적힌 문장은 외부 데이터입니다. 페이지 안의 문구가 에이전트에게 다른 행동을 요구하더라도, 그것이 사용자가 내린 지시와 같은 권한을 갖는 것은 아닙니다. Playwright MCP 자체도 보안 경계가 아니므로, 호스트의 권한 정책과 실행 환경의 격리가 별도로 필요합니다.[5]

같은 시나리오를 반복 확인할 때는 탐색 과정에서 알아낸 조건을 테스트 코드로 남기면 좋습니다. 에이전트가 매번 판단하게 할 부분과, 정해진 단언으로 확인할 부분을 나누면 결과를 비교하기 쉬워집니다.

## 이어서 읽기

- [Playwright와 Puppeteer 비교](/blog/programming/playwright-vs-puppeteer)
- [Playwright Java 바인딩의 내부 동작](/blog/programming/playwright-java-binding)

## 참고

2026년 10월 16일 공식 문서 기준으로 확인했습니다. 제품별 도구 이름과 연결 방식은 달라질 수 있습니다.

1. [MCP — Architecture overview](https://modelcontextprotocol.io/docs/learn/architecture)
2. [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)
3. [Playwright Java — Browsers](https://playwright.dev/java/docs/browsers)
4. [Puppeteer — FAQ](https://pptr.dev/faq)
5. [Microsoft — Playwright MCP](https://github.com/microsoft/playwright-mcp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "플랫화이트는 달콤한 커피일까? 라떼와의 차이"
description: "플랫화이트의 기본 재료와 은은한 단맛, 라떼와 다른 커피·우유 비율과 마이크로폼의 질감을 알아봅니다."
pubDate: "2026-10-16T17:10:00+09:00"
categories: "Lifestyle"
tags: ["커피", "플랫화이트", "카페라떼"]
slug: "lifestyle/flat-white-vs-latte"
---

## 핵심 요약

- 기본적인 플랫화이트는 에스프레소와 우유로 만드는 커피로, 설탕이나 시럽을 꼭 넣는 음료는 아닙니다.
- 라떼와 비교하면 대체로 커피 대비 우유의 비중이 작고, 얇고 고운 우유 거품의 매끄러운 질감이 특징입니다.
- 잔 크기와 샷 구성은 카페마다 다릅니다. 메뉴 이름만으로 단맛이나 카페인 양을 확정하기는 어렵습니다.

## 플랫화이트에는 시럽이 들어갈까?

플랫화이트라는 이름만 보면 달콤한 우유 커피를 떠올리기 쉽습니다. 하지만 기본 구성은 **에스프레소와 우유**입니다. 네스프레소의 플랫화이트 레시피도 커피와 우유를 기본 재료로 안내합니다.[1]

따라서 “플랫화이트는 달다”보다는 **“설탕이나 시럽을 넣지 않아도 우유에서 은은한 단맛을 느낄 수 있는 커피”**라고 이해하는 편이 정확합니다. 기본 라떼 역시 시럽을 필수로 넣는 음료는 아닙니다.

다만 카페가 바닐라 시럽이나 연유 등을 더한 변형 메뉴를 판매할 수는 있습니다. 달지 않은 음료를 원한다면 메뉴 설명을 보거나 “기본 레시피에 시럽이나 설탕이 들어가나요?”라고 확인하는 것이 가장 확실합니다.

## 라떼와는 무엇이 다를까?

둘 다 에스프레소에 우유를 더한다는 점은 같습니다. 차이를 느끼게 만드는 것은 주로 **커피와 우유의 비율**, 그리고 **우유 거품의 양과 질감**입니다.[2]

| 구분 | 플랫화이트 | 카페라떼 |
| --- | --- | --- |
| 기본 재료 | 에스프레소 + 우유 | 에스프레소 + 우유 |
| 커피와 우유의 비율 | 대체로 커피의 비중이 높은 편 | 대체로 우유의 비중이 높은 편 |
| 잔 크기 | 비교적 작은 잔에 제공하는 경우가 많음 | 비교적 큰 잔에 제공하는 경우가 많음 |
| 우유 거품 | 얇고 고운 마이크로폼이 특징 | 가벼운 거품층을 더하며 매장에 따라 차이가 있음 |
| 맛의 인상 | 커피 풍미가 더 또렷하게 느껴지는 편 | 우유의 부드러움이 더 두드러지는 편 |
| 시럽·설탕 | 기본 구성의 필수 재료가 아님 | 기본 구성의 필수 재료가 아님 |

이 표는 일반적인 경향을 비교한 것이며, 모든 매장에 적용되는 규격은 아닙니다. 같은 카페에서도 사이즈나 샷 수에 따라 비율이 달라집니다.

샷 수가 같다면 우유가 적을수록 커피 풍미가 상대적으로 또렷하게 느껴질 수 있습니다. 그렇다고 **맛이 진한 커피가 반드시 카페인도 더 많은 것은 아닙니다.** 카페인 양을 비교하려면 원두와 샷 구성 등 실제 레시피를 확인해야 합니다.

## 마이크로폼은 어떤 거품일까?

마이크로폼(microfoam)은 우유를 스팀하면서 만든 **아주 작고 고운 기포가 섞인 질감**을 말합니다. 플랫화이트는 두꺼운 거품을 높게 쌓기보다, 고운 거품이 우유와 어우러지는 매끄러운 질감을 강조합니다.[1][2]

여기서 “Flat”을 거품이 전혀 없다는 뜻으로 받아들이면 헷갈립니다. 핵심은 **두껍고 푹신한 거품층보다 얇고 부드러운 질감**입니다. 라떼에도 마이크로폼을 사용할 수 있으므로, 마이크로폼의 유무만으로 두 음료를 나누기는 어렵습니다.

## 설탕을 안 넣었는데 왜 달게 느껴질까?

우유에는 원래 당이 들어 있습니다. 그래서 시럽을 추가하지 않은 커피에서도 은은한 단맛을 느낄 수 있습니다. 우유의 부드러운 질감과 커피의 향이 어우러지면, 시럽의 강한 단맛과는 다른 인상을 줍니다.[2]

일부 플랫화이트는 **리스트레토(ristretto)** 샷을 사용합니다. 리스트레토는 일반적인 에스프레소보다 적은 추출량으로 만드는 방식입니다. 스타벅스는 자사 플랫화이트에 리스트레토 샷을 사용하며, 이를 농축된 풍미와 단맛이 특징인 추출로 설명합니다.[3]

다만 리스트레토가 모든 플랫화이트의 필수 조건은 아닙니다. 원두와 추출 조건도 다르므로 “플랫화이트는 항상 덜 쓰고 더 달다”고 단정할 수는 없습니다.

## 메뉴를 고를 때 기억할 것

라떼에서 우유 맛이 강하게 느껴져 커피 향을 더 또렷하게 즐기고 싶었다면 플랫화이트를 비교해 볼 만합니다. 반대로 넉넉한 우유와 부드러운 맛을 원한다면 라떼가 취향에 맞을 수 있습니다.

처음에는 같은 카페에서 두 음료의 **샷 수, 잔 크기, 시럽 첨가 여부**를 확인해 보세요. 따뜻한 음료로 비교하면 스팀 밀크와 거품의 질감을 살펴보기에도 좋습니다. 아이스 메뉴는 차가운 우유와 얼음을 쓰는 등 구성이 달라질 수 있습니다.

플랫화이트를 기억하는 키워드는 **시럽의 단맛보다 커피·우유의 균형과 고운 질감**입니다.

## 참고

아래 자료는 각 브랜드의 설명과 레시피입니다. 특정 브랜드의 레시피를 모든 카페의 공통 기준으로 해석하지 않았습니다.

1. [Nespresso UK — Flat White Coffee Recipe](https://www.nespresso.com/uk/en/coffee-recipes/flatwhite-recipe)
2. [Nespresso Australia — Your complete guide to flat white coffee](https://www.nespresso.com/au/en/news/your-complete-guide-to-flat-white-coffee)
3. [Starbucks — Espresso explained](https://about.starbucks.com/stories/2025/espresso-explained/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: "재시작 없이 코드가 반영되는 이유: DevTools·HCR·JRebel 비교"
description: "Spring Boot DevTools의 자동 재시작과 Eclipse Hot Code Replace, JRebel의 코드 재로딩을 구분하고 개발 환경에서 확인할 항목을 정리합니다."
pubDate: "2026-10-16T20:08:00+09:00"
categories: "Programming"
tags: ["Java", "Spring Boot", "Eclipse", "JRebel", "개발 환경"]
slug: "programming/devtools-hcr-jrebel"
relatedSlugs: ["programming/eclipse-nature-jrebel"]
---

## 핵심 요약

- DevTools는 주로 애플리케이션을 자동 재시작해 변경을 반영합니다.
- Eclipse HCR은 디버깅 중 JVM의 클래스 교체 기능을 사용하며, 기본적인 환경에서는 메서드 본문 변경을 중심으로 활용합니다.
- JRebel은 더 넓은 변경을 재배포 없이 반영하기 위한 도구지만, 지원 범위와 실행 설정을 확인해야 합니다.

## 저장했더니 바뀌었다고 모두 같은 기능은 아니다

Java 코드를 저장한 뒤 새 결과가 나온다고 해서 어떤 기능이 동작했는지 바로 알 수는 없습니다. IDE가 컴파일하고 DevTools가 재시작했을 수도 있고, 디버거가 변경된 클래스를 실행 중인 JVM에 전달했을 수도 있습니다.

프런트엔드 도구에서 말하는 HMR(Hot Module Replacement)과 Java 개발 환경의 변경 반영을 같은 이름으로 부르면 이 차이가 가려집니다. 먼저 **자동으로 다시 시작했는지, 실행 중 코드를 교체했는지**를 구분하는 것이 좋습니다.

| 구분 | Spring Boot DevTools | Eclipse HCR | JRebel |
| --- | --- | --- | --- |
| 주된 접근 | 변경 감지 후 애플리케이션 재시작 | 디버거를 통한 클래스 재정의 | Java agent 기반 재로딩 |
| 동작 조건 | DevTools와 클래스패스 변경 | Debug 연결과 JVM의 지원 | Agent 실행, 라이선스·프로젝트 설정 등 |
| 메서드 본문 변경 | 재시작 후 반영 | 일반적인 활용 범위 | 지원 |
| 메서드·필드 추가 | 재시작 후 반영 | 기본 HotSwap에서는 제약 | 더 넓게 지원하나 제한 확인 필요 |
| 초기화·메모리 상태 | 재시작에 따라 다시 구성 | 기존 객체·상태가 남을 수 있음 | 변경 종류와 프레임워크 연동에 따라 다름 |

## DevTools: JVM 종료와 다른 자동 재시작

DevTools의 재시작은 보통 JVM 프로세스를 통째로 종료하고 새로 실행하는 방식과 다릅니다. 변경이 적은 라이브러리와 개발 중인 클래스를 서로 다른 클래스 로더로 나누고, 재시작 때 개발 코드 쪽 클래스 로더를 새로 구성합니다.[1]

이 때문에 완전한 기동보다 빠를 수 있지만, Spring 컨텍스트와 관련 초기화 작업을 다시 수행하는 비용은 남습니다.

또한 감지 대상은 일반적으로 클래스패스의 변경입니다. 소스 파일을 저장해도 컴파일 결과가 갱신되지 않으면 기대한 재시작이 일어나지 않을 수 있습니다. IDE의 자동 빌드나 실제 클래스 출력 경로를 함께 봐야 합니다.

## HCR: 메서드 본문을 바꿀 때 유용한 디버깅 기능

Eclipse의 Hot Code Replace(HCR)는 디버깅 중 변경된 클래스를 JVM에 반영하는 기능입니다.[2] 예를 들어 다음 메서드의 반환 문자열을 바꾸는 수정은 일반적인 활용 사례입니다.

```java
public String getName() {
return "홍길동";
}
```

```java
public String getName() {
return "김철수";
}
```

반면 메서드나 필드 추가, 상속 관계 변경처럼 클래스의 구조를 바꾸는 작업은 기본적인 HotSwap의 지원 범위를 벗어날 수 있습니다. 정확한 범위는 디버거가 연결된 JVM의 기능에 달려 있으며, JDI API도 메서드 추가와 클래스 재정의 지원 여부를 따로 조회하도록 되어 있습니다.[3]

코드가 교체되어도 기존 객체의 생성자와 초기화 과정이 자동으로 다시 실행되는 것은 아닙니다. 이미 읽어 둔 설정이나 필드 값까지 바뀐다고 기대하면 안 됩니다.

## JRebel: 재로딩 범위를 넓히는 도구

JRebel은 Java agent로 동작하며, 실행 중 클래스와 지원되는 프레임워크 설정의 변경 반영을 돕습니다.[4] 기본 HotSwap보다 넓은 변경을 다룰 수 있어 재기동 비용이 큰 프로젝트에서 검토할 만합니다.

다만 “모든 변경을 재시작 없이 반영한다”는 보장은 아닙니다. 이미 만들어진 객체의 생성자·초기화 코드 변경처럼 객체 재생성이 필요한 상황도 있습니다.[5] JRebel이 활성화되었다는 표시와 실제 변경이 반영됐다는 검증을 구분해야 합니다.

JRebel 자체가 Java 소스를 컴파일해 주는 것도 아닙니다. 공식 Eclipse 안내는 컴파일 결과를 이용하므로 자동 빌드 설정을 확인하도록 설명합니다.[6]

## 현재 환경을 확인하는 순서

1. **실행 모드를 봅니다.** Debug 모드에서만 반영되는지 확인합니다.
2. **로그를 봅니다.** 컨텍스트 초기화나 서버 기동 로그가 반복되는지 살펴봅니다.
3. **컴파일을 확인합니다.** 저장 후 수정한 클래스의 출력물이 갱신되는지 봅니다.
4. **실행 인자를 봅니다.** JRebel agent가 실제로 붙어 있는지 확인합니다.
5. **변경 종류를 나눠 봅니다.** 메서드 본문 수정과 구조 변경을 구분해 확인합니다.

HCR로 필요한 변경을 충분히 반영하고 재시작도 부담되지 않는다면, JRebel을 추가할 이유는 크지 않을 수 있습니다. 재시작이 얼마나 자주 발생하고 얼마나 오래 걸리는지 측정한 뒤, 지원 범위와 비용을 비교하는 편이 현실적입니다.

프로젝트에 JRebel Nature가 남아 있다는 사실만으로 실행 중인 JRebel의 유무를 판단할 수는 없습니다. 이 차이는 [Eclipse Nature와 JRebel의 역할](/blog/programming/eclipse-nature-jrebel)에서 이어서 다룹니다.

## 참고

2026년 10월 16일 확인했습니다. DevTools 설명은 Spring Boot 3.5 문서를 기준으로 했으며, HCR과 JRebel은 사용하는 JVM·도구 버전의 지원 범위를 확인해야 합니다.

1. [Spring Boot 3.5 — Developer Tools](https://docs.spring.io/spring-boot/3.5/reference/using/devtools.html)
2. [Eclipse — Java Debug Preferences](https://help.eclipse.org/latest/topic/org.eclipse.jdt.doc.user/reference/preferences/java/debug/ref-debug.htm)
3. [Oracle Java 17 — VirtualMachine](https://docs.oracle.com/en/java/javase/17/docs/api/jdk.jdi/com/sun/jdi/VirtualMachine.html)
4. [JRebel — Frequently Asked Questions](https://www.jrebel.com/jrebel/learn/faq)
5. [JRebel — First aid](https://manuals.jrebel.com/jrebel/misc/firstaid.html)
6. [JRebel — Eclipse](https://manuals.jrebel.com/jrebel/ide/eclipse.html)
Loading
Loading