[Javascript] AXIOS 사용하여 Flask와 통신 - JSON, FormData 전송
AXIOS는 Javascript와 Flask 사이에 데이터를 주고 받는 AJAX 통신 방식 중 하나이다.
1. JSON 데이터 전송
AXIOS 통신은 자동으로 데이터를 JSON 형식으로 변환시켜 준다. JSON은 {key: vaue} 배열로 형식이 간단하여 데이터를 읽고 쓰기 쉽다. HTML에서 user-email 값을 받아와 JSON 형식으로 자동으로 변환하여 Flask 서버로 전달할 수 있다. Fetch API를 사용한다면 수동으로 JSON.stringify()을 사용하여 변환해야 한다.
<HTML>
<div class="form-group">
<label for="user-email">이메일</label>
<div class="email-form">
<input type="email" id="user-email" name="user-email" placeholder="Email" required>
<button type="button" id="confirm-email">중복 확인</button>
</div>
<p id="email-result"></p>
</div>
<Javascript>
confirm-email 버튼을 클릭하면 함수가 실행된다. 이메일 형식 검증 후, 이메일 형식이 올바르지 않으면 텍스트를 띄우고 함수가 종료된다. 검증이 통과되면, AXIOS 통신(POST)을 시작하여 JSON 형식으로 데이터를 Flask에 전송한다. 플라스크에서 처리 후 결과가 돌아오면 이를 email-result에 반영한다.
// comfirm email
document.getElementById('confirm-email').addEventListener('click', function(e) {
e.preventDefault();
const userEmail = document.getElementById('user-email').value;
const emailResult = document.getElementById('email-result');
// 이메일 형식 검증을 위한 정규표현식
const emailRegex = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
if (!emailRegex.test(userEmail)) {
emailResult.textContent = '올바른 이메일 형식이 아닙니다';
emailResult.style.color = 'red';
return;
}
axios.post('/confirm_email', {
userEmail: userEmail
})
.then(function(response) {
if (response.data.available) {
emailResult.textContent = "사용 가능한 이메일입니다.";
emailResult.style.color = 'green';
}
else {
emailResult.textContent = "이미 등록된 이메일입니다.";
emailResult.style.color = 'red';
}
})
.catch(function(error) {
console.error('에러 발생: ', error);
});
});
<Flask>
Flask는 데이터를 JSON 형식으로 전달받는다. User 테이블에 있는 이메일과 비교하여 이미 존재하는 이메일일 경우 available을 False로, 존재하지 않으면 True를 반환한다.
@api.route('/confirm_email', methods=['POST'])
def confirm_email():
data = request.json
user_email = data.get('userEmail')
user = User.query.filter_by(email=user_email).first()
if user:
return jsonify({
'available' : False
})
else:
return jsonify({
'available' : True
})
2. FormData 데이터 전송
전송할 데이터가 적다면 1번 방식을 써도 어려움이 없지만, 폼에 데이터가 많을 경우 하나하나 JSON으로 변환하기 귀찮다. 이럴 때는 FormData로 전송하면 한번에 처리할 수 있다.
<HTML>
<form class="signup-form" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="user-email">이메일</label>
<div class="email-form">
<input type="email" id="user-email" name="user-email" placeholder="Email" required>
<button type="button" id="confirm-email">중복 확인</button>
</div>
<p id="email-result"></p>
</div>
<div class="form-group">
<label for="user-pwd">비밀번호</label>
<input type="password" name="user-pwd" placeholder="Password" required>
</div>
<div class="form-group">
<label for="user-repwd">비밀번호 확인</label>
<input type="password" name="user-repwd" placeholder="Comfirm password" required>
<p id="pwd-result"></p>
</div>
<div class="form-group">
<label for="user-phone">휴대폰 번호</label>
<input type="tel" name="user-phone" placeholder="Phone number" required>
<p id="phone-result"></p>
</div>
<p id="warning-message" style="color: red; display: none">모든 필드를 입력해주세요.</p>
<div class="form-group">
<label for="user-birth">생년월일</label>
<input type="date" max="9999-12-31" name="user-birth" class="user-birth" placeholder="Birthday">
</div>
<div class="form-group">
<label for="user-interest">관심</label>
<input type="text" name="user-interest" placeholder="Interest">
</div>
<div class="form-group">
<label for="user-work">직장, 학교</label>
<input type="text" name="user-work" placeholder="Work">
</div>
<div class="form-group">
<label for="user-location">위치</label>
<input type="text" name="user-location" placeholder="Location">
</div>
<div class="form-group">
<label for="user-website">웹사이트</label>
<input type="text" name="user-website" placeholder="Website">
</div>
<div class="form-group">
<div class="image-div">
<img src="{{ url_for('static', filename='images/woman.png') }}" class="profile-image" id="profile-image">
</div>
<input type="file" id="image-input" name="user-image" style="display: none;" accept="image/*">
</div>
<div class="form-group">
<label for="user-name">이름</label>
<input type="text" name="user-name" placeholder="Name" required>
</div>
<div class="form-group">
<label for="user-description">설명</label>
<input type="text" name="user-description" placeholder="Description">
</div>
<button type="submit" class="submit-button">가입하기</button>
</form>
<Javascript>
new FormData로 FormData 객체를 생성해주면 해당 폼 내의 모든 필드 데이터들이 포함된다. FormData는 파일 등 다양한 데이터 형식을 포함할 수 있다. 이 formData를 axios.post에 인자로 전달해주면 모든 입력 필드의 데이터가 Flask로 전송된다.
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('.signup-form').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
axios.post('/register', formData)
.then(function(response) {
document.querySelector('.form-container').style.display = 'none';
document.querySelector('.welcome-message').style.display = 'block';
document.getElementById('welcome-name').textContent = response.data.name;
})
.catch(function(error) {
console.error('Error: ', error);
});
});
});
<Flask>
request.form으로 데이터들을 전달 받을 수 있다. User 객체(models/model.py에서 저장해 놓은 모델)를 생성한 후 모두 인자로 전달해준다. add한 후 commit 해주면 User 테이블에 새로운 데이터가 삽입된 것을 확인할 수 있다.
@api.route('/register', methods=['POST'])
def register():
user_email = request.form['user-email']
user_pwd = request.form['user-pwd']
user_phone = request.form['user-phone']
user_birth = request.form['user-birth']
if (user_birth == ''):
user_birth = None
user_interest = request.form['user-interest']
user_work = request.form['user-work']
user_location = request.form['user-location']
user_website = request.form['user-website']
user_image = request.files['user-image']
if user_image.filename == '':
file_path = ''
else:
file_name = secure_filename(user_image.filename)
file_path = os.path.join('app/static/images/profile', file_name)
user_image.save(file_path)
user_name = request.form['user-name']
user_description = request.form['user-description']
new_user = User(username=user_name,
email=user_email,
password=user_pwd,
phone=user_phone,
birth=user_birth,
interest=user_interest,
work=user_work,
location=user_location,
website=user_website,
description=user_description,
image_path=file_path)
db.session.add(new_user)
db.session.commit()
return jsonify ({
'name': user_name
})