반응형

🚨 CORS 정책 차단 오류 해결 방법

오류 메시지:
"has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

이 오류는 다른 도메인(origin)에서 API 요청을 보낼 때, 서버가 이를 허용하지 않아서 발생하는 문제입니다. 웹 브라우저는 보안상의 이유로 다른 출처(Origin)에서 온 요청을 차단합니다.


해결 방법

1️⃣ 서버에서 CORS 허용하기 (권장)

요청을 보내는 서버에서 CORS 헤더를 추가해야 합니다.

🔹 Node.js (Express 서버)

const cors = require('cors');
const express = require('express');
const app = express();

app.use(cors()); // 모든 도메인에서 요청 허용

// 특정 도메인만 허용
app.use(cors({
  origin: 'https://your-allowed-domain.com'
}));

app.listen(3000, () => console.log('Server running on port 3000'));

🔹 Apache 서버

.htaccess 파일 수정:

Header set Access-Control-Allow-Origin "*"

(* 대신 특정 도메인만 허용 가능: "https://your-allowed-domain.com")


2️⃣ 프록시 서버 사용하기

백엔드 서버를 직접 수정할 수 없을 경우, 프록시 서버를 사용하면 해결할 수 있습니다.

🔹 프록시 설정 (React/Vue 등)

📌 package.json에 프록시 설정 추가:

"proxy": "https://your-api-server.com"

3️⃣ 브라우저에서 CORS 무시하기 (임시 해결)

개발 중이라면, CORS 정책을 무시하는 방법도 있습니다.
⚠️ 보안상 안전하지 않으므로, 배포 환경에서는 사용하면 안 됩니다!

🔹 크롬 브라우저에서 CORS 비활성화 실행 (Windows)

chrome.exe --disable-web-security --user-data-dir="C:\chrome-dev"

🔹 크롬 확장 프로그램 사용


🔚 결론

  1. 서버에서 CORS 허용 설정 (가장 좋은 방법)
  2. 프록시 서버 사용
  3. 개발 중이라면 브라우저 설정 변경 (배포용 아님)
반응형
반응형

1. 필요한 라이브러리

Apache POI 라이브러리를 사용해야 해. 아래 의존성을 추가해 줘.

Maven 프로젝트라면 pom.xml에 추가:

<dependencies>
    <!-- Apache POI -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version> <!-- 최신 버전 확인 필요 -->
    </dependency>
</dependencies>

Gradle 프로젝트라면 build.gradle에 추가:

dependencies {
    implementation 'org.apache.poi:poi-ooxml:5.2.3'
}

2. Java 코드 구현

  1. 파일 A.xlsx, B.xlsx을 엶
  2. B.xlsx의 "GOOD" 시트를 읽어옴
  3. A.xlsx의 "GOOD" 시트를 지우고 B.xlsx의 "GOOD" 시트를 복사
  4. A.xlsx를 저장
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;

public class ExcelSheetReplace {
    public static void main(String[] args) {
        String fileA = "A.xlsx";  // 대상 파일
        String fileB = "B.xlsx";  // 소스 파일
        String sheetName = "GOOD";  // 덮어쓸 시트 이름

        try (FileInputStream fisA = new FileInputStream(fileA);
             FileInputStream fisB = new FileInputStream(fileB);
             XSSFWorkbook workbookA = new XSSFWorkbook(fisA);
             XSSFWorkbook workbookB = new XSSFWorkbook(fisB)) {

            // B.xlsx에서 "GOOD" 시트를 가져옴
            XSSFSheet sheetB = workbookB.getSheet(sheetName);
            if (sheetB == null) {
                System.out.println("B.xlsx에 '" + sheetName + "' 시트가 없습니다.");
                return;
            }

            // A.xlsx에서 "GOOD" 시트 삭제 (기존 시트가 존재하면 제거)
            int sheetIndexA = workbookA.getSheetIndex(sheetName);
            if (sheetIndexA != -1) {
                workbookA.removeSheetAt(sheetIndexA);
            }

            // A.xlsx에 새로운 "GOOD" 시트 생성
            XSSFSheet sheetA = workbookA.createSheet(sheetName);

            // B.xlsx의 "GOOD" 시트 내용을 A.xlsx의 "GOOD" 시트로 복사
            copySheet(sheetB, sheetA, workbookA);

            // 변경된 A.xlsx 저장
            try (FileOutputStream fosA = new FileOutputStream(fileA)) {
                workbookA.write(fosA);
            }

            System.out.println("B.xlsx의 'GOOD' 시트가 A.xlsx의 'GOOD' 시트로 성공적으로 덮어씌워졌습니다.");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 시트 복사 함수
    private static void copySheet(XSSFSheet sourceSheet, XSSFSheet targetSheet, XSSFWorkbook targetWorkbook) {
        for (int rowIndex = 0; rowIndex <= sourceSheet.getLastRowNum(); rowIndex++) {
            Row sourceRow = sourceSheet.getRow(rowIndex);
            Row targetRow = targetSheet.createRow(rowIndex);

            if (sourceRow != null) {
                for (int colIndex = 0; colIndex < sourceRow.getLastCellNum(); colIndex++) {
                    Cell sourceCell = sourceRow.getCell(colIndex);
                    Cell targetCell = targetRow.createCell(colIndex);

                    if (sourceCell != null) {
                        copyCell(sourceCell, targetCell, targetWorkbook);
                    }
                }
            }
        }
    }

    // 셀 복사 함수
    private static void copyCell(Cell sourceCell, Cell targetCell, XSSFWorkbook workbook) {
        targetCell.setCellType(sourceCell.getCellType());

        switch (sourceCell.getCellType()) {
            case STRING:
                targetCell.setCellValue(sourceCell.getStringCellValue());
                break;
            case NUMERIC:
                targetCell.setCellValue(sourceCell.getNumericCellValue());
                break;
            case BOOLEAN:
                targetCell.setCellValue(sourceCell.getBooleanCellValue());
                break;
            case FORMULA:
                targetCell.setCellFormula(sourceCell.getCellFormula());
                break;
            case BLANK:
                targetCell.setBlank();
                break;
            default:
                break;
        }

        // 스타일 복사
        CellStyle newCellStyle = workbook.createCellStyle();
        newCellStyle.cloneStyleFrom(sourceCell.getCellStyle());
        targetCell.setCellStyle(newCellStyle);
    }
}

3. 코드 설명

  1. 파일 읽기: FileInputStream으로 A.xlsx, B.xlsx을 연다.
  2. 시트 삭제: A.xlsx에 "GOOD" 시트가 있다면 삭제한다.
  3. 새 시트 생성: A.xlsx"GOOD" 시트를 새로 만든다.
  4. 시트 복사: copySheet() 함수를 사용해 B.xlsx"GOOD" 내용을 A.xlsx로 복사한다.
  5. 파일 저장: FileOutputStream을 사용해 변경된 A.xlsx을 저장한다.

4. 실행 결과

A.xlsx의 "GOOD" 시트가 B.xlsx의 "GOOD" 시트 내용으로 덮어씌워진다.

📌 주의사항

  • A.xlsx와 B.xlsx가 존재해야 한다.
  • 두 파일이 열려 있으면 저장이 실패할 수 있으므로, Excel에서 닫아둬야 한다.

이제 실행하면 원하는 동작이 수행될 거야! 🚀

반응형
반응형

웹 개발에서 레이아웃을 구성할 때, 요소들이 겹치는 경우가 종종 발생합니다. 이때 특정 요소를 위로 올리거나 아래로 내리는 데 사용하는 속성이 바로 z-index 입니다. 하지만 초보자뿐만 아니라 숙련된 개발자들도 z-index가 예상대로 동작하지 않아 혼란을 겪는 경우가 많습니다. 본 글에서는 z-index의 개념, 작동 원리, 활용법, 그리고 실전에서 발생할 수 있는 문제와 해결 방법까지 깊이 있게 다루어 보겠습니다.

1. z-index란?

z-index는 CSS의 속성 중 하나로, HTML 요소의 쌓임 순서(stacking order) 를 결정하는 역할을 합니다. 기본적으로 HTML 요소들은 문서 흐름(Document Flow)에 따라 배치되지만, position 속성을 사용하여 요소를 상대적(relative), 절대적(absolute), 고정(fixed) 또는 스티키(sticky)로 변경하면 z-index를 이용해 요소의 순서를 조정할 수 있습니다.

2. z-index의 기본 원리

(1) 기본적인 동작 방식

  • z-index는 숫자 값을 가지며, 값이 클수록 위에 배치됩니다.
  • 기본적으로 요소들은 HTML 문서의 순서대로 쌓이며, z-index를 지정하지 않으면 기본값(0)이 적용됩니다.
  • z-index는 position이 static이 아닌 경우에만 동작합니다. 즉, position: static; 상태에서는 z-index를 설정해도 효과가 없습니다.

(2) z-index 값의 유형

z-index 값은 정수값을 가지며, 양수, 0, 음수 모두 설정할 수 있습니다.

.element1 {
  position: relative;
  z-index: 1;
}

.element2 {
  position: relative;
  z-index: 10; /* element2가 element1보다 위에 배치됨 */
}

위 코드에서 .element2.element1보다 더 높은 z-index 값을 가지므로 화면에서 위쪽에 나타납니다.

3. 쌓임 맥락(Stacking Context)

z-index를 제대로 이해하려면 쌓임 맥락(Stacking Context) 개념을 숙지해야 합니다. 쌓임 맥락은 특정 요소가 독립된 z-index 환경을 형성하는 개념으로, 다음과 같은 경우 생성됩니다.

(1) 쌓임 맥락이 생성되는 조건

  • position: absolute, position: relative, position: fixed, position: sticky와 함께 z-index 값이 설정된 경우
  • display: flex 또는 display: grid가 적용된 부모 요소에 z-index를 지정한 경우
  • opacity 값이 1보다 작은 경우 (예: opacity: 0.99;)
  • transform, filter, perspective, clip-path 등의 속성이 적용된 경우

(2) 쌓임 맥락 예제

.parent {
  position: relative;
  z-index: 1;
}

.child {
  position: absolute;
  z-index: 9999;
}

위와 같이 .child 요소에 높은 z-index 값을 부여해도 .parent 요소 내에서만 영향력을 가집니다. 즉, 쌓임 맥락이 형성되면 자식 요소의 z-index는 부모의 영향권을 벗어나지 못합니다.

4. z-index 활용 예제

(1) 여러 개의 요소가 겹칠 때

.box1 {
  position: absolute;
  top: 50px;
  left: 50px;
  width: 100px;
  height: 100px;
  background-color: red;
  z-index: 2;
}

.box2 {
  position: absolute;
  top: 70px;
  left: 70px;
  width: 100px;
  height: 100px;
  background-color: blue;
  z-index: 1;
}

위 코드에서는 .box1.box2보다 z-index 값이 크므로, .box1.box2 위에 표시됩니다.

(2) 모달 창을 최상단에 배치하기

모달 창은 사용자 인터페이스에서 매우 중요한 요소이며, 항상 페이지의 가장 위에 떠 있어야 합니다.

.modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  z-index: 1000;
}

이렇게 설정하면 z-index: 1000;을 통해 다른 요소들보다 위에 배치됩니다.

5. z-index가 동작하지 않을 때의 해결 방법

  1. position 속성 확인: position: static; 상태에서는 z-index가 적용되지 않으므로 relative, absolute, fixed 중 하나로 변경해야 합니다.
  2. 부모 요소의 z-index 확인: 부모 요소가 새로운 쌓임 맥락을 형성하는 경우, 자식 요소의 z-index가 기대한 대로 동작하지 않을 수 있습니다.
  3. opacity, transform 등의 속성 확인: opacity: 0.9; 등의 속성이 적용되면 새로운 쌓임 맥락이 형성될 수 있습니다.
  4. 개발자 도구(F12) 활용: 요소들의 쌓임 순서를 정확히 파악하려면 크롬 개발자 도구(F12)에서 z-index 값을 확인하는 것이 유용합니다.

6. 결론

z-index는 웹 개발에서 중요한 개념이지만, 쌓임 맥락(Stacking Context)과 연관되어 있어 쉽게 오해할 수 있는 속성입니다. 따라서, z-index를 올바르게 적용하려면 position 속성을 적절히 설정하고, 쌓임 맥락을 고려하며, 개발자 도구를 활용하여 디버깅하는 습관을 들이는 것이 중요합니다. 이를 잘 활용하면 복잡한 UI도 깔끔하게 구성할 수 있습니다.

반응형

+ Recent posts