useRef는 리액트 네이티브에서 DOM 요소나 컴포넌트의 참조를 유지하기 위해 사용되는 훅이다. 주로 컴포넌트의 상태를 관리하는 대신에 불변의 값을 저장하고, 렌더링 사이에 데이터를 유지할 때 유용하다.

# 기본 사용법

1. 참조 생성: useRef를 호출하여 참조 객체를 생성한다. 이 객체는 .current 속성을 가진다. 초기값을 설정할 수 있는데, 기본값은 undefined이다.

const myRef = useRef(initialValue);

2. DOM 요소에 할당: 생성한 참조를 특정 DOM 요소에 할당하여 그 요소에 접근할 수 있게 한다. 예를 들어, TextInput이나 View 컴포넌트에 ref 속성으로 전달한다.

<TextInput ref={myRef} />

3. 참조 값 접근: .current 속성을 통해 참조된 DOM 요소나 값에 접근한다. 이를 통해 포커스를 주거나, 요소의 크기 등을 직접 제어할 수 있다.

myRef.current.focus();

# 주의사항

  • 렌더링에 영향 없음: useRef를 통해 저장한 값은 렌더링 사이에서 유지되지만, 값이 변경되어도 컴포넌트가 재렌더링되지 않는다. 따라서 상태를 관리하는 데는 적합하지 않다.
  • 전역 상태 관리: useRef는 전역 상태 관리 도구와는 다르다. 상태를 공유해야 하는 경우에는 useContext나 상태 관리 라이브러리를 사용하는 것이 좋다.

# 활용 예시

1. 포커스 관리: 입력 필드에 포커스를 주기 위해 useRef를 활용할 수 있다.

const inputRef = useRef(null);

const focusInput = () => {
    inputRef.current.focus();
};

return (
    <>
        <TextInput ref={inputRef} />
        <Button title="Focus Input" onPress={focusInput} />
    </>
);

2. 타이머 관리: 타이머를 설정하고 해제할 때도 useRef를 사용할 수 있다.

const timerRef = useRef(null);

const startTimer = () => {
    timerRef.current = setTimeout(() => {
        console.log("타이머 완료");
    }, 1000);
};

const stopTimer = () => {
    clearTimeout(timerRef.current);
};

3. 애니메이션 효과: 애니메이션을 제어하는 데도 사용된다. 특정 애니메이션의 현재 상태를 저장하고 이를 기반으로 업데이트할 수 있다.

 

# 결론

useRef는 리액트 네이티브에서 DOM 요소나 값에 대한 참조를 쉽게 관리할 수 있도록 돕는 유용한 훅이다. 다양한 상황에서 활용할 수 있으며, 특히 상태 관리와는 다른 용도로 사용해야 함을 유념해야 한다. 이를 통해 보다 효율적으로 컴포넌트를 구성할 수 있다.

'JavaScript > ReactNative' 카테고리의 다른 글

Task 컴포넌트 정리  (0) 2024.09.27
IconButton 컴포넌트 정리  (0) 2024.09.26
input 컴포넌트 정리  (1) 2024.09.25
리액트 네이티브 navigation 정리  (1) 2024.09.17
리액트 네이티브 styled-components 정리  (0) 2024.09.16

React Native의 'Task' 구성 요소는 비동기 작업 및 백그라운드 작업을 처리하기 위해 애플리케이션에서 자주 사용되는 작업 관리 기능의 일부이다. 그러나 React Native 자체에는 'Task' 구성 요소가 내장되어 있지 않다는 점은 주목할 가치가 있다. 대신 작업 관리는 일반적으로 라이브러리나 사용자 정의 구현을 통해 처리된다.

 

# React Native 작업의 공통 컨텍스트

백그라운드 작업: 앱이 백그라운드에 있을 때에도 작업을 실행할 수 있는 react-native-Background-fetch 또는 react-native-Background-task와 같은 라이브러리를 통해 관리되는 경우가 많다.

Async/Await: 구성 요소 내에서 비동기 작업을 처리하기 위해 React Native는 JavaScript의 기본 async/await 구문을 사용하여 Promise를 관리하므로 더 깔끔하고 읽기 쉬운 비동기 코드를 쉽게 작성할 수 있다.

라이브러리 사용: Redux-Saga: 애플리케이션의 부작용을 관리하는 데 널리 사용되는 라이브러리이다. 생성기 기능을 사용하여 보다 관리하기 쉬운 방식으로 작업을 처리하고 비동기 작업을 위한 명확한 구조를 제공한다.
React Query: 데이터 가져오기 및 캐싱의 경우 자동 백그라운드 가져오기, 캐싱 및 동기화를 통해 데이터 관리를 단순화한다.

# 작업 구현

* 상태 관리:

React의 'useState' 또는 컨텍스트 API를 사용하여 작업 상태를 관리할 수 있다. 또한 대규모 애플리케이션에서는 Redux 또는 MobX가 전역 상태 관리에 도움이 될 수 있다.

 

1. 비동기 작업:
예시(async/await를 사용):

const fetchData = async () => {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
  } catch (error) {
    console.error(error);
  }
};

 

2. 백그라운드 작업:
- 예시(반응 네이티브 배경 가져오기):

import BackgroundFetch from "react-native-background-fetch";

const onBackgroundFetch = async (taskId) => {
  console.log("[BackgroundFetch] taskId:", taskId);
  BackgroundFetch.finish(taskId);
};

BackgroundFetch.configure({
  minimumFetchInterval: 15, 
}, onBackgroundFetch);

 

- 작업 수명 주기:
작업 완료를 올바르게 처리했는지 확인해야 한다. 사용하는 방법(예: 콜백 또는 약속)에 따라 작업이 완료되면 애플리케이션에 알리도록 하여 리소스가 효과적으로 관리되도록 한다.


- 오류 처리:
앱이 응답성을 유지하고 오류 발생 시 사용자에게 피드백을 제공할 수 있도록 작업에 대한 강력한 오류 처리를 구현한다.

 

# 성능 고려 사항

1. 제한 및 디바운싱: 특히 데이터 가져오기와 같은 기능의 경우 작업 실행 빈도를 제한하는 전략을 구현하여 성능을 향상하고 API의 부하를 줄인다.
2. 메모리 관리: 특히 대규모 데이터세트나 복잡한 계산을 처리할 때 작업 실행 시간과 작업이 메모리에 미치는 영향을 고려한다.

# 간단한 작업 구성 요소의 예

import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';

const TaskComponent = () => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const fetchData = async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch('https://api.example.com/data');
      const result = await response.json();
      setData(result);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData();
  }, []);

  return (
    <View>
      {loading && <Text>Loading...</Text>}
      {error && <Text>Error: {error}</Text>}
      {data && <Text>{JSON.stringify(data)}</Text>}
      <Button title="Refresh" onPress={fetchData} />
    </View>
  );
};

export default TaskComponent;

 

결론
React Native의 작업 개념은 주로 비동기 작업을 효과적으로 관리하는 것이다. 비동기 기능, 백그라운드 라이브러리 또는 상태 관리 솔루션을 통해 작업을 처리하든 목표는 반응성이 뛰어나고 효율적인 애플리케이션을 만드는 것이다. 구체적인 구현은 프로젝트 요구 사항에 따라 달라진다.

'JavaScript > ReactNative' 카테고리의 다른 글

useRef 정리  (1) 2024.09.30
IconButton 컴포넌트 정리  (0) 2024.09.26
input 컴포넌트 정리  (1) 2024.09.25
리액트 네이티브 navigation 정리  (1) 2024.09.17
리액트 네이티브 styled-components 정리  (0) 2024.09.16

IconButton 컴포넌트는 사용자가 아이콘을 클릭하여 특정 작업을 수행할 수 있도록 하는 버튼을 생성하는 데 사용된다. 일반적으로 이 컴포넌트는 모바일 애플리케이션에서 자주 사용되는 UI 요소로, 직관적인 사용자 경험을 제공하는 데 중요한 역할을 한다.

# 주요 특징

  1. 아이콘 표시: IconButton은 보통 텍스트 대신 아이콘을 사용하여 시각적으로 명확한 액션을 제시한다. 이를 통해 사용자가 버튼의 기능을 빠르게 이해할 수 있도록 돕는다.
  2. 스타일링: IconButton은 다양한 스타일링 옵션을 제공하여 사용자가 원하는 디자인에 맞게 버튼을 꾸밀 수 있다. 색상, 크기, 모양 등을 자유롭게 조정할 수 있다.
  3. 상태 관리: IconButton은 눌림 상태나 비활성 상태와 같은 다양한 상태를 관리할 수 있는 기능을 제공한다. 이를 통해 사용자가 버튼의 현재 상태를 쉽게 인식할 수 있게 된다.
  4. 터치 피드백: 사용자 인터랙션을 고려하여 터치 시 피드백을 제공하는 기능이 포함되어 있다. 예를 들어, 버튼을 누를 때 색상이 변경되거나 애니메이션 효과가 발생하여 사용자가 버튼을 클릭하고 있다는 것을 시각적으로 알 수 있게 한다.
  5. 접근성: IconButton은 접근성을 고려하여 설계되어, 화면 읽기 프로그램에서 아이콘의 의미를 설명할 수 있는 속성을 추가할 수 있다. 이를 통해 모든 사용자가 편리하게 이용할 수 있도록 한다.

# 예시

IconButton 컴포넌트를 사용하려면 다음과 같은 기본적인 코드를 참고할 수 있다:

import React from 'react';
import { IconButton } from 'react-native-paper';

const MyComponent = () => {
  return (
    <IconButton
      icon="plus"
      color="white"
      size={20}
      onPress={() => console.log('Button pressed')}
      style={{ backgroundColor: 'blue' }}
    />
  );
};

위의 예시에서 icon 속성은 버튼에 표시될 아이콘을 지정하며, color와 size는 각각 아이콘의 색상과 크기를 설정한다. onPress 속성은 버튼 클릭 시 실행될 함수를 정의한다.

# 통합 및 사용 시 유의사항

  • 라이브러리 설치: IconButton 컴포넌트를 사용하기 위해 필요한 라이브러리를 먼저 설치해야 한다. 예를 들어, react-native-paper와 같은 라이브러리를 사용하여 IconButton을 가져올 수 있다.
  • 아이콘 라이브러리: 아이콘은 보통 FontAwesome, MaterialIcons 등과 같은 아이콘 라이브러리를 통해 가져오게 되므로, 필요한 아이콘이 포함된 라이브러리를 사전에 설정해야 한다.
  • 상태 관리: 여러 상태를 관리해야 할 경우, React의 상태 관리 훅인 useState를 활용하여 버튼의 상태를 적절히 관리할 수 있다.

'JavaScript > ReactNative' 카테고리의 다른 글

useRef 정리  (1) 2024.09.30
Task 컴포넌트 정리  (0) 2024.09.27
input 컴포넌트 정리  (1) 2024.09.25
리액트 네이티브 navigation 정리  (1) 2024.09.17
리액트 네이티브 styled-components 정리  (0) 2024.09.16

리액트 네이티브 input 컴포넌트는 사용자로부터 데이터를 입력받기 위해 사용되는 기본적인 UI 요소이다. 주로 텍스트 입력 필드로 활용되며, 사용자가 정보를 입력할 수 있도록 도와준다.

# 기본 구성 요소

인풋 컴포넌트는 TextInput이라는 기본 컴포넌트를 사용하여 구현한다. 이 컴포넌트는 다음과 같은 기본 속성을 갖는다:

  • value: 입력 필드에 표시될 텍스트를 설정한다. 상태(state)를 통해 제어할 수 있다.
  • onChangeText: 사용자가 입력할 때마다 호출되는 콜백 함수를 정의한다. 이 함수를 통해 입력된 텍스트를 상태에 저장할 수 있다.
  • placeholder: 입력 필드에 사용자가 입력하기 전에 보여줄 힌트 텍스트를 설정한다.
  • secureTextEntry: 비밀번호 입력 시 사용하여 텍스트가 숨겨지도록 설정한다.

# 예제

기본적인 TextInput 사용 예시:

import React, { useState } from 'react';
import { View, TextInput, StyleSheet } from 'react-native';

const InputExample = () => {
  const [text, setText] = useState('');

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="여기에 입력하세요"
        value={text}
        onChangeText={setText}
        secureTextEntry={false}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 16,
  },
  input: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
    paddingHorizontal: 10,
  },
});

export default InputExample;

# 추가 속성

인풋 컴포넌트에는 여러 추가 속성을 설정할 수 있다. 예를 들어:

  • keyboardType: 입력할 키보드의 유형을 설정한다. 예를 들어, 숫자만 입력받고 싶을 때 keyboardType="numeric"을 설정할 수 있다.
  • maxLength: 입력 가능한 최대 문자 수를 제한할 수 있다.
  • multiline: 여러 줄 입력을 가능하게 하며, numberOfLines 속성과 함께 사용할 수 있다.

# 스타일링

인풋 컴포넌트의 스타일은 StyleSheet를 사용하여 조정할 수 있다. 기본적으로 borderColor, borderWidth, padding 등을 설정하여 시각적으로 구분할 수 있도록 한다.

# input 컴포넌트 요약

리액트 네이티브의 인풋 컴포넌트는 사용자와 상호작용하는 중요한 요소이며, 다양한 속성을 통해 사용자 입력을 쉽게 처리할 수 있도록 돕는다. 상태 관리를 통해 실시간으로 입력값을 업데이트하며, 필요에 따라 추가적인 기능을 구현할 수 있다.

jest.mock은 JavaScript 테스트 프레임워크인 Jest에서 특정 모듈이나 함수의 동작을 가짜(mock)로 바꾸기 위해 사용된다. jest.mock을 활용하면 외부 의존성(데이터베이스, API 호출, 파일 시스템 등) 없이 단위 테스트를 수행할 수 있어 테스트 속도가 빨라지고, 테스트 환경을 보다 안정적으로 만들 수 있다.

# 기본 사용법

jest.mock(moduleName, factory) 메서드는 두 가지 매개변수를 받는다:

  • moduleName: 모의(mock)하려는 모듈의 경로 또는 이름.
  • factory: 선택 사항으로, 가짜(mock) 구현을 반환하는 함수.
jest.mock('module-name');

예시는 'module-name' 모듈을 모의(mock)로 전환한다. 이 경우 기본적으로 자동 모의(자동으로 생성된 가짜 함수)가 제공된다.

# 모의 함수의 기본 동작

모듈을 jest.mock()으로 모의하게 되면:

  • 해당 모듈의 모든 함수는 자동으로 모의 함수(mock function)가 된다.
  • 모의 함수는 기본적으로 undefined를 반환하며, 호출 여부를 추적할 수 있다.
  • 필요에 따라 모의 함수의 반환값이나 동작을 설정할 수 있다.

# 자동 모의 vs 수동 모의

1) 자동 모의(Auto Mocking)

jest.mock('module-name')을 사용하면, Jest는 해당 모듈의 모든 함수를 자동으로 모의(mock)한다. 자동 모의는 해당 함수들이 단순한 jest.fn()으로 대체된다.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// math.test.js
import * as math from './math';

jest.mock('./math');

test('add function is mocked', () => {
  math.add.mockReturnValue(3); // mock에서 반환값을 정의
  expect(math.add(1, 2)).toBe(3); // 실제 동작과 관계 없이 3을 반환
});

예시에서 math.add는 더 이상 실제로 작동하지 않고 모의 함수로 대체된다.

2) 수동 모의(Manual Mocking)

Jest는 수동으로도 모듈을 모의(mock)할 수 있다. 이를 위해 factory 함수를 두 번째 인자로 전달하여 직접 가짜 구현을 정의할 수 있다.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// math.test.js
import * as math from './math';

jest.mock('./math', () => ({
  add: jest.fn(() => 10), // add 함수는 언제나 10을 반환
  subtract: jest.fn(() => 5), // subtract 함수는 언제나 5를 반환
}));

test('add function returns 10', () => {
  expect(math.add(1, 2)).toBe(10);
});

test('subtract function returns 5', () => {
  expect(math.subtract(10, 5)).toBe(5);
});

이 방식에서는 각 함수의 동작을 세밀하게 정의할 수 있으며, 모듈 내부의 특정 함수들만 모의할 수 있다.

# 모의 함수의 동작 설정

모의 함수는 다양한 방식으로 동작을 설정할 수 있다. 대표적인 방법은 다음과 같다:

1) mockReturnValue

모의 함수가 항상 특정 값을 반환하도록 설정한다.

const myMock = jest.fn();
myMock.mockReturnValue('default value');

console.log(myMock()); // 'default value'

2) mockResolvedValue

비동기 함수에서 Promise.resolve와 같이 동작하도록 설정한다. 즉, 모의 함수가 항상 특정 값을 포함한 Promise를 반환하게 한다.

const myMock = jest.fn();
myMock.mockResolvedValue('resolved value');

myMock().then((value) => console.log(value)); // 'resolved value'

3) mockRejectedValue

비동기 함수에서 Promise.reject와 같이 특정 에러를 포함한 Promise를 반환하게 한다.

const myMock = jest.fn();
myMock.mockRejectedValue(new Error('error'));

myMock().catch((e) => console.log(e.message)); // 'error'

4) mockImplementation

모의 함수의 전체 동작을 재정의할 수 있다. 이 방식은 복잡한 로직을 구현할 때 유용하다.

const myMock = jest.fn().mockImplementation((a, b) => a + b);
console.log(myMock(1, 2)); // 3

5) mockImplementationOnce

모의 함수의 동작을 한 번만 설정할 수 있다. 그 이후에는 기본 동작으로 돌아간다.

const myMock = jest.fn().mockImplementationOnce(() => 'first call').mockImplementationOnce(() => 'second call');
console.log(myMock()); // 'first call'
console.log(myMock()); // 'second call'
console.log(myMock()); // undefined (이후에는 기본 동작)

# 특정 함수만 모의하기

모듈 내에서 특정 함수만 모의하고 나머지는 실제로 동작하도록 설정하려면 jest.spyOn()을 사용할 수 있다.

// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;

// math.test.js
import * as math from './math';

test('spyOn add function', () => {
  const addSpy = jest.spyOn(math, 'add').mockReturnValue(10);
  expect(math.add(1, 2)).toBe(10);
  addSpy.mockRestore(); // 원래 함수로 복구
  expect(math.add(1, 2)).toBe(3); // 실제 함수가 실행됨
});

jest.spyOn을 사용하면 함수의 일부 호출을 모의(mock)로 대체하고, 이후 다시 원래 동작으로 복구할 수 있다.

# 타이머 및 글로벌 객체 모의

1) 타이머 모의

setTimeout, setInterval과 같은 타이머 함수들도 jest.useFakeTimers()를 사용하여 모의할 수 있다.

jest.useFakeTimers();

test('calls setTimeout with 1000ms', () => {
  const callback = jest.fn();
  setTimeout(callback, 1000);
  jest.runAllTimers(); // 모든 타이머 즉시 실행
  expect(callback).toBeCalled();
});

2) 글로벌 객체 모의

window.fetch 같은 글로벌 객체도 모의할 수 있다.

global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ data: 'test data' }),
  })
);

# 모의 리셋 및 초기화

모의 함수의 상태를 리셋하거나 초기화할 수 있다:

  • mockClear(): 함수 호출 기록을 초기화한다.
  • mockReset(): 호출 기록과 함께 모의 함수 구현 자체를 리셋한다.
  • mockRestore(): 원래 함수 구현을 복구한다(스파이 함수 사용 시 유용).
const myMock = jest.fn().mockReturnValue('test');

myMock();
expect(myMock).toHaveBeenCalled();

myMock.mockClear();
expect(myMock).not.toHaveBeenCalled();

# 모의 함수 호출 추적

모의 함수가 어떻게 호출되었는지, 몇 번 호출되었는지, 어떤 인자들로 호출되었는지를 추적할 수 있다.

const myMock = jest.fn();

myMock(1);
myMock(2, 'second call');

expect(myMock).toHaveBeenCalledTimes(2); // 2번 호출됨
expect(myMock).toHaveBeenCalledWith(1); // 첫 번째 호출에서 1로 호출됨
expect(myMock).toHaveBeenLastCalledWith(2, 'second call'); // 마지막 호출에서 2와 'second call'로 호출됨

결론

jest.mock은 테스트 환경에서 모듈과 함수의 동작을 모의하기 위한 강력한 도구이다. 이를 통해 외부 의존성을 제거하고, 테스트 환경을 제어할 수 있으며, 가짜 데이터를 기반으로 다양한 테스트 시나리오를 설정할 수 있다.

'JavaScript > JavaScript' 카테고리의 다른 글

Await 정리  (1) 2024.09.05

스프링 MVC에서 서블릿 컨테이너 초기화는 서블릿 기반의 웹 애플리케이션이 실행될 때 컨테이너가 애플리케이션을 시작하고, 요청을 처리하는 구조를 설정하는 중요한 단계이다. 이를 이해하려면 서블릿 컨테이너와 스프링의 역할을 각각 분리해서 설명할 필요가 있다.

# 서블릿 컨테이너의 역할

서블릿 컨테이너는 Java EE (지금은 Jakarta EE) 웹 애플리케이션 서버에서 제공되는 컴포넌트로, 서블릿을 실행하고 관리한다. 서블릿은 HTTP 요청을 처리하고 응답을 생성하는 역할을 한다. 대표적인 서블릿 컨테이너는 Tomcat, Jetty, Undertow 등이 있습니다.

서블릿 컨테이너는 애플리케이션이 시작될 때 다음과 같은 일들을 수행한다:

  • 서블릿 등록 및 초기화: web.xml 파일이나 애노테이션 기반 설정을 통해 서블릿 클래스를 인식하고, 해당 서블릿을 초기화한다.
  • HTTP 요청 수신 및 전달: HTTP 요청이 들어오면 적절한 서블릿으로 요청을 전달하고, 서블릿이 응답을 생성하면 클라이언트에게 반환한다.

# 스프링 MVC의 역할

스프링 MVC는 서블릿 컨테이너 위에서 동작하는 웹 프레임워크로, 사용자 요청을 효과적으로 처리하고, 비즈니스 로직과 프레젠테이션 로직을 분리하는 역할을 한다. 스프링 MVC는 자체적으로 서블릿을 포함하지 않지만, 스프링 MVC를 동작시키기 위해 서블릿 컨테이너에 통합된다.

# DispatcherServlet

스프링 MVC의 중심이 되는 것은 DispatcherServlet다. 이 서블릿은 스프링에서 제공하는 프론트 컨트롤러로, 모든 HTTP 요청을 받아서 적절한 컨트롤러로 전달하고, 그 결과를 뷰로 변환하여 응답을 반환한다.

DispatcherServlet의 초기화 과정:

  1. 서블릿 컨테이너가 실행되면 스프링 애플리케이션에서 정의된 DispatcherServlet이 서블릿 컨테이너에 의해 로드된다.
  2. 서블릿 초기화 단계: DispatcherServlet이 초기화될 때, 스프링의 WebApplicationContext가 생성된다. 이 WebApplicationContext는 애플리케이션의 전반적인 설정과 빈(bean)들을 관리한다.
  3. 핸들러 매핑과 뷰 리졸버 설정: WebApplicationContext는 컨트롤러, 서비스, 레포지토리 등의 빈을 생성하고, 요청을 처리할 핸들러(컨트롤러 메서드)를 찾기 위한 매핑 정보도 설정한다. 또한 뷰를 어떻게 렌더링할 것인지 결정하는 뷰 리졸버도 설정된다.
  4. 요청 처리: 서블릿 컨테이너가 HTTP 요청을 수신하면 DispatcherServlet이 그 요청을 처리하고, 적절한 컨트롤러로 요청을 전달한 후, 결과를 다시 클라이언트에게 반환한다.

# ServletContext 초기화

DispatcherServlet을 서블릿 컨테이너에 등록하려면 ServletContext와 같은 객체를 사용해야 한다. 전통적으로 web.xml 파일을 사용하여 서블릿을 등록했지만, 최근에는 애노테이션과 자바 기반 설정이 더 많이 사용된다.

 

예시: 자바 기반 설정을 사용한 DispatcherServlet 등록

WebApplicationInitializer 인터페이스를 사용하여 서블릿 초기화 과정을 정의할 수 있다. 이 인터페이스는 서블릿 컨테이너가 초기화될 때 호출된다.

public class MyWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(AppConfig.class); // 설정 클래스 등록

        DispatcherServlet dispatcherServlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", dispatcherServlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

# 서블릿 3.0 이상에서의 편리한 초기화

서블릿 3.0 이상에서는 web.xml을 사용하지 않고 서블릿을 등록할 수 있는 애노테이션 기반 설정을 사용할 수 있다. @WebServlet, @WebFilter, @WebListener 같은 애노테이션을 사용하여 서블릿, 필터, 리스너를 직접 코드에서 설정할 수 있다.

스프링 MVC에서는 이를 더욱 편리하게 하기 위해 AbstractAnnotationConfigDispatcherServletInitializer 클래스를 제공하여, 개발자가 간단하게 서블릿 컨테이너에 DispatcherServlet을 등록할 수 있도록 돕는다.

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

# 서블릿 컨테이너 초기화 지원 요약

  • 스프링 MVC에서 DispatcherServlet은 서블릿 컨테이너에 의해 관리되며, 모든 HTTP 요청을 프론트 컨트롤러 패턴을 사용해 처리한다.
  • 스프링은 자바 기반 설정이나 애노테이션을 사용하여 서블릿 초기화를 쉽게 지원하며, 서블릿 3.0 이후로는 코드 기반 서블릿 등록이 가능해졌다.
  • WebApplicationInitializer 또는 AbstractAnnotationConfigDispatcherServletInitializer 등을 사용하면 서블릿을 유연하게 초기화할 수 있다.

이 과정을 통해 스프링 MVC는 서블릿 컨테이너에서 실행되며, HTTP 요청을 받아서 적절한 핸들러(컨트롤러)로 전달하고, 결과를 클라이언트에게 반환하는 구조를 갖춘다.

'Java > Spring' 카테고리의 다른 글

스프링 컨테이너 정리  (0) 2024.09.20

+ Recent posts