Same-Origin Policy (SOP, 동일 출처 정책)

**Same-Origin Policy(SOP, 동일 출처 정책)**는 웹 보안 모델 중 하나로, 다른 출처(origin)에서 온 웹 페이지 간의 자원 공유를 제한하는 보안 정책

1. 동일 출처(Origin)의 기준

출처(Origin)는 프로토콜, 도메인, 포트 3가지 요소로 결정됩니다.
다음 요소 중 하나라도 다르면 다른 출처로 간주됩니다.

scheme (프로토콜)://host (도메인):port (포트)

위의 표에서 https://example.com:443을 기준으로 했을 때,
http://example.com:80, https://sub.example.com:443, https://example.com:8080다른 출처로 간주됩니다.

2. SOP의 작동 방식

SOP는 한 출처의 웹 페이지에서 다른 출처의 데이터에 접근하는 것을 제한합니다.

허용되는 경우 (Same-Origin)

// 같은 출처 내에서 접근 (가능)
fetch("https://example.com/api/data")
  .then(response => response.json())
  .then(data => console.log(data));

차단되는 경우 (Cross-Origin)

// 다른 출처의 API 호출 (차단됨)
fetch("https://api.example.com/data")
  .then(response => response.json())
  .then(data => console.log(data));

3. SOP 예외 (Cross-Origin 허용 방법)

SOP는 기본적으로 보안을 위해 출처가 다른 리소스 접근을 차단하지만, 다음과 같은 방법을 사용하면 예외적으로 허용할 수 있습니다.

1) CORS (Cross-Origin Resource Sharing)

  • 서버에서 CORS 헤더(Access-Control-Allow-Origin)를 설정하면 특정 출처에서의 요청을 허용할 수 있음.
    • https://example.com에서 요청을 허용함.
    • *을 사용하면 모든 출처에서 요청 가능.
Access-Control-Allow-Origin: https://example.com

2) JSONP (구식 방법)

  • <script> 태그를 이용해 다른 출처의 데이터를 가져오는 방식.
  • 보안 취약점으로 인해 현재는 거의 사용되지 않음.

3) 서버 프록시 사용

  • 백엔드 서버에서 프록시 역할을 하여 같은 출처에서 데이터를 받아오도록 처리.
    Client -> My Server (Same-Origin) -> External API (Cross-Origin)

4. 왜 SOP가 중요한가?

SOP가 없다면 악성 웹사이트에서 사용자의 데이터를 훔치는 보안 문제가 발생할 수 있습니다.

🔴 SOP가 없을 경우 발생할 수 있는 보안 위협

  • CSRF (Cross-Site Request Forgery): 사용자가 로그인된 상태에서 악성 사이트가 요청을 보내 사용자의 권한으로 수행하게 만듦.
  • XSS (Cross-Site Scripting): 다른 출처의 데이터를 삽입해 악성 스크립트를 실행.
  • 세션 탈취: 공격자가 사용자의 쿠키 및 인증 정보를 가로챌 가능성.

'WEB' 카테고리의 다른 글

3계층 티어  (0) 2025.01.21
SQL SESSION 메서드  (0) 2024.12.02
SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21

3계층 티어(3-tier architecture)는 소프트웨어 애플리케이션의 아키텍처 모델 중 하나로, 애플리케이션을 세 가지 주요 구성 요소로 분리하여 효율적으로 관리하고 유지보수할 수 있도록 도와줍니다. 이 모델은 프레젠테이션 계층, 비즈니스 계층, 데이터 계층으로 나뉩니다. 각 계층은 독립적으로 기능하며, 특정 역할을 담당합니다.

1. 프레젠테이션 계층 (Presentation Layer)

  • 역할: 사용자와 상호작용하는 부분입니다. 사용자의 입력을 받고, 데이터를 시각적으로 표시하는 역할을 합니다.
  • 기능:
    • 사용자 인터페이스(UI)와 관련된 모든 작업을 담당합니다.
    • 브라우저, 모바일 애플리케이션, 데스크탑 애플리케이션 등 클라이언트 측에서 실행되는 코드가 이 계층에 속합니다.
    • 요청을 받아 비즈니스 로직 계층에 전달하고, 비즈니스 로직의 처리 결과를 사용자에게 표시합니다.
  • 예시: 웹 애플리케이션의 HTML, CSS, JavaScript, 모바일 앱의 UI, Angular, React, Vue.js와 같은 프론트엔드 프레임워크.

2. 비즈니스 계층 (Business Layer)

  • 역할: 애플리케이션의 핵심 비즈니스 로직을 처리합니다. 사용자 요청을 처리하고, 데이터를 처리하며, 로직을 실행하는 계층입니다.
  • 기능:
    • 비즈니스 로직을 수행하는 데 필요한 계산이나 데이터를 처리합니다.
    • 유효성 검사, 트랜잭션 관리, 승인 절차 등의 비즈니스 규칙을 구현합니다.
    • 프레젠테이션 계층에서 요청을 받아 데이터 계층과 상호작용하고, 그 결과를 반환합니다.
  • 예시: 서버 측 애플리케이션 코드, Spring, Node.js, Django의 백엔드 로직, API 서버 등.

3. 데이터 계층 (Data Layer)

  • 역할: 데이터의 저장과 관리가 이루어지는 부분으로, 애플리케이션의 데이터를 처리하고 저장하는 역할을 합니다.
  • 기능:
    • 데이터베이스와의 상호작용을 담당합니다. 데이터의 CRUD(Create, Read, Update, Delete) 작업을 처리합니다.
    • 파일 시스템에 저장된 데이터나 외부 시스템과의 통신을 처리하기도 합니다.
    • 비즈니스 계층의 요청에 따라 필요한 데이터를 제공하고, 데이터를 관리합니다.
  • 예시: 관계형 데이터베이스(MySQL, PostgreSQL), NoSQL 데이터베이스(MongoDB, Cassandra), 파일 시스템, RESTful API 데이터 소스 등.

3계층 티어 아키텍처의 장점

  • 유지보수 용이: 각 계층이 독립적으로 존재하여, 특정 계층을 변경할 때 다른 계층에 미치는 영향을 최소화할 수 있습니다.
  • 확장성: 각 계층을 별도로 확장할 수 있어, 예를 들어 비즈니스 로직을 더 강력하게 만들거나 데이터베이스 성능을 향상시키는 것이 가능합니다.
  • 보안: 데이터 계층은 외부에서 직접 접근할 수 없고, 비즈니스 계층과 프레젠테이션 계층을 통해서만 데이터에 접근할 수 있어 보안성이 높습니다.
  • 재사용성: 비즈니스 로직을 다른 애플리케이션에서 재사용할 수 있습니다. 예를 들어, 웹 애플리케이션과 모바일 애플리케이션에서 같은 비즈니스 로직을 공유할 수 있습니다.

3계층 티어 아키텍처의 단점

  • 복잡성: 각 계층을 독립적으로 관리해야 하기 때문에 시스템 구조가 복잡해질 수 있습니다.
  • 성능 문제: 계층 간의 상호작용이 많아지면, 각 계층을 거칠 때마다 네트워크 호출이 이루어지므로 성능 저하가 있을 수 있습니다.
  • 비용: 각 계층을 별도로 관리하고 배포해야 하므로, 인프라와 유지보수 비용이 증가할 수 있습니다.

예시: 3계층 아키텍처의 흐름

  1. 사용자가 프레젠테이션 계층(웹 브라우저 또는 모바일 앱)을 통해 애플리케이션에 요청을 보냅니다.
  2. 프레젠테이션 계층은 이 요청을 비즈니스 계층에 전달하고, 필요한 비즈니스 로직을 처리합니다.
  3. 비즈니스 계층은 데이터를 처리하거나 데이터 계층에 필요한 데이터를 요청합니다.
  4. 데이터 계층은 데이터를 제공하고, 비즈니스 계층은 이를 바탕으로 최종 결과를 반환합니다.
  5. 프레젠테이션 계층은 사용자가 볼 수 있도록 결과를 표시합니다.

결론

3계층 아키텍처는 애플리케이션을 세 개의 주요 계층으로 나누어 각 계층이 독립적으로 동작하도록 하여 개발, 유지보수, 확장성 등을 용이하게 만듭니다. 이러한 구조는 대규모 애플리케이션이나 기업용 시스템에서 자주 사용되며, 각각의 계층을 효율적으로 관리하고 최적화할 수 있는 좋은 방법입니다.

 

 

 

'WEB' 카테고리의 다른 글

SOP  (0) 2025.02.18
SQL SESSION 메서드  (0) 2024.12.02
SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21

1. SELECT 관련 메서드

    • 결과가 없으면 null을 반환.
    • 결과가 여러 개라면 TooManyResultsException이 발생.<T> T selectOne(String statement)
      지정된 SQL ID를 실행하고 하나의 결과를 반환합니다.
  • <E> List<E> selectList(String statement)
    지정된 SQL ID를 실행하고 여러 개의 결과를 List로 반환합니다.
  • <K, V> Map<K, V> selectMap(String statement, String mapKey)
  • 결과를 Map 형태로 반환하며, mapKey를 기준으로 Map의 키를 설정합니다.
User user = sqlSession.selectOne("UserMapper.selectUserById", 1);
List<User> users = sqlSession.selectList("UserMapper.selectAllUsers");
Map<Integer, User> userMap = sqlSession.selectMap("UserMapper.selectAllUsers", "id");

2. INSERT 관련 메서드

  • int insert(String statement)
    지정된 SQL ID를 실행하여 삽입 작업을 수행하고, 영향을 받은 행(row) 수를 반환합니다.
int rows = sqlSession.insert("UserMapper.insertUser", newUser);

3. UPDATE 관련 메서드

  • int update(String statement)
    지정된 SQL ID를 실행하여 갱신 작업을 수행하고, 영향을 받은 행(row) 수를 반환합니다.
     
int rows = sqlSession.update("UserMapper.updateUser", user);

4. DELETE 관련 메서드

  • int delete(String statement)
    지정된 SQL ID를 실행하여 삭제 작업을 수행하고, 영향을 받은 행(row) 수를 반환합니다
int rows = sqlSession.delete("UserMapper.deleteUserById", 1);

'WEB' 카테고리의 다른 글

SOP  (0) 2025.02.18
3계층 티어  (0) 2025.01.21
SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21

SqlSessionFactory는 MyBatis에서 SQL 작업을 수행하기 위해 SqlSession 객체를 생성하는 역할을 하는 팩토리 클래스입니다.
MyBatis 애플리케이션에서 데이터베이스와 상호작용하려면 SqlSession 객체가 필요하며, 이 객체는 반드시 SqlSessionFactory를 통해 생성됩니다.

SqlSessionFactory의 주요 역할

  1. SqlSession 생성
    • MyBatis에서 SQL을 실행하기 위해 필요한 SqlSession 객체를 생성합니다.
    • 데이터베이스 작업이 끝난 후 SqlSession은 반드시 닫아야 합니다.
    • SqlSession은 Thread-Safe하지 않으므로 요청마다 새로운 세션을 생성해야 합니다.
  2. MyBatis 환경 설정 관리
    • MyBatis 설정 파일(mybatis-config.xml)에서 정의된 환경 설정(데이터베이스 연결 정보, 매퍼 파일 경로 등)을 로드하여 관리합니다.
  3. 캐싱 및 성능 관리
    • MyBatis는 SqlSessionFactory를 통해 1차 캐싱(로컬 캐시) 및 2차 캐싱(전역 캐시) 메커니즘을 관리할 수 있습니다.
  4. Thread-Safe
    • SqlSessionFactory는 멀티스레드 환경에서도 안전하게 사용할 수 있도록 설계되었습니다.

SqlSessionFactory 생성 과정

SqlSessionFactory는 주로 SqlSessionFactoryBuilder를 사용하여 생성됩니다. 이 과정에서 MyBatis 설정 파일(mybatis-config.xml)과 데이터베이스 매퍼 XML 파일을 로드합니다.

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
                <property name="username" value="root"/>
                <property name="password" value="password"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/example/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml"; // 설정 파일 경로
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to initialize SqlSessionFactory");
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
}
import org.apache.ibatis.session.SqlSession;

public class Main {
    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory = MyBatisUtil.getSqlSessionFactory();
        
        try (SqlSession session = sqlSessionFactory.openSession()) {
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = userMapper.selectUser(1); // SQL 실행
            System.out.println(user);
        }
    }
}

장점

  1. 재사용 가능
    • SqlSessionFactory는 생성된 이후 애플리케이션 전체에서 재사용할 수 있습니다.
    • 매번 새로 생성할 필요 없이 효율적으로 관리됩니다.
  2. 효율적인 자원 관리
    • 내부적으로 데이터베이스 연결 풀(예: PooledDataSource)을 관리하여 효율적인 커넥션 사용을 지원합니다.
  3. 환경 설정의 중앙화
    • MyBatis 환경 설정을 한 곳에서 관리할 수 있어 유지보수가 용이합니다.
  4. 멀티스레드 안전성
    • SqlSessionFactory는 멀티스레드 환경에서도 안전하게 사용할 수 있습니다.

유의 사항

  1. SqlSession의 사용 및 닫기
    • SqlSessionFactory로 생성된 SqlSession은 Thread-Safe하지 않습니다.
    • 각 요청마다 SqlSession 객체를 새로 생성해야 하며, 사용 후 반드시 close() 메서드로 닫아야 합니다.
  2. 싱글톤 관리
    • SqlSessionFactory는 애플리케이션에서 싱글톤으로 관리해야 합니다.
    • 위의 예제처럼 static 변수로 초기화하거나 Spring과 통합하여 관리할 수 있습니다.
  3. Spring과의 통합
    • Spring을 사용하는 경우, SqlSessionFactory를 자동으로 관리하는 **SqlSessionFactoryBean**을 활용할 수 있습니다.

결론

SqlSessionFactory는 MyBatis의 핵심 구성 요소로, 데이터베이스와의 연결을 효율적으로 관리하고, SQL 작업을 수행할 SqlSession 객체를 제공합니다.
다른 라이브러리나 프레임워크(Spring)와 통합하거나, 독립적으로 사용해도 안정적이고 효율적인 데이터베이스 작업 환경을 제공할 수 있습니다.

'WEB' 카테고리의 다른 글

3계층 티어  (0) 2025.01.21
SQL SESSION 메서드  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21
Scope  (0) 2024.11.20

1. 이미지 경로 저장 (추천)

  • 데이터베이스에 이미지를 직접 저장하지 않고, 서버의 특정 디렉토리에 이미지를 저장한 후 해당 이미지 파일의 경로를 artist_img 컬럼에 저장하는 방법입니다.
  • 이 방법은 데이터베이스의 크기를 효율적으로 관리하고 성능을 높이는 데 유리합니다.

구현 단계:

  1. 이미지 업로드 폼 작성 (JSP)
1. 이미지 경로 저장 (추천)
데이터베이스에 이미지를 직접 저장하지 않고, 서버의 특정 디렉토리에 이미지를 저장한 후 해당 이미지 파일의 경로를 artist_img 컬럼에 저장하는 방법입니다.
이 방법은 데이터베이스의 크기를 효율적으로 관리하고 성능을 높이는 데 유리합니다.
구현 단계:
이미지 업로드 폼 작성 (JSP)
jsp
코드 복사
<form action="uploadArtist" method="post" enctype="multipart/form-data">
    <label for="artistName">Artist Name:</label>
    <input type="text" name="artistName" id="artistName" required>
    <label for="artistImg">Artist Image:</label>
    <input type="file" name="artistImg" id="artistImg" accept="image/*" required>
    <button type="submit">Upload</button>
</form>
서블릿에서 이미지 처리 및 저장
java
코드 복사
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.*;
import java.sql.*;

@MultipartConfig // 파일 업로드를 처리하기 위한 어노테이션
public class UploadArtistServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistName = request.getParameter("artistName");
        Part filePart = request.getPart("artistImg"); // 업로드된 파일을 가져옴
        String fileName = getFileName(filePart);

        // 저장할 경로 설정
        String uploadPath = getServletContext().getRealPath("") + File.separator + "uploads";
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) uploadDir.mkdir();

        // 파일 저장
        String filePath = uploadPath + File.separator + fileName;
        filePart.write(filePath);

        // DB에 경로 저장
        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("INSERT INTO MusicArtist (artist_name, artist_img) VALUES (?, ?)")) {
            pstmt.setString(1, artistName);
            pstmt.setString(2, "uploads/" + fileName); // 경로만 저장
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        response.getWriter().println("Artist uploaded successfully.");
    }

    // 파일명 추출
    private String getFileName(Part part) {
        for (String content : part.getHeader("content-disposition").split(";")) {
            if (content.trim().startsWith("filename")) {
                return content.substring(content.indexOf("=") + 2, content.length() - 1);
            }
        }
        return null;
    }
}
이미지 표시
저장된 이미지의 경로를 통해 JSP에서 이미지를 표시할 수 있습니다.
jsp
코드 복사
<img src="uploads/artist_image.jpg" alt="Artist Image">
2. 이미지 데이터를 BLOB으로 저장 (직접 DB 저장)
이미지를 파일이 아닌 BLOB(Binary Large Object) 형태로 데이터베이스에 저장하는 방법입니다.
이미지 데이터를 DB에 직접 저장하면 별도의 파일 시스템을 관리할 필요가 없지만, DB 크기가 커질 수 있습니다.
테이블 수정
artist_img 컬럼을 BLOB 타입으로 변경해야 합니다.

sql
코드 복사
ALTER TABLE MusicArtist MODIFY artist_img BLOB;
서블릿 구현
이미지 업로드 및 저장
java
코드 복사
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.*;
import java.sql.*;

@MultipartConfig
public class UploadArtistServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistName = request.getParameter("artistName");
        Part filePart = request.getPart("artistImg");

        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("INSERT INTO MusicArtist (artist_name, artist_img) VALUES (?, ?)")) {
            pstmt.setString(1, artistName);
            pstmt.setBlob(2, filePart.getInputStream()); // 이미지 데이터를 BLOB으로 저장
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        response.getWriter().println("Artist uploaded successfully.");
    }
}
이미지 읽기 및 표시
DB에서 BLOB 데이터를 읽고 JSP에서 출력합니다.
java
코드 복사
@WebServlet("/getImage")
public class GetImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistId = request.getParameter("id");

        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("SELECT artist_img FROM MusicArtist WHERE artist_id = ?")) {
            pstmt.setInt(1, Integer.parseInt(artistId));
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                Blob blob = rs.getBlob("artist_img");
                InputStream inputStream = blob.getBinaryStream();
                int fileLength = inputStream.available();

                response.setContentType("image/jpeg");
                response.setContentLength(fileLength);

                OutputStream outputStream = response.getOutputStream();
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                inputStream.close();
                outputStream.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
JSP에서 이미지 표시
jsp
코드 복사
<img src="getImage?id=1" alt="Artist Image">
어느 방법을 선택해야 할까?
이미지 경로 저장 (방법 1): 서버 디스크를 사용하며 성능과 유지보수가 더 쉽습니다. 추천!
이미지 BLOB 저장 (방법 2): DB 내에 모든 데이터를 중앙 집중화하고 싶을 때 사용합니다.
추가로 구현 과정이나 궁금한 점이 있으면 말씀해 주세요! 😊
  1. 서블릿에서 이미지 처리 및 저장
java
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.*;
import java.sql.*;

@MultipartConfig // 파일 업로드를 처리하기 위한 어노테이션
public class UploadArtistServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistName = request.getParameter("artistName");
        Part filePart = request.getPart("artistImg"); // 업로드된 파일을 가져옴
        String fileName = getFileName(filePart);

        // 저장할 경로 설정
        String uploadPath = getServletContext().getRealPath("") + File.separator + "uploads";
        File uploadDir = new File(uploadPath);
        if (!uploadDir.exists()) uploadDir.mkdir();

        // 파일 저장
        String filePath = uploadPath + File.separator + fileName;
        filePart.write(filePath);

        // DB에 경로 저장
        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("INSERT INTO MusicArtist (artist_name, artist_img) VALUES (?, ?)")) {
            pstmt.setString(1, artistName);
            pstmt.setString(2, "uploads/" + fileName); // 경로만 저장
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        response.getWriter().println("Artist uploaded successfully.");
    }

    // 파일명 추출
    private String getFileName(Part part) {
        for (String content : part.getHeader("content-disposition").split(";")) {
            if (content.trim().startsWith("filename")) {
                return content.substring(content.indexOf("=") + 2, content.length() - 1);
            }
        }
        return null;
    }
}
 
  1. 이미지 표시
  • 저장된 이미지의 경로를 통해 JSP에서 이미지를 표시할 수 있습니다.
<img src="uploads/artist_image.jpg" alt="Artist Image">

2. 이미지 데이터를 BLOB으로 저장 (직접 DB 저장)

  • 이미지를 파일이 아닌 BLOB(Binary Large Object) 형태로 데이터베이스에 저장하는 방법입니다.
  • 이미지 데이터를 DB에 직접 저장하면 별도의 파일 시스템을 관리할 필요가 없지만, DB 크기가 커질 수 있습니다.

테이블 수정

artist_img 컬럼을 BLOB 타입으로 변경해야 합니다.

ALTER TABLE MusicArtist MODIFY artist_img BLOB;

서블릿 구현

  1. 이미지 업로드 및 저장
import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.http.*;
import java.sql.*;

@MultipartConfig
public class UploadArtistServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistName = request.getParameter("artistName");
        Part filePart = request.getPart("artistImg");

        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("INSERT INTO MusicArtist (artist_name, artist_img) VALUES (?, ?)")) {
            pstmt.setString(1, artistName);
            pstmt.setBlob(2, filePart.getInputStream()); // 이미지 데이터를 BLOB으로 저장
            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        response.getWriter().println("Artist uploaded successfully.");
    }
}
  1. 이미지 읽기 및 표시
  • DB에서 BLOB 데이터를 읽고 JSP에서 출력합니다.
@WebServlet("/getImage")
public class GetImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String artistId = request.getParameter("id");

        try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "username", "password");
             PreparedStatement pstmt = conn.prepareStatement("SELECT artist_img FROM MusicArtist WHERE artist_id = ?")) {
            pstmt.setInt(1, Integer.parseInt(artistId));
            ResultSet rs = pstmt.executeQuery();

            if (rs.next()) {
                Blob blob = rs.getBlob("artist_img");
                InputStream inputStream = blob.getBinaryStream();
                int fileLength = inputStream.available();

                response.setContentType("image/jpeg");
                response.setContentLength(fileLength);

                OutputStream outputStream = response.getOutputStream();
                byte[] buffer = new byte[4096];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }

                inputStream.close();
                outputStream.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
 

 

'WEB' 카테고리의 다른 글

SQL SESSION 메서드  (0) 2024.12.02
SQL Session Factory  (0) 2024.12.02
JSP INCLUDE  (0) 2024.11.21
Scope  (0) 2024.11.20
서블릿 리스너  (0) 2024.11.20

1. 정적 포함 (<%@ include %> Directive)

정적 포함은 컴파일 시 포함할 JSP 파일의 내용을 컴파일 타임 포함된다. 이는 JSP가 변환될 때 포함된 파일의 내용이 대상 JSP에 합쳐져 하나의 서블릿으로 변환된다.

사용법:

<%@ include file="header.jsp" %>
 

특징:

  • 포함 파일 내용이 컴파일 시점에 병합됩니다.
  • 포함된 JSP 파일은 원본 JSP와 함께 하나의 서블릿 파일로 컴파일됩니다.
  • 주로 공통적인 HTML 구조(예: 헤더, 푸터, 사이드바)를 삽입할 때 유용합니다.
  • 파일의 변경 사항은 JSP를 다시 컴파일해야 반영됩니다.

예제:

header.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <h1>Welcome to My Website</h1>
</body>
</html>

index.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <%@ include file="header.jsp" %>
    <p>This is the main content.</p>
</body>
</html>

결과 출력:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <h1>Welcome to My Website</h1>
    <p>This is the main content.</p>
</body>
</html>
 

2. 동적 포함 (<jsp:include /> Action Tag)

동적 포함은 런타임 시점에 다른 JSP 파일의 내용 포함함 이 방식은 요청 시 포함된 파일을 실행하고 결과를 현재 JSP에 포함

사용법:

<jsp:include page="footer.jsp" />

특징:

  • 포함된 파일은 독립적으로 컴파일되고 실행됩니다.
  • 포함 파일의 변경 사항이 즉시 반영됩니다.
  • 요청마다 결과를 동적으로 가져오므로 요청 시 실행 결과를 삽입합니다.
  • 주로 동적인 콘텐츠(예: 현재 날짜, 사용자 정보 등)를 삽입할 때 유용합니다.

예제:

footer.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <h1>Welcome to My Website</h1>
    <p>This is the main content.</p>

    <footer>
        <p>&copy; 2024 My Website</p>
    </footer>
</body>
</html>
 

index.jsp

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <h1>Welcome to My Website</h1>
    <p>This is the main content.</p>

    <jsp:include page="footer.jsp" />
</body>
</html>

결과 출력:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Website</title>
</head>
<body>
    <h1>Welcome to My Website</h1>
    <p>This is the main content.</p>

    <footer>
        <p>&copy; 2024 My Website</p>
    </footer>
</body>
</html>

정적 포함과 동적 포함의 차이점

특징정적 포함 (<%@ include %>)동적 포함 (<jsp:include />)

포함 시점 컴파일 타임 런타임
변경 반영 JSP 재컴파일 필요 즉시 반영
성능 한 번 컴파일된 후 빠름 요청마다 실행되므로 다소 느릴 수 있음
용도 공통적인 HTML 구조 삽입 동적인 콘텐츠 삽입

선택 기준

  • 정적 포함: 레이아웃 템플릿처럼 변경되지 않는 고정된 파일을 포함할 때.
  • 동적 포함: 변경될 가능성이 있는 동적인 파일이나 데이터를 삽입할 때.

'WEB' 카테고리의 다른 글

SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
Scope  (0) 2024.11.20
서블릿 리스너  (0) 2024.11.20
서블릿 filter 설명  (0) 2024.11.20

//1. request 가 유ㅎ효한 동안 존재 (reqeust ==> response => 소멸

request.setAttribute("company", "신한DS");

 

//2.Browser 가 최초 접속시 생성 sessionId 가 Browser 에 쿠키 저장

//쿠키에서 session id 를 delete 하거나 logout (session.invalidate) 하면 제거

HttpSession session = request.getSession();

session.setAttribute("company", "기업은행");

 

//3. 서버가 시자되면 생성 , 종료되면 소멸

ServletContext context = getServletContext();

context.setAttribute("company", "기업은행");

 

request.getRequestDispatcher("받을 jsp ").forward(request,response);

 

response.getWriter().append("<h1>ScopeTest Setting</h1>");

 

 

1..${requestScope.company}
2..${sessionScope.company}
3..${applicationScope.company}

 

웹 개발에서 **스코프(Scope)**는 주로 서버와 클라이언트 간의 데이터와 객체의 유효 범위를 정의합니다. Java 웹 개발에서는 Servlet, JSP, Spring Framework 등 다양한 기술에서 스코프를 다룹니다. 여기서는 Java 웹 애플리케이션을 중심으로 웹에서 쓰이는 주요 스코프를 설명하겠습니다.

1. 웹 애플리케이션의 주요 스코프

웹 애플리케이션에서 데이터와 객체를 저장하고 사용할 때, 스코프는 객체의 생명주기(lifespan)와 범위를 정의합니다. Java 웹 개발에서는 주로 아래 네 가지 스코프를 사용합니다:

1.1 Request Scope

  • 정의: 하나의 HTTP 요청 동안 데이터를 저장합니다.
  • 유효 범위: 해당 요청이 끝날 때까지 (예: 서버가 응답을 반환할 때까지) 유지됩니다.
  • 용도:
    • 요청마다 다른 데이터를 처리할 때 사용 (예: 폼 입력 데이터, 검색 결과 등).
    • 요청 간 데이터가 공유되지 않아야 할 때 사용.
  • 저장 방법:
    • HttpServletRequest 객체에 데이터 저장
    • JSP에서: <jsp:useBean scope="request" />
  • 예시 (Servlet):
     
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    
    request.setAttribute("message", "Hello, Request Scope!");
    
    RequestDispatcher dispatcher = request.getRequestDispatcher("example.jsp");
    dispatcher.forward(request, response); // message는 example.jsp에서만 유효
}

1.2 Session Scope

  • 정의: 하나의 사용자 세션(session) 동안 데이터를 저장합니다.
  • 유효 범위:
    • 클라이언트와 서버 간의 세션이 유지되는 동안 (세션이 종료되거나, 명시적으로 무효화될 때까지).
  • 용도:
    • 사용자 로그인 정보, 장바구니 등 사용자별로 유지해야 할 데이터.
  • 저장 방법:
    • HttpSession 객체 사용
    • JSP에서: <jsp:useBean scope="session" />
  • 예시 (Servlet):
  • 주의사항:
    • 세션 데이터는 서버 메모리를 사용하므로, 많은 사용자 데이터를 저장하면 서버 부담이 커질 수 있습니다.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    HttpSession session = request.getSession();
    session.setAttribute("username", "JohnDoe"); // 세션에 데이터 저장

    response.sendRedirect("dashboard.jsp"); // username은 모든 요청에서 유지됨
}

 

1.3 Application Scope

  • 정의: 애플리케이션 전체에서 데이터를 저장합니다. 모든 사용자와 모든 요청이 공유합니다.
  • 유효 범위:
    • 애플리케이션 시작부터 종료될 때까지 유지됩니다.
    • 서버 재시작 시 사라짐.
  • 용도:
    • 애플리케이션에서 공통으로 사용되는 데이터 (예: 설정 정보, 전체 방문자 수 등).
  • 저장 방법:
    • ServletContext 객체 사용
    • JSP에서: <jsp:useBean scope="application" />
  • 예시 (Servlet):
  • 주의사항:
    • 모든 사용자가 데이터를 공유하기 때문에, 동기화를 신경 써야 함.
@Override
public void init() throws ServletException {
    getServletContext().setAttribute("appName", "My Web App");
}

1.4 Page Scope

  • 정의: 하나의 JSP 페이지 내에서만 데이터를 저장합니다.
  • 유효 범위:
    • JSP 페이지의 실행이 끝날 때까지.
  • 용도:
    • 특정 JSP 페이지 내에서만 사용해야 하는 임시 데이터.
  • 저장 방법:
    • JSP에서: <jsp:useBean scope="page" />
  • 예시 (JSP):
<jsp:useBean id="localBean" class="com.example.MyBean" scope="page" />

2. 주요 스코프 비교

스코프유효 범위유지 시간용도

Request 현재 HTTP 요청 요청 처리 완료 시까지 요청별 데이터 (폼, 검색 결과 등).
Session 사용자 세션 세션 종료 시까지 로그인 정보, 사용자별 데이터.
Application 애플리케이션 전체 서버 종료 시까지 공통 데이터 (예: 설정, 방문자 수).
Page 현재 JSP 페이지 페이지 처리 완료 시까지 특정 JSP 내의 임시 데이터.

3. 스코프 사용 예시

JSP에서 스코프 사용

<jsp:useBean id="user" class="com.example.User" scope="session" />
<%
    user.setName("Alice");
%>
<p>Welcome, <%= user.getName() %>!</p>

Servlet에서 데이터 전달 (Request Scope)

request.setAttribute("error", "Invalid username or password.");

RequestDispatcher dispatcher = request.getRequestDispatcher("login.jsp");
dispatcher.forward(request, response);

4. Spring Framework에서의 스코프

Spring Framework에서는 빈(bean)의 스코프를 설정하여 객체의 생명주기를 제어합니다. 주요 스코프는 다음과 같습니다:

  1. Singleton: 애플리케이션 전체에서 하나의 인스턴스만 생성.
  2. Prototype: 요청할 때마다 새로운 인스턴스 생성.
  3. Request: HTTP 요청마다 새로운 인스턴스 생성.
  4. Session: HTTP 세션마다 새로운 인스턴스 생성.
  5. Application: ServletContext 범위에서 인스턴스 생성.

웹 개발에서 스코프를 이해하면 데이터의 유효 범위를 적절히 설정하고, 메모리 낭비를 방지하며, 성능을 최적화할 수 있습니다. 특정 상황에 맞는 스코프를 선택하여 데이터를 효율적으로 관리

'WEB' 카테고리의 다른 글

SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21
서블릿 리스너  (0) 2024.11.20
서블릿 filter 설명  (0) 2024.11.20

**리스너 (Listener)**는 서블릿 컨테이너에서 발생하는 특정 이벤트를 감지하고, 이에 대한 동작을 정의하기 위해 사용하는 인터페이스입니다. 웹 애플리케이션에서 중요한 상태 변화(예: 애플리케이션 시작/종료, 세션 생성/종료, 요청 발생 등)를 감지하고 처리하는 데 활용됩니다.

리스너의 역할

  1. 웹 애플리케이션, 세션, 요청 등의 생명 주기를 감지.
  2. 상태 변경 이벤트를 처리(예: 세션 추적, 리소스 초기화/해제, 로그 기록 등).
  3. 설정 파일(web.xml) 또는 애너테이션으로 등록하여 동작.

리스너의 주요 종류

리스너는 감지하려는 대상(애플리케이션, 세션, 요청)에 따라 구분됩니다.

1. ServletContextListener

  • 웹 애플리케이션의 시작과 종료를 감지.
  • 주로 리소스 초기화 및 종료(예: 데이터베이스 연결 풀 생성/해제)에 사용.

메서드:

  • contextInitialized(ServletContextEvent event)
    → 애플리케이션이 시작될 때 호출.
  • contextDestroyed(ServletContextEvent event)
    → 애플리케이션이 종료될 때 호출.

예제:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyAppListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("애플리케이션 시작");
        // 리소스 초기화 코드
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println("애플리케이션 종료");
        // 리소스 해제 코드
    }
}

2. HttpSessionListener

  • 세션의 생성과 소멸을 감지.
  • 주로 사용자 세션 추적, 통계 수집 등에 사용.

메서드:

  • sessionCreated(HttpSessionEvent event)
    → 세션이 생성될 때 호출.
  • sessionDestroyed(HttpSessionEvent event)
    → 세션이 소멸될 때 호출.

예제:

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MySessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent event) {
        System.out.println("세션 생성됨: " + event.getSession().getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        System.out.println("세션 소멸됨: " + event.getSession().getId());
    }
}

3. ServletRequestListener

  • **요청(Request)**의 생성과 소멸을 감지.
  • 요청별 초기화 작업이나 로깅에 사용.

메서드:

  • requestInitialized(ServletRequestEvent event)
    → 요청이 생성될 때 호출.
  • requestDestroyed(ServletRequestEvent event)
    → 요청이 소멸될 때 호출.

예제:

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyRequestListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent event) {
        System.out.println("요청 시작");
    }

    @Override
    public void requestDestroyed(ServletRequestEvent event) {
        System.out.println("요청 종료");
    }
}
 

4. AttributeListener (속성 변경 감지 리스너)

  • **속성(Attribute)**의 추가, 수정, 삭제를 감지.
  • 세 가지 대상에 대해 각각의 리스너가 있음:
    • ServletContextAttributeListener
    • HttpSessionAttributeListener
    • ServletRequestAttributeListener

메서드:

  • attributeAdded(AttributeEvent event)
    → 속성이 추가될 때 호출.
  • attributeRemoved(AttributeEvent event)
    → 속성이 제거될 때 호출.
  • attributeReplaced(AttributeEvent event)
    → 속성이 변경될 때 호출.

예제 (HttpSessionAttributeListener):

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MyAttributeListener implements HttpSessionAttributeListener {

    @Override
    public void attributeAdded(HttpSessionBindingEvent event) {
        System.out.println("속성 추가: " + event.getName() + " = " + event.getValue());
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent event) {
        System.out.println("속성 제거: " + event.getName());
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent event) {
        System.out.println("속성 변경: " + event.getName());
    }
}

리스너 등록

리스너는 web.xml 파일이나 애너테이션으로 등록할 수 있습니다.

1. web.xml로 등록

<listener>
    <listener-class>com.example.MyAppListener</listener-class>
</listener>

2. 애너테이션으로 등록

import javax.servlet.annotation.WebListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

@WebListener
public class MyAppListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        System.out.println("애플리케이션 시작");
        // 리소스 초기화 코드
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println("애플리케이션 종료");
        // 리소스 해제 코드
    }
}

리스너의 활용 예

  1. 로그 기록: 사용자 세션, 요청별 로그 추적.
  2. 리소스 관리: 데이터베이스 연결 풀 초기화 및 해제.
  3. 세션 추적: 사용자 수 통계 계산.
  4. 요청 처리: 요청 전후의 전처리/후처리 작업.

결론

리스너는 서블릿 기반 웹 애플리케이션의 이벤트 처리를 돕는 강력한 도구입니다. 적절한 리스너를 사용하면 시스템의 상태를 효과적으로 관리하고, 애플리케이션 동작을 세밀하게 제어할 수 있습니다.

'WEB' 카테고리의 다른 글

SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21
Scope  (0) 2024.11.20
서블릿 filter 설명  (0) 2024.11.20

서블릿 필터(Servlet Filter)란?

서블릿 필터는 클라이언트 요청(Request) 또는 서버 응답(Response)이 서블릿이나 JSP와 같은 자원에 도달하기 전에 중간에서 요청과 응답을 가로채어 처리하는 기능을 제공합니다. 필터는 웹 애플리케이션의 동작을 확장하거나 수정하는 데 사용됩니다.

필터의 주요 특징

  1. 요청(Request)와 응답(Response) 처리
    • 요청을 사전 처리하거나, 응답을 후처리
  2. 재사용 가능:
    • 필터는 여러 서블릿 또는 JSP에서 공유되고 재사용
  3. 체인 형태로 연결 가능:
    • 여러 필터를 순차적으로 연결하여 체인을 구성

필터의 주요 사용 사례

  1. 인증 및 권한 검사:
    • 사용자가 특정 자원에 접근할 자격이 있는지 확인.
  2. 로깅 및 감사:
    • 요청, 응답, 클라이언트 정보를 기록.
  3. 데이터 압축:
    • 응답 데이터를 GZIP으로 압축하여 전송.
  4. 글로벌 설정:
    • 모든 요청에 대한 인코딩 설정(UTF-8 등).
  5. CORS 처리:
    • 교차 출처 리소스 공유(Cross-Origin Resource Sharing) 정책 설정.

필터의 작동 흐름

  1. 클라이언트 요청 → 필터 실행 → 서블릿 실행 → 필터 후처리 → 클라이언트 응답
    • 필터는 요청(Request) 전에 실행되고 응답(Response) 후에도 처리할 수 있습니다.

필터 구현 방법

1. 필터 인터페이스 구현

javax.servlet.Filter 인터페이스를 구현합니다. 주요 메서드는 다음과 같습니다:

  • init(FilterConfig filterConfig):
    • 필터 초기화 메서드. 필터가 최초로 로드될 때 호출됩니다.
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain):
    • 요청과 응답을 처리하는 핵심 메서드.
    • FilterChain을 사용하여 다음 필터 또는 서블릿으로 요청을 전달합니다.
  • destroy():
    • 필터가 제거될 때 호출되는 메서드. 자원 정리에 사용됩니다.

2. 필터 클래스 작성

import javax.servlet.*;
import java.io.IOException;

public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("필터 초기화");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // 요청 전 처리
        System.out.println("요청 전 처리");

        // 다음 필터 또는 서블릿으로 요청 전달
        chain.doFilter(request, response);

        // 응답 후 처리
        System.out.println("응답 후 처리");
    }

    @Override
    public void destroy() {
        System.out.println("필터 제거");
    }
}

3. 필터 설정 (web.xml)

필터를 특정 URL 패턴에 적용합니다

<filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>com.example.MyFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4. 필터 설정 (어노테이션, Java Config)

Java EE 6 이상에서는 어노테이션으로 필터를 설정할 수 있습니다:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*") // 모든 URL 패턴에 적용
public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("필터 초기화");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("요청 전 처리");

        chain.doFilter(request, response);

        System.out.println("응답 후 처리");
    }

    @Override
    public void destroy() {
        System.out.println("필터 제거");
    }
}

 

필터 체인(Filter Chain)

  • 여러 개의 필터가 등록된 경우, 등록된 순서대로 실행됩니다.
  • 각 필터는 FilterChain 객체를 통해 다음 필터 또는 서블릿으로 요청을 전달합니다.

필터 체인 동작 예시:

  1. 필터 A → 요청 전 처리
  2. 필터 B → 요청 전 처리
  3. 서블릿 실행
  4. 필터 B → 응답 후 처리
  5. 필터 A → 응답 후 처리

필터와 인터셉터의 차이

항목필터(Filter)인터셉터(Interceptor)

기술 스택 서블릿(Java EE) 기반 스프링(Spring) 기반
적용 범위 요청/응답 전체 스프링 MVC 컨트롤러
주요 목적 요청 및 응답 전후 공통 처리 컨트롤러 로직 전후 처리
구현 방식 javax.servlet.Filter HandlerInterceptor 구현

필터는 스프링과 관계없이 서블릿 환경에서 작동하며, 인터셉터는 스프링 MVC에 특화된 기능입니다.

결론

필터는 서블릿 기반 웹 애플리케이션에서 공통 로직을 중앙에서 관리하는 강력한 도구입니다. 인증, 로깅, 응답 데이터 압축 등 다양한 사용 사례에 활용할 수 있습니다. 필요에 따라 어노테이션 또는 XML 설정을 사용해 URL 패턴에 적용할 수 있습니다.

'WEB' 카테고리의 다른 글

SQL Session Factory  (0) 2024.12.02
이미지 파일저장  (0) 2024.11.21
JSP INCLUDE  (0) 2024.11.21
Scope  (0) 2024.11.20
서블릿 리스너  (0) 2024.11.20

+ Recent posts