안녕하세요. 좋은 강좌 잘 듣고 있습니다. 종종 메서드가 호출이 되고, 그다음 정의되는 부분이 있습니다. 예를들어 아래의 코드에서는 SearchModel.list(query).then(data =>{ this.onSearchResult(data) }) 부분에서 onSearchResult가 먼저 호출되고, 정의 되는 것은 코드의 마지막 부분입니다. 이런식으로 사용해도 되는 이유가 export와 관계가 있는 건가요? 아니면 hosting과 관계가 있는 건가요? 이도 저도 아니라면 뭐때문에 가능한건지 알고 싶습니다. export default { init() { FormView.setup(document.querySelector('form')) .on('@submit', e => this.onSubmit(e.detail.input)) .on('@reset', e => this.onResetForm()) ResultView.setup(document.querySelector('#search-result')) }, search(query){ //search api를 사용. console.log(tag, 'search()', query); SearchModel.list(query).then(data =>{ this.onSearchResult(data) }) }, onSubmit(input){ console.log(tag, 'onSubmit()', input); this.search(input) }, onResetForm(){ console.log(tag, 'onResetForm()'); }, onSearchResult(data){ ResultView.render(data) //이 부분이 나중에 정의 되어도 상관 없는지? } }
함수를 선언하려면 정의 할 때에도 제목?이 똑같아야 한다고 이해했었습니다. 근데 복습을 하던 중 궁금한 점이 있어서 질문 드립니다. 선언 void setQuestion(int i, int num1, int num2); 정의 void setQuestion(int level, int num1, int num2) 보시는 것처럼 선언 부분은 int i 라고 넣었고 정의 부분은 int level 이라고 적었는데요. 에러가 나지 않고 정상 동작하였습니다. 이 것이 어떤 원리 인지 궁금 합니다. ㅠㅠ 아래는 코딩 내용 전문 입니다. include include void setQuestion(int i,int num1,int num2); int randomNumber(int level); void success(); void fail(); int main(void) { srand(time(NULL)); int count1 = 0; int count2 = 0; for (int i = 1; i <= 5; i++) { int answer; int num1 = randomNumber(i); int num2 = randomNumber(i); setQuestion(i,num1, num2); scanf_s("%d", &answer); if (answer == num1*num2) { success(); count1++; } else if (answer == -1) { printf("문제를 종료합니다.n"); exit(); } else { fail(); count2++; } } printf("5문제 중 총 %d 문제를 맞췄고, %d 문제를 틀렸습니다.n", count1,count2); return 0; } void setQuestion(int level,int num1,int num2) { printf("%d 번째 문제 입니다.n",level); printf("%d x %d = ?n", num1, num2); printf("정답을 입력하세요: "); printf("그만두려면 -1 을 입력하세요.n"); } int randomNumber(int level) { return rand() % (level * 7) + 1; } void success() { printf("정답입니다!!n"); } void fail() { printf("오답이네요...n"); }
안녕하세요. 너무 좋은 강의 잘 듣고 있습니다. 공부하다가 막히는 부분이 있어서 질문 올립니다. MainController.js 파일의 시작 부분을 보면 다음과 같은 부분이 있습니다 "const tag = '[MainController]' " 위와 같이 스트링으로 MainController 값을 집어 넣는 것을 처음 보는데, 이 부분은 어떤 명령어가 어떻게 처리하는 건가요? 마찬가지로, View.js 파일의 시작 부분에서도 "const tag = '[View]' " 부분이 있는데요, 이유와 쓰임세가 궁금합니다. KeywordModel.js 파일 안을 보면 Promise가 변수에 담기지 않고 바로 "new Promise" 식으로 구현이 되었습니다. 그럼 이 Promise의 instance는 무엇이 되는 건가요? 이하는 코드 부분입니다. list() { return new Promise(res => { // 변수에다가 담지 않고 바로 new Promise를 했는데, // 이경우 그럼 Promise의 instance는무엇인가요? setTimeout(() => { res(this.data) }, 200) }) } } HistoryModel.js 파일에서 add() 펑션 관련 질문입니다. 아래 코드를 보면 궁금한 점이 두가지 있습니다. a) const date = '12.31' 이 부분은 이렇게 해 버리면 나중에 수정이 안되지 않나요? 근데 바로 아래줄에 this.data =[{keyword, date}, ...this.data] 이런식으로 나오면 저 자료를 계속 활용한다는 이야기인데. 굳이 const 와 스트링 조합으로 한 이유가 있나요? b) some(item=> item.keyword == keyword)) 에서 item이 뜻하는게 뭔지 궁금합니다. add(keyword = '') { keyword = keyword.trim() if (!keyword) return if (this.data.some(item => item.keyword === keyword)) { this.remove(keyword) } const date = '12.31' this.data = [{keyword, date}, ...this.data] }
GenericXmlApplicationContext 객체를 생성하는 코딩에서 'The type org.springframework.core.io.Resource cannot be resolved. It is indirectly referenced from required .class files' 오류가 발생합니다. 어떻게 해결해야 하는지 모르겠습니다. 답변 부탁드립니다
extension Question { static var all: [Question] = { guard let dataAsset: NSDataAsset = NSDataAsset(name: "Questions") else { return [] } let jsonDecoder: JSONDecoder = JSONDecoder() do { return try jsonDecoder.decode([Question].self, from: dataAsset.data) } catch { return [] } }() } 위 코드에서 Initializer for conditional binding must have Optional type, not '<<error type>>' Use of undeclared type 'NSDataAsset' 위와 같은 에러가 발생합니다.!!
안녕하세요 강의 잘 듣고 있습니다. 다름 아니라 질문하고 싶은것이 하나 있는데, 클래스 상속에 관해서 설명을 해 주시는 강의 마지막 부분에서 playerCharacter palyer = (playerCharacter) character 이런식으로 형변환을 통해서 변환을 해 주셨잖아요 근데 그냥 처음부터 playerCharacter로 인자를 받으면 안되는건가요?
또 과제 제출에서 마지막 main() 부분이 fail 로 나오네요. 다른 함수는 다 success로 나오는데요... 막상 cmd에서 실행하면 정상적으로 작동 하는데 왜 fail 로 나올까요? 혹시 첨삭 가능한가요? 어떤 문제인지 몰라서 답답합니다. ''' def main(): print("Play Baseball (Y/N)") user_input = 999 yes_or_no = input() while is_yes(yes_or_no) == True: random_number = str(get_not_duplicated_three_digit_number()) print("Random Number is : ", random_number) while is_yes(yes_or_no) == True: print("Input Guess Number is:") user_input = str(input()) input_1 = is_validated_number(user_input) try: if input_1 is True: output = get_strikes_or_ball(user_input_number = user_input, random_number = random_number) print("결과는 %d Strike" % output[0], "and %d ball 입니다." %output[1]) if output[0] == 3: break except TypeError: output = False print("다시 입력해주세요") print("계속 하시겠습니까?") yes_or_no_2 = input() if is_yes(yes_or_no_2) == True: continue break ================================== print("Thank you for using this program") print("End of the Game") '''
※파일 전체의 코드는 질문 하단에 있습니다. 안녕하세요. 항상 최고의 node.js 강좌 잘 듣고 있습니다. 질문은 두개 입니다. main.pug 파일을 보면 다음과 같은 부분이 있습니다. [].forEach.call(document.querySelectorAll('.twit-follow'), function (tag) { tag.addEventListener('click', function () { [] 부분이 이해가 안갑니다. 빈 리스트를 forEach 하는게 어떻게 가능한지요. "변수".forEach라면 모르겠는데... 이 부분에는 어떤 값이 어떻게, 언제 오기에 저 문법이 가능한지 알고 싶습니다. 정적파일은 기왕이면 다른 미들웨어들 위에 두라고 하신 부분이 이해가 잘 되지 않습니다. 예를 들어, app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use('/img', express.static(path.join(__dirname, 'uploads'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser(process.env.COOKIE_SECRET)); 위와 같은 코드에서 morgan 뒤쪽에 static middleware 를 위치 시켜서, 다른 미들웨어들이 불필요하게 사용되지 않게 해서 자원을 아끼라고 말씀하셨습니다. 그러나, 미들웨어들은 일단 실행되면 (next() 가 있다는 가정하에, 에러가 없다면) 순서대로 마지막 미들웨어까지 계속 나가야 하는것 아닌가요? 결국 위에 위치시키나, 아래 위치시키나 다른 미들웨어들을 실행하는건 마찬가지 같은데요. a) express.static은 next()가 없는 건가요? b)만약 express static이, 다음 미들웨어를 실행하지 않고 저기서 끝난다면, app.js 파일을 사용할 때마다 모든 요청이 전부 express.static 에서 끝나 버릴텐데, 그럼 json, eurlencoded, cookieParser 등등도 사용할 수 없게 되는 거 아닐까요? 혹시 express.static은 특정 요청에만 응답하고, 일반적인 요청에는 응답을 안하는 기능이 있는 건가요? 그렇다고 하면, 결국 이 명령어를 상위에 위치시킬 필요는 없는것 같은데요. main.pug 파일 ----------- extends layout block content .timeline if user div form#twit-form(action='/post' method='post' enctype='multipart/form-data') .input-group textarea#twit(name='content' maxlength=140) .img-preview img#img-preview(src='' style='display: none;' width='250' alt='미리보기') input#img-url(type='hidden' name='url') div label#img-label(for='img') 사진 업로드 input#img(type='file' accept='image/*') button#twit-btn.btn(type='submit') 짹짹 .twits form#hashtag-form(action='/post/hashtag') input(type='text' name='hashtag' placeholder='태그 검색') button.btn 검색 for twit in twits .twit input.twit-user-id(type='hidden' value=twit.user.id) input.twit-id(type='hidden' value=twit.id) .twit-author= twit.user.nick -const follow = user && user.Followings.map(f => f.id).includes(twit.user.id); if user && user.id !== twit.user.id && !follow button.twit-follow 팔로우하기 .twit-content= twit.content if twit.img .twit-img img(src=twit.img alt='섬네일') script. if (document.getElementById('img')) { document.getElementById('img').addEventListener('change', function (e) { var formData = new FormData(); console.log(this, this.files); formData.append('img', this.files[0]); var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status === 200) { var url = JSON.parse(xhr.responseText).url; document.getElementById('img-url').value = url; document.getElementById('img-preview').src = url; document.getElementById('img-preview').style.display = 'inline'; } else { console.error(xhr.responseText); } }; xhr.open('POST', '/post/img'); xhr.send(formData); }); } [].forEach.call(document.querySelectorAll('.twit-follow'), function (tag) { tag.addEventListener('click', function () { var isLoggedIn = document.querySelector('#my-id'); if (isLoggedIn) { var userId = tag.parentNode.querySelector('.twit-user-id').value; var myId = isLoggedIn.value; if (userId !== myId) { if (confirm('팔로잉하시겠습니까?')) { var xhr = new XMLHttpRequest(); xhr.onload = function () { if (xhr.status === 200) { location.reload(); } else { console.error(xhr.responseText); } }; xhr.open('POST', '/user/' + userId + '/follow'); xhr.send(); } } } }); }); app.js 파일입니다. const express = require('express'); const cookieParser = require('cookie-parser'); const morgan = require('morgan'); const path = require('path'); const session = require('express-session'); const flash = require('connect-flash'); const passport = require('passport'); require('dotenv').config(); const pageRouter = require('./routes/page'); const authRouter = require('./routes/auth'); const postRouter = require('./routes/post'); const userRouter = require('./routes/user'); const { sequelize } = require('./models'); const passportConfig = require('./passport'); const app = express(); sequelize.sync(); passportConfig(passport); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); app.set('port', process.env.PORT || 8001); app.use(morgan('dev')); app.use(express.static(path.join(__dirname, 'public'))); app.use('/img', express.static(path.join(__dirname, 'uploads'))); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser(process.env.COOKIE_SECRET)); app.use(session({ resave: false, saveUninitialized: false, secret: process.env.COOKIE_SECRET, cookie: { httpOnly: true, secure: false, }, })); app.use(flash()); app.use(passport.initialize()); app.use(passport.session()); app.use('/', pageRouter); app.use('/auth', authRouter); app.use('/post', postRouter); app.use('/user', userRouter); app.use((req, res, next) => { const err = new Error('Not Found'); err.status = 404; next(err); }); app.use((err, req, res) => { res.locals.message = err.message; res.locals.error = req.app.get('env') === 'development' ? err : {}; res.status(err.status || 500); res.render('error'); }); app.listen(app.get('port'), () => { console.log(app.get('port'), '번 포트에서 대기중'); });
예제를 따라 보고 하다가 문의가 있습니다. 강사님의 경우 UPDATE를 테스트 코드에 작성을 하실때 아래와 같이 하셨습니다, Post save = savePost(); save.setTitle("hibernate"); List<Post> posts = postRepository.findAll(); assertThat(posts.get(0).getTitle()).isEqualTo("hibernate"); 위 의 경우 발생되는 쿼리를 보면 UPDATE & SELECT 쿼리가 모두 발생합니다. 저는 아래와 같이 findAll() 대신에 findById() 메서드를 통해 테스트 해보았습니다. Post save = savePost();<p>save.setTitle("hibernate"); Optional<Post> post = postRepository.findById(save.getId()); assertThat(post.get().getTitle()).isEqualTo("hibernate"); 테스트 결과는 Pass이나 발생되는 쿼리를 보면 실제 DB쪽으로는 UPDATE, SELECT 쿼리 모두 발생하지 않습니다. JPA Query 메서드인 findAll() 와 findById()가 차이가 있는 것인지 궁금합니다. 늘 빠르게 피드백 주셔서 감사드립니다.
Developer Default버전으로 설치하면 되나요?아니면 server only로 설치해야 되나요? 그리고 설치하는 과정에서 Path Conflicts 부분중에 하단에 install Directory와 data Directory가 같은 경로로 설정이 되어있습니다 그런경우 하단에 보면 노란색 느낌표 경고에 the selected path already exists라는 경고가 떠있는데 다른 폴더 하나 만들어서 경로를 바꾸어 주어야 하나요? 만약 경로가 똑같은 상태에서 넥스트를 누르면 you still have warnings with your selected paths, are you sure you want to continue? 라는 문구가 뜨는데요 제가 설치 후 자꾸 실습에서 에러나는 이유가 아마 설치과정에 있는거 같은데 원인이 뭔지 잘 모르겠습니다.