Select an item from the sidebar to view content.
브랜드 이미지와 비즈니스 요구 사항을 충족하고 사용자 경험과 매력을 향상시킬 수 있도록 자신만의 웹사이트 디자인을 제공하세요.
최고의 시청 경험을 제공하기 위해 데스크톱, 태블릿, 휴대폰 등 다양한 장치에 적응하는 웹사이트를 만드세요.
제품 디스플레이, 장바구니 시스템, 온라인 결제 통합 등 완전한 전자상거래 기능을 지원하여 쉽게 온라인 판매를 돕습니다.
데이터베이스 관리, API 통합, 서버 구성 등 안정적이고 효율적인 백엔드 시스템을 구축하여 웹사이트의 원활한 운영을 지원합니다.
웹 사이트의 속도 최적화 및 SEO 최적화를 수행하고, 웹 사이트 성능 및 검색 엔진 순위를 향상시키며, 더 많은 트래픽을 유도합니다.
정기적인 웹사이트 유지관리 및 콘텐츠 업데이트 서비스를 제공하여 웹사이트 보안과 최신 정보를 보장합니다.
우리는 언제든지 기술 지원을 제공하고 문제를 해결하며 전문적인 상담을 제공하여 귀하의 웹 사이트 운영 효율성을 향상시킬 수 있도록 돕습니다.
HTML(Hypertext Markup Language)은 웹 페이지를 구축하기 위한 기본 표준 언어입니다. 웹페이지의 구조와 내용을 정의하고 다양한 태그를 통해 텍스트, 이미지, 링크 및 기타 멀티미디어를 결합하는 역할을 담당합니다.
표준 HTML 요소는 시작 태그, 콘텐츠 및 종료 태그로 구성됩니다. 예를 들어:<p>텍스트입니다</p>. 태그를 중첩하여 계층적 DOM 트리 구조를 형성할 수 있습니다.
태그에는 추가 정보를 제공하는 속성이 포함될 수 있습니다. 일반적인 속성은 다음과 같습니다.
| 속성 이름 | 사용 지침 |
|---|---|
| href | 링크의 대상 URL을 정의합니다. |
| src | 이미지 또는 미디어의 소스 경로를 정의합니다. |
| alt | 이미지를 표시할 수 없는 경우 대체 텍스트입니다. |
| class / id | CSS 스타일 선택 또는 JavaScript 작업에 사용됩니다. |
최신 HTML은 의미를 강조하고 머리글, 바닥글, 기사, 탐색 등과 같은 태그를 사용합니다. 이는 검색 엔진 최적화(SEO)에 도움이 될 뿐만 아니라 웹 페이지의 가독성과 접근성도 향상시킵니다.
HTML은 콘텐츠 구조를 담당하고, CSS는 시각적 스타일을 담당하며, JavaScript는 대화형 동작을 담당합니다. 세 가지를 결합하면 현대적이고 완전한 웹 애플리케이션을 구성할 수 있습니다.
아래 목록은 HTML에서 지원하는 표준 웹 색상 이름입니다. 이러한 이름은 CSS 또는 HTML 속성에서 직접 사용할 수 있으며 브라우저는 해당 이름을 자동으로 해당 숫자 값으로 구문 분석합니다.
| 색상 미리보기 | 영어 이름 | 16진수 코드 |
|---|---|---|
| Black | #000000 | |
| White | #FFFFFF | |
| Red | #FF0000 | |
| Blue | #0000FF | |
| Yellow | #FFFF00 | |
| Lime | #00FF00 | |
| Cyan / Aqua | #00FFFF | |
| Magenta / Fuchsia | #FF00FF |
| 시사 | 이름 | 암호 |
|---|---|---|
| LightGray | #D3D3D3 | |
| Silver | #C0C0C0 | |
| DarkGray | #A9A9A9 | |
| Gray | #808080 | |
| DimGray | #696969 | |
| SlateGray | #708090 |
| Orange | #FFA500 | |
| Gold | #FFD700 | |
| Khaki | #F0E68C | |
| Chocolate | #D2691E | |
| SaddleBrown | #8B4513 |
JavaScript는 프런트엔드 및 백엔드 개발에 널리 사용되는 효율적이고 유연하며 동적 스크립팅 언어입니다. 다음은 JavaScript의 주요 기능입니다.
JavaScript는 동적으로 유형이 지정되는 언어이므로 변수가 선언될 때 데이터 유형을 지정할 필요가 없습니다. 이는 프로그램 실행 중에 변수 유형이 동적으로 변경될 수 있음을 의미합니다.
값 = 10으로 설정; // 숫자형으로 초기화됨
값 = "안녕하세요"; //문자열 타입으로 변경 가능
JavaScript는 객체 지향을 지원하고 다음을 사용합니다.프로토타입 상속객체의 상속과 재사용을 실현하는 방법. 이를 통해 JavaScript는 객체를 보다 유연하게 정의하고 조작할 수 있습니다.
let person = {
name: "Alice",
greet: function() {
return "Hello, " + this.name;
}
};
JavaScript에서 함수는 매개변수로 전달되거나, 반환되거나, 변수에 할당될 수 있는 객체이기도 합니다. 이 기능은 다양한 기능적 프로그래밍 패턴을 지원합니다.
함수 Greeting(이름) {
return "안녕하세요," + 이름;
}
let sayHello = 인사;
console.log(sayHello("앨리스")); // 함수를 변수로 사용할 수 있음
JavaScript는 기본적으로 특히 다음을 통해 비동기 작업을 지원합니다.Promise그리고async/await비동기 동작을 보다 직관적으로 처리합니다. 이는 네트워크 요청 및 타이밍 이벤트와 같은 비동기 작업을 처리하는 데 유용합니다.
async function fetchData() {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
}
fetchData();
JavaScript는 원래 웹 브라우저의 프런트엔드 개발에 사용되었지만 이제는 백엔드 개발(예: Node.js), 데스크톱 애플리케이션, 모바일 애플리케이션, 심지어 IoT 장치에서도 널리 사용됩니다.
JavaScript의 유연성과 다양성은 현대 웹 개발의 핵심 기술 중 하나이며 다양한 응용 분야에서 강력한 지원을 제공합니다.
JavaScript에서 부울은 두 가지 가능한 상태 또는 값만 갖는 기본 데이터 유형입니다.
true: 진실, 예, 개방 또는 성공을 나타냅니다.false: false, no, 종료 또는 실패를 나타냅니다.부울 값은 다음과 같은 모든 논리적 판단 및 프로세스 제어의 기초입니다.if...else명령문과 루프.
부울 값을 변수에 직접 할당하거나 비교 연산자를 사용하여 부울 값을 생성할 수 있습니다.
isLogged = true로 설정합니다.
isGuest = false로 놔두세요;
// 비교 연산자는 부울 값을 반환합니다.
let isGreater = (10 > 5); // 사실
let isEqual = (5 === '5'); // false(데이터 유형이 다르기 때문에)
이것은 볼린저 가치의 가장 일반적인 사용입니다.if문은 대괄호 안의 표현식 결과가 다음과 같은지 확인합니다.true를 누른 다음 코드 블록을 실행할지 여부를 결정합니다.
나이 = 20이라고 놔두세요;
if (나이 >= 18) {
console.log("나는 성인이고 투표할 수 있습니다.");
} 그렇지 않으면 {
console.log("미성년자.");
}
userValid = checkUserStatus()를 하자; // true 또는 false를 반환한다고 가정합니다.
if (userValid) {
// userValid가 true인 경우
디스플레이대시보드();
} 그렇지 않으면 {
// userValid가 거짓인 경우
showLoginError();
}
논리 연산자는 부울 값을 결합하거나 반전하는 데 사용됩니다. 세 가지 주요 유형이 있습니다.
!(NOT): 논리 부정, 부울 값을 반전합니다.&&(AND): 논리 AND, 양쪽이 모두 동일한 경우에만true그래야만 메시지가 반환됩니다.true。||(OR): 한쪽이 논리합인 경우true그냥 다시 보내세요true。isLoggedIn = true로 설정합니다.
hasPermission = false로 설정합니다.
// ! (아님)
isNotLoggedIn = !isLoggedIn; // 거짓
// && (AND)
if (isLoggedIn && hasPermission) {
console.log("사용자가 로그인되어 있으며 권한이 있습니다.");
}
// || (또는)
if (isLoggedIn || isGuest) {
console.log("계속하려면 로그인하거나 게스트로 로그인하세요.");
}
JavaScript에서는 부울 값이 필요한 다른 데이터 유형을 사용할 수 있으며 암시적 변환이 수행됩니다. 이 값은 다음과 같이 처리됩니다.true또는false:
false값):조건부 판단에서는 다음 6가지 값을 다음과 같이 간주합니다.false:
false(볼린저 가치 자체)0(숫자 0)""또는''(빈 문자열)nullundefinedNaN (Not a Number)true값):**다음을 포함하여 위에 언급된 6가지 Falsy 값을 제외한 기타 모든 값**:
"0"(비어있지 않은 문자열)"false"(비어있지 않은 문자열)1, -100)[]{}myString = "안녕하세요";
myNumber = 0으로 설정합니다.
if (myString) {
// myString은 "Hello"이며, 이는 Truthy 값이며 실행될 것입니다.
console.log("문자열이 비어있지 않습니다.");
}
if (myNumber) {
// myNumber는 0입니다. 이는 거짓 값이므로 실행되지 않습니다.
console.log("0이 아닌 숫자입니다.");
}
만약 ({}) {
// 빈 객체 {}는 Truthy 값이며 실행됩니다.
console.log("이미 존재하는 개체입니다.");
}
JavaScript 배열(Array)은 여러 값을 저장하는 데 사용되는 변수입니다. 배열의 각 값을 요소라고 하며, 각 요소는 0부터 시작하는 숫자 인덱스(Index)를 갖습니다.
// 배열 생성
let 과일 = ["사과", "바나나", "체리", "날짜"];
//배열 요소에 접근
console.log(과일[0]); // 출력: 애플
console.log(과일.길이); // 출력: 4
//배열 끝에 요소 추가
Fruits.push("엘더베리");
console.log(과일); // 출력: ["사과", "바나나", "체리", "날짜", "엘더베리"]
//배열의 꼬리 요소를 제거합니다.
let lastFruit =fruits.pop();
console.log(lastFruit); // 출력: 엘더베리
console.log(과일); // 출력: ["사과", "바나나", "체리", "날짜"]
slice()이 메서드는 원래 배열에서 선택한 요소를 포함하는 새 배열을 반환합니다. 원래 배열은 수정되지 않습니다.
문법:array.slice(start, end)
start(선택 사항): 검색할 시작 인덱스(포함)입니다. 지정하지 않으면 인덱스 0에서 시작합니다.end(선택 사항): 검색 끝 인덱스(포함되지 않음). 지정하지 않으면 배열의 끝까지 검색합니다.숫자 = [10, 20, 30, 40, 50, 60, 70]; // 인덱스 2(30)에서 시작하여 인덱스 2(30)에서 끝납니다. 슬라이스1 = 숫자.슬라이스(2); console.log(slice1); // 출력: [30, 40, 50, 60, 70] // 인덱스 1(20)에서 시작하여 인덱스 4(50) 이전 슬라이스2 = 숫자.슬라이스(1, 4); console.log(slice2); // 출력: [20, 30, 40] // 음수 인덱스 사용: -1은 마지막 요소를 가리키고, -3은 세 번째에서 마지막 요소(50)를 가리킵니다. 슬라이스3 = 숫자.슬라이스(-3, -1); console.log(slice3); // 출력: [50, 60] //전체 배열을 복사합니다. 복사 = 숫자.슬라이스(); console.log(복사); // 출력: [10, 20, 30, 40, 50, 60, 70] console.log(숫자); // 원래 배열은 수정되지 않았습니다.
다음 함수는 배열에서 지정된 수의 요소(예: 5)를 무작위로 선택하는 효율적인 방법을 제공합니다. 이 방법을 사용하면 선택한 요소가 반복되지 않습니다.
/**
* 배열에서 지정된 수의 요소를 무작위로 선택
* @param {Array} arr 원본 배열
* @param {number} count 선택할 요소의 개수 (기본값은 5)
* @returns {Array} 무작위로 선택된 요소를 포함하는 새 배열
*/
함수 getRandomElements(arr, count = 5) {
// 배열 요소가 필요한 수보다 작거나 같으면 배열의 복사본을 반환합니다.
if (arr. 길이<= count) {
return arr.slice();
}
// 建立一個原始陣列的副本,用於隨機選取
let tempArray = arr.slice();
let result = [];
for (let i = 0; i < count; i++) {
// 隨機產生一個索引
let randomIndex = Math.floor(Math.random() * tempArray.length);
// 將選中的元素加入結果陣列
result.push(tempArray[randomIndex]);
// 將選中的元素從 tempArray 中移除,確保不會重複選取
tempArray.splice(randomIndex, 1);
}
return result;
}
let largeArray = [
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T"
];
let randomFive = getRandomElements(largeArray, 5);
console.log(randomFive); // 輸出範例: ["P", "A", "H", "R", "M"] (每次執行結果不同)
JavaScript 개발에는 값이 배열에 존재하는지 확인하는 몇 가지 일반적인 방법이 있습니다. 선택할 방법은 "부울 값 결과"만 필요한지 아니면 멤버의 "인덱스 위치" 또는 "객체 내용"을 가져와야 하는지에 따라 다릅니다.
이는 가장 명확한 의미를 가지며 true 또는 false를 직접 반환하는 ES6 이후 가장 권장되는 표준 관행입니다.
const fruits = ['apple', 'banana', 'orange'];
const hasApple = fruits.includes('apple'); // true
오래된 브라우저에서 사용하거나 요소의 위치를 알아야 할 때 사용하세요. 존재하는 경우 인덱스 값(0부터 시작)을 반환하고, 존재하지 않으면 -1을 반환합니다.
const 태그 = ['js', 'php', 'css'];
if (tags.indexOf('php') !== -1) {
//요소 존재 논리
}
배열 구성원이 객체이거나 정확한 값이 아닌 특정 논리를 기반으로 확인해야 하는 경우 some을 사용하세요. 한 멤버가 조건을 충족하는 한 true가 반환됩니다.
const users = [
{ id: 101, name: 'Alex' },
{ id: 102, name: 'Bob' }
];
const exists = users.some(user => user.id === 101); // true
| 필요 | 제안된 방법 | 포스트백 예시 |
|---|---|---|
| 자격을 갖춘 첫 번째 회원 찾기 | find() | { ID: 101, 이름: 'Alex' } 또는 정의되지 않음 |
| 기준에 맞는 첫 번째 인덱스 찾기 | findIndex() | 0 또는 -1 |
| 자격을 갖춘 모든 회원 찾기 | filter() | [일치 1, 일치 2] 또는 [] |
매우 큰 데이터 세트에서 멤버의 존재 여부를 자주 확인해야 하는 경우 배열을 Set 개체로 변환하는 것이 좋습니다. Set의 메서드 쿼리 복잡성은 O(1)이며 이는 배열의 O(n)보다 훨씬 빠릅니다.
const hugeArray = [/* 대량의 데이터 */];
const mySet = new Set(hugeArray);
if (mySet.has('targetValue')) {
//빠른 적중
}
당신은 사용할 수 있습니다concat두 배열을 병합하는 방법:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let result = arr1.concat(arr2);
console.log(result); // [1, 2, 3, 4, 5, 6]
스프레드 연산자를 사용하는 것도 일반적인 방법입니다.
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let result = [...arr1, ...arr2];
console.log(result); // [1, 2, 3, 4, 5, 6]
두 번째 배열의 요소를 첫 번째 배열에 추가하려면 다음을 결합하면 됩니다.push스프레드 연산자:
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
arr1.push(...arr2);
console.log(arr1); // [1, 2, 3, 4, 5, 6]
할 것이다console.log('op_panel_htm()')예를 들어 함수 이름을 동적으로 가져와 출력하도록 변경합니다.console.log(get_curr_method_name())。
함수 get_curr_method_name() {
const 스택 = 새로운 Error().stack;
const 라인 = stack.split("\n");
// 0행은 오류, 1행은 get_curr_method_name, 2행은 이를 호출하는 함수입니다.
const callerLine = 라인[2] || '';
const match = callerLine.match(/at (.+?) \(/);
반환 일치? match[1] : '익명';
}
TableOperator.prototype.op_panel_htm = function () {
console.log(get_curr_method_name());
};
다음과 같이 실행하면:
const t = new TableOperator();
t.op_panel_htm();
이는 콘솔에 출력될 수 있습니다:
TableOperator.op_panel_htm
실제 출력은 브라우저 스택 형식에 따라 달라지며, Chrome/Edge는 일반적으로 함수의 전체 경로를 출력합니다.
Error().stack, 다른 브라우저의 형식은 약간 다릅니다.이는 사용자 정의 디버깅 기능으로 캡슐화될 수 있습니다.
function debug_log(msg = '') {
console.log(`[${get_curr_method_name()}] ${msg}`);
}
사용 방법:
debug_log("초기화 완료");
출력 결과는 다음과 같습니다.
[TableOperator.op_panel_htm] 초기화 완료
JavaScript 프로젝트가 커지고 기능이 많아지면 유지 관리성과 가독성을 높이기 위해 모듈화 및 분류를 사용해야 합니다. 다음은 사용 여부를 포함하여 여러 기능을 효과적으로 관리하는 방법에 대해 설명합니다.class。
기능 분류에 따라 관련 기능을 다른 파일에 저장합니다. 예:
/utils/mathUtils.js → 수학적 연산 관련 함수
/utils/domUtils.js → DOM 작업 기능
/modules/tableOperator.js → 테이블 연산 관련 클래스 또는 함수
각 파일은 다음을 사용합니다.export / import문법:
// mathUtils.js
export function add(a, b) {
return a + b;
}
// main.js
import { add } from './utils/mathUtils.js';
console.log(add(2, 3));
객체나 클래스의 관련 논리로 함수를 래핑하는 것이 더 구조적입니다. 예를 들면 다음과 같습니다.
// domUtils.js
export const DomUtils = {
createElement(tag) {
return document.createElement(tag);
},
removeElement(el) {
el.parentNode.removeChild(el);
}
};
또는 클래스를 사용하십시오.
// tableOperator.js
export class TableOperator {
constructor(tableId) {
this.table = document.getElementById(tableId);
}
highlightRow(index) {
// ...
}
sortByColumn(colIndex) {
// ...
}
}
단지 도구 기능(문자열 처리, 수학 연산 등)인 경우에는 다음을 사용하는 것이 좋습니다.export function또는export const obj = { ... }그냥 관리하세요.
/src
/utils
stringUtils.js
mathUtils.js
/components
tableOperator.js
chartViewer.js
main.js
자바스크립트에서class생성자를 포함하여 다른 OOP 언어와 유사하게 사용됩니다.constructor, 멤버 변수 및 메소드(함수) 정의.
클래스 사람 {
//멤버변수(공개)
이름;
나이;
//생성자
생성자(이름, 나이) {
this.name = 이름;
this.나이 = 나이;
}
//멤버 메소드
인사() {
console.log(`안녕하세요, 저는 ${this.name}이고 올해 ${this.age}입니다`);
}
// 정적 메서드(인스턴스화할 필요 없음)
정적 종() {
'인간'을 반환합니다.
}
}
const p = new Person("샤오밍", 25);
p.greet(); // 출력: 안녕하세요. 저는 올해 25세인 Xiao Ming입니다.
console.log(p.name); // 샤오밍
console.log(Person.species()); // 인간
this.name, 외부에서 액세스할 수 있습니다.클래스 카운터 {
#개수 = 0; // 개인 변수
증분() {
this.#count++;
console.log(this.#count);
}
#비밀() {
console.log("비공개 메소드입니다.");
}
공개비밀() {
this.#비밀(); // 내부적으로 호출 가능
}
}
클래스 동물 {
말하다() {
console.log("소리를 내세요");
}
}
클래스 Dog 확장 동물 {
말하다() {
console.log("멍멍!");
}
}
클래스 메소드에서this이 인스턴스를 가리킵니다. 하지만 이벤트나 콜백에 사용되는 경우에는bind()또는 화살표 기능을 사용하여 포인팅을 보장합니다.
클래스 버튼 {
생성자() {
this.label = "클릭";
document.addEventListener("클릭", this.handleClick.bind(this));
}
핸들클릭() {
console.log(`${this.label}을 누르셨습니다`);
}
}
JavaScript 클래스는 다른 언어와 유사한 캡슐화, 상속, 메서드 및 속성 지원을 제공합니다. 중대형 프로젝트에 적합하며 모듈과도 쉽게 통합할 수 있습니다. 보다 엄격한 타이핑과 제어가 필요한 경우 TypeScript 사용을 고려해보세요.
JavaScript 모듈(모듈)은 파일에 변수와 함수를 캡슐화하는 방법을 제공합니다. 당신은 사용할 수 있습니다import/export메커니즘은 다음과 유사합니다.class노동 분업과 구조화 기능은 도구 기능이나 단일 기능 논리 장치에 적합합니다.
| 기능 | class | module |
|---|---|---|
| 데이터 및 동작 캡슐화 | ✅ | ✅(수출 패키지를 통해) |
| 인스턴스화 가능 | ✅ | ❌(싱글톤으로 존재) |
| 상속과 다형 | ✅ | ❌(수동 관리 필요) |
| 단일 기능 구성 요소 | 할 수 있다 | 더 적합 |
// file: mathUtils.js
export const MathUtils = {
add(a, b) {
return a + b;
},
multiply(a, b) {
return a * b;
}
};
// file: main.js
import { MathUtils } from './mathUtils.js';
console.log(MathUtils.add(3, 4)); // 7
console.log(MathUtils.multiply(2, 5)); // 10
// file: stringHelper.js
export function toUpper(str) {
return str.toUpperCase();
}
export function truncate(str, len) {
return str.length > len ? str.slice(0, len) + '…' : str;
}
// file: main.js
import { toUpper, truncate } from './stringHelper.js';
console.log(toUpper("hello")); // HELLO
console.log(truncate("JavaScript", 5)); // JavaS…
// file: config.js
let config = {
env: "dev",
version: "1.0"
};
export function getConfig() {
return config;
}
export function setEnv(env) {
config.env = env;
}
// file: app.js
import { getConfig, setEnv } from './config.js';
console.log(getConfig()); // { env: "dev", version: "1.0" }
setEnv("prod");
console.log(getConfig()); // { env: "prod", version: "1.0" }
모듈은 도구 기능, 상수 및 설정을 캡슐화하는 데 적합합니다.class모듈은 다릅니다.로드 시 자동으로 실행되며 전체 도메인에서 고유합니다., 논리적 분류 및 깔끔한 프로그램 구조에 매우 적합합니다. 여러 번 생성할 수 있는 객체 인스턴스나 객체 지향 상속이 필요할 때 사용하세요.class더 적합합니다.
function runExclusive(fn) {
let last = Promise.resolve();
return function (...args) {
last = last.then(() => fn(...args));
return last;
};
}
비동기 함수 doTask(이름) {
console.log(`${name} 시작`);
새로운 약속을 기다리세요(resolve => setTimeout(resolve, 2000));
console.log(`${name} 끝`);
}
const doTaskOnce = runExclusive(doTask);
//동시에 여러번 호출
doTaskOnce("A");
doTaskOnce("B");
doTaskOnce("C");
Start A
End A
Start B
End B
Start C
End C
웹 페이지(예: $\lt$table$\gt$)의 특정 HTML 요소를 로컬 $\text{.html}$ 파일로 저장하려면 일반적으로 JavaScript를 사용하여 요소의 HTML 코드를 얻은 다음 브라우저의 다운로드 API를 통해 저장 프로세스를 트리거해야 합니다. 이는 클라이언트 측 솔루션입니다.
$\text{document.getElementById}$ 또는 $\text{document.querySelector}$ 선택기를 사용하여 저장하려는 $\lt$table$\gt$ 요소를 가져오고 해당 $\text{outerHTML}$을 검색합니다.
var tableElement = document.getElementById('myTableId');
var tableHtml = tableElement.outerHTML;
$\lt$table$\gt$ 코드만으로는 완전한 $\text{.html}$ 파일을 구성하기에 충분하지 않습니다. 아카이브가 브라우저에서 올바르게 열리고 표시되도록 하려면 기본 $\lt$html$\gt$, $\lt$head$\gt$ 및 $\lt$body$\gt$ 태그로 래핑해야 합니다. 또한 테이블의 스타일(CSS)을 유지하려면 필요한 $\lt$style$\gt$ 태그 또는 $\lt$link$\gt$ 태그를 포함해야 합니다.
var fullHtml = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>저장된 테이블</title></head><body>' + tableHtml + '</body></html>';
Blob(Binary Large Object) 개체는 이진 또는 이진 유사 데이터를 저장하는 데 사용됩니다. 완전한 HTML 코드가 포함된 문자열을 $\text{text/html}$ 유형의 $\text{Blob}$로 변환합니다.
var blob = new Blob([fullHtml], { type: 'text/html' });
$\text{URL.createObjectURL}$를 사용하여 $\text{Blob}$를 가리키는 로컬 $\text{URL}$을 생성하고 이를 $\lt$a$\gt$ 요소의 $\text{href}$ 속성에 할당하고 $\text{download}$ 속성을 설정하여 다운로드한 파일의 이름을 지정합니다.
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'exported_table.html'; //다운로드한 파일명 지정
a.클릭(); // 클릭을 시뮬레이션하고 다운로드 대화 상자를 트리거합니다.
// 리소스 해제
URL.revokeObjectURL(a.href);
테이블 스타일이 페이지의 외부 $\text{CSS}$ 파일 또는 $\text{JavaScript}$를 통해 동적으로 추가된 경우 $\text{outerHTML}$을 저장하면 해당 스타일이나 기능이 손실될 수 있습니다. 이 문제를 해결하려면:
C/C++ 에뮬레이트#ifdef DEBUGJavaScript에서 제어 가능한 성능을 달성하기 위한 조건부 컴파일 메커니즘debug_log(), 개발 단계(개발 중, 테스트 중, 공식 버전)에 따라 로그의 출력 레벨 및 전환을 제어합니다.
// 0 = 출력 없음, 1 = 오류, 2 = 경고, 3 = 메시지, 4 = 디버그
const LOG_LEVEL = 3;
함수 debug_log(msg, 레벨 = 3) {
만약 (레벨<= LOG_LEVEL) {
const name = get_curr_method_name();
console.log(`[${name}] ${msg}`);
}
}
function get_curr_method_name() {
const stack = new Error().stack;
const lines = stack.split("\n");
const callerLine = lines[2] || '';
const match = callerLine.match(/at (.+?) \(/);
return match ? match[1] : 'anonymous';
}
함수 initApp() {
debug_log("초기화 중", 4); // 디버그 수준
debug_log("설정을 성공적으로 로드했습니다.", 3); // 메시지
debug_log("설정값이 너무 오래되었을 수 있습니다.", 2); // 경고
debug_log("로딩 실패", 1); // 오류
}
LOG_LEVEL = 4(활짝 열려 있음)LOG_LEVEL = 2(오류와 경고만 표시됩니다)LOG_LEVEL = 0(완전한 침묵)Webpack/Vite/ESBuild와 같은 도구와 함께 사용하면 조건부 상수를 사용할 수 있습니다.process.env.NODE_ENV로그 제거:
if (process.env.NODE_ENV === '개발') {
debug_log("개발 환경의 메시지");
}
또한 Babel 플러그인(예: babel-plugin-transform-remove-console)과 함께 사용하여 모든 항목을 제거할 수도 있습니다.console.*。
JavaScript에는 조건부 컴파일이 없지만 변수 제어 및 패키징 최적화 전략을 통해 C++와 유사한 디버깅 수준 및 릴리스 제어 메커니즘을 달성하여 개발 단계의 정보가 완전하고 공식 버전이 깨끗하고 노이즈가 없음을 보장할 수 있습니다.
브라우저 콘솔은 개발자 도구의 일부이며 다음 작업에 사용됩니다.
F12또는Ctrl + Shift + I→ “콘솔” 탭을 클릭하세요.Cmd + Option + Iconsole.log("메시지"):메시지 인쇄$0: 요소 패널에서 현재 선택된 요소를 선택합니다.document.querySelector():DOM 요소 선택dir(obj): 객체 속성 나열copy(obj): 변수를 클립보드에 복사합니다.//메시지 인쇄
console.log("안녕하세요 콘솔");
// 페이지 요소를 가져와서 작동합니다.
const btn = document.querySelector("버튼");
btn.textContent = "새 라벨";
btn.click();
//객체 보기
console.dir(btn);
---
콘솔에 다음 메시지가 나타나면 보안상의 이유로 Chrome에서 여러 줄의 코드를 직접 붙여넣는 것을 금지한다는 의미입니다.
Don’t paste code into the DevTools Console ... Please type ‘allow pasting’ below and press Enter
입력하다allow pasting제한을 제거하려면 Enter를 누르세요.
clear():콘솔 메시지 지우기inspect(element): 요소 패널로 바로 이동하여 요소를 찾습니다.$그리고$$:예querySelector그리고querySelectorAll약어보안상의 이유와 악의적인 웹사이트 또는 기타 웹사이트가 위험한 코드를 게시하도록 유도하는 것을 방지하기 위해 Chrome에서는 기본적으로 여러 줄 코드를 콘솔에 직접 붙여넣는 것을 금지합니다.
메시지가 나타납니다:
Warning: Don’t paste code into the DevTools Console that you don’t understand or haven’t reviewed yourself.
This could allow attackers to steal your identity or take control of your computer.
Please type ‘allow pasting’ below and press Enter to allow pasting.
---
allow pasting(따옴표 제외)// 1. 콘솔에 들어가서 붙여넣기를 허용하고 Enter를 누릅니다.
붙여넣기 허용
// 2. 실행하려는 JavaScript 코드를 붙여넣습니다.
const 호스트 = document.querySelector('i18n-message[key="login.button.loginWithLine"]');
// ...(다음 코드)
---
<script>
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById("result").innerHTML = xhr.responseText;
}
};
xhr.open("GET", "data.php", true);
xhr.send();
</script>
<스크립트>
var xhr = 새로운 XMLHttpRequest();
xhr.open("POST", "submit.php", true);
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = 함수() {
if (xhr.readyState === 4 && xhr.status === 200) {
Alert("서버 응답: " + xhr.responseText);
}
};
xhr.send("name=샤오밍&점수=90");
</스크립트>
<스크립트>
var xhr = 새로운 XMLHttpRequest();
xhr.open("GET", "data.json", true);
xhr.onreadystatechange = 함수() {
if (xhr.readyState === 4 && xhr.status === 200) {
var json = JSON.parse(xhr.responseText);
console.log("이름: " + json.name);
}
};
xhr.send();
</스크립트>
$.아약스({
URL: "data.php",
메소드: "GET",
성공: 함수(응답) {
$("#result").html(응답);
},
오류: 함수(xhr) {
Alert("오류: " + xhr.status);
}
});
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = 함수() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
console.log("응답 내용: " + xmlhttp.responseText);
}
};
xmlhttp.open("GET", "api/data.php", true);
xmlhttp.send();
xmlhttp.open("POST", "api/save.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("name=test&value=123");
xmlhttp.onreadystatechange = 함수() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var 데이터 = JSON.parse(xmlhttp.responseText);
console.log("상태: " + data.status);
}
};
<스크립트>
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = 함수() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
{를 시도해보세요
var json = JSON.parse(xmlhttp.responseText);
console.log("데이터가 성공적으로 수신되었습니다:", json);
} 잡기 (e) {
console.error("반환된 내용은 유효한 JSON이 아닙니다.", xmlhttp.responseText);
}
}
};
xmlhttp.open("GET", "data.php", true);
xmlhttp.send();
</스크립트>
error_reporting(0)오류 출력을 끕니다.
<br />
<b>Deprecated</b>: Facebook\FacebookApp implements the Serializable interface...
...
{ "status": "ok", "data": [...] }
error_reporting(0);
ini_set('display_errors', 0);이는 PHP가 오류나 경고 메시지를 출력하는 것을 방지합니다.<?php
error_reporting(0);
ini_set('display_errors', 0);
header('콘텐츠 유형: 애플리케이션/json');
// 이것이 반환될 데이터라고 가정합니다.
$data = ["상태" => "확인", "값" => 123];
echo json_encode($data);
출구;
?>
composer update facebook/graph-sdk또는 PHP 8.1 호환 버전을 사용하려면 작곡가.json의 버전 요구 사항을 확인하세요.응답 = xmlhttp.responseText;
jsonStart = response.indexOf("{");
if (jsonStart >= 0) {
jsonStr = response.substring(jsonStart);
json = JSON.parse(jsonStr);
//json을 사용하여 데이터 처리
}
<div id="msg"></div>
<스크립트>
이름 = "샤오밍";
document.getElementById("msg").textContent = 이름;
</스크립트>
<div id="box"></div>
<스크립트>
색상 = "빨간색"으로 설정합니다.
document.getElementById("box").innerHTML =
`<p style="color:${color}">텍스트 색상: ${color}</p>`;
</스크립트>
<a id="link">링크</a>
<input id="nameInput">
<스크립트>
URL = "https://example.com"으로 설정하세요.
이름 = "샤오화";
document.getElementById("link").href = URL;
document.getElementById("nameInput").value = 이름;
</스크립트>
<img id="avatar" alt="사용자 아바타">
<스크립트>
이미지 소스 = "https://example.com/avatar.png";
document.getElementById("avatar").setAttribute("src", 이미지 소스);
</스크립트>
<div id="카드"></div>
<스크립트>
사용자 ID = 456을 설정합니다.
document.getElementById("card").dataset.userid = 사용자 ID; // data-userid="456"에 해당합니다.
</스크립트>
<a id="myLink">링크</a>
<input id="myInput">
<스크립트>
URL = "https://example.com"으로 설정하세요.
이름 = "샤오밍";
document.getElementById("myLink").href = URL;
document.getElementById("myInput").value = 이름;
</스크립트>
<img id="아바타">
<스크립트>
이미지 소스 = "https://example.com/avatar.png";
document.getElementById("avatar").setAttribute("src", 이미지 소스);
</스크립트>
<div id="카드"></div>
<스크립트>
사용자 이름 = 123으로 설정합니다.
document.getElementById("card").dataset.userid = 사용자 코드; // data-userid="123"에 해당합니다.
</스크립트>
<div id="컨테이너"></div>
<스크립트>
let title = "동적 제목";
document.getElementById("컨테이너").innerHTML =
`<h3 data-title="${title}">${title}</h3>`;
</스크립트>
다음 예에서는<div class="abc">하위 요소:
// 부모 요소가 있다고 가정
const parent = document.getElementById("myParent");
//div 요소 생성
const child = document.createElement("div");
// 클래스 설정
child.className = "abc"; // or use classList.add("abc");
//상위 요소에 추가
parent.appendChild(자식);
<div id="myParent"></div>
<스크립트>
const parent = document.getElementById("myParent");
const child = document.createElement("div");
child.className = "abc";
child.textContent = "새 DIV입니다.";
parent.appendChild(자식);
</스크립트>
child.classList.add("abc", "def")id、style、dataset속성~에 있을 것이다#myParent표시 위치:
<div class="abc">새 DIV입니다</div>
querySelectorAll()CSS 선택기 구문을 사용하여 기준을 충족하는 모든 요소를 선택하고 정적을 반환합니다.NodeList。
// <div>를 모두 선택합니다. 카테고리가 "항목"인 경우
let items = document.querySelectorAll("div.item");
// forEach를 사용하여 결과를 반복합니다.
items.forEach(항목 => {
item.style.color = "파란색";
});
그리고querySelectorAll()유사하지만 기준을 충족하는 "첫 번째" 요소만 반환합니다. 찾지 못한 경우 반품null。
// ID가 "main-title"인 첫 번째 요소를 선택합니다.
let title = document.querySelector("#main-title");
// 첫 번째 <p> 페이지의 태그
let firstPara = document.querySelector("p");
이는 고유 ID로 단일 요소를 선택하도록 설계된 가장 빠르고 직접적인 방법입니다.
let header = document.getElementById("header-section");
카테고리 이름을 기준으로 요소를 선택하고 "라이브"를 반환합니다.HTMLCollection. 이 컬렉션은 DOM 구조가 변경되면 자동으로 업데이트됩니다.
let 버튼 = document.getElementsByClassName("btn-submit");
// 참고: HTMLCollection에서는 forEach를 직접 사용할 수 없습니다. 먼저 배열로 변환해야 합니다.
Array.from(buttons).forEach(btn => console.log(btn));
태그 이름(예: div, p,span)을 기반으로 요소를 선택하고 인스턴트를 반환합니다.HTMLCollection。
let allLinks = document.getElementsByTagName("a");
console.log("이 페이지에는 총 " + allLinks.length + " 링크가 있습니다.");
| 방법 | 포스트백 유형 | 매개변수 유형 | 성능 |
|---|---|---|---|
| querySelector | 단일 요소 | CSS 선택기 | 평범한 |
| querySelectorAll | NodeList(정적) | CSS 선택기 | 평범한 |
| getElementById | 단일 요소 | ID 문자열 | 가장 빠른 |
| getElementsByClassName | HTMLCollection(인스턴트) | 카테고리 문자열 | 빠른 |
querySelectorAll반환NodeList정적입니다. 즉, 나중에 DOM에서 요소가 제거되더라도 매니페스트의 내용은 변경되지 않습니다. 그리고getElementsBy...반환된 시리즈HTMLCollection이는 동적이며 언제든지 DOM의 최신 상태를 반영합니다.
여러 조건을 동시에 만족하는 요소를 선택하고 싶다면, 선택자를 사이에 공백 없이 가깝게 배치하면 됩니다.
// 카테고리에 "btn"과 "primary"가 모두 포함된 요소를 선택합니다.
let PrimaryButtons = document.querySelectorAll(".btn.primary");
// <li> 클래스가 "item"인 태그
let listItems = document.querySelectorAll("li.item");
조건 A 또는 조건 B와 일치하는 모든 요소를 선택하려면 "쉼표"를 사용하십시오.,서로 다른 선택기를 분리합니다.
// <h1>을 모두 선택합니다. 그리고 모든 <h2>
let headers = document.querySelectorAll("h1, h2");
// 카테고리가 "활성"인 요소 또는 "강조" 카테고리가 있는 요소를 선택합니다.
let markers = document.querySelectorAll(".active, .highlight");
HTML 속성의 존재 여부 또는 값을 기준으로 필터링합니다. 이는 양식이나 사용자 정의 데이터 속성으로 작업할 때 유용합니다.
// <button>을 모두 선택합니다. "비활성화" 속성 포함
let 비활성화Btns = document.querySelectorAll("버튼[비활성화]");
// <input>을 모두 선택합니다. 이름 속성이 "user"로 시작하는 경우(^= 사용)
let userInputs = document.querySelectorAll("input[name^='user']");
// 데이터 유형 속성이 "video"와 정확히 동일한 모든 요소를 선택합니다.
let videos = document.querySelectorAll("[data-type='video']");
심층 심사를 위해 요소 간의 구조적 관계를 사용합니다.
// 하위 선택자: <a>를 모두 선택합니다. #nav 내부(레벨에 관계없음)
let navLinks = document.querySelectorAll("#nav a");
//하위 선택기: <div> .container 바로 아래(첫 번째 레이어만 해당)
let directDivs = document.querySelectorAll(".container > div");
// 인접한 형제 선택자: 첫 번째 <p> <h1> 바로 다음에
let firstParas = document.querySelectorAll("h1 + p");
이는 목록이나 상태 필터로 작업할 때 매우 강력합니다.
// 테이블의 짝수 열을 모두 선택합니다(2번째, 4번째, 6번째...).
let evenRows = document.querySelectorAll("tr:nth-child(even)");
// 현재 체크되어 있는 체크박스를 모두 선택
let selectedBoxes = document.querySelectorAll("input[type='checkbox']:checked");
// 모든 <섹션>을 선택합니다. "숨겨진" 카테고리가 없는 항목(:not 사용)
let visibleSections = document.querySelectorAll("section:not(.hidden)");
위의 모든 규칙을 결합하여 복잡한 쿼리 조건을 만들 수 있습니다.
// <div>를 모두 선택합니다. ID가 "main"이고 클래스가 "card" 및 "data-id" 속성이 있는 컨테이너
let complexQuery = document.querySelectorAll("#main div.card[data-id]");
// 첫 번째 <li> 그리고 마지막 <li>
let 끝점 = document.querySelectorAll("li:first-child, li:last-child");
찾기 위해currElem처음으로<footer>가장 신뢰할 수 있는 방법은 모든 요소를 반복하는 것입니다.<footer>요소와 용도Node.compareDocumentPosition()그들의 친척을 결정하는 방법currElem위치.
document.querySelectorAll('footer')페이지의 모든 항목 가져오기<footer>요소.<footer>요소, 호출currElem.compareDocumentPosition(footer). 결과 비트마스크에 $4$(NODE_FOLLOWING), 이는 다음을 의미합니다.<footer>파일 순서대로currElem후에.<footer>, 이동을 중지합니다.목표를 찾아라<footer>요소를 사용하면 최신 DOM 인터페이스를 사용할 수 있습니다.Element.before()이 요소 앞에 새 콘텐츠를 삽입하세요.
targetFooter.before(contentToAdd);
여기contentToAdd문자열(텍스트 노드로 변환됨) 또는 하나 이상의 DOM 노드/요소일 수 있습니다.
함수 addContentBeforeNextFooter(currElem, contentToAdd) {
// 1. 파일의 모든 바닥글 요소를 가져옵니다.
const allFooters = document.querySelectorAll('footer');
nextFooter = null로 놔두세요;
// 2. currElem 이후의 첫 번째 바닥글을 탐색하여 찾습니다.
for (allFooters의 const 바닥글) {
// 바닥글이 currElem을 따르는지 확인합니다(비트마스크 4).
// 4: 인수 노드는 참조 노드를 따릅니다.
if (currElem.compareDocumentPosition(footer) & 4) {
nextFooter = 바닥글;
부서지다; // 첫 번째 것을 찾은 후 즉시 중지
}
}
// 3. 대상 바닥글을 찾으면 그 앞에 내용을 삽입합니다.
if (다음바닥글) {
nextFooter.before(contentToAdd);
console.log('currElem 이후 첫 번째 바닥글 앞에 콘텐츠가 성공적으로 삽입되었습니다.');
다음 바닥글을 반환합니다.
} 그렇지 않으면 {
console.log('currElem 다음에 바닥글 요소가 없습니다.');
null을 반환;
}
}
// 예시: 삽입할 콘텐츠 생성
const newDiv = document.createElement('div');
newDiv.textContent = '새로 삽입된 내용입니다. ';
// currElem이 획득한 DOM 요소라고 가정합니다.
// const currElem = document.getElementById('some-id');
// addContentBeforeNextFooter(currElem, newDiv);
이 업데이트된 기능findNearestFooter방향을 지정할 수 있습니다('before'또는'after') 가장 가까운 것을 찾으려면currElem~의<footer>요소.
Node.compareDocumentPosition()결정하는 방법의 비트 마스크<footer>에 있습니다currElem이전 또는 이후.'after'): 비트 $4$(NODE_FOLLOWING)。
document.querySelectorAll이미 파일순으로 정렬되어 있어서 조건에 맞는 것을 먼저 찾아요<footer>그것이 목표입니다.'before'): 비트 $2$(NODE_PRECEDING)。
document.querySelectorAll위에서 아래로 정렬되어 있습니다. 목록을 역방향으로 탐색하여 조건을 충족하는 첫 번째 목록을 찾아야 합니다.<footer>가장 가깝습니다currElem그거./**
* 첫 번째 <바닥글> currElem 앞이나 뒤에 요소를 추가하고 그 앞과 뒤에 콘텐츠를 삽입합니다.
* @param {HTMLElement} currElem - 참조점으로 사용되는 요소입니다.
* @param {('before'|'after')} 방향 - 찾을 방향('이전' 또는 '이후')입니다.
* @param {HTMLElement|string} contentToAdd - 삽입할 콘텐츠(요소 또는 문자열)입니다.
* @returns {HTMLElement|null} - 바닥글 요소가 발견되었거나 발견되지 않은 경우 null입니다.
*/
함수 findNearestFooter(currElem, 방향, contentToAdd) {
const allFooters = document.querySelectorAll('footer');
가장 가까운 바닥글 = null;
if (방향 === '이후') {
// "after"의 첫 번째 바닥글을 찾습니다.
for (allFooters의 const 바닥글) {
// 4 (NODE_FOLLOWING): currElem 뒤의 바닥글
if (currElem.compareDocumentPosition(footer) & 4) {
가장 가까운 바닥글 = 바닥글;
부서지다; // 가장 가까운 첫 번째 항목을 찾으면 중지합니다.
}
}
//내용 삽입(찾은 바닥글 앞)
if (nearestFooter) {
최근접Footer.before(contentToAdd);
console.log('currElem 이후 첫 번째 바닥글 앞에 내용이 삽입되었습니다.');
}
} else if (방향 === '이전') {
// "이전"의 첫 번째 바닥글을 찾습니다.
// currElem에 가장 가까운 바닥글을 찾으려면 목록 끝에서 뒤로 이동해야 합니다.
for (let i = allFooters.length - 1; i >= 0; i--) {
const 바닥글 = allFooters[i];
// 2 (NODE_PRECEDING): currElem 앞의 바닥글
if (currElem.compareDocumentPosition(footer) & 2) {
가장 가까운 바닥글 = 바닥글;
부서지다; // 첫 번째 발견 시 중지(역순회에서 첫 번째 발견)
}
}
// 내용 삽입(발견된 바닥글 뒤)
// 우리의 요구 사항은 "이전" 바닥글을 찾는 것이므로 일반적으로 내용은 바닥글 뒤에 삽입됩니다.
if (nearestFooter) {
// 이전 요청(바닥글 앞에 삽입)과 일관성을 유지하기 위해 우리는 여전히
// 찾은 바닥글 "뒤"에 삽입해야 하는 경우 NearestFooter.after(contentToAdd)를 사용합니다.
최근접Footer.before(contentToAdd);
console.log('currElem 앞의 첫 번째 바닥글 앞에 내용이 삽입되었습니다.');
}
}
if (!nearestFooter) {
console.log(`currElem ${direction === 'before' ? 'before' : 'after'}에 바닥글 요소가 없습니다.`);
}
가장 가까운 바닥글을 반환합니다.
}
// 예: currElem 및 contentToAdd가 정의되어 있다고 가정합니다.
// const currElem = document.getElementById('some-reference');
// const newContent = document.createElement('p');
// newContent.textContent = '삽입된 내용입니다.';
// // 호출 예: currElem 이후 첫 번째 바닥글 찾기
// findNearestFooter(currElem, 'after', newContent.cloneNode(true));
// // 호출 예: currElem 앞의 첫 번째 바닥글 찾기
// findNearestFooter(currElem, 'before', newContent.cloneNode(true));
document.querySelectorAll()반환되는 것은 **NodeList**입니다. NodeList는 진정한 JavaScript 배열은 아니지만length속성과 숫자 인덱스를 사용하여Array.from()또는 스프레드 연산자(스프레드 연산자...) 배열로 변환한 다음 사용합니다.Array.prototype.slice()초기 하위 집합을 가져오는 방법입니다.
/**
* querySelectorAll이 반환한 컬렉션의 처음 5개 요소를 가져옵니다.
* @param {string} 선택기 - CSS 선택기 문자열입니다.
* @returns {배열} - 처음 5개 요소를 포함하는 배열(요소가 5개 미만인 경우 모든 요소가 반환됨)
*/
함수 getFirstFiveElements(선택기) {
const nodeList = document.querySelectorAll(selector);
// 1. NodeList를 배열로 변환
const allElements = Array.from(nodeList);
// 2. 처음 5개 요소를 가져오려면 Slice(0, 5)를 사용하세요.
const firstFive = allElements.slice(0, 5);
첫 번째 다섯을 반환;
}
//사용 예:
// const topFiveDivs = getFirstFiveElements('div');
// console.log("처음 5개 요소:", topFiveDivs);
컬렉션에서 임의의 요소를 가져오려면 다음 단계를 수행해야 합니다.
가장 효율적인 방법은 일반적으로 배열을 무작위로 정렬한 다음 상위 5개를 선택하는 것입니다.
/**
* querySelectorAll이 반환한 컬렉션에서 무작위로 5개의 요소를 얻습니다.
* @param {string} 선택기 - CSS 선택기 문자열입니다.
* @returns {배열} - 5개의 임의 요소가 포함된 배열(5개 미만의 요소가 있는 경우 모든 요소가 반환됨)
*/
함수 getRandomFiveElements(선택기) {
const nodeList = document.querySelectorAll(selector);
// 1. NodeList를 배열로 변환
allElements = Array.from(nodeList);
// 총 요소 수가 5개 미만인 경우 모든 요소를 직접 반환합니다.
if (allElements.length<= 5) {
return allElements;
}
// 2. 實作 Fisher-Yates (或稱 Knuth) 隨機排序法
// 這是一種高效且公平的隨機排列方法。
for (let i = allElements.length - 1; i >0; 나--) {
// 0과 i 사이의 무작위 인덱스 j를 생성합니다.
const j = Math.floor(Math.random() * (i + 1));
// allElements[i]와 allElements[j]를 교환합니다.
[allElements[i], allElements[j]] = [allElements[j], allElements[i]];
}
// 3. 무작위로 정렬된 배열의 처음 5개 요소를 가져옵니다.
const randomFive = allElements.slice(0, 5);
무작위5를 반환합니다.
}
//사용 예:
// const randomFiveImages = getRandomFiveElements('img');
// console.log("임의의 5개 요소:", randomFiveImages);
반응형 웹 디자인은 웹 사이트가 다양한 장치의 화면 크기와 해상도에 적응할 수 있도록 하는 웹 사이트 디자인 방법입니다. 즉, 웹사이트의 콘텐츠는 휴대폰, 태블릿, 데스크톱 컴퓨터 등 어느 기기에서 사용하든 최상의 경험을 제공하기 위해 자동으로 조정됩니다.
반응형 디자인의 핵심은 유연한 레이아웃, 크기 조정 가능한 이미지, CSS 미디어 쿼리입니다. 이러한 기술을 통해 웹사이트는 장치의 너비에 따라 요소의 크기를 자동으로 조정하고 정렬할 수 있습니다.
CSS의 미디어 쿼리를 사용하여 레이아웃을 조정합니다. 예:
@media (max-width: 600px) { body { font-size: 14px; } }
반응형 디자인은 사용자 경험을 향상시키고, 개발 비용을 절감하며, SEO 효과를 높일 수 있습니다. 반응형 웹 페이지는 각 장치마다 다른 버전을 디자인할 필요가 없기 때문에 유지 관리가 더 쉽습니다.
JavaScript는 코드가 사용자의 브라우저에 다운로드되어 실행되므로 쉽게 보거나 복사할 수 있는 프런트엔드 프로그래밍 언어입니다. 코드의 리버스 엔지니어링을 완전히 방지하는 것은 불가능하지만 보호 강도를 높이고 평가판 및 공식 버전에 대한 인증 메커니즘을 구현하기 위해 다양한 조치를 취할 수 있습니다.
도구를 사용하여 소스 코드를 읽을 수 없는 형식으로 변환하세요.
npm install -g javascript-obfuscator
javascript-obfuscator input.js --output output.js
난독화된 코드 예:
var _0x1a2b=["\x68\x65\x6C\x6C\x6F"];console[_0x1a2b[0]]("Hello World!");
압축 도구를 사용하여 공백과 주석을 제거하여 코드 가독성을 줄입니다.UglifyJS。
중요한 로직을 서버에 저장하고 프런트엔드에서 직접 실행하는 대신 API를 통해 서비스를 제공합니다.
fetch('https://example.com/api').then(response => response.json()).then(data => console.log(data));
개발자 도구 사용을 방지하려면 페이지에 감지 메커니즘을 추가하세요.
document.addEventListener('keydown', (event) => {
if (event.key === 'F12' || (event.ctrlKey && event.shiftKey && event.key === 'I')) {
event.preventDefault();
}
});
인증 코드를 기준으로 사용자 신원을 확인하는 등 시험 및 생산 로직을 API와 결합합니다.
fetch('https://example.com/verify_license', {
메소드: 'POST',
헤더: { 'Content-Type': 'application/json' },
본문: JSON.stringify({ LicenseKey: userLicenseKey })
}).then(응답 => response.json()).then(데이터 => {
if (data.valid) {
console.log('공식 버전이 활성화되었습니다');
} 그렇지 않으면 {
console.log('체험판 기능 제한');
}
});
UI 구성요소 가용성이나 데이터 액세스와 같은 평가판의 특정 기능을 비활성화합니다.
사용자의 첫 사용 날짜를 기준으로 평가판 기간 확인 로직을 설정합니다.
const startDate = localStorage.getItem('startDate') || 새로운 날짜();
localStorage.setItem('startDate', startDate);
if (new Date() - new Date(startDate) > 14 * 24 * 60 * 60 * 1000) {
console.log('평가판 기간이 종료되었습니다');
} 그렇지 않으면 {
console.log('평가판 기간 중');
}
웹 페이지에서 스크롤 위치의 변화를 모니터링하면 맨 위로 돌아가기 버튼 표시, 부동 탐색 표시줄 표시 등과 같은 많은 동적 효과를 얻을 수 있습니다. 이러한 이벤트 수신은 JavaScript를 사용하여 쉽게 구현할 수 있습니다.
JavaScript에서는 다음을 통해 이를 수행할 수 있습니다.window.addEventListener('scroll', handler)스크롤 이벤트를 수신하는 방법입니다. 스크롤 시 발생handler해당 처리를 수행하는 기능입니다.
다음 예제에서는 현재 페이지 스크롤의 세로 위치를 표시하고 페이지 하단에 표시합니다.
<스크립트>
//스크롤 이벤트 핸들러 정의
함수 핸들스크롤() {
const scrollPosition = window.scrollY; // 세로 스크롤 위치를 가져옵니다.
document.getElementById("scrollPositionDisplay").textContent = "현재 스크롤 위치: " + scrollPosition + " px";
}
//스크롤 이벤트 리스너 추가
window.addEventListener('scroll', handlerScroll);
</스크립트>
<div id="scrollPositionDisplay" 스타일="위치: 고정; 하단: 20px; 왼쪽: 20px; 배경색: #eee; 패딩: 10px;">
현재 스크롤 위치: 0px
</div>
스크롤 이벤트에 너무 많은 작업을 추가하면 성능에 영향을 미칠 수 있으므로 다음을 사용하는 것이 좋습니다.requestAnimationFrame또는setTimeout이벤트 트리거의 빈도를 줄이려면 조절을 수행하십시오.
스크롤 위치 변경을 수신하는 이벤트는 다양한 동적 효과에 사용되어 웹 페이지의 상호 작용을 향상시킬 수 있습니다. 간단한 JavaScript를 통해 스크롤 이벤트를 모니터링하여 사용자 경험을 향상시킬 수 있습니다.
width: max-content이 접근 방식을 사용하면 요소의 너비를 새 줄에 유지하면서 내용에 따라 자동으로 조정할 수 있습니다.
pre {
display: inline-block;
width: max-content;
}
효과:
이것은 텍스트입니다.
이것은 코드 블록입니다.
float: left이 방법은float요소를 왼쪽으로 띄우고 새 줄에서 시작합니다.
pre {
display: inline-block;
float: left;
}
효과:
이것은 텍스트입니다.
이것은 코드 블록입니다.
::before가상 요소적응형 너비를 유지하면서 요소를 강제로 감싸려면 가상 요소를 사용하세요.
pre {
display: inline-block;
}
pre::before {
content: '';
display: block;
clear: both;
}
효과:
이것은 텍스트입니다.
이것은 코드 블록입니다.
white-space: pre사용white-space블록 너비가 콘텐츠에 자연스럽게 적응되도록 줄 바꿈 동작을 제어합니다.
pre {
display: inline-block;
white-space: pre;
}
효과:
이것은 텍스트입니다.
이것은 코드 블록입니다.
<!DOCTYPE html>
<html lang="ko">
<머리>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Windows 앱 UI 시뮬레이션</title>
<스타일>
몸 {
글꼴 모음: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
여백: 0;
패딩: 0;
배경색: #f0f0f0;
}
.app-창 {
너비: 800px;
높이: 500px;
여백: 50px 자동;
배경: #ffffff;
테두리: 1px 실선 #ccc;
테두리 반경: 8px;
상자 그림자: 0 4px 10px rgba(0, 0, 0, 0.2);
오버플로: 숨김;
디스플레이: 플렉스;
플렉스 방향: 열;
}
.제목 표시줄 {
배경: #0078d7;
색상: #ffffff;
패딩: 10px 15px;
디스플레이: 플렉스;
내용 정당화: 공백 사이;
항목 정렬: 중앙;
}
.title-bar h1 {
글꼴 크기: 16px;
여백: 0;
}
.제목 표시줄 .버튼 {
디스플레이: 플렉스;
간격: 5px;
}
.title-bar .buttons 버튼 {
너비: 20px;
높이: 20px;
배경: #ffffff;
테두리: 없음;
테두리 반경: 50%;
커서: 포인터;
}
.title-bar .buttons 버튼:hover {
배경: #e0e0e0;
}
.내용 {
플렉스: 1;
패딩: 15px;
오버플로: 자동;
}
.사이드바 {
너비: 200px;
배경: #f3f3f3;
테두리 오른쪽: 1px 단색 #ddd;
디스플레이: 인라인 블록;
수직 정렬: 상단;
}
.main-콘텐츠 {
디스플레이: 인라인 블록;
너비: 계산(100% - 200px);
수직 정렬: 상단;
}
.사이드바 ul {
목록 스타일: 없음;
여백: 0;
패딩: 0;
}
.sidebar 울리 {
패딩: 10px 15px;
커서: 포인터;
테두리 하단: 1px 솔리드 #ddd;
}
.sidebar ul li:hover {
배경: #e9e9e9;
}
.main-content p {
여백: 0;
패딩: 0;
}
</스타일>
</머리>
<본문>
<div class="app-window">
<div class="title-bar">
<h1>내 Windows 앱</h1>
<div class="버튼">
<버튼 제목="최소화"></button>
<button title="최대화"></button>
<button title="닫기" style="배경: #e81123;"></button>
</div>
</div>
<div class="content">
<div class="사이드바">
<li onclick="showContent('Home')">홈</li>
<li onclick="showContent('Settings')">설정</li>
<li onclick="showContent('About')">정보</li>
</ul>
</div>
<div class="main-content" id="mainContent">
<p>컨텐츠를 보려면 사이드바에서 항목을 선택하세요.</p>
</div>
</div>
</div>
<스크립트>
함수 showContent(섹션) {
const 내용 = {
홈: '<h2>홈</h2><p>홈 페이지에 오신 것을 환영합니다.</p>',
설정: '<h2>설정</h2><p>여기에서 애플리케이션 기본 설정을 조정하세요.</p>',
정보: '<h2>정보</h2><p>이것은 HTML과 JavaScript를 사용하여 만든 모의 Windows 앱입니다.</p>',
};
document.getElementById('mainContent').innerHTML = 콘텐츠[섹션] || '<p>콘텐츠를 찾을 수 없습니다.</p>';
}
</스크립트>
</body>
</html>
index.html。Select an item from the sidebar to view content.
React는 동적이고 효율적인 사용자 인터페이스를 구축하기 위해 Facebook에서 개발한 인기 있는 JavaScript 라이브러리입니다. 구성 요소 기반 설계를 통해 개발자는 UI 구성 요소를 빠르게 생성하고 재사용할 수 있습니다.
Vue.js는 중소 규모 애플리케이션 개발에 적합한 가볍고 사용하기 쉬운 프레임워크입니다. 간단한 API와 직관적인 디자인으로 UI 디자인을 빠르게 할 수 있습니다.
부트스트랩은 반응형 웹사이트를 빠르게 구축할 수 있도록 다양한 기성 UI 구성요소와 레이아웃 도구를 제공하는 프런트엔드 프레임워크입니다.
Material-UI는 Google Material Design을 기반으로 한 React UI 프레임워크입니다. 아름다운 구성 요소가 많이 포함되어 있어 고품질 인터페이스를 빠르게 디자인하는 데 적합합니다.
Tailwind는 JavaScript와 함께 사용하면 맞춤형 UI를 빠르게 구축할 수 있는 실용적인 CSS 프레임워크입니다. 원자적 설계를 통해 개발자는 스타일을 유연하게 제어할 수 있습니다.
Foundation은 현대적인 웹 디자인을 빠르게 구축하는 데 적합한 다양한 UI 구성 요소와 그리드 시스템을 제공하는 반응형 프런트 엔드 프레임워크입니다.
Chakra UI는 직관적인 API와 다양한 구성 요소를 제공하는 간단하고 사용자 정의 가능한 React UI 프레임워크입니다.
Quasar는 반응성이 뛰어난 크로스 플랫폼 애플리케이션을 빠르게 구축할 수 있는 Vue.js 기반의 UI 프레임워크입니다.
React는 사용자 인터페이스 구축에 중점을 두고 Meta에서 개발한 선언적 JavaScript 라이브러리입니다. 컴포넌트 개발 및 가상 DOM 기술을 통해 데이터베이스 기반 애플리케이션의 개발 효율성과 유지 관리성을 크게 향상시킵니다.
데이터베이스 기반 애플리케이션을 개발할 때 React는 종종 데이터 흐름을 처리하기 위해 최신 도구 체인과 결합됩니다.
React 개발에는 일반 텍스트 편집기를 사용할 수 있지만 데이터베이스 필드 힌트 및 유형 검사와 협력하기 위해 업계에서 가장 일반적인 선택은 다음과 같습니다.
React 및 데이터베이스 애플리케이션의 개발 프로세스를 최적화하려면 IDE에 다음 도구를 설치하는 것이 좋습니다.
| 도구 유형 | 인기있는 선택 | 핵심가치 |
|---|---|---|
| 코드 편집기(IDE) | VS Code, WebStorm | 효율적인 코드 작성 및 유형 힌트 |
| 패키지 관리 도구 | npm, pnpm, yarn | React 및 해당 생태계 종속성 관리 |
| 빌드 도구 | Vite, Turbopack | 매우 빠른 핫 업데이트 및 프로젝트 패키징 성능 |
| 디버거 | React DevTools | 구성 요소 상태 및 성능 병목 현상에 대한 실시간 모니터링 |
import React, { useState, useEffect } from 'react';
함수 데이터베이스뷰() {
//시뮬레이션된 데이터베이스 데이터
const [data, setData] = useState([]);
const [searchTerm, setSearchTerm] = useState('');
// 데이터베이스에서 데이터 가져오기 시뮬레이션
useEffect(() => {
const fetchData = async () => {
const mockData = [
{ ID: 1, 이름: 'John Doe', 이메일: '[email protected]', 연령: 28 },
{ ID: 2, 이름: 'Jane Smith', 이메일: '[email protected]', 연령: 34 },
{ ID: 3, 이름: 'Alice Brown', 이메일: '[email protected]', 연령: 25 },
{ ID: 4, 이름: 'Bob White', 이메일: '[email protected]', 연령: 40 },
];
setData(mockData);
};
페치데이터();
}, []);
//데이터 필터링
constfilteredData = data.filter(
(항목) =>
item.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
item.email.toLowerCase().includes(searchTerm.toLowerCase())
);
반환 (
<div style={{ padding: '20px',fontFamily: 'Arial, sans-serif' }}>
<h1>데이터베이스 보기</h1>
<입력
유형="텍스트"
placeholder="이름이나 이메일로 검색"
값={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
스타일={{
marginBottom: '20px',
패딩: '10px',
너비: '300px',
글꼴 크기: '16px',
}}
/>
<테이블
스타일={{
너비: '100%',
borderCollapse: '축소',
marginTop: '10px',
}}
>
<머리>
<tr>
<번째 스타일={{ border: '1px solid #ddd', padding: '10px' }}>ID</th>
<번째 스타일={{ border: '1px solid #ddd', padding: '10px' }}>이름</th>
<번째 스타일={{ border: '1px solid #ddd', padding: '10px' }}>이메일</th>
<번째 스타일={{ border: '1px solid #ddd', padding: '10px' }}>Age</th>
</tr>
</머리>
<본문>
{filteredData.map((항목) => (
<tr key={item.id}>
<td style={{ border: '1px solid #ddd', padding: '10px' }}>
{item.id}
</td>
<td style={{ border: '1px solid #ddd', padding: '10px' }}>
{항목.이름}
</td>
<td style={{ border: '1px solid #ddd', padding: '10px' }}>
{항목.이메일}
</td>
<td style={{ border: '1px solid #ddd', padding: '10px' }}>
{항목.연령}
</td>
</tr>
))}
</tbody>
</테이블>
</div>
);
}
기본 DatabaseView 내보내기;
create-react-app。DatabaseView.js。App.js가져오기 및 사용<DatabaseView />。React와 PHP는 코드를 직접 혼합하지 않고,JSON통신을 위한 데이터 형식. 반응 사용fetch또는axios요청을 보내면 PHP가 처리 후 결과를 반환합니다.
백엔드 PHP 코드는 더 이상 HTML을 출력하지 않고 대신 JSON 헤더와 데이터를 출력합니다.
<?php
// 교차 출처 요청(CORS) 허용
header("액세스 제어-허용-원본: *");
header("콘텐츠 유형: 애플리케이션/json; charset=UTF-8");
// 데이터베이스에서 데이터 가져오기 시뮬레이션
$stocks = ["AAPL", "TSLA", "NVDA", "GOOGL", "MSFT"];
echo json_encode($stocks);
?>
React에서는 일반적으로 다음을 수행합니다.useEffect후크에서 PHP API를 호출합니다.
import { useEffect, useState } from 'react';
function StockList() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("https://your-server.com/api.php")
.then(res => res.json())
.then(json => setData(json));
}, []);
return (
<ul>
{data.map(item => <li key={item}>{item}</li>)}
</ul>
);
}
| 유형 | 추천 플랜 | 설명하다 |
|---|---|---|
| 기존 PHP | 기본 PHP 또는 CodeIgniter | 간단한 API 인터페이스에 적합합니다. |
| 현대 프레임 | Laravel | 완벽한 내장 API 지원을 갖춘 가장 강력한 PHP 프레임워크입니다. |
| 하이브리드 솔루션 | Inertia.js | Laravel은 API를 작성하지 않고도 React와 원활하게 통합될 수 있습니다. |
개발 환경에서는 React가 일반적으로 다음에서 실행되기 때문에localhost:5173, PHP가 실행되는 동안localhost:8000, 당신은 만날 것입니다CORS(교차 원본 리소스 공유)실수. PHP 상단에 반드시 포함시키세요.Access-Control-Allow-Origin헤더.
Vue.js는 사용자 인터페이스 구축을 위한 진보적인 JavaScript 프레임워크입니다. 다른 대형 프레임워크와 달리 Vue는 아래에서 위로 레이어별로 적용되도록 설계되었습니다. 핵심 라이브러리는 뷰 레이어에만 중점을 두므로 매우 쉽게 시작하고 기존 프로젝트와 통합할 수 있습니다.
Vue는 HTML 템플릿과 JavaScript 개체를 결합하여 개발자가 직관적인 방식으로 웹 콘텐츠를 관리할 수 있도록 합니다. 현재 주류 권장사항은 Vue 3을 사용하는 것입니다.Composition API。
<!-- Vue 템플릿 -->
<div id="app">
<h1>{{ 메시지 }}</h1>
<button @click="reverseMessage">텍스트 반전</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<스크립트>
const { createApp, ref } = Vue;
createApp({
설정() {
const message = ref("Hello Vue!");
const reverseMessage = () => {
message.value = message.value.split('').reverse().join('');
};
return { 메시지, reverseMessage };
}
}).mount('#앱');
</스크립트>
지시 사항은 다음과 같습니다.v-접두사의 특수 속성은 데이터를 DOM 동작에 바인딩하는 역할을 합니다.
| 지침 | 사용 | 예 |
|---|---|---|
| v-bind (:) | HTML 속성 바인딩 | :src="imageUrl" |
| v-on (@) | 이벤트 듣기 | @click="doSomething" |
| v-if / v-else | 조건부 렌더링 | v-if="isVisible" |
| v-for | 목록 렌더링(배열 사용법과 유사) | v-for="item in items" |
| v-model | 양방향 데이터 바인딩 | v-model="inputText" |
앞서 언급한 내용을 쉽게 통합할 수 있습니다.slice()또는 선택기 개념을 통해 로직을 무작위로 선택하고 구성 요소를 조작할 수도 있습니다.
<스크립트 설정>
'vue'에서 { 참조 } 가져오기;
const allStocks = ref(['AAPL', 'TSLA', 'GOOGL', 'MSFT', 'AMZN', 'NVDA', 'META']);
const selectedStocks = ref([]);
// 무작위 선택 로직과 결합
const pickFive = () => {
const shuffled = [...allStocks.value].sort(() => 0.5 - Math.random());
selectedStocks.value = shuffled.slice(0, 5);
};
</스크립트>
<템플릿>
<div>
<button @click="pickFive">5개 주식을 무작위로 선택</button>
Web API(웹 애플리케이션 프로그래밍 인터페이스)는 서로 다른 시스템 간의 데이터 교환을 허용하는 HTTP 프로토콜 기반 인터페이스이며 프런트엔드와 백엔드 간의 통신에 자주 사용됩니다.
| 방법 | 사용 |
|---|---|
| GET | 정보 얻기 |
| POST | 새로운 정보 추가 |
| PUT | 정보 업데이트 |
| DELETE | 데이터 삭제 |
다음은 JavaScript를 사용하여 GET 요청을 보내는 예입니다.
가져오기('https://api.example.com/data')
.then(응답 => response.json())
.then(데이터 => console.log(데이터))
.catch(error => console.error('오류:', error));
한자를 입력하면 시스템에서 해당 문자의 발음 표기를 표시합니다.
아직 쿼리되지 않음
이 예에서는 Pinyin API를 사용하여 Zhuyin을 쿼리합니다. 발음이 여러 개인 경우 모든 결과가 표시됩니다.
Google Cloud Platform(GCP)은 Google이 제공하는 클라우드 컴퓨팅 서비스 플랫폼으로, Google의 내부 인프라를 기반으로 구축되었습니다. 컴퓨팅 및 스토리지부터 빅데이터 분석 및 인공 지능에 이르기까지 150개 이상의 서비스를 제공하여 기업의 디지털 전환 및 애플리케이션 개발을 지원합니다.
| 범주 | 주요 서비스 | 주요 기능 |
|---|---|---|
| 컴퓨팅 | Compute Engine | 사용자 정의 가능한 VM(가상 머신)을 제공합니다. |
| 컨테이너 | GKE / Cloud Run | Kubernetes 클러스터를 호스팅하거나 서버리스 컨테이너를 실행하세요. |
| 저장 | Cloud Storage | 이미지, 동영상 등 비정형 데이터를 저장하는 객체 스토리지입니다. |
| 데이터 베이스 | Cloud SQL / Spanner | MySQL, PostgreSQL 또는 글로벌 관계형 데이터베이스를 제공합니다. |
| 데이터 분석(데이터) | BigQuery | 대규모 SQL 쿼리를 지원하는 서버리스 엔터프라이즈급 데이터 웨어하우징입니다. |
| 인공지능(AI) | Vertex AI | Gemini 모델 개발 도구를 포함한 통합 기계 학습 플랫폼입니다. |
Google Cloud의 리소스 조직은 계층적 시스템을 따라 권한 제어 및 비용 추적을 용이하게 합니다.
Google Cloud는 '사용한 만큼만 지불' 메커니즘을 채택하고 다음과 같은 이점을 제공합니다.
Google ID 로그인은 사용자가 자신의 Google 계정을 사용하여 타사 웹사이트나 애플리케이션에 로그인할 수 있도록 하는 OAuth 2.0 프로토콜 기반의 인증 방법입니다. 이러한 접근 방식은 사용자 편의성을 향상시킬 뿐만 아니라 사용자가 추가 비밀번호를 기억할 필요가 없기 때문에 보안도 강화됩니다.
<script src="https://apis.google.com/js/platform.js" async defer></script>
<div class="g_id_signin" data-type="standard" data-shape="rectangular" data-theme="outline" data-text="signin_with" data-size="large" data-logo_alignment="left"></div>
사용자가 로그인 버튼을 클릭하면 Google이 인증을 수행합니다. 로그인에 성공하면 사용자 정보(예: 이메일, 이름 등)가 애플리케이션으로 다시 전송되며, 이 정보를 기반으로 후속 처리를 수행할 수 있습니다.
Google ID로 로그인하면 사용자에게 간단하고 안전한 로그인 방법이 제공되며 여러 계정을 관리하는 번거로움이 줄어듭니다. Google의 로그인 시스템을 통합함으로써 개발자는 사용자 경험을 개선하고 웹사이트나 애플리케이션에 더 많은 사용자를 유치할 수 있습니다.
YouTube 동영상을 삽입하려면 원본 링크를 삽입 형식으로 수정하세요.
<iframe width="560" height="315" src="https://www.youtube.com/embed/{vid}" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
~에{vid}YouTube 동영상의 ID입니다.
예를 들어 동영상 링크는 다음과 같습니다.https://www.youtube.com/watch?v=dQw4w9WgXcQ, 삽입 코드는 다음과 같습니다.
<iframe width="560" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
이러한 삽입 형식은 다음을 방지합니다.X-Frame-Options페이지에 영상이 정상적으로 표시될 수 있도록 제한합니다.
HTML에서 직접 사용할 수 있습니다.<iframe>YouTube 동영상 삽입,
하지만 유튜브는 그렇지 않아요'검색결과 페이지'에 직접 iframe을 삽입하는 것은 지원되지 않습니다.,
검색결과는 대화형 콘텐츠(로그인, 추천, 추적 등 기능 포함)이므로 YouTube의 삽입 정책에 따라 차단됩니다.
검색 결과를 삽입하려는 다음 시도는 실패하거나 오류 메시지를 표시합니다.
<!-- ⚠️ 제대로 표시할 수 없습니다 -->
<iframe 너비="800" 높이="600"
src="https://www.youtube.com/results?search_query=cat+video">
</iframe>
이 방법은 브라우저나 YouTube에 의해 차단되며 'iframe에 표시가 거부됨'이 표시됩니다.
---검색 결과 효과를 웹 페이지에 포함하려면 다음을 사용하세요.YouTube Data API v3동영상을 동적으로 쿼리한 다음 JavaScript를 사용하여 결과를 직접 표시하고<iframe>。
이동Google Cloud Console"YouTube Data API v3"을 활성화하고 API 키를 얻으세요.
<div>
<input id="search" type="text" placeholder="검색 키워드">
<button onclick="searchYouTube()">검색</button>
</div>
<div id="results" style="display:grid;grid-template-columns:repeat(auto-fill,300px);gap:1em;margin-top:1em;"></div>
<스크립트>
const API_KEY = "YOUR_API_KEY";
함수 검색YouTube() {
const q = document.getElementById("search").value;
const url = `https://www.googleapis.com/youtube/v3/search?part=snippet&type=video&maxResults=6&q=${encodeURIComponent(q)}&key=${API_KEY}`;
가져오기(URL)
.then(r => r.json())
.then(데이터 => {
const 컨테이너 = document.getElementById("results");
컨테이너.innerHTML = "";
data.items.forEach(항목 => {
const vid = item.id.videoId;
const 제목 = item.snippet.title;
const 프레임 = document.createElement("iframe");
프레임.폭 = "300";
프레임.높이 = "170";
프레임.src = `https://www.youtube.com/embed/${vid}`;
Frame.allow = "가속도계; 자동 재생; 클립보드 쓰기; 암호화된 미디어; 자이로스코프; PIP(Picture-in-Picture)";
프레임.allowFullscreen = true;
const div = document.createElement("div");
const caption = document.createElement("p");
caption.textContent = 제목;
caption.style.fontSize = "14px";
caption.style.fontWeight = "굵게";
div.appendChild(프레임);
div.appendChild(캡션);
컨테이너.appendChild(div);
});
});
}
</스크립트>
---
<iframe>내장되어 직접 재생할 수 있습니다.iframe.src = "https://www.youtube.com/embed/" + videoId + "?autoplay=1"자동으로 재생됩니다.snippet.thumbnails즉시 삽입하는 대신 미리보기 이미지를 표시합니다.Node.js는 개발자가 JavaScript를 사용하여 백엔드 애플리케이션을 작성할 수 있도록 하는 Chrome V8 JavaScript 엔진을 기반으로 하는 서버 측 실행 환경입니다.
express:경량 웹 애플리케이션 프레임워크fs: 파일 시스템 작업http:HTTP 서버 생성path: 프로세스 파일 경로const http = require('http');
const 서버 = http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('안녕하세요, Node.js!');
});
server.listen(3000, () => {
console.log('서버가 시작되었습니다. 수신 포트 3000');
});
Node.js는 프런트엔드 개발자에게 통합 언어 백엔드 개발 환경을 제공하고 개발 효율성을 향상시키며 최신 네트워크 애플리케이션을 구축하는 데 적합합니다.
Node.js를 설치하는 방법은 여러 가지가 있지만 개발자의 경우 공식 웹사이트 설치 파일을 직접 다운로드하는 대신 버전 관리 도구(예: nvm)를 사용하는 것이 좋습니다. 이렇게 하면 향후 권한 오류를 방지하고 버전 간 전환이 쉬워집니다.
이는 가장 유연한 접근 방식이며 장기적인 개발이 필요한 컴퓨터 환경에 적합합니다.
nvm-setup.exe그리고 설치하세요.nvm install lts //최신 장기 지원 버전(LTS) 설치 nvm use lts // 이 버전을 전환하고 활성화합니다. node -v // 설치 성공 확인
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install --lts //LTS 버전 설치 node -v // 버전 번호 보기
빠른 설치만 필요하고 버전을 자주 변경할 계획이 없다면 다음으로 이동하세요.Node.js 공식 웹사이트。
Node.js를 설치하면 다음 핵심 구성 요소도 포함됩니다.
| 구성요소 이름 | 설명하다 |
|---|---|
| Node.js 실행 환경 | JavaScript가 서버 측에서 실행될 수 있도록 하는 핵심입니다. |
| npm (Node Package Manager) | 패키지(예: Vue, React) 다운로드를 위한 세계 최대 규모의 소프트웨어 레지스트리입니다. |
| Corepack | 패키지 관리자 관리를 위한 새로운 도구(예: Yarn, pnpm) |
설치가 완료되면 다음 명령을 입력하여 모든 도구가 준비되었는지 확인할 수 있습니다.
node -v // v20.11.0과 같은 노드 버전을 표시합니다. npm -v // 10.2.4와 같은 npm 버전을 표시합니다.
Windows에서 실행할 때 "시스템에서 스크립트 실행이 금지되어 있기 때문에" 오류가 발생하는 경우 관리자 권한으로 PowerShell을 열고 다음을 실행하십시오.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
nvm(Node Version Manager)은 Node.js용으로 특별히 설계된 버전 관리 도구입니다. 이를 통해 동일한 컴퓨터에 여러 다른 버전의 Node.js를 설치하고 전환할 수 있습니다. 이는 동시에 다른 Node 버전을 사용하여 여러 프로젝트를 유지해야 하는 개발자에게 필수적인 도구입니다.
프런트엔드 프로젝트(예: Vue, React)를 개발할 때 특정 Node.js 버전에 따라 다양한 프로젝트가 달라질 수 있습니다. 공식 홈페이지에서 직접 설치 파일을 다운로드하면 단일 버전만 설치할 수 있는데, nvm은 버전 충돌 문제를 해결해줍니다.
다음은 개발 중에 자주 사용되는 nvm 명령어입니다.
// 현재 설치된 모든 버전 보기 nvml // 클라우드에 설치할 수 있는 모든 Node.js 버전을 봅니다. nvm ls-원격 // 특정 버전(예: v18.16.0)을 설치합니다. nvm 설치 18.16.0 //지정된 버전으로 전환 nvm은 18.16.0을 사용합니다. //현재 사용중인 버전 확인 nvmcurrent //기본 버전 설정(단말기를 켤 때마다 자동으로 사용되는 버전) nvm 별칭 기본값 18.16.0
당신이 실행할 때nvm usenvm은 시스템을 동적으로 수정합니다.PATH환경 변수는 Node 실행 파일을 가리키는 주소를 해당 버전 폴더로 전환하여 어려움 없이 전환할 수 있습니다.
| 운영 체제 | 권장 버전/도구 | 주목 |
|---|---|---|
| macOS / Linux | nvm (nvm-sh) | 가장 독창적이고 안정적인 버전입니다. |
| Windows | nvm-windows | 같은 팀에서 개발한 것은 아니지만 기능은 거의 동일합니다. 설치하려면 .exe를 다운로드해야 합니다. |
Windows에 설치nvm-windows이전에는 전환 오류를 일으킬 수 있는 환경 변수 충돌을 방지하기 위해 원래 컴퓨터에 설치된 Node.js를 제거하는 것이 좋습니다.
NPM(Node Package Manager)은 JavaScript 코드의 라이브러리와 모듈을 관리하는 데 사용되는 Node.js용 패키지 관리 도구입니다. 이를 통해 개발자는 프로젝트에 필요한 다양한 패키지를 설치, 공유 및 버전 제어할 수 있습니다.
npm init: 새 프로젝트를 초기화하고 생성합니다.package.json파일.npm install:설치하다package.json에 나열된 모든 종속 패키지.npm install [패키지 이름]: 지정된 패키지를 설치합니다.npm 제거 [패키지 이름]: 지정된 패키지를 제거합니다.npm update: 설치된 패키지를 업데이트합니다.package.json프로젝트 이름, 버전, 설명, 종속 패키지 및 기타 정보를 기록하는 프로젝트의 핵심 파일입니다. 이는 NPM 관리 제품군의 기초입니다.
NPM은 가장 초기이자 가장 널리 사용되는 JavaScript 패키지 관리 도구이지만 Yarn과 같은 최신 대안이 등장하여 더 빠른 설치 속도와 병렬 처리를 제공합니다. 둘 다 대부분의 Node.js 프로젝트에서 사용할 수 있습니다.
Vite(프랑스어로 "빠르다")는 매우 빠른 개발 경험을 제공하도록 설계된 차세대 프런트엔드 구성 도구입니다. 이는 주로 개발 서버(네이티브 ES 모듈 기반)와 빌드 지침 세트(롤업을 사용하여 패키징됨)의 두 부분으로 구성됩니다.
Vite가 등장하기 전에는 Webpack이 주류 도구였지만, 프로젝트가 커지면서 컴파일 속도가 매우 느려졌습니다. Vite는 이러한 문제점을 해결합니다.
한 줄의 명령으로 Vue, React, Svelte 또는 순수 JavaScript 프로젝트를 생성하도록 빠르게 선택할 수 있습니다.
// npm을 사용하여 프로젝트 생성 npm은 vite@latest my-vue-app을 생성합니다. //폴더로 이동하여 패키지를 설치합니다. CD my-vue-app npm 설치 //개발 환경 시작 npm 런데브
프로젝트에서package.json, 일반적으로 사용되는 다음 스크립트를 볼 수 있습니다.
| 지침 | 사용 | 설명하다 |
|---|---|---|
| npm run dev | 개발 서버 시작 | 로컬 개발 중에 사용되며 실시간 업데이트를 지원합니다. |
| npm run build | 프로젝트 패키징 | 고도로 최적화된 정적 파일을 생성합니다(dist 폴더에 넣음). |
| npm run preview | 패키징 결과 미리보기 | 로컬로 배포 후 실행 상태를 시뮬레이션합니다. |
Vite의 구성은 매우 직관적이며 일반적으로 플러그인(Plugins)을 추가하거나 서버 프록시(Proxy)를 설정하는 데 사용됩니다.
'vite'에서 { 정의 구성 } 가져오기
'@vue/plugin-vue'에서 vue 가져오기
기본 정의 구성 내보내기({
플러그인: [vue()],
서버: {
port: 3000, // 개발 서버 포트 번호 수정
open: true // 시작 시 자동으로 브라우저 열기
}
})
Webpack:완전한 기능을 갖춘 "대규모 가공 공장"과 마찬가지로 모든 부품은 작업을 시작하기 전에 가공되어야 합니다. 속도는 느리지만 매우 기능적입니다.
Vite:"Modern Express"와 마찬가지로 필요한 모든 부분을 매우 빠르고 최신 브라우저 표준에 맞춰 동적으로 로드합니다.
Electron은 개발자가 HTML, CSS 및 JavaScript를 사용하여 크로스 플랫폼 데스크톱 애플리케이션을 구축할 수 있는 오픈 소스 프레임워크입니다. Chromium과 Node.js를 결합하여 웹 기술이 기본 시스템 리소스에 액세스할 수 있도록 합니다.
npm install --save-dev electron
// main.js
const { app, BrowserWindow } = require('electron');
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile('index.html');
}
app.whenReady().then(createWindow);
<!DOCTYPE html>
<html>
<본문>
안녕하세요, 일렉트론! </h1>
</body>
</html>
npx electron .
electron-builder설치 파일을 생성하는 데 사용할 수 있습니다.TypeScript는 Microsoft에서 개발한 JavaScript의 상위 집합입니다. JavaScript에 "유형 시스템"을 추가하고 결국 브라우저에서 실행하기 위해 순수 JavaScript로 컴파일됩니다. 이는 약한 유형의 언어인 JavaScript가 대규모 프로젝트에서 유지 관리가 어렵고 오류가 발생하기 쉬운 문제를 해결합니다.
변수 뒤에 추가하면: type유형을 선언합니다.
이름을 알려주세요: string = "Gemini";
나이: 숫자 = 18;
let isStudent: 부울 = true;
//배열 유형
주식을 보자: string[] = ["AAPL", "TSLA", "NVDA"];
// 함수 매개변수 및 반환 값 유형
함수 add(a: 숫자, b: 숫자): 숫자 {
a + b를 반환합니다.
}
이는 객체의 구조(Shape)를 정의하는 데 사용되는 TypeScript의 가장 강력한 기능 중 하나입니다.
인터페이스 사용자 {
아이디: 번호;
사용자 이름: 문자열;
이메일?: 문자열; // 물음표는 선택적 속성을 나타냅니다.
}
const newUser: 사용자 = {
아이디: 1,
사용자 이름: "Alex"
};
Vite와 같은 최신 개발 환경은 기본적으로 TypeScript를 지원합니다. 프로젝트 생성 시 선택vue-ts또는react-ts, Vite가 자동으로 처리합니다.tsconfig.json구성.
// Vite를 사용하여 TS 프로젝트 생성 npm은 vite@latest my-ts-app을 만듭니다 -- --template vue-ts
이전에 언급한 무작위 선택 기능을 TypeScript 버전으로 다시 작성하면 더 안전해집니다.
// 일반 <T> 이 함수를 사용하면 모든 유형의 배열을 처리할 수 있습니다.
function getRandomElements<T>(arr: T[], count: number = 5): T[] {
if (arr. 길이<= count) return [...arr];
const tempArray = [...arr];
const result: T[] = [];
for (let i = 0; i < count; i++) {
const randomIndex = Math.floor(Math.random() * tempArray.length);
result.push(tempArray.splice(randomIndex, 1)[0]);
}
return result;
}
const randomStocks = getRandomElements<string>(["AAPL", "TSLA", "GOOGL"], 2);
TypeScript 파일(.ts)은 브라우저에서 직접 실행할 수 없으며 수명 주기는 다음과 같습니다.
| 단계 | 행동 | 도구 |
|---|---|---|
| 집필 기간 | 유형 정의 및 .ts 코드 작성 | VS Code + TS Engine |
| 컴파일 시간 | 유형 오류를 확인하고 유형 태그를 제거하세요. | tsc / Vite / esbuild |
| 집행기간 | 브라우저에서 순수 .js 파일 실행 | Browser Engine |
브라우저 확장은 일반적으로 HTML, CSS 및 JavaScript로 작성된 브라우저 기능을 확장하는 데 사용되는 작은 응용 프로그램입니다. 웹 페이지 콘텐츠를 수정하고, 도구 모음 버튼을 추가하고, 백그라운드 서비스와 상호 작용하고, 사용자 경험을 향상시킬 수 있습니다.
manifest.json: 확장기능명, 버전, 권한, 진입방법을 기술합니다.popup.html: 툴바 아이콘을 클릭하면 표시되는 인터페이스입니다.background.js: 이벤트 및 로직을 처리하는 데 사용되는 백그라운드 상주 스크립트입니다.content.js: 웹페이지에 삽입된 스크립트는 DOM을 직접 조작할 수 있습니다.chrome://extensions/짐.manifest.json그리고 관련 파일.my-extension/
├─ manifest.json
├─ popup.html
├─ popup.js
└─ icon.png
{
"manifest_version": 3,
"name": "안녕하세요 확장 프로그램",
"버전": "1.0",
"description": "간단한 Chrome 확장 프로그램 예",
"액션": {
"default_popup": "popup.html",
"default_icon": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
}
},
"권한": []
}
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
<style>
body { width:200px; font-family:sans-serif; text-align:center; }
button { margin-top:10px; padding:5px 10px; }
</style>
</head>
<body>
<h3>Hello from Chrome Extension</h3>
<button id="btn">Click me</button>
<script src="popup.js"></script>
</body>
</html>
document.getElementById("btn").addEventListener("click", () => {
Alert("버튼이 클릭되었습니다!");
});
도구 모음이 표시될 PNG 아이콘(권장 크기 128x128)을 배치합니다.
chrome://extensions/Chrome 확장 프로그램은 표준 웹 기술을 기반으로 구축되었으므로 핵심 언어는 필수 기반인 웹 개발과 완전히 일치합니다.
보다 복잡하고 반응적인 사용자 인터페이스(특히 팝업 및 옵션 페이지)를 구축하려면 일반적인 프런트 엔드 프레임워크를 사용할 수 있습니다. 그러나 기능을 확장하는 백그라운드 서비스 워커에서는 중량급 프레임워크를 사용하는 것이 일반적으로 권장되지 않습니다.
개발 프로세스를 단순화하고 코드 패키징, 핫 리로딩(Hot Reloading) 및 브라우저 간 호환성을 처리하기 위해 최신 개발 도구를 사용하는 것이 추세입니다.
| 도구/키트 | 사용 | 장점 |
|---|---|---|
| Vite / Webpack | 번들러 | 여러 코드 파일, 스타일 및 리소스를 브라우저에서 읽을 수 있는 형식으로 패키징하여 코드 크기를 최적화합니다. Vite는 빠른 HMR(핫 모듈 교체)로 매우 유명합니다. |
| WXT / Plasmo | 확장된 기능 전용 프레임워크 | 확장 개발을 위해 특별히 설계된 프레임워크로 매니페스트 파일 생성, TypeScript 구성, 핫 리로딩 및 브라우저 간 지원(Chrome, Firefox, Edge 등)을 자동으로 처리하여 개발 환경을 크게 단순화할 수 있습니다. |
| pnpm / npm / yarn | 패키지 관리 도구 | 프로젝트가 의존하는 타사 JavaScript 라이브러리 및 도구를 관리합니다. |
이는 모든 Chrome 확장 프로그램 개발에 필수적인 도구입니다.
php.iniPHP의 주요 구성 파일로 PHP의 실행 모드와 기능에 영향을 줍니다.
이 파일을 수정하면 오류 출력, 메모리 제한, 업로드 크기, 시간대 등을 조정할 수 있습니다.C:\php\php.ini또는 설치 디렉터리에 있습니다./etc/php/버전 번호/apache2/php.ini또는/etc/php/version/cli/php.ini。php --iniCLI에서 사용하는 구성 파일을 쿼리합니다.-c매개변수를 지정하면 경로가 먼저 로드됩니다.php.ini。PHPRC지정된 디렉토리.php --ini또는phpinfo()질문)./etc/php.ini또는C:\Windows。; 시간대 설정
date.timezone = 아시아/타이베이
; 오류 표시
display_errors = 켜짐
error_reporting = E_ALL
; 업로드 파일 크기
upload_max_filesize = 20M
post_max_size = 25M
; 메모리 한도
memory_limit = 256M
; 최대 실행 시간(초)
max_execution_time = 30
php.ini그런 다음 Apache, Nginx 또는 PHP-FPM을 다시 시작해야 적용됩니다.phpinfo()현재 로드된 내용을 확인하세요.php.ini경로 및 매개변수 값.php.ini。.user.ini또는.htaccess일부 설정을 덮어씁니다.부울 값은 PHP에서 가장 간단한 데이터 유형입니다. **true** 또는 **false**의 두 가지 상태만 나타낼 수 있습니다. 부울 값은 제어 프로세스에 자주 사용됩니다(예:if/else조건부 판단) 및 논리 연산.
키워드를 사용할 수 있습니다.true또는false부울 변수를 정의합니다. 이러한 키워드는 대소문자를 구분하지 않습니다(예:TRUE、True또는true동일), 일반적으로 소문자를 사용하는 것이 좋습니다.true그리고false표준 관행을 준수합니다.
$is_active = 사실;
$is_logged_out = 거짓; // 대문자도 가능하지만 권장하지 않습니다.
//조건부 판단
if ($is_active) {
echo "<p>이 사용자는 현재 활동 중입니다.</p>";
} 그렇지 않으면 {
echo "<p>이 사용자는 현재 비활성 상태입니다.</p>";
}
PHP가 부울 값을 기대하지만 다른 데이터 유형이 제공되는 경우(예:if조건), PHP는 자동으로 값을 부울 값으로 변환(또는 유형 변환)합니다.
다음 값은 거짓으로 간주됩니다(거짓 값이라고 함).
false그 자체.0(영).0.0(영).""또는''。"0"(한 자리 숫자 0을 포함하는 문자열)array()또는[]。NULL。0이 아닌 숫자, 비어 있지 않은 문자열(심지어"false"또는" "[공백 포함])은 **true(true)**(Truthy 값이라고 함)로 처리됩니다.
$a = 0;
$b = "안녕하세요";
$c = "";
$d = [1, 2];
$e = 널;
echo "<h3>잘못된 값의 예</h3>";
if (!$a) { // $a (0)은 false로 변환됩니다.
echo "<p>$a(정수 0)은 FALSE로 처리됩니다.</p>";
}
if (!$c) { // $c (빈 문자열)은 false로 변환됩니다.
echo "<p>$c(빈 문자열)는 FALSE로 처리됩니다.</p>";
}
if (!$e) { // $e (NULL)은 false로 변환됩니다.
echo "<p>NULL은 FALSE로 처리됩니다.</p>";
}
echo "<h3>진짜 값의 예</h3>";
if ($b) { // $b ("Hello")는 true로 변환됩니다.
echo "<p>$b(비어 있지 않은 문자열)는 TRUE로 처리됩니다.</p>";
}
if ($d) { // $d (비어 있지 않은 배열)는 true로 변환됩니다.
echo "<p>비어 있지 않은 배열은 TRUE로 처리됩니다.</p>";
}
당신은 또한 사용할 수 있습니다(bool)또는boolval()이 함수는 변수를 부울 값으로 명시적으로 변환합니다. 이는 디버깅할 때나 엄격한 유형 검사가 필요할 때 유용합니다.
$f = "0"; // 숫자 0의 문자열 $g = 100; // 양의 정수 $f_bool = (부울)$f; $g_bool = boolval($g); echo "<p>'0' 문자열은 다음으로 변환됩니다: "; var_dump($f_bool); // 출력: bool(false) echo "</p>"; echo "<p>정수 100은 다음으로 변환됩니다: "; var_dump($g_bool); // 출력: bool(true) echo "</p>";
PHP에서는 비교 연산자를 사용하여 두 값(숫자 또는 문자열)을 비교합니다. 비교 결과에 따라 반환됩니다.true또는false. "느슨한 비교"와 "엄격한 비교"의 차이점을 이해하는 것이 프로그램 버그를 피하는 열쇠입니다.
| 연산자 | 이름 | 예 | true가 되는 조건 |
|---|---|---|---|
== |
같음 (느슨함) | $a == $b |
값이 동일함(유형 비교가 자동으로 변환됨) |
=== |
합동 (엄격) | $a === $b |
값도 같고 종류도 같고 |
!= / <> |
같지 않음 | $a != $b |
값이 동일하지 않습니다 |
!== |
일치하지 않음 | $a !== $b |
값이 동일하지 않거나 유형이 동일하지 않습니다. |
> |
보다 큼 | $a > $b |
$a가 $b보다 큼 |
< |
미만 | $a < $b |
$a는 $b보다 작습니다. |
>= |
이상 | $a >= $b |
$a는 $b보다 크거나 같습니다. |
<= |
보다 작거나 같음 | $a <= $b |
$a는 $b보다 작거나 같습니다. |
<=> |
우주선 운영자 | $a <=> $b |
-1, 0 또는 1을 반환합니다(PHP 7+). |
이것은 PHP 개발에서 가장 흔히 혼동되는 영역입니다. PHP는 약한 유형의 언어입니다.==비교하기 전에 서로 다른 유형의 변수를 동일한 유형으로 변환하려고 시도합니다.===변환이 전혀 수행되지 않습니다.
변환 후 "값"이 동일하다면 이는 사실입니다.
$a = 100; // 정수 (int)
$b = "100"; // 문자열(문자열)
if ($a == $b) {
echo "같음"; // PHP가 문자열을 숫자 비교로 변환하기 때문에 실행됩니다.
}
"값"은 "데이터 유형"과 정확히 동일해야 합니다.
$a = 100;
$b = "100";
if ($a === $b) {
echo "같음";
} 그렇지 않으면 {
echo "같지 않음"; // int가 string과 같지 않기 때문에 실행됩니다.
}
단축 구문을 사용하면 비교 논리를 처리할 때 코드가 더 깔끔해집니다.
$결과 = ($a > $b) ? "A 빅" : "B 빅";$name = $input_name ?? "방문객";(변수가 존재하지 않거나 null인 경우 기본값을 제공합니다.)안전 조언:인증, 권한 확인, API 반환 값 판단 시에는 반드시===. 예를 들어 확인strpos()반환 값0(위치) 및false(찾을 수 없음)==동일하게 취급되므로 논리적 오류가 발생합니다.
PHP에서 배열은 단일 변수에 여러 값을 저장할 수 있는 매우 유용한 복합 데이터 유형입니다. PHP의 배열은 실제로 순서가 지정된 맵입니다. 맵은 Value와 Key를 연결하는 유형입니다.
PHP의 배열은 키 유형에 따라 대략 세 가지 일반적인 형식으로 나눌 수 있습니다.
연속된 정수를 키로 사용합니다. 배열을 만들 때 키를 지정하지 않으면 PHP는 다음으로 시작합니다.0정수 인덱스 자동 할당을 시작합니다.
//인덱스 배열 생성
$fruits = array("사과", "바나나", "오렌지");
// 또는 단축 구문을 사용합니다(PHP 5.4 이후).
$colors = ["빨간색", "녹색", "파란색"];
//액세스 요소
에코 $fruits[0]; // 출력: 사과
에코 $colors[2]; // 출력: 파란색
문자열을 키(키 이름)로 사용합니다. 이를 통해 의미 있는 이름을 사용하여 배열의 값에 액세스할 수 있습니다.
//연관배열 생성
$사람 = 배열(
"이름" => "샤오밍",
"나이" => 25,
"도시" => "타이베이"
);
// 또는 단축 구문을 사용합니다.
$점수 = [
"수학" => 90,
"영어" => 85
];
//액세스 요소
echo $사람["이름"]; // 출력: 샤오밍
echo $scores["영어"]; // 출력: 85
배열의 값은 차례로 또 다른 배열입니다. 이는 일반적으로 테이블 형식 또는 계층적 데이터를 저장하는 데 사용됩니다.
$학생 = [
[
"이름" => "앨리스",
"점수" => ["수학" => 95, "과학" => 88]
],
[
"이름" => "밥",
"점수" => ["수학" => 78, "과학" => 92]
]
];
//요소에 액세스(Bob의 과학 점수에 액세스)
echo $students[1]["점수"]["과학"]; // 출력: 92
PHP는 배열 작업을 위한 수백 가지 내장 함수를 제공합니다. 가장 일반적으로 사용되는 것들은 다음과 같습니다:
count($array): 배열의 요소 수를 계산합니다.print_r($array): 배열의 구조와 값을 사람이 읽을 수 있는 형식으로 표시합니다(보통 디버깅에 사용됨).array_push($array, $value1, ...): 하나 이상의 요소를 배열 끝에 푸시(추가)합니다.array_pop($array): 배열의 마지막 요소를 팝(제거 및 반환)합니다.array_keys($array): 배열의 모든 키 이름으로 구성된 새 배열을 반환합니다.array_values($array): 배열의 모든 값으로 구성된 새 배열을 반환합니다.in_array($needle, $haystack): 배열에 특정 값이 존재하는지 확인합니다.array_key_exists($key, $array): 배열에 특정 키가 존재하는지 확인합니다.일반적으로 사용되는foreach배열의 모든 요소를 반복합니다.
$staff = ["매니저" => "장산", "엔지니어" => "리시", "디자이너" => "왕우"];
// 연관 배열을 탐색합니다(키와 값 가져오기).
foreach ($title => $name인 $staff) {
$제목을 에코합니다. ": " . $이름 . "<br>";
}
// 인덱스 배열을 순회합니다(값만 가져옴).
$items = ["A", "B", "C"];
foreach ($item을 $item으로) {
$item 을 에코합니다. "<br>";
}
strcasecmp()대소문자를 구분하지 않는 문자열 비교를 수행합니다.
반환된 값이 0이면 두 문자열이 동일하다는 의미입니다.<?php
$str1 = "안녕하세요";
$str2 = "안녕하세요";
if (strcasecmp($str1, $str2) === 0) {
echo "문자열은 동일합니다(대소문자 무시)";
} 그렇지 않으면 {
echo "문자열이 동일하지 않습니다.";
}
?>
str_ireplace()。
<?php
$text = "안녕하세요.";
$result = str_ireplace("안녕하세요", "안녕하세요", $text);
에코 $결과; // "Hi World" 출력
?>
i대소문자를 무시합니다.<?php
if (preg_match("/hello/i", "HeLLo PHP")) {
echo "비교 성공";
}
?>
PHP에서 파일 경로 문자열을 처리할 때 손으로 쓴 문자열 슬라이싱(예:explode), 운영 체제가 다르기 때문에(Windows에서는\, 리눅스용/)은 다르게 처리됩니다. PHP에는 경로를 안전하게 분해하기 위한 몇 가지 강력한 기능이 내장되어 있습니다.
제가 가장 추천하는 기능입니다. 경로를 디렉터리 이름, 전체 파일 이름, 파일 확장자 및 확장자가 없는 파일 이름으로 분해할 수 있습니다.
$path = "/var/www/html/assets/img/logo.png"; $info = 경로정보($path); echo $info['디렉토리 이름']; // /var/www/html/assets/img echo $info['베이스이름']; // 로고.png echo $info['확장자']; // png echo $info['파일명']; // 로고(PHP 5.2+ 지원)
$path = "C:\projects\web\index.php"; echo 베이스이름($path); // index.php echo 기본 이름($path, ".php"); // 인덱스(지정된 파일 확장자 제거) echo 디렉토리명($path); // C:\프로젝트\웹
모든 상대 경로 기호(예:../또는./), 운영 체제의 실제 절대 경로를 반환합니다. 파일이 존재하지 않으면 반환됩니다.false。
echo realpath("../../config.php");
//다음과 유사한 출력: /var/www/config.php
---
Windows 개발 및 Linux 배포 중에 오류가 발생하지 않도록 하려면 백슬래시를 슬래시로 균일하게 변환하는 것이 좋습니다.
$path = "C:\사용자\관리\Desktop\test.txt";
$safe_path = str_replace('\\', '/', $path);
// 결과: C:/User/Admin/Desktop/test.txt
수동 접합$dir . '/' . $file나타나기 쉬운//이중 슬래시 오류입니다. 사용될 수 있다DIRECTORY_SEPARATOR(시스템 구분 기호) 또는rtrim:
$dir = "/var/www/html/"; $파일 = "index.php"; //범용 접합 방법 $full_path = rtrim($dir, '/\\') . DIRECTORY_SYSTEM_SEPARATOR . $파일;
$allowed = ['jpg', 'png', 'gif'];
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (in_array($ext, $allowed)) {
echo "올바른 형식입니다";
}
---
| 기능 | 입력 예:/data/web/test.php |
결과 반환 |
|---|---|---|
| pathinfo() | pathinfo($p) |
모든 정보를 포함하는 연관 배열(Array)을 반환합니다. |
| basename() | basename($p) |
test.php(순수한 파일 이름) |
| dirname() | dirname($p) |
/data/web(목차) |
| realpath() | realpath("./test.php") |
/absolute/path/to/test.php(실제 경로) |
경로 문자열에서 정확한 최상위 디렉터리 이름을 얻으려면(예:var), 가장 강력한 방법은 먼저 경로를 변환하는 것입니다.표준화, 그런 다음 사용explode()문자열을 분해합니다. 경로는 일반적으로 슬래시로 시작하므로 디스어셈블된 배열의 첫 번째 요소가 비어 있는 경우가 많으므로 특별한 처리가 필요합니다.
이것은 가장 일반적인 방법입니다.ltrim()분할하기 전에 선행 슬래시를 제거하고 배열의 첫 번째 위치가 원하는 이름인지 확인하십시오.
$path = "/var/www/html/assets/img/logo.png";
// 1.explod에 의해 생성된 빈 첫 번째 요소를 피하기 위해 가장 왼쪽 슬래시를 먼저 제거합니다.
// 2. 슬래시에 따라 배열로 분할
$parts =explod('/', ltrim($path, '/'));
// 3. 배열의 첫 번째 요소를 가져옵니다.
$rootDir = $parts[0];
에코 $rootDir; // 출력: var
경로가 Windows 또는 Linux에서 제공되는 경우 먼저 슬래시 형식을 통합하고 중복 슬래시를 필터링하는 것이 좋습니다.
$path = "/var/www/html/assets/img/logo.png";
//슬래시를 균일하게 변환하고 빈 요소를 필터링합니다.
$parts = array_values(array_filter(explode('/', $path)));
$rootDir = $parts[0] ?? '';
에코 $rootDir; // 출력: var
"특정 문자열"을 처리하고 싶지 않지만 웹 서버의 루트 폴더 이름을 알고 싶다면 다음을 사용할 수 있습니다.$_SERVER:
// DOCUMENT_ROOT가 /var/www/html이라고 가정합니다.
$rootParts = 폭발('/', ltrim($_SERVER['DOCUMENT_ROOT'], '/'));
에코 $rootParts[0]; // 출력: var
---
| 목표 | 해당 코드 | 결과의 예 |
|---|---|---|
| 최상위 디렉토리 | explode('/', ltrim($path, '/'))[0] |
var |
| 이전 디렉토리 | basename(dirname($path)) |
img |
| 전체 디렉터리 경로 | dirname($path) |
/var/www/html/assets/img |
경로 작업 시 경로 시작 부분에 슬래시가 있는지 주의하세요."/var"분할 후에는["", "var"],그리고"var"분할 후에는["var"]. 사용ltrim($path, '/')이렇게 하면 시작 부분에 슬래시가 있는지 여부에 관계없이 결과가 일관되게 유지됩니다.
| 우선 사항 | 설명하다 |
|---|---|
| 1. | 지정된 절대 경로 또는 상대 경로: 파일 경로를 직접 지정하면 PHP는 먼저 이 경로에서 파일을 검색합니다. |
| 2 | 실행 파일의 현재 디렉터리: 전체 경로가 지정되지 않은 경우 PHP는 먼저 실행 파일이 있는 디렉터리에서 파일을 찾습니다. |
| 3 | include_path 설정: 실행 디렉터리에서 파일을 찾을 수 없으면 PHP는 확인합니다.php.ini설정하다include_path길. |
| 4 | 파일이 존재하지 않습니다: 위 경로 중 어느 곳에서도 파일을 찾을 수 없으면 경고가 생성됩니다(Warning) 및 반환false。 |
통과할 수 있다$_SERVER['PHP_SELF']현재 실행의 파일 경로를 가져온 다음 사용하십시오.basename파일 이름 가져오기:
<?php
$current_page = 기본 이름($_SERVER['PHP_SELF']);
echo "현재 페이지 이름:" . $현재_페이지;
?>
~을 통해$_SERVER['REQUEST_URI']전체 URL 경로를 얻은 다음 사용하십시오.parse_url그리고basename구문 분석 파일 이름:
<?php
$url_path = pars_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$current_page = 기본 이름($url_path);
echo "현재 페이지 이름:" . $현재_페이지;
?>
URL에 쿼리 매개변수가 포함된 경우 별도로 처리할 수 있습니다.
<?php
$url_path = pars_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
$query_string = pars_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
$current_page = 기본 이름($url_path);
echo "파일 이름:" . $현재_페이지 . "<br>";
echo "쿼리 매개변수:" .$query_string;
?>
현재 URL은 다음과 같다고 가정합니다.https://example.com/page.php?id=123:
현재 페이지 이름: page.php
파일명 : page.php
쿼리 매개변수: ID=123
PHP에서는 언제main.php사용include소개하다subpage.php이때 실제로는 두 파일이 "병합되어 실행"됩니다. "기본 프로그램 경로"와 "도입된 파일 경로"를 각각 얻으려면 서로 다른 슈퍼 전역 변수와 상수를 사용해야 합니다.
파일을 가져온 사람이 누구인지에 관계없이 마법 상수를 사용하십시오.__FILE__항상 "이 코드가 있는 파일"의 경로를 가리킵니다.
//subpage.php에 작성 $thisFilePath = __FILE__; echo "현재 파일 경로: " . $thisFilePath; //다음과 유사한 출력: /var/www/html/fullpath/subpage.php
당신이 있을 때subpage.php원래 진입점이 누구인지 알아내려면 다음과 같은 몇 가지 방법이 있습니다.
$_SERVER['SCRIPT_FILENAME'](가장 정확함)$mainPath = $_SERVER['SCRIPT_FILENAME'];
get_included_files()(고급 추적)0초기 입력 파일입니다.$allFiles = get_included_files(); $mainPath = $allFiles[0];
다음 코드를subpage.php중간 테스트:
<?php
// 1. 소개된 파일 자체의 경로
$sub_page_path = str_replace('\\', '/', __FILE__);
// 2. 메인 실행 파일의 경로
$main_page_path = str_replace('\\', '/', $_SERVER['SCRIPT_FILENAME']);
echo "하위 페이지 경로: " . $sub_page_path . "<br>";
echo "메인 페이지 경로: " . $main_page_path . "<br>";
?>
팁: str_replace('\\', '/', ...)Windows(백슬래시)와 Linux(슬래시)의 경로 형식을 통일하는 것인데, 이는 크로스 플랫폼 개발에 매우 실용적입니다.
---
서버 하드 드라이브 경로(전체 경로)가 아니라 브라우저의 URL 경로를 참조하는 경우 다음을 사용해야 합니다.
| 목표 | 문법 | 설명하다 |
|---|---|---|
| URL 경로 | $_SERVER['REQUEST_URI'] |
다음과 같이 받기/project/main.php?id=1URL 조각. |
| 스크립트 가상 경로 | $_SERVER['PHP_SELF'] |
웹페이지에서 기본 프로그램의 경로를 가져옵니다(매개변수 없이). |
글쓰기$mainTableView__whereclause, 다른 기본 페이지를 기반으로 SQL 조건을 전환해야 하는 경우 다음과 같이 작성할 수 있습니다.
if (basename($_SERVER['SCRIPT_FILENAME']) == 'main.php') {
// main.php에서 진입할 때만 실행되는 로직
}
include본질PHP에서는include또는require, 당신은 그것을 다음과 같이 생각할 수 있습니다파일로 가져온 코드를 현재 파일에 직접 "복사하여 붙여넣기". 따라서 둘 다 동일한 실행 환경(범위)을 공유합니다.
global?그것은 당신에게 달렸습니다호출 변수의 위치:
main.php변수를 정의하고 변수에 넣습니다.library.php가장 바깥쪽 레이어에서는 별도의 선언 없이 바로 사용합니다.// 메인.php $var1 = "사과"; 'library.php'를 포함; // 라이브러리.php 에코 $var1; // 출력: 애플
library.php내부에기능액세스하려면 선언해야 합니다.
// library.php
function printVar() {
global $var1;
echo $var1;
}
include_once매개변수 전달에 대한 오해특별한 주의:PHPinclude_once 지원되지 않음두 번째 인수(배열과 같은)를 전달합니다. 유일한 매개변수는 파일 경로 문자열입니다.
| 잘못된 사용법 (❌) | 올바른 사용법 (✅) |
|---|---|
include_once('lib.php', ['v1' => $v1]); |
$v1 = "Data"; include_once 'lib.php'; |
| 매개변수 개수가 일치하지 않아 PHP에서 오류를 보고합니다. | 변수는 가져온 파일로 자동으로 전달됩니다. |
변수 명명 충돌(네임스페이스 오염)을 방지하려면 "전역 변수에 직접 의존하는" 작성 방법을 버리고 대신 다음 두 가지 방법을 사용하는 것이 좋습니다.
할 것이다library.php순수한 도구 상자로서 함수만 작성되고 변수는 매개변수를 통해 전달됩니다.
// 라이브러리.php
<?php
함수 processStock($name) {
"재고 처리 중: "을 반환합니다. $이름;
}
?>
// 메인.php
<?php
include_once 'library.php';
echo processStock("TSLA"); // 변수를 명시적으로 전달합니다.
?>
이는 현대 PHP 개발(예: Laravel 개념)에서 더 일반적이며 코드를 효과적으로 구성할 수 있습니다.
// library.php
class StockTool {
public static function handle($var) {
return "Result: " . $var;
}
}
// main.php
include_once 'library.php';
echo StockTool::handle($var1);
1. 원하지 않는다존재하다include명령문에 매개변수를 전달하는 것이 잘못되었습니다.
2. 피하려고 노력하세요global, 사용함수 매개변수통과하면 코드를 더 쉽게 디버그하고 유지 관리할 수 있습니다.
PHP에는 변수가 설정(정의)되었는지 확인하는 세 가지 주요 핵심 함수가 있습니다.isset()、empty()그리고array_key_exists(). 작동 논리는 약간 다르며 잘못된 것을 선택하면 논리 구멍이 발생할 수 있습니다.
변수를 결정하는 데 사용됨선언됐나요그리고그 가치는NULL。
$var = "쌍둥이자리";
if (isset($var)) {
echo "변수가 설정되었으며 NULL이 아닙니다.";
}
$var = null;,isset($var)다시 보내드립니다false。변수인지 여부를 결정하는 데 사용됩니다.존재하지 않는다또는 그 값은 다음과 같습니다.false. 그것은 동등하다!isset($var) || $var == false。
다음 값은empty()로 간주true:
""(빈 문자열)0(정수 0)0.0(부동 소수점 숫자 0)"0"(문자열 0)nullfalse[](빈 배열)| 문법 | 대상 확인 | 장면에 적합 |
|---|---|---|
isset($var) |
변수가 존재하고 NULL이 아닌지 여부 | 옵션 필드를 확인하여 변수가 정의되었는지 확인하세요. |
empty($var) |
변수에 내용이 있나요? | 양식 유효성 검사(메시지가 비어 있지 않고 수량이 0이 아닌지 확인) |
is_null($var) |
변수가 정확히 NULL인지 여부 | 변수가 의도적으로 null로 설정되었는지 확인해야 하는 경우. |
당신이에 있다면main.php변수 전달library.php, 다음을 수행하는 것이 좋습니다.library.php내부 오류 방지 검사를 수행합니다.
// 라이브러리.php
if (isset($var1)) {
echo "수신된 변수는 다음과 같습니다:" . $var1;
} 그렇지 않으면 {
echo "경고: 변수 var1이 아직 정의되지 않았습니다.";
}
이것이 더 간결하게 작성하는 방법입니다. 변수가 설정되지 않은 경우 기본값이 제공됩니다.
// $var1이 설정되지 않은 경우 $data는 '기본값'과 같습니다. $data = $var1 ?? '기본값';
프런트 엔드에서 값을 전달하는 경우 확인 방법은 다음과 같습니다.
if (isset($_GET['var1'])) {
$v1 = $_GET['var1'];
}
팁:개발 단계에서 추가하는 것이 좋습니다.error_reporting(E_ALL);, 정의되지 않은 변수에 접근하면 PHP가 직접 변수를 내뱉게 됩니다.Notice: Undefined variable명심하세요.
debug_backtrace()현재 실행 스택(호출 경로)을 얻기 위해 PHP에서 사용하는 함수입니다. 통화 소스를 디버깅하고 녹음하는 데 자주 사용됩니다.
$trace = debug_backtrace();
print_r($trace);
debug_backtrace()호출 순서대로 정렬된 배열이 반환됩니다.
file:파일 경로line:프로그램 줄 번호function:함수 이름은class: 카테고리 이름(있는 경우)args: 매개변수 전달함수 showCaller() {
$trace = debug_backtrace();
echo '보낸 사람: ' . $trace[1]['파일'] . ' 아니요. ' . $trace[1]['라인'] . ' 선';
}
'subpageA.php'를 포함합니다; // subpageA.php 내에서 showCaller()를 호출합니다.
main.php include subA.phpsubA.php include subB.phpsubB.php사용:$trace = debug_backtrace();
echo '현재 파일:' . $trace[0]['파일'] . "\N";
echo '이전 레벨:' . $trace[1]['파일'] . "\N"; // subA.php
echo '홈페이지:' . $trace[2]['파일'] . "\N"; // 메인.php
debug_backtrace()포함/함수 호출의 소스를 보는 가장 실용적인 방법입니다.error_log()오류나 사용자 정의 메시지를 기록하기 위해 PHP에서 사용하는 함수입니다.
화면 출력에 영향을 주지 않고 디버깅, 프로그램 흐름 추적 및 예외 기록에 자주 사용됩니다.<?php
error_log("테스트 메시지입니다.");
?>
<?php
$data = ["a" => 1, "b" => 2];
error_log(print_r($data, true));
?>
<?php
error_log("사용자 정의 파일 쓰기", 3, "D:/logs/php_debug.log");
?>
<?php
error_log("[INFO] 프로그램이 실행을 시작합니다.");
error_log("[WARN] 매개변수가 비어 있습니다.");
error_log("[ERROR] 데이터베이스 연결 실패");
?>
php.ini제어:log_errors = On
error_log = "D:/logs/php_errors.log"
설정되지 않은 경우error_log, 기본값은 다음과 같습니다.<?php
{를 시도해보세요
throw new Exception("예외가 발생했습니다.");
} 잡기(예외 $e) {
error_log($e->getMessage());
}
?>
display_errors, 그냥 사용하세요error_logPHP에서 error_log()를 사용하여 중국어 문자가 포함된 문자열을 기록하면 로그 파일이 \xe6\xb2\x92 형식과 같은 16진수 인코딩으로 표시되는 경우가 많습니다. 이는 일반적으로 프로그래밍 오류가 아니지만 서버(Apache/Nginx)가 보안이나 호환성 이유로 비ASCII 문자를 이스케이프하도록 강제한 결과입니다.
이것이 가장 간단하고 효과적인 방법입니다. 파일을 직접 조작함으로써 error_log()에 대한 서버의 필터링 메커니즘을 우회할 수 있습니다.
함수 write_utf8_log($message) { $log_file = DIR . '/debug.log'; $timestamp = date('연월일 H:i:s'); // 원시 바이트를 쓰려면 FILE_APPEND 모드를 사용하세요. file_put_contents($log_file, "[$timestamp] $message" . PHP_EOL, FILE_APPEND | LOCK_EX); }
// 호출 예 $title = $_GET["title"]; write_utf8_log("제목 내용: " . $title);
error_log()의 경로 설정을 유지하려면 JSON_UNESCAPED_UNICODE 매개변수와 함께 json_encode를 사용할 수 있습니다. 이렇게 하면 PHP가 UTF-8 형식으로 출력하게 되지만 일부 서버 환경에서는 여전히 두 번 이스케이프될 수 있습니다.
$title = $_GET["title"]; error_log('title: ' . json_encode($title, JSON_UNESCAPED_UNICODE));
Apache 2.4+를 사용하는 경우 ErrorLogFormat을 수정하여 로그 출력의 이스케이프 동작을 조정할 수 있습니다.
1. Apache 구성 파일(예: httpd.conf)에서 형식을 정의합니다.
ErrorLogFormat "[%t] [%l] [pid %P] %F: %E: [client %a] %M"
2. 운영 체제 언어가 UTF-8을 지원하는지 확인하십시오. Ubuntu에서 /etc/apache2/envvars를 수정합니다.
export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8
로그가 생성되었고 서버 설정을 변경할 수 없는 경우 다음 방법을 사용하여 중국어 원본을 볼 수 있습니다.
| 방법 | 이점 | 결점 |
|---|---|---|
| 사용자 정의 로그(file_put_contents) | 100% 중국어로 표시되며 권한이 필요하지 않습니다. | 파일 크기 및 권한을 수동으로 관리해야 함 |
| JSON_UNESCAPED_UNICODE | 최소한의 코드 변경 | 여전히 서버 전역 구성의 영향을 받음 |
| Apache 구성 수정 | 모든 시스템 로그 문제를 근본 원인부터 해결 | 관리자 권한이 필요합니다. 서비스를 다시 시작하세요. |
parse_url()기능 배열PHP_URL_QUERY전체 URL에서 쿼리 문자열 부분을 검색하는 상수입니다. 예를 들어:$url = "https://example.com/page.php?name=John&age=30&lang=php";
$query = pars_url($url, PHP_URL_QUERY); // 결과는 "name=John&age=30&lang=php"입니다.
parse_str()이 함수는 쿼리 문자열을 연관 배열로 구문 분석합니다. 여기서 각 이름과 값 세트는 자동으로 디코딩되어 배열 요소로 변환됩니다.parse_str($query, $params);
이 시간에$params내용은 다음과 같습니다:[
"name" => "John",
"age" => "30",
"lang" => "php"
]
<?php
$url = "https://example.com/page.php?name=John&age=30&lang=php";
$query = parse_url($url, PHP_URL_QUERY);
parse_str($query, $params);
foreach ($params as $key => $value) {
echo "$key = $value\n";
}
?>
name = John
age = 30
lang = php
parse_url()쿼리 부분만 검색되고 콘텐츠는 구문 분석되지 않습니다.parse_str()URL 인코딩을 처리할 수 있습니다.%20공백으로 변환됩니다.tags[]=php&tags[]=html배열로 변환됩니다.JavaScript 사용하기<h1>내용을 작성한 다음 PHP로 보냅니다.
<!DOCTYPE html>
<html lang="zh-Hant">
<머리>
<meta charset="UTF-8">
<title>H1 콘텐츠 가져오기</title>
<스크립트>
함수 sendH1Content() {
var h1Content = document.querySelector('h1').innerText;
var xhr = 새로운 XMLHttpRequest();
xhr.open('POST', 'process.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('h1Content=' + encodeURIComponent(h1Content));
}
window.onload = sendH1Content;
</스크립트>
</머리>
<본문>
<h1>페이지 제목입니다</h1>
</body>
</html>
존재하다process.php다음에서 H1 콘텐츠를 수신하고 처리합니다.
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$h1Content = $_POST['h1Content'] ?? '';
// $h1Content를 데이터베이스에 저장하거나 다른 작업을 수행하는 등 처리합니다.
echo "수신된 H1 콘텐츠: " . htmlspecialchars($h1Content);
}
?>
HTML 파일이 정적 파일인 경우 PHP를 사용하여 파일을 읽고 구문 분석할 수 있습니다.
<?php
$htmlContent = file_get_contents('path/to/your/file.html');
preg_match('/<h1>(.*?)<\/h1>/', $htmlContent, $matches);
$h1Content = $matches[1] ?? '';
// $h1Content 처리
echo "H1 내용: " . htmlspecialchars($h1Content);
?>
가장 일반적인 방법은 JavaScript를 사용하여 클라이언트 측에서 콘텐츠를 가져온 다음 AJAX를 통해 처리하기 위해 PHP로 보내는 것입니다. 서버측 구문 분석은 일반적으로 정적 콘텐츠에 사용되며 동적으로 생성된 페이지에는 권장되지 않습니다.
abc.php여러개가 인쇄되었습니다<h2>, 그런 다음 포함subpage.php인 경우 출력 HTML에서 콘텐츠를 캡처할 수 없습니다.
올바른 방법은 ─ **마지막 <h2> 포함하기 전에 abc.php에서 subpage.php**(변수)로 변환하고 subpage.php에서 사용합니다.<!-- abc.php -->
<h2>AAA</h2>
<h2>BBB</h2>
<h2>lasth2</h2>
<?php
$last_h2 = "lasth2";
include "subpage.php";
?>
<!-- subpage.php -->
<?php
echo "홈페이지의 마지막 H2는 다음과 같습니다. " . $last_h2;
?>
<!-- abc.php -->
<?php
ob_start(); // 버퍼링 시작
?>
<h2>AAA</h2>
BBB
last2
<?php
$html = ob_get_clean(); // 모든 출력을 얻고 버퍼를 지웁니다.
preg_match_all('/(.*?)<\\/h2>/i', $html, $matches);
$last_h2 = end($matches[1]); //마지막 h2의 내용
"subpage.php"를 포함합니다;
//마지막으로 원본 HTML을 인쇄합니다.
에코 $html;
?>
<!-- abc.php -->
<?php
$h2_list = ["AAA", "BBB", "lasth2"];
?>
<h2>AAA</h2>
<h2>BBB</h2>
<h2>lasth2</h2>
<?php
$last_h2 = end($h2_list);
include "subpage.php";
?>
ob_start()+ 정규식 구문 분석urlencode()함수는 문자열을 URL 인코딩(퍼센트 인코딩)하는 데 사용됩니다. 데이터를 URL 매개변수로 전달할 때 모든 특수 문자가 올바르게 전송되고 구문 분석되는지 확인하는 데 필요한 단계입니다.
string urlencode(string $string): string이 함수는 주어진 문자열을 URL 안전 형식으로 변환합니다. 빼기 기호(-), 결론(_), 기간 (.) 및 물결표(~) 밖의.
대체된 특수 문자는 퍼센트 기호(%) 뒤에 문자의 ASCII 값을 나타내는 두 자리 16진수 표현(예: 공백 $\rightarrow$)이 옵니다.%20)。
?、&、=、/)에는 특별한 의미가 있습니다. 이러한 문자가 매개변수에 포함되면 브라우저나 서버가 URL의 구조를 오해할 수 있습니다.urlencode()이러한 문자는 UTF-8 형식으로 인코딩됩니다.urlencode()공백을 더하기 기호로 변환합니다(+) 또는%20(하지만urlencode()생산되는 것은+, 그러나 URL 매개변수에서는 두 표현 모두 공백을 나타냅니다.$data = "PHP 어레이 $100 및 50% 할인"; $encoded_data = urlencode($data); echo "<h3>특수문자 및 중국어 예시</h3>"; echo "<p>원래 문자열: " . htmlspecialchars($data) . "</p>"; echo "<p>인코딩 결과: " . htmlspecialchars($encoded_data) . "</p>"; // 출력 결과는 유사합니다: PHP+array 및 +%24100+%26+50%25+offer // (중국어 '배열'은 %E9%99%A3%E5%88%97 등으로 인코딩됩니다.)
쿼리 문자열을 변경해야 한다고 가정해 보겠습니다.q_strAPI URL에 안전하게 추가됩니다.
$api_base = "http://api.example.com/search"; $search_query = "모바일 사진 촬영 팁(2025)"; // 쿼리 문자열 보안을 보장합니다. $encoded_query = urlencode($search_query); //최종 URL 구성 $final_url = $api_base . "?q_str=" . $encoded_query; echo "<h3>구성 URL 예</h3>"; echo "<p>쿼리 문자열: " . htmlspecialchars($search_query) . "</p>"; echo "<p>최종 URL: " . htmlspecialchars($final_url) . "</p>"; // 최종 URL은 유사합니다: http://api.example.com/search?q_str=%E6%89%8B%E6%A9%9F%E6%94%9D%E5%BD%B1%E6%8A%80%E5%B7%A7+%282025+%E5%B9%B4%29
PHP에는 또 다른 유사한 기능이 있습니다rawurlencode(), 이들 사이의 주요 차이점은 공백 처리입니다.
urlencode(): 공백을 더하기 기호로 변환합니다(+). 이는 일반적으로 **GET 매개변수**의 값을 인코딩하는 데 사용됩니다(예:?key=value~에value부분).rawurlencode(): 공백을 다음으로 변환합니다.%20. 이는 다음과 일치합니다.RFC 3986보다 제한적인 정의는 일반적으로 URL의 **경로 세그먼트**(경로 세그먼트)를 인코딩하는 데 사용되거나 정확한 정보가 필요할 때 사용됩니다.%20오히려+시간.$space_test = "테스트입니다"; echo "<h3>urlencode() 대 rawurlencode()</h3>"; echo "<p>urlencode(): " . urlencode($space_test) . "</p>"; // 출력: This+is+a+test echo "<p>rawurlencode(): " . rawurlencode($space_test) . "</p>"; // 출력: This%20is%20a%20test
ob_start(): 출력 버퍼링을 활성화합니다.ob_get_contents(): 현재 버퍼링된 콘텐츠를 가져옵니다.ob_end_clean(): 버퍼링을 종료하고 출력 없이 클리어합니다.ob_end_flush(): 버퍼링을 종료하고 내용을 출력합니다.ob_get_clean(): 콘텐츠를 가져오고 버퍼링을 종료합니다.<?php
ob_start(); // 출력 버퍼링 시작
echo "안녕하세요!";
$content = ob_get_clean(); // 버퍼 내용을 가져오고 지웁니다.
echo strtoupper($content); // 수정된 내용 출력: HELLO WORLD!
?>
<?php
ob_start();
Register_shutdown_function(함수 () {
$html = ob_get_clean();
echo "<div class='컨테이너'>" . $html . "</div>";
});
?>
<h1>콘텐츠 제목</h1>
<p>내용 단락입니다. </p>
<h2>제목과 그 아래 블록을 입력하고 오른쪽에 해당 이미지를 추가합니다. 이미지 파일의 이름은 순서대로 지정됩니다.h2-1.jpg、h2-2.jpg...등등은 미리 지정된 이미지 파일 폴더에 넣어두어야 합니다.h2-image-right.php):
<?php
ob_start();
function add_images_next_to_h2($html) {
$pattern = '/(<h2.*?>.*?<\/h2>)(.*?)(?=<h2|\z)/is';
$index = 1;
return preg_replace_callback($pattern, function($matches) use (&$index) {
$h2 = $matches[1];
$body = $matches[2];
$imgPath = "/images/h2-$index.jpg";
$imgFile = $_SERVER['DOCUMENT_ROOT'] . $imgPath;
if (file_exists($imgFile)) {
$output = "<div style='display: flex; align-items: flex-start; gap: 20px; margin-bottom: 1.5em;'>";
$output .= "<div style='flex: 1;'>" . $h2 . $body . "</div>";
$output .= "<img src='$imgPath' style='max-width: 200px; height: auto; border: 1px solid #ccc;'>";
$output .= "</div>";
} else {
$output = $h2 . $body;
}
$index++;
return $output;
}, $html);
}
register_shutdown_function(function() {
$html = ob_get_clean();
echo add_images_next_to_h2($html);
});
?>
/images/폴더 예:/images/h2-1.jpg/images/h2-2.jpg/images/h2-3.jpg<?php include "h2-image-right.php"; ?>
<h2>첫 번째 단락 제목</h2>
<p>첫 문단의 내용입니다. </p>
<h2>두 번째 문단 제목</h2>
<p>두 번째 문단의 내용입니다. </p>
<h2>나타나는 순서에 따라 이름을 지정하세요.<h2> ~ 아래 내용순수 콘텐츠 페이지에 적합한 플렉스 블록입니다.ob_start()。서버 로그를 확인하는 것은 검색 엔진 봇을 식별하는 중요한 방법입니다. 다음은 검색 엔진 로봇을 위한 User-Agent의 몇 가지 예입니다.
Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)
Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)웹사이트를 확인하세요robots.txt웹사이트의 특정 부분에 대한 액세스가 허용되거나 차단되는 검색 엔진 로봇을 알 수 있는 파일입니다. 예를 들어:
User-agent: *
Disallow: /private/
검색 엔진 봇은 일반적으로 특정 범위의 IP 주소를 가지고 있습니다. 방문자의 IP 주소가 이 범위에 속하는지 비교할 수 있습니다. 예를 들어:
방문자의 IP가 실제로 검색 엔진에서 나온 것인지 여부를 확인하는 데 도구를 사용할 수 있습니다.
다음은 서버 측에서 PHP를 사용하여 사용자 에이전트 검사를 수행하는 방법의 예입니다.
<?php
$userAgent = $_SERVER['HTTP_USER_AGENT'];
if (strpos($userAgent, 'Googlebot') !== false) {
echo "Googlebot 트래픽입니다.";
} 그렇지 않으면 {
echo "검색엔진 로봇 트래픽이 아닙니다.";
}
?>
Google Analytics 또는 기타 웹사이트 분석 도구를 사용하여 트래픽 소스를 추적하세요. 이러한 도구는 일반적으로 대부분의 봇 트래픽을 자동으로 필터링합니다.
URL의 해시 값은 URL의 "#" 기호 뒤의 부분을 나타내며 조각 식별자(Fragment Identifier)라고도 합니다. 일반적으로 페이지 내의 위치나 상태를 식별하는 데 사용됩니다.
다음은 몇 가지 일반적인 URL 해시 예입니다.
https://example.com/page#section1https://example.com/app#/dashboardhttps://example.com/search#filter=activeid。<스크립트>
// URL의 해시 값을 가져옵니다.
const hashValue = window.location.hash.substring(1);
//해시 값 표시
console.log("해시 값:", hashValue);
</스크립트>
<?php
//모의 URL
$url = "http://example.com/page#section2";
// hash 값을 분석하기 위해 hash_url을 사용합니다.
$parsedUrl = pars_url($url);
$hash = isset($parsedUrl['fragment']) ? $parsedUrl['fragment'] : null;
// 해시값 출력
if ($hash) {
echo "해시 값은: " . htmlspecialchars($hash, ENT_QUOTES, 'UTF-8');
} 그렇지 않으면 {
echo "URL에 해시 부분이 없습니다.";
}
?>
window.location.hash。name재산덜 일반적으로 사용되지만name속성 추가<a>태그를 지정하고 대상 태그 앞에 배치하세요.
<a name="특정-제목1"></a> <h3>타겟 타이틀 1</h3> <a href="#special-heading1">특정 제목에 대한 링크</a>
효과:
data-attribute자바스크립트 사용다음과 같은 사용자 정의 속성을 설정하여data-anchor, JavaScript를 사용하여 점프 동작을 처리합니다.
<h3 data-anchor="heading-1">타겟 제목 3</h3>
<a href="#" onclick="jumpToHeading('heading-1')">특정 제목으로 링크</a>
<스크립트>
함수 jumpToHeading(앵커) {
const target = document.querySelector(`[data-anchor="${anchor}"]`);
if (대상) {
target.scrollIntoView({ 동작: '부드럽게' });
}
}
</스크립트>
효과:
h2JavaScript를 사용한 텍스트 콘텐츠검색으로h2대상을 동적으로 대상으로 지정하기 위해 JavaScript를 사용하여 대상으로 지정할 텍스트 콘텐츠입니다.
<h3>타겟 타이틀 5</h3>
<a href="#" onclick="jumpToText('대상 제목')">특정 제목 링크</a>
<스크립트>
함수 jumpToText(텍스트) {
const target = Array.from(document.querySelectorAll('h2')).find(el => el.textContent === text);
if (대상) {
target.scrollIntoView({ 동작: '부드럽게' });
}
}
</스크립트>
효과:
cURL은 PHP에서 HTTP 요청을 보내는 데 사용되는 라이브러리입니다. GET, POST, PUT, DELETE 및 기타 메소드를 지원하며 API 데이터 액세스에 자주 사용됩니다.
curl_init()curl_setopt()curl_exec()curl_close()<?php
$url = "https://api.example.com/data";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
<?php
$url = "https://api.example.com/post";
$data = ['이름' => '테스트', '이메일' => '[email protected]'];
$ch = 컬_init($url);
컬_setopt($ch, CURLOPT_POST, true);
컬_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
컬_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$응답 = 컬_exec($ch);
컬_닫기($ch);
에코 $응답;
?>
<?php
$url = "https://api.example.com/json";
$data = json_encode(['id' => 123]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Content-Length: ' . strlen($data)
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
CURLOPT_URL: 도착 URL 설정CURLOPT_RETURNTRANSFER: 결과를 반환할지 여부(직접 출력하지 않음)CURLOPT_POSTFIELDS:보낸 정보CURLOPT_HTTPHEADER: 사용자 정의 HTTP 헤더<?php
if(curl_errno($ch)) {
에코 '오류:' . 컬_오류($ch);
}
?>
PHP에서는 특정 네트워크 포트(포트)가 수신 대기 중인지 확인합니다. 일반적으로 로컬 또는 원격 서비스가 실행 중이고 연결을 수락하는지 확인합니다. 가장 일반적인 방법은 소켓 관련 기능을 사용하여 TCP 연결을 설정하는 것입니다.
fsockopen()기능은 네트워크 연결이나 Unix 도메인 소켓 연결을 여는 데 사용됩니다. 연결이 성공하면 포트가 수신 중임을 의미합니다. 연결에 실패하면 일반적으로 포트가 열려 있지 않거나 방화벽에 의해 차단되었음을 의미합니다.
/**
* 지정된 IP/호스트 이름의 포트가 수신 대기 중인지 확인
*
* @param string $host 확인할 호스트 이름이나 IP 주소
* @param int $port 확인할 포트 번호
* @param int $timeout 연결 시간 초과 초
* @return bool 연결에 성공하면 true를 반환합니다. 그렇지 않으면 거짓을 반환
*/
함수 is_port_listening(string $host, int $port, int $timeout = 2): bool {
// 소켓 연결을 설정합니다. @ 기호는 연결 오류 메시지를 표시하지 않는 데 사용됩니다.
$connection = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (is_resource($connection)) {
// $connection이 리소스 타입이면 연결이 성공했음을 의미
fclose($연결); //성공 후 즉시 연결을 종료합니다.
사실을 반환;
} 그렇지 않으면 {
// 연결에 실패했습니다. 포트가 열려 있지 않거나 서비스가 실행되고 있지 않을 수 있습니다.
// 선택 사항: 디버깅을 위해 여기에서 $errstr 및 $errno를 인쇄할 수 있습니다.
// echo "연결 실패: $errstr ($errno)<br>";
거짓을 반환;
}
}
// --- 테스트 예 ---
$remote_host = 'www.google.com';
$remote_port = 80; // Google의 HTTP 포트를 확인합니다.
$local_host = '127.0.0.1';
$local_web_port = 80; // 로컬 웹 서버의 포트를 확인합니다.
$비점유_포트 = 65432; // 이 포트가 사용되지 않는다고 가정합니다.
echo "<h3>포트 모니터링 확인 결과</h3>";
// 원격 서비스 확인
if (is_port_listening($remote_host, $remote_port)) {
echo "<p>{$remote_host}:{$remote_port}이(가) 수신 중입니다(연결 성공).</p>";
} 그렇지 않으면 {
echo "<p>{$remote_host}:{$remote_port}가 열려 있지 않거나 연결에 실패했습니다.</p>";
}
// 로컬 웹 서버를 확인합니다(웹 서버가 포트 80에서 실행 중인 경우).
if (is_port_listening($local_host, $local_web_port)) {
echo "<p>{$local_host}:{$local_web_port}가 수신 중입니다(웹 서버 실행 중).</p>";
} 그렇지 않으면 {
echo "<p>{$local_host}:{$local_web_port}이(가) 수신 대기 중이 아닙니다.</p>";
}
// 비어있는 포트가 있는지 확인
if (is_port_listening($local_host, $unowned_port)) {
echo "<p>{$local_host}:{$unowned_port} 님이 듣고 있습니다.</p>";
} 그렇지 않으면 {
echo "<p>{$local_host}:{$unowned_port}이(가) 수신 대기 중이 아닙니다(예상 결과).</p>";
}
낮은 수준의 소켓 작업(예: 설정 옵션, 비차단 모드 등)이 필요한 경우 PHP의 소켓 함수 라이브러리를 사용할 수 있습니다(활성화해야 함).php_sockets확대).
함수 is_port_listening_socket(string $host, int $port): bool {
// TCP/IP 소켓 생성
$socket = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
// echo "socket_create 실패: " . 소켓_strerror(socket_last_error()) . "<br>";
거짓을 반환;
}
//연결을 시도합니다
//socket_connect()는 지정된 호스트와 포트에 연결을 설정하려고 시도합니다.
$result = @socket_connect($socket, $host, $port);
소켓_닫기($소켓);
반환($결과 !== 거짓);
}
$timeout값(예: 2~5초). 이 설정이 없으면 대상 호스트에 연결할 수 없을 때 스크립트가 오랫동안 차단될 수 있습니다.fsockopen()여전히 실패할 것입니다.fsockopen()함수는 일반적으로 PHP 구성 파일에 포함되지 않습니다.allow_url_fopen네트워크 소켓에서 직접 작동하기 때문에 명령이 제한됩니다.$host로 설정127.0.0.1또는localhost。
PHP에서는 웹 API의 결과를 얻고 JSON을 구문 분석하기 위해 일반적으로 다음을 사용합니다.file_get_contents()또는 cURL 라이브러리를 사용하여 HTTP 요청을 보낸 다음 사용json_decode()반환된 JSON 문자열을 구문 분석하는 함수입니다.
간단한 GET 요청의 경우file_get_contents()빠른 방법이다. 그러나 API에 특정 HTTP 헤더나 더 복잡한 요청이 필요한 경우 cURL이 더 적합합니다.
$api_url = 'https://jsonplaceholder.typicode.com/posts/1'; // 샘플 API URL
// API에서 반환된 콘텐츠를 가져옵니다(JSON 형식 문자열).
$json_data = @file_get_contents($api_url);
if ($json_data === FALSE) {
echo "API 데이터를 얻을 수 없거나 API 요청이 실패했습니다.";
} 그렇지 않으면 {
// JSON 문자열을 PHP 배열이나 객체로 구문 분석합니다.
// 두 번째 매개변수는 true로 설정되며 연관 배열로 구문 분석됩니다.
// 객체로 구문 분석하려면 false(기본값)로 설정합니다.
$data = json_decode($json_data, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
echo "JSON 구문 분석 오류:" .json_last_error_msg();
} 그렇지 않으면 {
echo "<h3>API 반환 데이터(연관 배열)</h3>";
//예: 데이터의 특정 필드에 액세스
echo "<p>제목(제목): " . htmlspecialchars($data['title']) . "</p>";
echo "<p>콘텐츠(본문): " . htmlspecialchars($data['body']) . "</p>";
// 검사를 위해 전체 구조를 출력합니다.
echo "전체 데이터 구조(print_r)
";
echo "<사전>";
print_r($data);
echo "</pre>";
}
}
cURL은 요청 방법(POST, PUT, DELETE), 헤더, 시간 초과 설정 등 더 많은 제어 기능을 제공합니다.
$api_url = 'https://jsonplaceholder.typicode.com/posts/2';
//cURL 세션 초기화
$ch = 컬_초기화();
//cURL 옵션 설정
컬_setopt($ch, CURLOPT_URL, $api_url);
컬_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 결과를 직접 출력하는 대신 문자열로 반환합니다.
//cURL 세션을 실행하고 결과를 가져옵니다.
$json_data = 컬_exec($ch);
//오류가 발생했는지 확인
if (curl_errno($ch)) {
echo "cURL 오류:" . 컬_오류($ch);
$데이터 = 널;
} 그렇지 않으면 {
// JSON 구문 분석
$data = json_decode($json_data, true);
if ($data === null && json_last_error() !== JSON_ERROR_NONE) {
echo "JSON 구문 분석 오류:" .json_last_error_msg();
}
}
// cURL 세션을 닫습니다.
컬_닫기($ch);
if ($data !== null) {
echo "API 반환 데이터(cURL 예)
";
echo "<p>제목(제목): " . htmlspecialchars($data['title']) . "</p>";
echo "<p>사용자 ID(userId): " . htmlspecialchars($data['userId']) . "</p>";
}
json_decode($json_string, $associative)true, 연관된 배열을 반환합니다. 만약에false(기본값), 객체가 반환됩니다.PHPexec()기능과shell_exec()、system()마찬가지로 이는 본질적으로 동기식 차단입니다. 즉, PHP 스크립트는 계속하기 전에 외부 명령이 완료될 때까지 기다립니다. 기본 PHP 프로그램을 차단하지 않고 외부 명령을 실행하려면("비동기" 또는 "백그라운드 실행" 구현) 셸 자체의 특성을 활용하여 명령을 구분해야 합니다.
비차단 실행을 달성하는 열쇠는 다음을 통과하는 것입니다.exec()명령 문자열에 특정 셸 구문을 추가합니다.
&:** 명령을 백그라운드 실행으로 푸시하기 위한 핵심 기호입니다.> /dev/null 2>&1:** 이는 PHP가 차단되는 것을 방지하는 열쇠입니다. 표준 출력(STDOUT)과 표준 오류 출력(STDERR)을 모두 빈 장치로 리디렉션합니다./dev/null. 리디렉션 없이 사용하더라도&기호에 따르면, 일부 PHP 버전은 여전히 I/O 스트림이 닫힐 때까지 대기하여 허위 차단이 발생할 수 있습니다.nohup(선택 사항이지만 권장됨): ** Linux/Unix 시스템에서는 다음을 사용합니다.nohup이렇게 하면 HTTP 요청이 종료되거나 사용자가 브라우저를 닫는 등 웹 서버가 종료된 후에도 프로세스가 계속 실행됩니다.이 예제는 HTTP 요청이 완료된 후 실행할 필요가 없는 단기 백그라운드 작업에 적합합니다.
$command_to_run = 'php /path/to/my_long_task.php arg1 arg2'; // 비차단 명령 결합 // 1. 명령 자체 // 2. STDOUT을 /dev/null로 지정 // 3. STDERR(2)를 STDOUT(&1)으로 직접 지정 // 4. & 기호를 사용하여 배경을 푸시합니다. $async_command = $command_to_run . ' > /dev/null 2>&1 &'; $출력 = []; $return_var = 0; //비차단 명령 실행 exec($async_command, $output, $return_var); echo "<h3>비동기 실행 결과(exec)</h3>"; echo "<p>명령이 백그라운드 실행으로 전송되었습니다.</p>"; echo "<p>PHP 스크립트는 즉시 실행을 계속하며 외부 스크립트가 완료될 때까지 기다리지 않습니다.</p>"; echo "<p>exec()에서 반환된 출력 배열(\$output)은 거의 비어 있습니다.</p>";
이 예제에서는nohup백그라운드 작업이 PHP 웹 서버의 상위 프로세스와 완전히 분리되도록 하기 위해 웹 서버가 종료되더라도 작업은 계속 실행됩니다.
$command_to_run = '/usr/bin/python3 /path/to/process_data.py'; $log_file = '/var/log/my_app/task_log.log'; // 특수 로그 파일 // 쉘 주입 공격을 방지하기 위해 명령 매개변수가 올바르게 이스케이프되었는지 확인합니다. $safe_command = escapeshellcmd($command_to_run); // /dev/null 대신 로그 파일에 직접 출력 및 오류 출력 $detached_command = 'nohup' . $safe_command . ' >> ' . escapeshellarg($log_file) . ' 2>&1 &'; exec($detached_command); echo "<h3>프로세스를 분리하려면 nohup을 사용하세요</h3>"; echo "<p>nohup을 사용하여 명령이 시작되었으며 출력이 로그 파일로 전달되었습니다.</p>"; echo "<p>작업은 완료될 때까지 백그라운드에서 계속 실행됩니다.</p>";
외부 명령을 실행할 때 가장 중요한 고려 사항은 보안입니다. **절대** 처리되지 않거나 이스케이프된 사용자 입력을 전달하지 마세요.exec()또는 기타 쉘 실행 가능 기능. PHP는 처리를 지원하는 두 가지 기능을 제공합니다.
escapeshellcmd($command): 악의적인 사용자가 여러 명령을 삽입하는 것을 방지하려면 **전체 명령 문자열**을 이스케이프 처리하세요.escapeshellarg($arg):매개변수가 단일 문자열로 처리되도록 하려면 **단일 매개변수**를 이스케이프 처리하세요.$user_input = "테스트; rm -rf /"; // 잠재적으로 악의적인 입력
// 오류: 안전하지 않은 관행
// exec('my_script.sh' . $user_input);
// 정답: 안전한 접근
$safe_input = escapeshellarg($user_input);
$safe_command = 'my_script.sh' . $safe_input;
//실행 결과: my_script.sh 'test; rm -rf /'(단일 매개변수로 처리됨)
exec()shell_exec()passthru()proc_open()(고급의)<?php
$cmd = "python3 myscript.py 123";
$output = shell_exec($cmd);
echo $output;
?>
<?php
$arg1 = 100;
$arg2 = "hello";
$cmd = "python3 script.py " . escapeshellarg($arg1) . " " . escapeshellarg($arg2);
$result = shell_exec($cmd);
echo $result;
?>
#script.py
importsys
a = sys.argv[1]
b = sys.argv[2]
print(f"입력 매개변수: {a}, {b}")
<?php
exec("python3 test.py", $output_lines, $status);
echo "<pre>";
print_r($output_lines);
echo "</pre>";
?>
<?php
$설명자 = [
0 => ["파이프", "r"],
1 => ["파이프", "w"],
2 => ["파이프", "w"]
];
$process = proc_open("python3 calc.py", $descriptor, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], "50\n");
fclose($파이프[0]);
$output = stream_get_contents($pipes[1]);
fclose($파이프[1]);
$error = stream_get_contents($pipes[2]);
fclose($파이프[2]);
proc_close($프로세스);
echo "출력: $output<br>";
echo "오류: $error<br>";
}
?>
/usr/bin/python3또는C:\\Python39\\python.exeescapeshellarg()명령 주입 방지php -m로드 확인php-gtk개조.<?php
if (!class_exists('gtk')) {
die("PHP-GTK가 설치되지 않았습니다\n");
}
$window = 새로운 GtkWindow();
$window->set_title("PHP-GTK 예");
$window->set_size_request(300, 200);
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$button = new GtkButton("클릭하세요");
$button->connect_simple('클릭됨', function() {
echo "버튼을 클릭했습니다!\n";
});
$창->추가($버튼);
$window->show_all();
Gtk::메인();
?>
Electron(Chromium 및 Node.js 기반) 데스크톱 GUI를 생성하면 백엔드에서 여전히 PHP 프로그램을 호출할 수 있습니다.
이를 통해 HTML/CSS/JavaScript를 사용하여 아름다운 크로스 플랫폼 애플리케이션을 구축하고 API를 통해 PHP와 통신할 수 있습니다.php -S localhost:8000),
그런 다음 브라우저를 사용하여 페이지를 열면 데스크톱 응용 프로그램처럼 보입니다. PWA(Progressive Web App)를 사용하면 바탕화면 아이콘으로 설치할 수도 있습니다.SPA(단일 페이지 애플리케이션)는 서버에서 전체 새 페이지를 로드하는 대신 현재 페이지를 동적으로 다시 작성하여 사용자와 상호 작용하는 웹 애플리케이션 또는 웹 사이트 모델입니다. 이 접근 방식은 페이지 전환 간의 중단을 방지하고 사용자 경험을 데스크톱 애플리케이션에 더 가깝게 만듭니다.
기존 모델에서는 링크를 클릭할 때마다 서버에서 새 HTML 파일이 요청됩니다. SPA에서는 첫 번째 로드 시에만 필요한 HTML, CSS, JavaScript가 다운로드되고 이후 데이터 교환은 AJAX 또는 Fetch API를 통해 완료됩니다.
| 특성 | SPA(단일 페이지 애플리케이션) | MPA(다중 페이지 애플리케이션) |
|---|---|---|
| 페이지 로딩 | 한 번만 로드하고 부분적으로 업데이트됨 | 각 작업마다 전체 페이지를 다시 로드합니다. |
| 사용자 경험 | 매끄럽고 튀는 느낌이 없습니다. | 뻔한 하얀 화면과 기다림의 느낌이 있다 |
| 서버 부하 | 하위(JSON 데이터만 전송) | 높음(HTML은 매번 렌더링되어야 함) |
| SEO 최적화 | 더 어렵고 추가 처리가 필요함 | 쉽고 자연스럽게 검색 엔진 친화적 |
이는 SPA 전환 콘텐츠의 논리를 시뮬레이션하기 위해 기본 JavaScript만 사용하는 프레임워크 독립적입니다.
<!-- index.html -->
<탐색>
<a href="#home" onclick="route()">홈페이지</a>
<a href="#trading" onclick="route()">거래 차트</a>
</nav>
<div id="content">
<!-- 동적 콘텐츠가 여기에 삽입됩니다 --->
</div>
<스크립트>
const 경로 = {
"#home": "<h2>돌아오신 것을 환영합니다</h2><p>이것이 귀하의 대시보드입니다.</p>",
"#trading": "<h2>실시간 시세</h2><div id='tv-container'>차트 로딩...</div>"
};
함수 경로() {
const 해시 = window.location.hash || "#집";
const contentDiv = document.querySelector("#content");
contentDiv.innerHTML = 경로[해시];
// 트레이딩 페이지로 전환하면 여기에서 이전 TradingView 위젯을 초기화할 수 있습니다
if (해시 === "#trading") {
// initTradingView();
}
}
// URL 변경 모니터링
window.addEventListener("hashchange", 경로);
// 초기 로드
경로();
</스크립트>
이점:빠른 속도, 감소된 대역폭 소비, 별도의 프런트엔드 및 백엔드 개발(백엔드는 API만 제공하면 됨)
결점:초기 로딩 시간이 길고(First Load), SEO는 SSR(Server-Side Rendering)이나 프리렌더링 기술을 통해 보완이 필요합니다.
단일 페이지 애플리케이션(SPA)을 개발할 때 적절한 프레임워크 솔루션을 선택하면 개발 효율성과 코드 유지 관리성이 크게 향상될 수 있습니다. 현재 시장은 세 가지 주류 프레임워크가 지배하고 있으며 많은 신흥 프레임워크가 등장하고 있습니다.
Meta(Facebook)에서 개발하고 유지 관리하는 이 라이브러리는 현재 전 세계에서 가장 많이 사용되는 UI 함수 라이브러리입니다. 가상 DOM(Virtual DOM)과 JSX 구문을 도입하여 구성 요소화와 단방향 데이터 흐름을 강조합니다.
You Yuxi가 개발한 이 프로그램은 "진보적인" 프레임워크로 유명합니다. 학습 곡선은 상대적으로 완만하며 공식은 개발 효율성을 추구하는 프로젝트에 매우 적합한 매우 완벽한 도구 체인을 제공합니다.
TypeScript로 작성된 Google에서 유지관리하는 완전한 프레임워크입니다. 라우팅, 양식 검증, HTTP 클라이언트 등 필요한 모든 기능을 포함하는 "Family Bucket" 솔루션을 제공합니다.
위의 세 가지 주요 프레임워크 외에도 최근 몇 년 동안 성능 최적화를 위한 많은 대안이 등장했습니다.
| 프레임 이름 | 특징 |
|---|---|
| Svelte | 가상 DOM이 없으며 프로그램 코드는 컴파일 단계에서 효율적인 기본 JS로 변환됩니다. |
| SolidJS | React 구문과 유사하지만 최고의 실행 성능을 제공합니다. |
| Preact | React의 경량 버전으로 크기가 약 3KB에 불과하고 호환성이 뛰어납니다. |
프레임워크를 선택할 때 일반적으로 다음 벤치마크를 고려하는 것이 좋습니다.
Python 생태계에서 SPA(Single Page Application) 개발 솔루션은 크게 두 가지 범주로 나누어집니다. 하나는 Python을 백엔드 API로 사용하는 것이고, 다른 하나는 개발자가 Python 코드를 작성하기만 하면 SPA 기능이 포함된 프런트엔드 인터페이스를 자동으로 생성할 수 있는 특정 프레임워크를 사용하는 것입니다.
이러한 프레임워크는 개발자가 즉시 대화형 단일 페이지 웹 페이지를 개발하기 위해 HTML/CSS/JS 지식을 요구하지 않기 때문에 가장 널리 사용됩니다.
이러한 유형의 프레임워크는 기존 React/Vue + FastAPI 모델에 도전하고 전체 개발을 더욱 통합하려고 시도합니다.
| 프레임 이름 | 특징 | 기술 아키텍처 |
|---|---|---|
| 반사(이전에는 Pynecone으로 알려짐) | 순수 Python으로 작성되었으며 React 애플리케이션으로 컴파일되었습니다. | Python + Next.js / Tailwind |
| NiceGUI | 하드웨어, 가젯 또는 간단한 웹 페이지를 제어하는 데 적합한 매우 간단한 구문입니다. | Python + Vue / Quasar |
| Flet | 웹 SPA와 데스크톱 애플리케이션으로 동시에 게시할 수 있는 Flutter 기반 Python 프레임워크입니다. | Python + Flutter |
이는 가장 표준적인 상용 소프트웨어 개발 모델이다. Python은 논리와 데이터만 담당하며 프런트 엔드는 전문 JavaScript 프레임워크에 맡겨져 있습니다.
// 아키텍처 다이어그램 백엔드(Python): FastAPI / Django Ninja / Flask 전송 프로토콜: RESTful API 또는 WebSocket 프론트엔드(JavaScript): Vue.js / React / Svelte(SPA 렌더링 담당)
이는 최근 몇 년간 매우 인기 있는 추세입니다. HTMX를 사용하면 전통적인 Python 웹 프레임워크(예: Django 또는 Flask)가 복잡한 JavaScript를 작성하지 않고도 AJAX 부분 페이지 업데이트 효과를 얻을 수 있습니다.
# Django + HTMX 예제(부분 업데이트 버튼)
# 클릭하면 #result 영역만 교체되고 웹페이지는 새로고침되지 않습니다.
<버튼 hx-post="/get-data/" hx-target="#result">
데이터를 얻으려면 나를 클릭하세요
</버튼>
<div id="result">대기 중...</div>
이러한 유형의 솔루션의 핵심 개념은 "HTML로 복귀"입니다. 그들은 SPA의 동적 효과를 달성하기 위해 복잡한 JavaScript 프레임워크를 작성할 필요가 없다고 주장합니다.
WebAssembly를 사용하면 개발자는 C++, Rust 또는 Go와 같은 고성능 언어를 사용하여 브라우저 측 로직을 작성할 수 있어 JavaScript의 독점을 깨뜨릴 수 있습니다.
| 언어 | 메인 프레임 | 특징 |
|---|---|---|
| C# / .NET | Blazor WebAssembly | .NET 개발자가 JS 대신 C#으로 프런트 엔드를 작성할 수 있도록 허용합니다. |
| Rust | Yew / Leptos | 최고의 실행 성능과 강력한 유형 안전성. |
| Go | Hugo / TinyGo | 컴파일은 매우 빠르며 논리적으로 복잡한 작업을 수행하는 데 적합합니다. |
이러한 유형의 솔루션은 "빌드 타임"에 모든 페이지를 정적 HTML 파일로 생성합니다. 이는 매우 빠르게 로드되고 SEO 친화적입니다.
Google이 출시한 솔루션은 Dart 언어를 사용합니다. 표준 HTML/CSS 렌더링 경로를 사용하지 않고 Canvas를 통해 전체 인터페이스를 그립니다.
// Flutter 논리 예제
무효 메인() {
runApp(const MyApp());
}
// 인터페이스는 Canvas로 완전히 그려지므로 시각적 일관성이 높은 앱을 이식하는 데 적합합니다.
내부 엔터프라이즈 도구 또는 빠른 실행 요구 사항의 경우 필기 코딩 없이 SPA를 만들 수 있습니다.
| 계획 | 적용 가능한 상황 | 기술적 한계점 |
|---|---|---|
| HTMX | 상호작용성을 고려한 기존 웹사이트 업그레이드 | 낮음(백엔드 언어만 필요) |
| WebAssembly | 이미지 처리, 복잡한 작업, 게임 | 높음(컴파일 언어 기초 필요) |
| Astro (SSG) | 블로그, 문서, 공식 웹사이트 | 가운데 |
| Flutter for Web | 앱이 웹페이지에 동시에 게시됩니다. | 중간(Dart 필요) |
PHP + JavaScript와 같은 기존 웹 아키텍처는 일반적으로 서버 측 배포에 사용되지만 소스 코드에 대한 액세스 또는 복사를 효과적으로 방지할 수 없으므로 신뢰할 수 없는 환경에서의 상용 라이선스 및 배포에는 적합하지 않습니다. 이 문제를 해결하기 위해 "자체 호스팅 웹 애플리케이션" 아키텍처가 등장했습니다. 백엔드 로직을 읽을 수 없는 실행 파일로 컴파일하고 HTTP 서비스 기능이 내장되어 있어 프런트엔드가 HTML/JS와 계속 상호 작용하는 동시에 백엔드에서 암호화, 보안, 권한 부여 제어 및 기타 요구 사항을 구현할 수 있습니다.
| 이름 | 언어를 사용하세요 | 라이선스 관리 지원 여부 | C#을 지원하나요? | 바이너리 생성 가능 | 목적에 적합 | 이용률/시장점유율 |
|---|---|---|---|---|---|---|
| Electron | JavaScript + Node.js | 검증 시스템과 함께 사용할 수 있습니다. | 아니요 | 예(데스크톱 앱) | 크로스 플랫폼 데스크톱 웹 앱 | 매우 높다 |
| Node.js + pkg | JavaScript | JWT/키 검증과 함께 사용할 수 있습니다. | 아니요 | 예 | 웹 API 애플리케이션 캡슐화 | 높은 |
| ASP.NET Core + Kestrel | C# | 기본 지원 | 예 | 예(.exe/.dll) | 엔터프라이즈 웹 API/도구 | 높은 |
| Go HTTP Server | Go | 내장 또는 맞춤형 | 아니요 | 예 | 고성능 웹 백엔드 | 높은 |
| Blazor WebAssembly + ASP.NET | C# | 지원 인증 확인 | 예 | 예 | SPA + 웹 API 통합 | 중간에서 높음 |
| Gradio | Python | 제3자와 함께 사용할 수 있습니다. | 아니요 | 가능(PyInstaller) | ML/AI Web UI | 가운데 |
| Streamlit | Python | 제3자와 함께 사용할 수 있습니다. | 아니요 | 가능(PyInstaller) | 데이터 시각화 웹 UI | 가운데 |
| Tauri | Rust + JS | 맞춤 검증 지원 | 아니요 | 예 | 초경량 데스크톱 앱 | 가운데 |
| Mongoose / Civetweb | C / C++ | 내장된 검증 로직 | 예(CLI 사용) | 예 | 내장 웹 서버 | 가운데 |
ASP.NET Core는 Microsoft에서 개발한 크로스 플랫폼, 오픈 소스, 고성능 웹 애플리케이션 프레임워크이며 Windows, Linux 및 macOS를 지원합니다. .NET 플랫폼의 일부이며 최신 웹 API, 웹 앱 및 마이크로서비스용으로 설계되었습니다. 기존 ASP.NET과 비교할 때 Core 버전은 더 가볍고 모듈식이며 독립적인 실행 파일(.exe)로 컴파일될 수 있어 자체 캡슐화된 웹 애플리케이션 아키텍처에 매우 적합합니다.
dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true
이 명령은 ASP.NET Core 애플리케이션을 독립 실행형 실행 파일(예: `MyApp.exe`)로 컴파일할 수 있으며, 이는 .NET Runtime을 설치하지 않고도 대상 시스템에서 직접 실행할 수 있습니다.
ASP.NET Core는 .NET MAUI + Blazor의 백엔드로 사용되어 데이터와 API를 제공할 수 있습니다.
Blazor 웹 프로젝트가 이미 있는 경우 거의 어려움 없이 MAUI 앱으로 이동하고 많은 코드를 재사용할 수 있습니다.
ASP.NET Core는 백엔드 및 웹 아키텍처에 중점을 두고 있으며 클라우드 및 API 개발에 적합합니다.
.NET MAUI + Blazor는 사용자 측 크로스 플랫폼 애플리케이션에 중점을 두고 있으며 특히 이미 Blazor 프런트 엔드 기술 스택을 보유하고 있는 팀에 적합합니다.
이 두 가지가 결합되면 "백엔드 서비스 + 프런트엔드 크로스 플랫폼 앱"의 완전한 솔루션이 달성될 수 있습니다.
| IDE | 지원 플랫폼 | 특징 | 무료인가요? | 물체에 적합 |
|---|---|---|---|---|
| Visual Studio | Windows | 전체 기능, 최고의 공식 지원 | 커뮤니티 무료(기타 수수료 적용) | 엔터프라이즈 및 풀엔드 개발자 |
| Visual Studio Code | Windows / Linux / macOS | 가볍고 확장성이 뛰어남 | 무료 | 크로스 플랫폼 개발자, 학생 |
| JetBrains Rider | Windows / Linux / macOS | ReSharper 통합, 크로스 플랫폼 | 수수료 필요 | 고급 개발자 및 크로스 플랫폼 팀 |
Ctrl + `)。dotnet new webapp -o MyAspNetApp
webapp: Razor Pages를 사용하여 ASP.NET Core 웹 애플리케이션을 빌드합니다.-o MyAspNetApp:프로젝트 폴더의 이름을 지정합니다.cd MyAspNetApp
dotnet run
https://localhost:5001또는http://localhost:5000구현하다.파일 → 폴더 열기, 새로 생성된 로드MyAspNetApp。dotnet 패키지 패키지 이름 추가
dotnet new webapp → Razor Pages Web Appdotnet new mvc→ MVC 아키텍처dotnet new webapi→ 웹 API 프로젝트Ctrl + Shift + P, 입력 및 선택Debug: Open launch.json。.vscode/launch.json。{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/MyAspNetApp.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}
]
}
.vscode폴더 생성tasks.json。{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/MyAspNetApp.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
F5또는 왼쪽의 "실행 및 디버그" 패널에서 선택하세요..NET Core Launch (web)。https://localhost:5001。dotnet new webapi -o MyWebApiApp
cd MyWebApiApp
code .
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (web API)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/bin/Debug/net8.0/MyWebApiApp.dll",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/Views"
}
}
]
}
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/MyWebApiApp.csproj"
],
"problemMatcher": "$msCompile"
}
]
}
F5또는 실행 및 디버그 패널에서 선택.NET Core Launch (web API)。https://localhost:5001또는http://localhost:5000。.http또는.rest아카이브 테스트 API.### GET API 테스트
https://localhost:5001/weatherforecast를 받으세요.
수락: 애플리케이션/json
###
### 테스트 POST API 예시
POST https://localhost:5001/api/sample
콘텐츠 유형: 애플리케이션/json
{
"ID": 1,
"name": "테스트 데이터"
}
test.http。Send Request단추.케스트렐은ASP.NET CoreMicrosoft에서 개발한 내장형 크로스 플랫폼 웹 서버입니다. 고성능, 경량으로 설계되었으며 HTTP/1.1 및 HTTP/2를 지원하며 ASP.NET Core 애플리케이션의 기본 서버입니다. Kestrel을 사용하면 개발자는 웹 애플리케이션을 다음과 같이 직접 래핑할 수 있습니다.자체 패키징 실행 파일을 사용하면 IIS, Apache 또는 Nginx와 같은 외부 서버에 의존하지 않고 로컬로 HTTP 서비스를 시작하고 제공할 수 있습니다.
UseUrls서비스의 로컬 포트 및 경로 설정public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseKestrel()
.UseUrls("http://localhost:5000");
var app = builder.Build();
app.MapGet("/", () => "Hello from Kestrel!");
app.Run();
}
}
dotnet publishKestrel을 사용하여 애플리케이션을 단일 실행 파일로 패키징| 프로젝트 | Kestrel | IIS / Nginx |
|---|---|---|
| 내장 여부 | 예(ASP.NET Core에 기본 제공) | 아니요(별도로 설치해야 함) |
| 지원 플랫폼 | Windows / Linux / macOS | 서버에 따라 다름 |
| 관리자 권한이 필요합니까? | 아니요 | 플랫폼 및 설정에 따라 다름 |
| 자체 캡슐화에 적합한가요? | 매우 적합 | 적합하지 않음 |
| 성능 | 높은 | 높음(단, 설정이 더 복잡함) |
ASP.NET Core는 프런트 엔드 리소스(HTML, CSS, JavaScript, SPA 등)와 백엔드 API 서비스를 단일 애플리케이션으로 통합하고 이를 독립적인 실행 단위(자체 포함 애플리케이션)로 배포하여 간단한 배포, 소스 코드 보호 및 라이선스 제어라는 목표를 달성하도록 지원합니다.
wwwroot/정적 리소스 역할을 하는 ASP.NET Core용 폴더입니다.wwwroot/。wwwroot,예를 들어:npm run build나중에dist/복사 대상wwwroot/npm run build나중에build/복사 대상wwwroot/Program.cs정적 파일 서비스는 다음에서 활성화됩니다.app.UseStaticFiles();
app.MapFallbackToFile("index.html");
dotnet publish -c Release -r win-x64 --self-contained
ASP.NET Core MVC는 Microsoft에서 출시한 크로스 플랫폼 웹 애플리케이션 프레임워크입니다. 이는 Model-View-Controller(모델-뷰-컨트롤러) 디자인 패턴을 기반으로 하며 동적 웹 사이트 및 웹 API를 개발하기 위한 구조화된 모듈식 방법을 제공합니다.
// 모델
공개 클래스 제품
{
공개 int ID { get; 세트; }
공개 문자열 이름 { get; 세트; }
공개 십진수 가격 { get; 세트; }
}
//컨트롤러
공개 클래스 ProductsController : 컨트롤러
{
공개 IActionResult 인덱스()
{
var products = 새 List<Product>
{
새 제품 { ID = 1, 이름 = "노트북", 가격 = 29999 },
새 제품 { ID = 2, 이름 = "마우스", 가격 = 499 },
새 제품 { ID = 3, 이름 = "키보드", 가격 = 899 }
};
반품보기(제품);
}
}
// 보기(Index.cshtml)
@모델 목록<제품>
<table border="1" cellpadding="6" cellpacing="0">
<머리>
<tr>
<번째>번호</th>
<번째> 이름
<번째> 가격
</tr>
</머리>
<본문>
@foreach(모델의 var 항목)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>@item.Price.ToString("C")</td>
</tr>
}
</tbody>
</테이블>
<!-- Product.cs - 데이터 모델 -->
공개 클래스 제품
{
공개 int ID { get; 세트; }
공개 문자열 이름 { get; 세트; }
공개 십진수 가격 { get; 세트; }
}
<!-- ProductsController.cs - 컨트롤러(ASP.NET Core MVC) -->
공개 클래스 ProductsController : 컨트롤러
{
공개 IActionResult 인덱스()
{
var products = 새 List<Product>
{
새 제품 { ID = 1, 이름 = "노트북", 가격 = 29999 },
새 제품 { ID = 2, 이름 = "마우스", 가격 = 499 },
새 제품 { ID = 3, 이름 = "키보드", 가격 = 899 }
};
반품보기(제품);
}
}
<!-- Views/Products/Index.cshtml - Razor 보기 페이지 -->
@모델 목록<제품>
<table border="1" cellpadding="6" cellpacing="0">
<머리>
<tr>
<번째>번호</th>
<번째> 이름
<번째> 가격
</tr>
</머리>
<본문>
@foreach(모델의 var 항목)
{
<tr>
<td>@item.Id</td>
<td>@item.Name</td>
<td>@item.Price.ToString("C")</td>
</tr>
}
</tbody>
</테이블>
Razor는 개발자가 HTML 페이지에 C# 코드를 포함할 수 있도록 Microsoft에서 ASP.NET Core용으로 개발한 마크업 언어입니다. 이는 표준 HTML과 C#을 결합하여 동적으로 생성되는 웹 페이지를 간단하고 직관적으로 만듭니다.
@페이지
@model IndexModel
<h1>Razor 페이지에 오신 것을 환영합니다</h1>
<p>오늘 날짜: @DateTime.Now.ToString("yyyy-MM-dd")</p>
@if(Model.Items != null && Model.Items.Any())
{
@foreach(Model.Items의 변수 항목)
{
- @item
}
</ul>
}
그렇지 않으면
{
<p>표시된 데이터가 없습니다</p>
}
Razor View에서 사용:
@foreach(var item in Model)
{
<div>@item</div>
}
다음 오류가 발생하는 경우:
System.NullReferenceException: Object reference not set to an instance of an object.
표현하다Model~을 위한null, 결과적으로 루프가 불가능해졌습니다.
public IActionResult Index()
{
var data = new List<string> { "A", "B", "C" };
return View(data);
}
@model IEnumerable<string>
@if(모델 != null)
{
foreach(모델의 var 항목)
{
<div>@item</div>
}
}
그렇지 않으면
{
<div>데이터 없음</div>
}
모범 사례는모델이 컨트롤러에 값을 가지고 있는지 확인하세요(빈 컬렉션이라도) View가 null 상황을 처리하는 것을 방지합니다. 예를 들어:
return View(data ?? new List<string>());
ASP.NET Core MVC에서는 프로젝트에 여러 컨트롤러가 있을 수 있으며, 각 컨트롤러는 서로 다른 기능이나 영역을 담당합니다. 예를 들어:
HomeController— 홈페이지 및 정적 페이지 처리ProductController— 제품 관리를 담당합니다.모든 컨트롤러는 상속받아야 합니다.Controller카테고리에 저장되어 있습니다.Controllers접는 사람.
// HomeController.cs
공개 클래스 HomeController : 컨트롤러
{
공개 IActionResult 인덱스()
{
보기()를 반환합니다.
}
}
// ProductController.cs
공개 클래스 ProductController : 컨트롤러
{
공개 IActionResult 목록()
{
var products = new List<string> { "컴퓨터", "휴대폰", "태블릿" };
반품보기(제품);
}
}
MVC의 보기는 기본적으로 컨트롤러 이름을 기반으로 폴더를 생성합니다. 예를 들면 다음과 같습니다.
Views/Home/Index.cshtmlViews/Product/List.cshtml사용될 수 있다asp-controller그리고asp-action태그 도우미:
<a asp-controller="Home" asp-action="Index">홈페이지로 돌아가기</a>
<a asp-controller="제품" asp-action="List">제품 목록</a>
존재하다Program.cs또는Startup.cs, 기본 경로는 일반적으로 다음과 같습니다.
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
즉, URL이/, 자동으로 안내합니다HomeController.Index().
URL이 다음과 같은 경우/Product/List, 실행됩니다ProductController.List()。
다음과 같은 경우 MVC에서 동시에 여러 컨트롤러를 가질 수 있습니다.
ControllerViews해당 폴더와 파일을 생성합니다.asp-controller그리고asp-action올바른 통화Model(또는 복합 ViewModel)이지만 동일한 페이지에 있는 여러 컨트롤러의 데이터/작업을 표시하거나 연결할 수 있습니다.// 모델/ViewModels.cs
공개 클래스 HomePageViewModel {
공개 IEnumerable<Product> 제품 {얻다; 세트; }
공개 IEnumerable<Order> 최근 주문 { get; 세트; }
}
// HomeController.cs
공개 IActionResult Index() {
var vm = 새로운 HomePageViewModel {
제품 = productService.GetTopProducts(),
RecentOrders = orderService.GetRecentOrders()
};
뷰(vm)를 반환합니다.
}
// 보기/홈/Index.cshtml
@model HomePageViewModel
<h2>제품</h2>
@foreach(Model.Products의 var p){ <div>@p.Name</div> }
<h2>최근 주문</h2>
@foreach(Model.RecentOrders의 var o){ <div>@o.Id</div> }
// Views/Product/_ProductList.cshtml (일부)
@model IEnumerable<Product>
@foreach(모델의 var p){ <div>@p.Name</div> }
// Views/Home/Index.cshtml(상위 뷰)
@model HomePageViewModel
<div>
@Html.Partial("_ProductList", Model.Products)
</div>
// 구성요소/ProductListViewComponent.cs
공용 클래스 ProductListViewComponent : ViewComponent {
개인 읽기 전용 IProductService _svc;
공개 ProductListViewComponent(IProductService svc){ _svc = svc; }
공개 IViewComponentResult Invoke(int 개수) {
var 제품 = _svc.GetTopProducts(count);
반품보기(제품); // 보기/공유/구성 요소/ProductList/Default.cshtml
}
}
// 면도기에서 사용됨
@await Component.InvokeAsync("ProductList", new { count = 5 })
<!-- Views/Home/Index.cshtml -->
<div id="product-area">로드 중...</div>
<스크립트>
가져오기('/api/제품/top5')
.then(r => r.json())
.then(데이터 => {
document.getElementById('제품 영역').innerHTML =
data.map(p => `${p.name}`).join('');
});
</script>
<a asp-controller="제품" asp-action="List">제품 목록</a>
<a asp-controller="주문" asp-action="History">주문 내역</a>
ViewModel또는ViewComponent(더 모듈화됨).Partial View또는ViewComponent。Java 애플릿은 웹 브라우저를 통해 실행되고 HTML 페이지에 포함될 수 있는 Java 언어로 작성된 작은 응용 프로그램입니다. 1990년대에 처음으로 애니메이션, 게임, 차트 시각화와 같은 대화형 웹 페이지를 만드는 데 널리 사용되었습니다.
애플릿은 Java Plugin을 지원하는 브라우저에서 실행되어야 합니다.<applet>또는<object>태그는 HTML에 포함되어 있으며 사용자 측 JVM(Java Virtual Machine)에 의해 로드되고 실행됩니다.
애플릿은 클라이언트 측에서 실행될 수 있으므로 악의적인 행위를 방지하기 위해 실행 환경에서는 로컬 파일 시스템에 대한 접근이나 외부 프로그램 실행을 금지하는 등 보안 격리를 위한 '샌드박스 메커니즘'을 채택합니다.
오라클은 Java 9부터 Applet API를 제거한다고 발표했으며 Java 11에서는 Applet을 완전히 제거할 예정입니다. 또 다른 데스크탑 실행 기술인 Java Web Start도 유지 관리가 중단됩니다.
Java 애플릿은 제거 단계에 진입했으며 현대 웹 개발 추세는 HTML5, JavaScript 및 WebAssembly와 같은 개방형 표준 기술을 사용하는 경향이 있습니다. 개발자는 애플릿 사용을 피하고 기존 애플리케이션을 최신 기술 플랫폼으로 이동해야 합니다.
다음은 간단한 메시지를 표시하는 Java 애플릿의 예입니다.
<!DOCTYPE html>
<html lang="zh-Hant">
<머리>
<meta charset="UTF-8">
<title>Java 애플릿 예</title>
</머리>
<본문>
<h1>Java 애플릿 예</h1>
<applet code="HelloWorldApplet.class" width="300" height="300>
<param name="message" value="안녕하세요! ">
귀하의 브라우저는 Java 애플릿을 지원하지 않습니다.
</애플릿>
</body>
</html>
import java.applet.Applet;
import java.awt.Graphics;
public class HelloWorldApplet extends Applet {
String message;
public void init() {
message = getParameter("message");
}
public void paint(Graphics g) {
g.drawString(message, 20, 20);
}
}
1. Java 코드를 다음과 같이 저장하십시오.HelloWorldApplet.java, 명령줄에서 실행javac HelloWorldApplet.java컴파일합니다.
2. 생성된 내용을 확인하세요..class파일은 HTML 파일과 동일한 디렉터리에 있습니다.
3. HTML 파일을 실행하려면 Java Applet을 지원하는 환경을 사용하십시오.
대부분의 최신 브라우저는 더 이상 Java 애플릿을 지원하지 않으므로 유사한 기능을 구현하려면 다른 기술(예: JavaFX 또는 웹 애플리케이션)을 사용하는 것이 좋습니다.
email: [email protected]