[Front] React 소스 구현(1) - UserListComponent

조성권·2021년 10월 16일
0
post-thumbnail

이번 게시글은 기본적인 개발환경을 구축한 상태라는 가정하에 React를 통한 front 개발과정을 노트하려 한다.
본 작성글은 프로젝트 전체 소스가 아닌 일부 컴포넌트(UserListComponent)에 대한 소스 리뷰이며 계속해서 남은 컴포넌트들에 대해 작성해보도록 하겠다.

개발 목표

이번 프로젝트를 통해 이루고자 하는 궁극적인 개발 목표는 CRUD가 가능한 게시판을 만드는 것이다.

이를 위해 Back단과 Front단을 각각 Spring-Boot와 React로 구성하려 하고 있으며 본 작성글은 Front단에 대한 내용을 작성한다.

tree 구조

React 프로젝트의 tree 구조는 아래와 같이 작성하려 한다.

  • 구성 요소
    src/component/user: 실제 사용자가 보게되는 화면에 대한 컴포넌트
    src/component/route: 페이지 이동 간, 라우팅 관련 컴포넌트
    ApiService.js: Back단과 통신을 하기 위한 API 컴포넌트

소스 분석

이번 글은 서두에 언급한 것처럼 등록된 사용자의 정보를 출력하는 메인 컴포넌트(UserListComponent)에 대해 집중적으로 알아보겠다.

1. constructor

React 생명주기 상, 컴포넌트가 처음 띄워질 때, 호출되는 constructor(props) 부분부터 살펴보자

constructor(props){
	super(props);
    
	this.state={
		user:[]
		message:null
	}
}
  • constructor 역할:
    Component를 생성할 때, state 값을 초기화하거나 메서드를 바인딩할 때 사용

우리는 해당 페이지에서 필요한 state가 크게 두 가지이다.

  1. 화면에 뿌려줄 user 데이터 목록
  2. api 통신 결과에 대한 message

그래서 위와 같이 state에 대한 초기화를 진행했다.
state에 대한 개념이 아직 익숙치 않다면 이곳을 통해 한번 집고 오도록 하자.


2. componentDidMount

다음은 componentDidMount()부분이다.
이 역시 constructor(props)와 동일하게 react 생명주기를 담당하는 함수 중, 하나이다.

  • 컴포넌트 생성 시 LifeCycle:
    constructor > componentwillMount > render > componentDidMount

위와 같이 컴포넌트가 처음 화면에 띄워지기 위한 Cycle 중, 하나로써 실행되며 우리는 위 함수를 통해 다음과 같이 작성했다.

componentDidMount(){
	this.reloadUserList();
}

그렇다면 reloadUserList()는 무엇일까?

reloadUserList=()={
	ApiService.getAllUsers(
	.then(res=>{
		this.setState({users:res.data})
	})
	.catch(err=>{
		console.log('reload ERROR',err);
	})
}

아직 ApiService 컴포넌트에 대한 설명을 하지 않았기 때문에 디테일한건 알 수 없지만 함수명을 통해 API를 통해 전체 User 리스트를 불러온다는 것을 어림짐작할 수 있다.

.then(~):
비동기 호출을 처리하는 콜백함수로서 데이터를 불러왔을 때, 해당 데이터를 state.users에 저장
.catch(~):
호출에 대한 처리 중, 오류 발생으로 비정상 처리되었을 때, 호출

종합하자면 화면이 처음 띄워질 때, ComponentDidMount() > reloadUserList()로 넘어가며 user정보를 모두 끌어오고 이를 state에 저장하는 기능을 담당한다고 볼 수 있다.


3. 주요 기능 호출 Func (delete,edit,add)

deleteUser=(userID)=>{
	ApiService.deleteUserByID(userID)
	.then(res=>{
		this.setState({message:'User deleted successfully'});
		this.setState({
			users:this.state.users.filter(user=>user.id != userID)
		});
	})
	.catch(err=>{
		console.log('delete ERROR', err);
	})
}

위 코드는 함수명 그대로 유저 삭제 버튼 클릭 시, 호출되는 함수이다.
ApiService를 통해 해당 userID정보를 Back단에 넘김으로써 데이터 삭제를 유도한다.
그 후, 정상적으로 데이터가 지워졌다면 해당 message를 저장하고
기존 users 정보 중, 해당 userID를 filter를 통해 걸러낸 나머지 것들로만 다시 users를 구성한다.


editUser=(ID)=>{
window.localStorage.setItem("userID",ID);
this.props.history.push('/edit-user');
}

위 코드는 함수명 그대로 유저 정보 수정 버튼 클릭 시, 호출되는 함수이다.

  • localStorage:
    말 그대로 사용자 로컬환경에 데이터를 보존하는 방식이다.
    이는 일정시간 or 영구적으로 값을 저장/사용할 수 있으며 JavaScript를 통해 조작할 수 있다.
  • window.localStorage.setItem(Key, Value);
    localStorage에 Key:Value 형태로 저장하게 되며 페이지 이동 후 getItem(Key)를 통해 값을 불러올 수 있다.
  • this.props.history.push(pathname):
    라우팅을 통해 현재 페이지에서 pathname에 해당하는 페이지로 이동시켜주는 역할

즉 다시 말해, editUser 함수는 해당 유저 ID를 localStorage에 담고 현재 페이지의 pathname에 해당하는 다음 페이지로 넘겨주는 역할을 수행한다고 볼 수 있다.


addUser=()=>{
	window.localStorage.removeItem("userID");
	this.props.history.push('/add-user');
}

위 코드는 함수명 그대로 유저 추가 버튼 클릭 시, 호출되는 함수이다.

  • window.localStorage.removeItem("userID");: 만약, 아직 userID라는 key안에 데이터가 남아있다면 삭제를 통한 초기화
  • this.props.history.push('/add-user'):: '/add-user'로 넘어갈 때, 현재 페이지의 props를 넘김

4. render 함수

마지막으로 render 함수에 대해 알아보도록 하겠다.
render함수는 실질적으로 화면 렌더링 작업을 진행하는 영역으로 화면 레이아웃을 구성하기 위한 JSX로 구성되어 있다.
JSX에 대한 이론적인 부분이 궁금한 분들은 이곳을 통해 한번 훓어보면 좋을 것 같다.

render(){
	return(
		<div>
			<Typography variant="h4" style={style}>User List</Typography>
			<Button variant="contained" color="primary" onClick={this.addUser}> Add User</Button>
			<Table>
				<TableHead>
					<TableRow>
						<TableCell>index</TableCell>
						<TableCell align="right">FirstName</TableCell>
						<TableCell align="right">LastName</TableCell>
						<TableCell align="right">Username</TableCell>
						<TableCell align="right">Age</TableCell>
						<TableCell align="right">Salary</TableCell>
						<TableCell align="right">Edit</TableCell>
						<TableCell align="right">Delete</TableCell>
					</TableRow>
				</TableHead>
					
				<TableBody>
					{
						this.state.users.map(user=>
						<TableRow key={user.id}>
							<TableCell component="th" scop="user">{user.id}</TableCell>
							<TableCell align="right">{user.firstName}</TableCell>
							<TableCell align="right">{user.lastName}</TableCell>
							<TableCell align="right">{user.username}</TableCell>
							<TableCell align="right">{user.age}</TableCell>
							<TableCell align="right">{user.salary}</TableCell>
							<TableCell align="right" onClick={()=>this.editUser(user.id)}>
								<CreateIcon/>
							</TableCell>
							<TableCell align="right" onClick={()=>this.deleteUser(user.id)}>
								<DeleteIcon/>
							</TableCell>
						</TableRow>
					)}
				</TableBody>
			</Table>
		</div>
	);
}

여기서 가장 특이하다고 느끼는 부분은 <Typography>, <TextField>와 같은 태그일 것이다.
이들은 모두 Material UI의 일부이다.

이론적인 부분을 여기서 깊게 다루진 않겠지만 간단히 말하자면 화면에 대한 css를 입힐 때, 이에 대한 이해나 경험이 부족한 경우 보다 편하게 UI를 입힐 수 있는 React UI 컴포넌트 라이브러리라고 해두자.

그래서 우리는 이러한 태그들을 조합하여 아래와 같은 메인 페이지를 만들 수 있다.

profile
천천히, 완벽히 배워나가고자 하는 웹 서비스 엔지니어

0개의 댓글