오류 코드를 그대로 구글링
해보았다.
jsfiddle
이 문제라는 내용을 보았고, 또 링크되어 있는 jsfiddle의 페이지도 들어가 보았으나, 나의 문제에 대입하여 해결을 하지 못하였다. 함수의 이름이 정의되어 있지 못하였다는 에러 메세지의 내용을 보고 현재 해당 함수가 api.js에 존재하고, index.js에서 해당 함수를 호출해 실행하는 것이므로 한 번 api.js 안에서 함수를 실행해보자 생각을 하였다.
index.html 파일을 실행하였더니 아래와 같은 오류 메세지가 나왔다.
해당 오류를 해결하고자 또 구글링을 해보았다.
경로를 아래와 같이 재설정해보니 다른 오류가 떴다.
<script src="../frontend/api.js"></script>
위의 오류를 그대로 구글링해보았다. 아래의 링크에서 script 태그의 위치를 바꿔주면 오류가 해결된다 해서 그대로 시도해보았다.
cannot-set-property-of-null
역시 별 효과가 없었다.
오류 메세지의 Cannot set properties of null
이라는 내용이 맞다기에는 아래와 같이 response가 아예 오지 않는 것도 아닌 것 같다.
오랫동안 해결하지 못하고 튜터님께 질문을 드렸고, 다시 보다보니 예상하지도 못한 곳에서 오타
가 있었다. ㅋ
오타 체크 꼭하자!!!!!!!!!!!!!!!!!!!!!!!!!!!!!ㅅㅂ!!!!!! ㅋㅋㅋㅋ
@authorize
를 쓰고, 해당 route에 해당하는 함수의 인자로 user
를 부여하면 된다.# decorator 함수를 사용해 사용자의 토큰값 확인
def authorize(f):
@wraps(f)
def decorated_function():
# 만약 Authorization이 헤더 안에 없다면
if not 'Authorization' in request.headers:
abort(401) # 401 에러를 반환
# Authorization이 헤더 안에 있다면 'token' 변수에 저장
token = request.headers['Authorization']
try:
# 토큰을 디코드한 값을 user에 저장
# _id, email, exp가 들어있음
user = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
except:
abort(401)
return f(user)
return decorated_function
@app.route("/")
@authorize
def home(user):
print(user)
return jsonify({'msg': 'success'})
@authorize와 user
를 받아옴으로써 없애 코드가 간단해졌다. _id
를 통해 사용자를 식별해야 하는데, user에 들어있던 값은 문자열이므로 다시 ObjectId로 변환해주는 과정을 거친다.@app.route("/getuserinfo", methods=['GET'])
@authorize
def get_user_info(user):
user_info = db.user.find_one({'_id': ObjectId(user['id'])})
print('3', user_info)
return jsonify({'msg': 'success', 'email': user_info['email']})
title, content
와 함께 user에 들어있는 ObjectId로 타입을 변경한 _id와 email, 그리고 작성 시간을 같이 article
이라는 db 안에 입력해 준다._id
값의 타입이 현재 어떤 것인지 항상 생각하고 있어야 된다는 것이다.@app.route("/article", methods=['POST'])
@authorize
def post_article(user):
data = json.loads(request.data)
print(data)
# 여기서의 user는 authorize에 들어가는 인자값
# user에는 payload로 만들어진 token이 존재하고, payload에는 사용자의 str화 시킨 _id가 존재한다.
# 이 값을 mongoDB에서 사용하기 위해서는 다시 ObjectId로 변환해줘야 하기 때문에 아래와 같은 작업 진행
db_user = db.user.find_one({'_id': ObjectId(user.get('id'))})
# 현재 시각 표시
now_date = datetime.datetime.now().strftime('%H : %M : %S')
doc = {
'title': data.get('title', None), # 현재는 None 처리를 통해 값이 없더라도 입력 가능
# 추후 값이 없을 때 에러 처리하는 것을 만들어 활용해보기
'content': data.get('content', None),
'user': user['id'],
'user_email': db_user['email'],
'time': now_date
}
db.article.insert_one(doc)
return jsonify({'msg': 'success'})
onclick
함수를 새로운 방법으로 활용한 부분이라 작성한다. location.href
를 통해 다른 페이지로 넘어갈 수 있다.<button type="button" onclick="location.href='article_create.html';">게시글 작성하러 가기</button>
getElementById
를 통해 해당 id 값을 가지는 부분의 value 값을 각 변수에 저장하고, postArticle()
함수의 인자로 넘겨준다.function handleArticleCreate() {
const title = document.getElementById('article_title').value
const content = document.getElementById('article_content').value
// 여기서 뽑아온 타이틀과 콘텐트의 값을 api.js에 있는 postArticle 함수에 넘기기 위해 함수 실행
postArticle(title, content)
}
articleData
라는 변수에 저장한다. body
에 실어 Authorization이 담긴 headers
와 함꼐 ${backend_base_url}/article
이란 주소를 가진 app.py의 함수로 POST 방식으로 데이터를 보내준다.@app.route("/article", methods=['POST'])
를 주소로 가진 곳에서 데이터를 받게 된다. headers에 담긴 Authorization
은 앞에서 정의한 authorize
함수로 이동하게 되고, 나머지 데이터는 data = json.loads(request.data)
를 통해 JSON 방식의 데이터로 변환되어 나머지 작업들을 할 수 있게 되는 것이다. async function postArticle(title, content) {
const articleData = {
title: title,
content: content
}
console.log(articleData)
const response = await fetch(`${backend_base_url}/article`, {
method: 'POST',
headers: {
'Authorization': localStorage.getItem('token')
},
body: JSON.stringify(articleData)
})
response_json = await response.json()
console.log(response_json)
if (response.status == 200) {
window.location.replace(`${frontend_base_url}/`)
}
}
async function getArticles() {
const response = await fetch(`${backend_base_url}/article`, {
method: 'GET'
})
response_json = await response.json()
return response_json.articles
}
getArticles
함수를 통해 받아온 값을 articles라는 변수에 지정한다. forEach
함수 안에서 createElement
와 setAttribute
를 통해 새로운 li를 만들고 id 값을 부여하게 된다. 그리고 각 게시글의 제목만 따와서 appendChild
를 통해서 ol 안에 각 제목들을 붙여주게 된다. async function loadArticles() {
articles = await getArticles();
const article_list = document.getElementById('articles')
articles.forEach(article => {
console.log(article)
const newArticle = document.createElement('li');
newArticle.setAttribute('id', article._id)
newArticle.innerText = article.title;
article_list.appendChild(newArticle)
});
}