inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

묻고 답해요

173만명의 커뮤니티!! 함께 토론해봐요.

클로저 예시 함수에서 nonlocal 사용이 필요한 여부에 대해 질문드립니다.

미해결

우리를 위한 프로그래밍 : 파이썬 중급 (Inflearn Original)

안녕하세요. 강의 감사히 잘 듣고 있는 수강생입니다. 클로저 관련 내용을 듣다 궁금한 점이 있어 질문 드립니다. 해당 문제와 관련하여 다른 분들도 동일한 질문을 여러 번 올려주셨는데 "명확하게 이렇기 때문이다"라는 답변이 없이 외부 링크를 걸어주시거나 단답형으로 답변을 주셨던 것 같아 다시 질문을 드립니다. def closure_ex1(): # Free variable series = [] # 클로저 영역 def averager(v): # series = [] # 주석 해제 후 확인 series.append(v) print('inner >>> {} / {}'.format(series, len(series))) return sum(series) / len(series) return averager avg_closure1 = closure_ex1() # 잘못된 클로저 사용 def closure_ex2(): # Free variable cnt = 0 total = 0 def averager(v): cnt += 1 # cnt = cnt + 1 total += v return total / cnt return averager avg_closure2 = closure_ex2() 위 두 함수 closure_ex1과 closure_ex2를 비교하면 차이는 series는 list, cnt와 total은 int형 변수라는 것, averager 함수 내부에서 series는 append 작업을 하고, cnt와 total은 값을 더해주는 작업을 한다는 것 입니다. 그런데 closure_ex1에서는 오류가 나지 않고, closure_ex2에서는 averager 안에 nonlocal cnt, total을 작성하지 않으면 오류가 납니다. 여쭤보고 싶은 것은, [1] closure_ex1의 averager 함수 내부에 nonlocal series 라는 코드를 작성하지 않아도 되는 이유가 무엇 때문인가 입니다. closure_ex2의 averager 안에 nonlocal cnt, total 이 필요한 것은 내부 함수의 영역은 local 영역이고 closure_ex2 내부이면서 average 외부인 영역은 nonlocal 영역이기 때문에 local 영역에서 free variable을 write 작업하기 위해서는 nonlocal 변수 선언이 필요한 것으로 알고 있습니다. 하지만 series 변수에 대해서는 왜 nonlocal series 라는 코드가 필요하지 않은 것인지요? 제가 추가로 공부할 링크를 주시는 것은 감사하지만, 이 질문에 대한 답변을 명확하게 댓글로 작성해주시면 감사드리겠습니다. 다른 분들의 질문에 올려 주신 링크는 모두 읽어보았습니다. 또한 명확한 답변을 주시면 공부하시는 다른 분들께도 유용할 것이라고 생각합니다. 감사합니다. ps. 강의 영상을 확인하라는 답변도 주셨었는데, 수업에서 정확하게 list나 int형 자료의 scope 별 생명 주기까지 설명한 내용은 찾지 못하였으니 만약 해당 내용이 필요하다면 강의 시간을 알려주시면 감사드리겠습니다.

  • python
  • closure
힌턴 댓글 2 좋아요 1 조회수 470

안녕하세요 강사님 로그인 질문있씁니다!

미해결

스프링부트 시큐리티 & JWT 강의

public class LoginFilter extends UsernamePasswordAuthenticationFilter 이 작업을 통해서 login으로 들어오는 것을 @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { User user = objectMapper.readValue(request.getInputStream(), User.class); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()); return authenticationManager.authenticate(authenticationToken); } catch (IOException e) { log.error("{}", e); } return super.attemptAuthentication(request, response); } 이 작업을 통해서 로그인 하는 걸로 알고있는데, 이러한 경우에 컨트롤러 테스트 코드를 어떻게 작성할 수 있는 건지 궁금합니다. api가 아니라 자꾸 에러가 발생하는데 혹시 이러한 경우에 api 테스트 코드 작성 팁좀 가르쳐주실 수 있나요? 이러한 예외가 발생합니다. 이유를 모르겠습니다. Postman으로 할 때는 잘 동작합니다 ㅜㅜ 그냥 /api/login 이라는 api를 생성해서 테스트해야 될까요?

  • spring
  • spring-security
  • jwt
진짜 잘하고싶다 댓글 2 좋아요 0 조회수 496

11.4 강의 :Jest worker encountered 4 child process exceptions, exceeding retry limit

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

---- 처음에 코드를 작성했다가 Fail이 떠서 githuub 에 있는 자료를 그대로 옮겼는데, 다시 저런 Fail이 뜹니다. 제가 어떻게 접근을 해야 Fail을 잡을 수 있을까요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
ysm6514 댓글 1 좋아요 0 조회수 797

규제 적용시 cross_val_score NaN반환

미해결

[개정판] 파이썬 머신러닝 완벽 가이드

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요! - 먼저 유사한 질문이 있었는지 검색해보세요. - 강의 내용을 질문할 경우 몇분 몇초의 내용에 대한 것인지 반드시 기재 부탁드립니다. - 서로 예의를 지키며 존중하는 문화를 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요. 안녕하세요. 규제 부분 코드 실습 중 규제 클래스에 관해서 cross_val_score적용 시 NaN값이 반환되는 것이 확인되어 질문드립니다. 싸이킷런 버전의 경우 1.0.2버전인데 구글링을 했을 때는, 데이터 내에 NaN값이 있어서 그럴 것이라는데 제가 확인해봤을 때는 NaN값이 없었습니다. 혹시 버전과 관련된 문제일까요...? 동일 코드에 Ridge클래스대신 LinearRegression클래스로 대체시 정상적으로 코드가 동작하는 것을 확인하여 우선 Ridge클래스에 대한 문제로 간주하고 있습니다...ㅠ

  • python
  • 머신러닝
  • 통계
RYU 댓글 3 좋아요 0 조회수 734

sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") 오류

해결됨

실전! FastAPI 입문

OS: macOS python 3.10 버전을 사용하고 있고, sqlalchemy 2.0.19, pymysql 1.1.0 등등 최신 패키지 사용중입니다. from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker DATABASE_URL = "mysql+pymysql://root:todos@127.0.0.1/todos" engine = create_engine(DATABASE_URL, echo=True) SessionFactory = sessionmaker(autocommit=False, autoflush=False, bind=engine) connection.py 는 위와 같이 동일하게 작성했고, session.scalar(select(1)); 실행시 아래와 같은 오류가 발생하여 더 이상 진행을 할 수가 없습니다. Traceback (most recent call last): File "/Users/someone/Library/Application Support/JetBrains/Toolbox/apps/PyCharm-P/ch-0/232.8660.197/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py", line 364, in runcode coro = func() File "<input>", line 1, in <module> File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2296, in scalar return self._execute_internal( File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 2131, in _execute_internal conn = self._connection_for_bind(bind) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1998, in _connection_for_bind return trans._connection_for_bind(engine, execution_options) File "<string>", line 2, in _connection_for_bind File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go ret_value = fn(self, *arg, **kw) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/orm/session.py", line 1123, in _connection_for_bind conn = bind.connect() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 3264, in connect return self._connection_cls(self) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 147, in __init__ Connection._handle_dbapi_exception_noconnection( File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 2426, in _handle_dbapi_exception_noconnection raise sqlalchemy_exception.with_traceback(exc_info[2]) from e File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 145, in __init__ self._dbapi_connection = engine.raw_connection() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/base.py", line 3288, in raw_connection return self.pool.connect() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 452, in connect return _ConnectionFairy._checkout(self) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 1267, in _checkout fairy = _ConnectionRecord.checkout(pool) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 716, in checkout rec = pool._do_get() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/impl.py", line 169, in _do_get with util.safe_reraise(): File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 147, in __exit__ raise exc_value.with_traceback(exc_tb) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/impl.py", line 167, in _do_get return self._create_connection() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 393, in _create_connection return _ConnectionRecord(self) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 678, in __init__ self.__connect() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 902, in __connect with util.safe_reraise(): File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/util/langhelpers.py", line 147, in __exit__ raise exc_value.with_traceback(exc_tb) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 898, in __connect self.dbapi_connection = connection = pool._invoke_creator(self) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/create.py", line 637, in connect return dialect.connect(*cargs, **cparams) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 615, in connect return self.loaded_dbapi.connect(*cargs, **cparams) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/connections.py", line 358, in __init__ self.connect() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/connections.py", line 664, in connect self._request_authentication() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/connections.py", line 976, in _request_authentication auth_packet = _auth.caching_sha2_password_auth(self, auth_packet) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/_auth.py", line 267, in caching_sha2_password_auth pkt = _roundtrip(conn, data) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/_auth.py", line 120, in _roundtrip pkt = conn._read_packet() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/connections.py", line 772, in _read_packet packet.raise_for_error() File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/protocol.py", line 221, in raise_for_error err.raise_mysql_exception(self._data) File "/Users/someone/.pyenv/versions/fastapi-env/lib/python3.10/site-packages/pymysql/err.py", line 143, in raise_mysql_exception raise errorclass(errno, errval) sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1045, "Access denied for user 'root'@'localhost' (using password: YES)") (Background on this error at: https://sqlalche.me/e/20/e3q8) Check the PassWord Hashing Method: If the MySQL server is using caching_sha2_password but the client (like PyMySQL) doesn't support it, it can give rise to such issues. You can switch the MySQL user's password hashing method to mysql_native_password . 이런 글도 있어서 따라하고 새로 비밀번호를 todos 로 넣어줬는데도 마찬가지네요. 더 참고할만한 내용이 있을까요?

  • python
  • 리팩토링
  • orm
  • FastAPI
  • pytest
댓글 1 좋아요 2 조회수 2357

토큰반환이 안되는거같아요

해결됨

Spring Boot JWT Tutorial

회원가입 까지는 db에 값이 잘 들어갔는데 그 정보로 포스트맨을 통해 로그인하려고 하면 아무런 에러없이 토큰도 반환해주지 않는데 어떻게 해결하나요 ㅜ "C:\Program Files\Java\jdk-17\bin\java.exe" -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always - Dcom.sun.management .jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.3\lib\idea_rt.jar=60002:C:\Program Files\JetBrains\IntelliJ IDEA 2022.3.3\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\qkral\Desktop\GoJiSik_BE\out\production\classes;C:\Users\qkral\Desktop\GoJiSik_BE\out\production\resources;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.28\a2ff5da8bcd8b1b26f36b806ced63213362c6dcc\lombok-1.18.28.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-data-jpa\3.1.2\a37d54373b11d2de70dfb8bcd6612dc63787f4a8\spring-boot-starter-data-jpa-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-security\3.1.2\f51204b86f626c2a7f0d41f88e8e3bd86091dd1d\spring-boot-starter-security-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-validation\3.1.2\1e2f4bdd1913af954d3a929e692807cb3a19b0b4\spring-boot-starter-validation-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\3.1.2\30b824817e764a5a5a1e9fb46e7ace40bcfa3185\spring-boot-starter-web-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.h2database\h2\2.1.214\d5c2005c9e3279201e12d4776c948578b16bf8b2\h2-2.1.214.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-api\0.11.5\f742940045619d06383e7df37b21ac422b476cf1\jjwt-api-0.11.5.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-aop\3.1.2\e882bf8c8853807a8e69cce9465ec12233fb5437\spring-boot-starter-aop-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-jdbc\3.1.2\e864f6a34d620e7e698c115881ea23b08f7125e9\spring-boot-starter-jdbc-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.hibernate.orm\hibernate-core\6.2.6.Final\9c4586a4a2dc721439ee454d5c858c1235b6ecba\hibernate-core-6.2.6.Final.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-jpa\3.1.2\e9507688bc27006a5fb9ae4d13c1a5685354eb4a\spring-data-jpa-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aspects\6.0.11\7b6fcc5d4f06c36c332b7a122dca863163a127d4\spring-aspects-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\3.1.2\c09a48df6fbc2b07b7aef1256b45260a3478b49f\spring-boot-starter-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-config\6.1.2\f6391123f7c3cb7a158266fc81cc4c82c5c4fe19\spring-security-config-6.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-web\6.1.2\c1f133de05e895e58b34461f6b1189a8d6a0d56a\spring-security-web-6.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\6.0.11\15b85c825558fadb85e3c77779d7225ce7e4a7bc\spring-aop-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\10.1.11\97aa65b1f036f722e869f582f8d607d01508d420\tomcat-embed-el-10.1.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.hibernate.validator\hibernate-validator\8.0.1.Final\e49e116b3d3928060599b176b3538bb848718e95\hibernate-validator-8.0.1.Final.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\3.1.2\c48d521879dbbcebe1a99f47257612968e022f5b\spring-boot-starter-json-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\6.0.11\892b4a63b5d930c2c43058c6db0c2c65401fb078\spring-webmvc-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\3.1.2\2e7284f8ecf2989e1a6ffc7faf964eccb309bfd4\spring-boot-starter-tomcat-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\6.0.11\c32a7bf6b88b83bac6aa63866fcf208892640446\spring-web-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.aspectj\aspectjweaver\1.9.19\afbffb1210239fbba5cad73093c5b216d515838f\aspectjweaver-1.9.19.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.zaxxer\HikariCP\5.0.1\a74c7f0a37046846e88d54f7cb6ea6d565c65f9c\HikariCP-5.0.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jdbc\6.0.11\dc495b5cb8052f044fd29aa68bb2231b1895b8f4\spring-jdbc-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.persistence\jakarta.persistence-api\3.1.0\66901fa1c373c6aff65c13791cc11da72060a8d6\jakarta.persistence-api-3.1.0.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.transaction\jakarta.transaction-api\2.0.1\51a520e3fae406abb84e2e1148e6746ce3f80a1a\jakarta.transaction-api-2.0.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\6.0.11\a7b10f3d3c1492bfc4e6d7c966cd2e21f4d441f5\spring-context-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-orm\6.0.11\dde0c5f956052c8c3865e95202dd35b7437b2c6f\spring-orm-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.data\spring-data-commons\3.1.2\cf75c8a2a11d24df5bdb4d796d4b449bab3bed07\spring-data-commons-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-tx\6.0.11\59cd03d2ba6968ade8c192b4d6488efb48ec36f\spring-tx-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\6.0.11\8513efc6e94b407b5cd85f69eeec511f1ef34164\spring-beans-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\6.0.11\87834b5cf95c6fa28f5bdf8a85e0daf0bff918a8\spring-core-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.antlr\antlr4-runtime\4.10.1\10839f875928f59c622d675091d51a43ea0dc5f7\antlr4-runtime-4.10.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\2.1.1\48b9bda22b091b1f48b13af03fe36db3be6e1ae3\jakarta.annotation-api-2.1.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\2.0.7\41eb7184ea9d556f23e18b5cb99cad1f8581fc00\slf4j-api-2.0.7.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\3.1.2\ea294976f925441fc1d5a5414d5d31717f06aa3c\spring-boot-autoconfigure-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\3.1.2\3cf070561716277ec91ebadc07362dd0b4a9f63f\spring-boot-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\3.1.2\4e47bd132fdd0d60ad57d70bdc99198b182166ee\spring-boot-starter-logging-3.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\1.33\2cd0a87ff7df953f810c344bdf2fe3340b954c69\snakeyaml-1.33.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-core\6.1.2\acd42f051b0f38d043ad807ca542f1f53bfa2fe\spring-security-core-6.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\6.0.11\1d0940120a275719c3988c592068f4acf807fe59\spring-expression-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.validation\jakarta.validation-api\3.0.2\92b6631659ba35ca09e44874d3eb936edfeee532\jakarta.validation-api-3.0.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.jboss.logging\jboss-logging\3.5.3.Final\c88fc1d8a96d4c3491f55d4317458ccad53ca663\jboss-logging-3.5.3.Final.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml\classmate\1.5.1\3fe0bed568c62df5e89f4f174c101eab25345b6c\classmate-1.5.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.15.2\30d16ec2aef6d8094c5e2dce1d95034ca8b6cb42\jackson-datatype-jsr310-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.15.2\75f8d2788db20f6c587c7a19e94fb6248c314241\jackson-module-parameter-names-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.15.2\66a50e089cfd2f93896b9b6f7a734cea7bcf2f31\jackson-datatype-jdk8-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.15.2\9353b021f10c307c00328f52090de2bdb4b6ff9c\jackson-databind-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\10.1.11\ac9ecc8a2b6a2cd8123554259faabc2e7b4aa013\tomcat-embed-websocket-10.1.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\10.1.11\9d1ba230cbe0dfb410b0beba102eff20e14793a1\tomcat-embed-core-10.1.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-observation\1.11.2\704e145c4801320b4c7abf6c1a5b000155b069db\micrometer-observation-1.11.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\6.0.11\c9b16cdb6d4874ba4118fcdd4b0335f6278b378\spring-jcl-6.0.11.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.4.8\f00ba91d993e4d14301b11968d3cacc3be7ef3e1\logback-classic-1.4.8.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.20.0\d37f81f8978e2672bc32c82712ab4b3f66624adc\log4j-to-slf4j-2.20.0.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\2.0.7\a48f44aeaa8a5ddc347007298a28173ac1fbbd8b\jul-to-slf4j-2.0.7.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.springframework.security\spring-security-crypto\6.1.2\3acab1c7979cc9d44d5e12e7f5acd4d9552e6b83\spring-security-crypto-6.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.15.2\4724a65ac8e8d156a24898d50fd5dbd3642870b8\jackson-annotations-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.15.2\a6fe1836469a69b3ff66037c324d75fc66ef137c\jackson-core-2.15.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.micrometer\micrometer-commons\1.11.2\f03f87bd7eacf79b00aa89907c6e30e0ec86b4\micrometer-commons-1.11.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.4.8\3fba9c105e0efc5ffdcda701379687917d5286f7\logback-core-1.4.8.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.20.0\1fe6082e660daf07c689a89c94dc0f49c26b44bb\log4j-api-2.20.0.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-impl\0.11.5\40a599f0e8a8e4e0701596fbb15e67bfda64fdf0\jjwt-impl-0.11.5.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.jsonwebtoken\jjwt-jackson\0.11.5\3b83a06809e98a69402d7333dcf67df6f6ea4579\jjwt-jackson-0.11.5.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.hibernate.common\hibernate-commons-annotations\6.0.6.Final\77a5f94b56d49508e0ee334751db5b78e5ccd50c\hibernate-commons-annotations-6.0.6.Final.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\io.smallrye\jandex\3.0.5\c548a4871b552292dbdd65409d3fda145c8925c1\jandex-3.0.5.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy\1.14.5\28a424c0c4f362568e904d992c239c996cf7adc7\byte-buddy-1.14.5.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\4.0.3\93af25be25b2c92c83e0ce61cb8b3ed23568f316\jaxb-runtime-4.0.3.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.xml.bind\jakarta.xml.bind-api\4.0.0\bbb399208d288b15ec101fa4fcfc4bd77cedc97a\jakarta.xml.bind-api-4.0.0.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.inject\jakarta.inject-api\2.0.1\4c28afe1991a941d7702fe1362c365f0a8641d1e\jakarta.inject-api-2.0.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-core\4.0.3\e9093b4a82069a1d78ee9a3233ca387bca88861f\jaxb-core-4.0.3.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\jakarta.activation\jakarta.activation-api\2.1.2\640c0d5aff45dbff1e1a1bc09673ff3a02b1ba12\jakarta.activation-api-2.1.2.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.eclipse.angus\angus-activation\2.0.1\eaafaf4eb71b400e4136fc3a286f50e34a68ecb7\angus-activation-2.0.1.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\txw2\4.0.3\47b8fe31c6d1a3382203af919400527389e01e9c\txw2-4.0.3.jar;C:\Users\qkral\.gradle\caches\modules-2\files-2.1\com.sun.istack\istack-commons-runtime\4.1.2\18ec117c85f3ba0ac65409136afa8e42bc74e739\istack-commons-runtime-4.1.2.jar com.likelion.nsu.gojisik.GojisikApplication . ____ _ /\\ / ___'_ __ ( _)_ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.2) 2023-08-14T05:24:36.414+09:00 INFO 18164 --- [ main] c.l.nsu.gojisik.GojisikApplication : Starting GojisikApplication using Java 17.0.6 with PID 18164 (C:\Users\qkral\Desktop\GoJiSik_BE\out\production\classes started by qkral in C:\Users\qkral\Desktop\GoJiSik_BE) 2023-08-14T05:24:36.417+09:00 INFO 18164 --- [ main] c.l.nsu.gojisik.GojisikApplication : No active profile set, falling back to 1 default profile: "default" 2023-08-14T05:24:37.478+09:00 INFO 18164 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2023-08-14T05:24:37.579+09:00 INFO 18164 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 89 ms. Found 2 JPA repository interfaces. 2023-08-14T05:24:38.352+09:00 INFO 18164 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http) 2023-08-14T05:24:38.367+09:00 INFO 18164 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2023-08-14T05:24:38.367+09:00 INFO 18164 --- [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.11] 2023-08-14T05:24:38.521+09:00 INFO 18164 --- [ main] o.a.c.c.C.[Tomcat].[ localhost ].[/] : Initializing Spring embedded WebApplicationContext 2023-08-14T05:24:38.522+09:00 INFO 18164 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2049 ms 2023-08-14T05:24:38.574+09:00 INFO 18164 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2023-08-14T05:24:38.669+09:00 INFO 18164 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:tcp:// localhost/~/GoJiSik_BE1 user=SA 2023-08-14T05:24:38.671+09:00 INFO 18164 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2023-08-14T05:24:38.682+09:00 INFO 18164 --- [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:tcp:// localhost/~/GoJiSik_BE1 ' 2023-08-14T05:24:38.881+09:00 INFO 18164 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2023-08-14T05:24:38.958+09:00 INFO 18164 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.2.6.Final 2023-08-14T05:24:38.961+09:00 INFO 18164 --- [ main] org.hibernate.cfg.Environment : HHH000406: Using bytecode reflection optimizer 2023-08-14T05:24:39.169+09:00 INFO 18164 --- [ main] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy 2023-08-14T05:24:39.352+09:00 INFO 18164 --- [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer 2023-08-14T05:24:39.773+09:00 INFO 18164 --- [ main] o.h.b.i.BytecodeProviderInitiator : HHH000021: Bytecode provider name : bytebuddy 2023-08-14T05:24:40.918+09:00 INFO 18164 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2023-08-14T05:24:40.950+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists answer cascade Hibernate: drop table if exists answer cascade 2023-08-14T05:24:40.953+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists authority cascade Hibernate: drop table if exists authority cascade 2023-08-14T05:24:40.954+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists file cascade Hibernate: drop table if exists file cascade 2023-08-14T05:24:40.955+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists member cascade Hibernate: drop table if exists member cascade 2023-08-14T05:24:40.955+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists question cascade Hibernate: drop table if exists question cascade 2023-08-14T05:24:40.956+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop table if exists user_authority cascade Hibernate: drop table if exists user_authority cascade 2023-08-14T05:24:40.957+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop sequence if exists answer_seq Hibernate: drop sequence if exists answer_seq 2023-08-14T05:24:40.957+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop sequence if exists file_seq Hibernate: drop sequence if exists file_seq 2023-08-14T05:24:40.957+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : drop sequence if exists question_seq Hibernate: drop sequence if exists question_seq 2023-08-14T05:24:40.963+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create sequence answer_seq start with 1 increment by 50 Hibernate: create sequence answer_seq start with 1 increment by 50 2023-08-14T05:24:40.964+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create sequence file_seq start with 1 increment by 50 Hibernate: create sequence file_seq start with 1 increment by 50 2023-08-14T05:24:40.964+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create sequence question_seq start with 1 increment by 50 Hibernate: create sequence question_seq start with 1 increment by 50 2023-08-14T05:24:40.968+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table answer ( is_adopted boolean, created_date timestamp(6), id bigint not null, member_id bigint, question_id bigint, contents varchar(255), primary key (id) ) Hibernate: create table answer ( is_adopted boolean, created_date timestamp(6), id bigint not null, member_id bigint, question_id bigint, contents varchar(255), primary key (id) ) 2023-08-14T05:24:40.969+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table authority ( authority_name varchar(50) not null, primary key (authority_name) ) Hibernate: create table authority ( authority_name varchar(50) not null, primary key (authority_name) ) 2023-08-14T05:24:40.971+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table file ( file_size bigint, id bigint not null, origin_file_name varchar(255), saved_file_name varchar(255), type varchar(255) check (type in ('Image','Audio')), primary key (id) ) Hibernate: create table file ( file_size bigint, id bigint not null, origin_file_name varchar(255), saved_file_name varchar(255), type varchar(255) check (type in ('Image','Audio')), primary key (id) ) 2023-08-14T05:24:40.973+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table member ( activated boolean not null, font integer not null, grade tinyint check (grade between 0 and 2), birthday timestamp(6), member_id bigint generated by default as identity, point bigint, password varchar(255), phone_number varchar(255), username varchar(255), primary key (member_id) ) Hibernate: create table member ( activated boolean not null, font integer not null, grade tinyint check (grade between 0 and 2), birthday timestamp(6), member_id bigint generated by default as identity, point bigint, password varchar(255), phone_number varchar(255), username varchar(255), primary key (member_id) ) 2023-08-14T05:24:40.975+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table question ( created_date timestamp(6), file_id bigint unique, hits bigint, id bigint not null, user_id bigint, category varchar(255), contents varchar(255), title varchar(255), primary key (id) ) Hibernate: create table question ( created_date timestamp(6), file_id bigint unique, hits bigint, id bigint not null, user_id bigint, category varchar(255), contents varchar(255), title varchar(255), primary key (id) ) 2023-08-14T05:24:40.978+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : create table user_authority ( member_id bigint not null, authority_name varchar(50) not null, primary key (member_id, authority_name) ) Hibernate: create table user_authority ( member_id bigint not null, authority_name varchar(50) not null, primary key (member_id, authority_name) ) 2023-08-14T05:24:40.981+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists answer add constraint FKn2sp5pa6h0u2kixjl2r4vfluf foreign key (member_id) references member Hibernate: alter table if exists answer add constraint FKn2sp5pa6h0u2kixjl2r4vfluf foreign key (member_id) references member 2023-08-14T05:24:40.982+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists answer add constraint FK8frr4bcabmmeyyu60qt7iiblo foreign key (question_id) references question Hibernate: alter table if exists answer add constraint FK8frr4bcabmmeyyu60qt7iiblo foreign key (question_id) references question 2023-08-14T05:24:40.983+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists question add constraint FK6fsg3647bhqmogxrp2bqksnf3 foreign key (file_id) references file Hibernate: alter table if exists question add constraint FK6fsg3647bhqmogxrp2bqksnf3 foreign key (file_id) references file 2023-08-14T05:24:40.985+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists question add constraint FK1f5tvh6o6n30k5h6iqefshhu5 foreign key (user_id) references member Hibernate: alter table if exists question add constraint FK1f5tvh6o6n30k5h6iqefshhu5 foreign key (user_id) references member 2023-08-14T05:24:40.986+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists user_authority add constraint FK6ktglpl5mjosa283rvken2py5 foreign key (authority_name) references authority Hibernate: alter table if exists user_authority add constraint FK6ktglpl5mjosa283rvken2py5 foreign key (authority_name) references authority 2023-08-14T05:24:40.989+09:00 DEBUG 18164 --- [ main] org.hibernate.SQL : alter table if exists user_authority add constraint FKb27h85xa52amfh4qk85mlxudl foreign key (member_id) references member Hibernate: alter table if exists user_authority add constraint FKb27h85xa52amfh4qk85mlxudl foreign key (member_id) references member 2023-08-14T05:24:40.996+09:00 INFO 18164 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2023-08-14T05:24:41.596+09:00 WARN 18164 --- [ main] ocalVariableTableParameterNameDiscoverer : Using deprecated '-debug' fallback for parameter name resolution. Compile the affected code with '-parameters' instead or avoid its introspection: com.likelion.nsu.gojisik.repository.UserRepository 2023-08-14T05:24:41.845+09:00 WARN 18164 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2023-08-14T05:24:42.025+09:00 INFO 18164 --- [ main] o.s.s.web.DefaultSecurityFilterChain : Will secure any request with [ org.springframework.security .web.session.DisableEncodeUrlFilter@3fc7abf6, org.springframework.security .web.context.request.async.WebAsyncManagerIntegrationFilter@1016b44e, org.springframework.security .web.context.SecurityContextHolderFilter@565030b7, org.springframework.security .web.header.HeaderWriterFilter@43c3354, org.springframework.security .web.authentication.logout.LogoutFilter@6bbac73d, org.springframework.web.filter.CorsFilter@5e593b08, com.likelion.nsu.gojisik.security .JwtFilter@6c6c93f8, org.springframework.security .web.savedrequest.RequestCacheAwareFilter@2eb31735, org.springframework.security .web.servletapi.SecurityContextHolderAwareRequestFilter@73753326, org.springframework.security .web.authentication.AnonymousAuthenticationFilter@38e88e13, org.springframework.security .web.session.SessionManagementFilter@750adad8, org.springframework.security .web.access.ExceptionTranslationFilter@2fafa9bf, org.springframework.security .web.access.intercept.AuthorizationFilter@7ec75228] 2023-08-14T05:24:42.643+09:00 INFO 18164 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8081 (http) with context path '' 2023-08-14T05:24:42.652+09:00 INFO 18164 --- [ main] c.l.nsu.gojisik.GojisikApplication : Started GojisikApplication in 6.984 seconds (process running for 7.725) 2023-08-14T05:24:56.675+09:00 INFO 18164 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[ localhost ].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2023-08-14T05:24:56.675+09:00 INFO 18164 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2023-08-14T05:24:56.677+09:00 INFO 18164 --- [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms 2023-08-14T05:24:57.142+09:00 DEBUG 18164 --- [nio-8081-exec-1] org.hibernate.SQL : select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? Hibernate: select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? 2023-08-14T05:24:57.143+09:00 TRACE 18164 --- [nio-8081-exec-1] org.hibernate.orm.jdbc.bind : binding parameter [1] as [VARCHAR] - [01084912125] 2023-08-14T05:25:00.654+09:00 DEBUG 18164 --- [nio-8081-exec-3] org.hibernate.SQL : select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? Hibernate: select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? 2023-08-14T05:25:00.655+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [1] as [VARCHAR] - [01084912125] 2023-08-14T05:25:00.775+09:00 DEBUG 18164 --- [nio-8081-exec-3] org.hibernate.SQL : insert into member (activated,birthday,font,grade,password,phone_number,point,username,member_id) values (?,?,?,?,?,?,?,?,default) Hibernate: insert into member (activated,birthday,font,grade,password,phone_number,point,username,member_id) values (?,?,?,?,?,?,?,?,default) 2023-08-14T05:25:00.790+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [1] as [BOOLEAN] - [true] 2023-08-14T05:25:00.790+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [2] as [TIMESTAMP] - [null] 2023-08-14T05:25:00.790+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [3] as [INTEGER] - [0] 2023-08-14T05:25:00.790+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [4] as [TINYINT] - [null] 2023-08-14T05:25:00.790+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [5] as [VARCHAR] - [$2a$10$lXqx/USXvQtMk5U7tGg7.OIcNUGHOSRTGzpigXehAMAahzcYpcHJO] 2023-08-14T05:25:00.791+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [6] as [VARCHAR] - [01084912125] 2023-08-14T05:25:00.791+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [7] as [BIGINT] - [null] 2023-08-14T05:25:00.791+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [8] as [VARCHAR] - [null] 2023-08-14T05:25:00.824+09:00 DEBUG 18164 --- [nio-8081-exec-3] org.hibernate.SQL : insert into authority (authority_name) values (?) Hibernate: insert into authority (authority_name) values (?) 2023-08-14T05:25:00.825+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [1] as [VARCHAR] - [ROLE_USER] 2023-08-14T05:25:00.830+09:00 DEBUG 18164 --- [nio-8081-exec-3] org.hibernate.SQL : insert into user_authority (member_id,authority_name) values (?,?) Hibernate: insert into user_authority (member_id,authority_name) values (?,?) 2023-08-14T05:25:00.831+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [1] as [BIGINT] - [1] 2023-08-14T05:25:00.831+09:00 TRACE 18164 --- [nio-8081-exec-3] org.hibernate.orm.jdbc.bind : binding parameter [2] as [VARCHAR] - [ROLE_USER] 2023-08-14T05:25:04.414+09:00 DEBUG 18164 --- [nio-8081-exec-4] org.hibernate.SQL : select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? Hibernate: select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? 2023-08-14T05:25:04.414+09:00 TRACE 18164 --- [nio-8081-exec-4] org.hibernate.orm.jdbc.bind : binding parameter [1] as [VARCHAR] - [01084912125] 2023-08-14T05:38:49.268+09:00 DEBUG 18164 --- [io-8081-exec-10] org.hibernate.SQL : select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? Hibernate: select m1_0.member_id, m1_0.activated, a1_0.member_id, a1_1.authority_name, m1_0.birthday, m1_0.font, m1_0.grade, m1_0.password, m1_0.phone_number, m1_0.point, m1_0.username from member m1_0 left join (user_authority a1_0 join authority a1_1 on a1_1.authority_name=a1_0.authority_name) on m1_0.member_id=a1_0.member_id where m1_0.username=? 2023-08-14T05:38:49.269+09:00 TRACE 18164 --- [io-8081-exec-10] org.hibernate.orm.jdbc.bind : binding parameter [1] as [VARCHAR] - [01084912125]

  • spring-boot
  • jwt
  • 토큰
  • token
qkrals2475 댓글 2 좋아요 0 조회수 623

npx cli 명령어가 작동되지 않습니다.

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

이전 강의까진 npx cli가 작동이 잘 되었는데 이번 강의 코드에선 npx cli -v 하니깐 에러가 나는 것도 아니고 아무것도 안 뜨고 그냥 이렇게 끝나는데 이거 해결법이 있나요? 물론 node command -v는 잘 작동이 됩니다.

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
roider2316 댓글 1 좋아요 0 조회수 407

특정 게시물을 찾을 때 없는 경우 에러 메세지 생성 에러

미해결

따라하며 배우는 NestJS

아래와 같이 NotFoundException()을 설정해줬는데요, 에러 메세지에 작성한 텍스트로 나오지 않습니다. Delete는 message에 잘 찍혀서 나오는데 GET만 안되네요.. 같은 문제 있으셨던 분 계시나요? getBoardById(id: string): Board { const found = this.boards.find((board) => board.id === id); if (!found) { throw new NotFoundException('게시물 없음'); } return found; } { "message": "Cannot GET /boards/wefqwefe", "error": "Not Found", "statusCode": 404 } { "name": "project-test", "version": "0.0.1", "description": "", "author": "", "private": true, "license": "UNLICENSED", "scripts": { "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main", "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "test": "jest", "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json" }, "dependencies": { "@nestjs/common": "^10.0.0", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "class-transformer": "^0.5.1", "class-validator": "^0.14.0", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", "uuid": "^9.0.0" }, "devDependencies": { "@nestjs/cli": "^10.0.0", "@nestjs/schematics": "^10.0.0", "@nestjs/testing": "^10.0.0", "@types/express": "^4.17.17", "@types/jest": "^29.5.2", "@types/node": "^20.3.1", "@types/supertest": "^2.0.12", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", "source-map-support": "^0.5.21", "supertest": "^6.3.3", "ts-jest": "^29.1.0", "ts-loader": "^9.4.3", "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", "typescript": "^5.1.3" }, "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "rootDir": "src", "testRegex": ".*\\.spec\\.ts$", "transform": { "^.+\\.(t|j)s$": "ts-jest" }, "collectCoverageFrom": [ "**/*.(t|j)s" ], "coverageDirectory": "../coverage", "testEnvironment": "node" } }

  • postgresql
  • jwt
  • nestjs
  • typeorm
댓글 1 좋아요 0 조회수 494

shebang주석 질문

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

#!/usr/bin/env node 코드는 윈도우에선 주석처리가 되어 아무런 영향이 없어야 하는데 경로 부분에 오타를 내보니 npx cli명령어 실행 시 "지정된 경로를 찾을 수 없습니다." 에러가 뜨더라고요. 윈도우도 이 코드에 영향을 받나요??

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
roider2316 댓글 1 좋아요 0 조회수 336

10.4 토큰테스트에는 표시되지만 api 서버에는 유효하지 않다고 나와요.

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

질문1) 4000/test에서는 토큰이 표시되지만, 8002/v1/test 에서는 유효하지 않은 토큰으로 뜨는 이유가 무엇일까요? 로그에서는 401코드가 뜨다가 4000/test 접속 후 새로고침을 하면 200 코드가 로그에 다시 뜹니다. api 코딩 내용 첨부합니다. app.js controllers/v1 middleware/v1 routes/v1

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
ysm6514 댓글 2 좋아요 0 조회수 590

async await 함수 사용에 대해서 문의드립니다.

미해결

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

아직 노드버드 ch10 진행중입니다. 진행하면서 다른 글들도 참고하면서 진행중인데요 async await 사용 방식에 대해 문의드립니다. DB 데이타 조회, 생성 시 async 로 진행하는데 코딩 방식1 try{ const user = await User.findOne(...); ... await user.addFollowing(...); }catch(err){ next(err); } 코딩 방식2 User.findOne() .then((result) => { user.addFollowing(...); }) .then((result) => { ... }) .catch((err) => { next(err)}); 방식1은 await 키워드로 비동기 함수 호출하는 방식이구 아래는 then 을 통해 비동기 함수 호출 하는 방식인듯 한데요. 둘중 많이 쓰는 방식이 있을까요..?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
카이 댓글 3 좋아요 1 조회수 451

checkAuction() 호출 위치 질문

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

const checkAuction = require("./checkAuction"); const app = express(); passportConfig(); checkAuction(); app.set("port", process.env.PORT || 8010); app.set("view engine", "html"); nunjucks.configure("views", { express: app, watch: true, }); sequelize .sync({ force: false }) .then(() => { console.log("데이터베이스 연결 성공"); }) .catch((err) => { console.error(err); }); 이렇게 checkAuction함수의 호출이 sequelize.sync호출보다 위에있는데 어떻게 시퀄라이즈를 쓰는checkAuction함수가 에러없이 돌아가는게 가능한 것이죠?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
roider2316 댓글 1 좋아요 0 조회수 276

현업에서 환경변수 같은 건 어떻게 관리하시나요?

해결됨

실리콘밸리 엔지니어가 가르치는 파이썬 장고 웹프로그래밍

민감한 URL 이라든지 환경변수를 통해 사용하고 싶은게 있을 때 강사님께서는 어떻게 관리하시는지 궁금합니다. 그냥 UNIX 환경에서 export url = http://example.com 이런식으로 하고 os 모듈을 통해 쓰고있는데, 더 보안상 좋은 방법이 있을까요?

  • python
  • django
  • bootstrap
  • rest-api
  • drf
댓글 1 좋아요 1 조회수 406

api 서버 만들기: 도메인주소, 클라이언트비밀키가 화면에 표시되지 않습니다.

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

무료/프리미엄 고르고 도메인주소 입력하면 밑에 화면에 주소와 타입 비밀키가 표시되지 않습니다. 로그는 계속 이렇게만 뜨고, 워크벤치 들어가보면 키는 보입니다. 키가 발급은 되었는데, 브라우저로 못 띄우는 것 같다고 판단했습니다. 어떤 부분을 확인해봐야 될까요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
ysm6514 댓글 1 좋아요 0 조회수 614

XML파일도 링크 공유해주시면 감사하겠습니다.

미해결

따라하며 배우는 NestJS

안녕하세요? 인프런 수업자료 페이지에서 받은 파일이 모두 비어있어 커뮤니티에서 검색을 해보니 강사님께서 PDF파일 링크를 올려주신 답변을 찾았는데 PDF파일은 중간중간 글자가 짤리는부분이 좀 있는 듯 하여 DrawIo로 XML파일 불러와서 봐보고싶은데 XML파일은 링크를 찾을수가 없더라구요~ XML파일도 링크 공유해주시면 감사하겠습니다. Nest 처음 공부하는데 강사님 강의 정말 도움 많이 되고 있습니다. 감사합니다!

  • postgresql
  • jwt
  • nestjs
  • typeorm
Donggun Jang 댓글 1 좋아요 0 조회수 364

권한 인증 403가 뜹니다

미해결

스프링부트 시큐리티 & JWT 강의

https://github.com/bgseong/Security-test public class JwtAuthorizationFilter extends BasicAuthenticationFilter { private TokenService tokenService; public JwtAuthorizationFilter(AuthenticationManager authenticationManager, TokenService tokenService) { super(authenticationManager); this.tokenService = tokenService; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { super.doFilterInternal(request, response, chain); String token = tokenService.resolveToken(request); if(token == null){ chain.doFilter(request, response); return; } if (tokenService.validateToken(token)) { Authentication authentication = tokenService.getAuthentication(token); SecurityContextHolder.getContext().setAuthentication(authentication); System.out.println(SecurityContextHolder.getContext().getAuthentication()); } chain.doFilter(request,response); } } @EnableWebSecurity @Configuration @RequiredArgsConstructor @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig { @Autowired TokenService tokenService; @Autowired CorsConfig corsConfig; @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http .csrf().disable() .httpBasic().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .formLogin().disable() .apply(new MyCustomDsl()) .and() .authorizeHttpRequests(authorize -> authorize .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // 특정 정적 리소스 허용 .requestMatchers("/api/v1/user/**").hasAnyRole("ADMIN", "MANAGER") .requestMatchers("/api/v1/manager/**").hasRole("ADMIN") .requestMatchers("/api/v1/admin/**").hasRole("ROLE_ADMIN") .anyRequest().permitAll()); return http.build(); } public class MyCustomDsl extends AbstractHttpConfigurer<MyCustomDsl, HttpSecurity> { @Override public void configure(HttpSecurity http) throws Exception { AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); http .addFilter(corsConfig.corsFilter()) .addFilter(new LoginFilter(authenticationManager,tokenService)) .addFilter(new JwtAuthorizationFilter(authenticationManager,tokenService)); } } } @Component public class TokenService implements InitializingBean { private final UserRepository usersrepository; private final Logger logger = LoggerFactory.getLogger(TokenService.class); private static final String AUTHORITIES_KEY = "auth"; private final String secret; private final long accessTokenValidityInMilliseconds; private final long refreshTokenValidityInMilliseconds; public static final String AUTHORIZATION_HEADER = "Authorization"; public static final String REFRESHTOKEN_HEADER = "RefreshToken"; private Key key; public TokenService( UserRepository usersrepository, @Value("${spring.jwt.secret}") String secret, @Value("${spring.jwt.token-validity-in-seconds}") long tokenValidityInSeconds) { this.usersrepository = usersrepository; this.secret = secret; this.accessTokenValidityInMilliseconds = tokenValidityInSeconds * 500; this.refreshTokenValidityInMilliseconds = tokenValidityInSeconds * 1000 * 336; } @Override public void afterPropertiesSet() { byte[] keyBytes = Decoders.BASE64.decode(secret); this.key = Keys.hmacShaKeyFor(keyBytes); } public String createAccessToken(PrincipalDetails principalDetails) { return createAccessToken(principalDetails.getUser().getEmail(), principalDetails.getAuthorities()); } public String createRefreshToken(PrincipalDetails principalDetails) { return createRefreshToken(principalDetails.getUser().getEmail(), principalDetails.getAuthorities()); } public String createAccessToken(String email, Collection<? extends GrantedAuthority> inputAuthorities) { String authorities = inputAuthorities.stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); long now = (new Date()).getTime(); String accessToken = Jwts.builder() .setSubject(email) .claim(AUTHORITIES_KEY, authorities) .signWith(key, SignatureAlgorithm.HS512) .setExpiration(new Date(now + this.accessTokenValidityInMilliseconds)) .compact(); return accessToken; } public String createRefreshToken(String email, Collection<? extends GrantedAuthority> inputAuthorities) { String authorities = inputAuthorities.stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.joining(",")); long now = (new Date()).getTime(); String Token = Jwts.builder() .setSubject(email) .claim(AUTHORITIES_KEY, authorities) .signWith(key, SignatureAlgorithm.HS512) .setExpiration(new Date(now + this.refreshTokenValidityInMilliseconds)) .compact(); return Token; } public Authentication getAuthentication(String token) { Claims claims = Jwts .parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); User user = usersrepository.findByEmail(claims.get("sub",String.class)); Collection<? extends GrantedAuthority> authorities = Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(",")) .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); PrincipalDetails principal = new PrincipalDetails(user); return new UsernamePasswordAuthenticationToken(principal, null, authorities); } public String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader(AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; } public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token); return true; } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) { logger.info("worng JWT sign"); } catch (ExpiredJwtException e) { logger.info("expire JWT"); } catch (UnsupportedJwtException e) { logger.info("No support JWT"); } catch (IllegalArgumentException e) { logger.info("JWT is worng"); } return false; } } 이렇게 구성해 놨습니다. 그런데 모든 권한이 적용된 url에 접근을 하면 403 에러가 뜹니다. 필터에서 SecurityContextHolder를 출력하면 아래와 같이 출력이 되는 걸 확인했고 [Principal=com.securitytest.Securitytest.auth.PrincipalDetails@45095607, Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[ROLE_ADMIN]] 컨트롤러에서 PrincipalDetails를 호출해보니, null이라서 오류가 난다고 뜹니다. 무엇이 문제일까요ㅠㅠ..

  • spring
  • spring-security
  • jwt
성부근 댓글 2 좋아요 0 조회수 1826

room계층 소켓 연결 후 소통 질문

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

서버쪽에선 socket.on("join", (data) => { socket.join(data); // 방 참가 socket.to(data).emit("join", { user: "system", chat: `${socket.request.session.color}님이 입장하셨습니다.`, }); }); 이렇게 room계층 소켓으로 연결했고, 해당 room으로 join이벤트를 보냈는데 브라우저 쪽에선 const socket = io.connect("http://localhost:8005/chat", { path: "/socket.io", }); socket.emit("join", new URL(location).pathname.split("/").at(-1)); socket.on("join", function (data) {...} /chat 네임스페이스 계층 소켓으로 밖에 연결하지 못했는데 어떻게 해당 room계층으로 온 join이벤트인지 구별하는 게 가능한지 궁금합니다. room계층보다 상위인 네임스페이스 계층에 연결했으니 어느 room으로 오든 네임스페이스만 같으면 모든 이벤트를 다 감지하게 되는 것 아닌가요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
roider2316 댓글 1 좋아요 0 조회수 301

1강 환경설정을 따라하는데 run하면 에러가 나요

미해결

스프링부트 시큐리티 & JWT 강의

설정 후 run 하면 If you want an embedded database (H2, HSQL or Derby), please put it on the classpath. 라는 문구가 뜹니다. 그래서 mysql에 다시 한번 sql문구를 쓰고 다시 처음부터 강의대로 해봤는데도 안되서 구글링해도 모르겠어서요ㅠㅠ

  • spring
  • spring-security
  • jwt
댓글 2 좋아요 0 조회수 846

소셜 로그인 후 JWT 발급

미해결

스프링부트 시큐리티 & JWT 강의

아무리 해도 해결이 안되네요... package com.example.project1.config.oauth2; import com.example.project1.config.auth.PrincipalDetails; import com.example.project1.config.oauth2.provider.GoogleUserInfo; import com.example.project1.config.oauth2.provider.NaverUserInfo; import com.example.project1.config.oauth2.provider.OAuth2UserInfo; import com.example.project1.domain.member.UserType; import com.example.project1.entity.member.MemberEntity; import com.example.project1.repository.member.MemberRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.stereotype.Service; import java.util.Map; @Service @Slf4j @RequiredArgsConstructor public class PrincipalOauth2UserService extends DefaultOAuth2UserService { private final BCryptPasswordEncoder bCryptPasswordEncoder; private final MemberRepository memberRepository; // 구글로부터 받은 userReuest 데이터에 대한 후처리되는 함수 @Override public PrincipalDetails loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException { // registrationId로 어떤 OAuth로 로그인 했는지 확인가능 log.info("clientRegistration in PrincipalOauth2UserService : " + userRequest.getClientRegistration() ); log.info("accessToken in PrincipalOauth2UserService : " + userRequest.getAccessToken().getTokenValue() ); OAuth2User oAuth2User = super.loadUser(userRequest); // 구글 로그인 버튼 클릭 →구글 로그인 창 → 로그인 완료 → code 를 리턴(OAuth-Client 라이브러리) → AccessToken 요청 // userRequest 정보 → 회원 프로필 받아야함(loadUser 함수 호출) → 구글로부터 회원 프로필을 받아준다. log.info("getAttributes in PrincipalOauth2UserService : " + oAuth2User.getAttributes()); // 회원가입을 강제로 진행 OAuth2UserInfo oAuth2UserInfo = null; if(userRequest.getClientRegistration().getRegistrationId().equals("google")) { log.info("구글 로그인 요청"); oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes()); } else if(userRequest.getClientRegistration().getRegistrationId().equals("naver")) { log.info("네이버 로그인 요청"); // 네이버는 response를 json으로 리턴을 해주는데 아래의 코드가 받아오는 코드다. // response={id=5SN-ML41CuX_iAUFH6-KWbuei8kRV9aTHdXOOXgL2K0, email=zxzz8014@naver.com, name=전혜영} // 위의 정보를 NaverUserInfo에 넘기면 oAuth2UserInfo = new NaverUserInfo((Map)oAuth2User.getAttributes().get("response")); } else { log.info("구글과 네이버만 지원합니다."); } // 사용자가 로그인한 소셜 서비스(provider)를 가져옵니다. // 예를 들어, "google" 또는 "naver"와 같은 값을 가질 수 있습니다. String provider = oAuth2UserInfo.getProvider(); // 사용자의 소셜 서비스(provider)에서 발급된 고유한 식별자를 가져옵니다. // 이 값은 해당 소셜 서비스에서 유니크한 사용자를 식별하는 용도로 사용됩니다. String providerId = oAuth2UserInfo.getProviderId(); // 예) google_109742856182916427686 String userName = provider + "_" + providerId; String password = bCryptPasswordEncoder.encode("get"); // 사용자의 이메일 주소를 가져옵니다. 소셜 서비스에서 제공하는 이메일 정보를 사용합니다. String email = oAuth2UserInfo.getEmail(); // 사용자의 권한 정보를 설정합니다. UserType. // 여기서는 소셜로그인으로 가입하면 무조건 User로 권한을 주는 방식으로 했습니다. UserType role = UserType.USER; // 이메일 주소를 사용하여 이미 해당 이메일로 가입된 사용자가 있는지 데이터베이스에서 조회합니다. MemberEntity member = memberRepository.findByUserEmail(email); if(member == null) { log.info("OAuth 로그인이 최초입니다."); log.info("↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓"); log.info("OAuth 자동 회원가입을 진행합니다."); member = MemberEntity.builder() .userName(userName) .userPw(password) .userEmail(email) .userType(role) .provider(provider) .providerId(providerId) .build(); log.info("userEmail in PrincipalOauth2UserService : " + member.getUserEmail()); log.info("userName in PrincipalOauth2UserService : " + member.getUserName()); log.info("userPw in PrincipalOauth2UserService : " + member.getUserPw()); log.info("userType in PrincipalOauth2UserService : " + member.getUserType()); log.info("provider in PrincipalOauth2UserService : " + member.getProvider()); log.info("providerId in PrincipalOauth2UserService : " + member.getProviderId()); memberRepository.save(member); } else { log.info("로그인을 이미 한적이 있습니다. 당신은 자동회원가입이 되어 있습니다."); MemberEntity findUser = memberRepository.findByUserEmail(email); log.info("findUser in PrincipalOauth2UserService : " + findUser); } OAuth2User oAuth2User1 = super.loadUser(userRequest); log.info("getAttributes in PrincipalOauth2UserService : " + oAuth2User1.getAttributes()); // attributes가 있는 생성자를 사용하여 PrincipalDetails 객체 생성 // 소셜 로그인인 경우에는 attributes도 함께 가지고 있는 PrincipalDetails 객체를 생성하게 됩니다. PrincipalDetails principalDetails = new PrincipalDetails(member, oAuth2User.getAttributes()); log.info("principalDetails in PrincipalOauth2UserService : " + principalDetails); return principalDetails; } } package com.example.project1.config.oauth2.provider; public interface OAuth2UserInfo { String getProviderId(); String getProvider(); String getEmail(); String getName(); } package com.example.project1.config.oauth2.provider; import java.util.Map; public class GoogleUserInfo implements OAuth2UserInfo{ // getAttributes()를 받음 private Map<String, Object> attributes; public GoogleUserInfo(Map<String, Object> attributes) { this.attributes = attributes; } @Override public String getProviderId() { return (String) attributes.get("sub"); } @Override public String getProvider() { return "google"; } @Override public String getEmail() { return (String) attributes.get("email"); } @Override public String getName() { return (String) attributes.get("name"); } } package com.example.project1.config.oauth2.provider; import java.util.Map; public class NaverUserInfo implements OAuth2UserInfo{ // oauth2User.getAttributes()를 받음 private Map<String,Object> attributes; // PrincipalOauth2UserService에서 new NaverUserInfo((Map)oAuth2User.getAttributes().get("response"))로 // Oauth2 네이버 로그인 정보를 받아온다. // → {id=5SN-ML41CuX_iAUFH6-KWbuei8kRV9aTHdXOOXgL2K0, email=zxzz8014@naver.com, name=전혜영} public NaverUserInfo(Map<String, Object> attributes) { this.attributes = attributes; } @Override public String getProviderId() { return (String)attributes.get("id"); } @Override public String getProvider() { return "naver"; } @Override public String getEmail() { return (String)attributes.get("email"); } @Override public String getName() { return (String)attributes.get("name"); } } package com.example.project1.config.auth; import com.example.project1.entity.member.MemberEntity; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.core.user.OAuth2User; import java.util.ArrayList; import java.util.Collection; import java.util.Map; @Setter @Getter @ToString @NoArgsConstructor @Slf4j public class PrincipalDetails implements UserDetails, OAuth2User { // 일반 로그인 정보를 저장하기 위한 필드 private MemberEntity member; // OAuth2 로그인 정보를 저장하기 위한 필드 // attributes는 Spring Security에서 OAuth2 인증을 수행한 후에 사용자에 대한 추가 정보를 저장하는 데 사용되는 맵(Map)입니다. // OAuth2 인증은 사용자 인증 후에 액세스 토큰(Access Token)을 발급받게 되는데, // 이 토큰을 사용하여 OAuth2 서비스(provider)로부터 사용자의 프로필 정보를 요청할 수 있습니다. // 예를 들어, 소셜 로그인을 사용한 경우에는 attributes에는 사용자의 소셜 서비스(provider)에서 제공하는 프로필 정보가 담겨 있습니다. // 소셜 로그인 서비스(provider)마다 제공하는 프로필 정보가 다를 수 있습니다. // 일반적으로 attributes에는 사용자의 아이디(ID), 이름, 이메일 주소, 프로필 사진 URL 등의 정보가 포함됩니다. /* * 구글의 경우 * { "sub": "100882758450498962866", // 구글에서 발급하는 고유 사용자 ID "name": "John Doe", // 사용자 이름 "given_name": "John", // 이름(이름 부분) "family_name": "Doe", // 성(성(성) 부분) "picture": "https://lh3.googleusercontent.com/a/AAcHTtdzQomNwZCruCcM0Eurcf8hAgBHcgwvbXEBQdw3olPkSg=s96-c", // 프로필 사진 URL "email": "johndoe@example.com", // 이메일 주소 "email_verified": true, // 이메일 주소 인증 여부 "locale": "en" // 지역 설정 } * */ private Map<String, Object> attributes; // 일반 로그인 public PrincipalDetails(MemberEntity member) { this.member = member; } // OAuth2 로그인 public PrincipalDetails(MemberEntity member, Map<String, Object> attributes) { this.member = member; this.attributes = attributes; } // 해당 유저의 권한을 리턴하는 곳 @Override public Collection<? extends GrantedAuthority> getAuthorities() { Collection<GrantedAuthority> collection = new ArrayList<>(); collection.add(new SimpleGrantedAuthority("ROLE_" + member.getUserType().toString())); log.info("collection : " + collection); return collection; } // 사용자 패스워드를 반환 @Override public String getPassword() { log.info("password : "+ member.getUserPw()); return member.getUserPw(); } // 사용자 이름 반환 @Override public String getUsername() { log.info("id : " + member.getUserEmail()); return member.getUserEmail(); } // 계정 만료 여부 반환 @Override public boolean isAccountNonExpired() { // 만료되었는지 확인하는 로직 // true = 만료되지 않음 return true; } // 계정 잠금 여부 반환 @Override public boolean isAccountNonLocked() { // true = 잠금되지 않음 return true; } // 패스워드의 만료 여부 반환 @Override public boolean isCredentialsNonExpired() { // 패스워드가 만료되었는지 확인하는 로직 // true = 만료되지 않음 return true; } // 계정 사용 가능 여부 반환 @Override public boolean isEnabled() { // 계정이 사용 가능한지 확인하는 로직 // true = 사용 가능 return true; } @Override public Map<String, Object> getAttributes() { log.info("attributes : " + attributes); return attributes; } @Override // OAuth2 인증에서는 사용되지 않는 메서드이므로 null 반환 public String getName() { return null; } } // Oauth2 google로 JWT 발급 @GetMapping("/success-oauth") public ResponseEntity<?> createTokenForGoogle(@AuthenticationPrincipal OAuth2User oAuth2User , @RequestBody MemberDTO member) { Object email = oAuth2User.getAttribute("email"); log.info("oAuth2User : " + email); if(oAuth2User == null) { log.info("받아올 정보가 없습니다 ㅠㅠ"); return ResponseEntity.status(HttpStatus.NOT_FOUND).body("정보가 없어...."); } else { // OAuth2User에서 필요한 정보를 추출하여 UserDetails 객체를 생성합니다. ResponseEntity<TokenDTO> token = memberService.createToken((String) email, member); log.info("token : " + token); return ResponseEntity.ok().body(token); } } // 소셜 로그인 성공시 jwt 반환 // OAuth2User에서 필요한 정보를 추출하여 UserDetails 객체를 생성하는 메서드 public ResponseEntity<TokenDTO> createToken(String userEmail, MemberDTO member) { MemberEntity findUser = memberRepository.findByUserEmail(userEmail); log.info("findUser in MemberService : " + findUser); findUser = MemberEntity.builder() // id를 식별해서 수정 // 이거 없으면 새로 저장하기 됨 // findUser꺼를 쓰면 db에 입력된거를 사용하기 때문에 // 클라이언트에서 userEmail을 전달하더라도 서버에서 기존 값으로 업데이트가 이루어질 것입니다. // 이렇게 하면 userEmail을 수정하지 못하게 할 수 있습니다. .userId(findUser.getUserId()) .userEmail(findUser.getUserEmail()) .userPw(passwordEncoder.encode(findUser.getUserPw())) .userName(findUser.getUserName()) .nickName(member.getNickName()) .userType(findUser.getUserType()) .address(AddressEntity.builder() .userAddr(member.getAddressDTO().getUserAddr()) .userAddrDetail(member.getAddressDTO().getUserAddrDetail()) .userAddrEtc(member.getAddressDTO().getUserAddrEtc()) .build()) .build(); memberRepository.save(findUser); // 권한 정보 추출 List<GrantedAuthority> authorities = getAuthoritiesForUser(findUser); // UserDetails 객체 생성 (사용자의 아이디 정보를 활용) // 첫 번째 인자 : username 사용자 아이디 // 두 번째 인자 : 사용자의 비밀번호 // 세 번째 인자 : 사용자의 권한 정보를 담은 컬렉션 UserDetails userDetails = new User(userEmail, null, authorities); log.info("userDetails in MemberService : " + userDetails); TokenDTO token = jwtProvider.createToken2(userDetails); log.info("token in MemberService : " + token); return ResponseEntity.ok().body(token); } // 소셜 로그인 성공시 JWT 발급 public TokenDTO createToken2(UserDetails userDetails) { long now = (new Date()).getTime(); Date now2 = new Date(); // userDetails.getAuthorities()는 사용자의 권한(authorities) 정보를 가져오는 메서드입니다. // claims.put("roles", userDetails.getAuthorities()) 코드는 사용자의 권한 정보를 클레임에 추가하는 것입니다. // 클레임에는 "roles"라는 키로 사용자의 권한 정보가 저장되며, 해당 권한 정보는 JWT의 페이로드 부분에 포함됩니다. Claims claims = Jwts.claims().setSubject(userDetails.getUsername()); claims.put(AUTHORITIES_KEY, userDetails.getAuthorities()); log.info("claims : " + claims); // access token Date accessTokenExpire = new Date(now + this.accessTokenTime); String accessToken = Jwts.builder() .setSubject(userDetails.getUsername()) .setClaims(claims) .setIssuedAt(now2) .setExpiration(accessTokenExpire) .signWith(key,SignatureAlgorithm.HS256) .compact(); // RefreshToken 생성 Date refreshTokenExpire = new Date(now + this.refreshTokenTime); String refreshToken = Jwts.builder() .setIssuedAt(now2) .setClaims(claims) .setExpiration(refreshTokenExpire) .signWith(key, SignatureAlgorithm.HS256) .compact(); TokenDTO tokenDTO = TokenDTO.builder() .grantType("Bearer ") .accessToken(accessToken) .refreshToken(refreshToken) .userEmail(userDetails.getUsername()) .build(); log.info("tokenDTO in JwtProvider : " + tokenDTO); return tokenDTO; } http // oauth2Login() 메서드는 OAuth 2.0 프로토콜을 사용하여 소셜 로그인을 처리하는 기능을 제공합니다. .oauth2Login() // OAuth2 로그인 성공 이후 사용자 정보를 가져올 때 설정 담당 .userInfoEndpoint() // OAuth2 로그인 성공 시, 후작업을 진행할 서비스 .userService(principalOauth2UserService) .and() .defaultSuccessUrl("/success-oauth"); 소셜 로그인 후 쇼핑몰 프로젝트라 주소가 필 수라서 JSON을 추가로 받아서 주소를 DB에 저장 후 JWT를 반환해주는 로직을 구성하려고 합니다. 소셜 로그인을 했을 때 PrincipalOauth2UserService여기서 모든 값이 제대로 들어갔고 PrincipalDetails principalDetails = new PrincipalDetails(member, oAuth2User.getAttributes()); log.info("principalDetails in PrincipalOauth2UserService : " + principalDetails); return principalDetails; 로그를 찍어본 결과 제대로 값이 로그에 찍혔습니다. 이거를 principalDetails에 보내줬으니 principalDetails 클래스에서도 제대로 받아졌는지 확인해봤습니다. Oaut2User를 상속받아서 오버라이드 한 @Override public Map<String, Object> getAttributes() { log.info("attributes : " + attributes); return attributes; } 여기서도 로그에 제대로 값이 나왔습니다. 여기서부터가 문제인데 컨트롤러에서 @AuthenticationPrincipal OAuth2User oAuth2User로 소셜 로그인한 정보를 받아와서 토큰을 만들려고 하는데 null이 뜹니다. 별방법을 다했는데 다른 부분은 다 해결을 했는데 이부분이 해결이 안되네요 ㅠㅠ

  • spring
  • spring-security
  • jwt
유요한 댓글 1 좋아요 0 조회수 679

pending 질문입니다.

해결됨

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지

메인화면으로가는 버튼을 빠르게 반복해서 누르면 로딩중만 나오길래 개발자모드에서 network를 보면 (pending)이렇게 나오면서 응답을 못하는상태인데 왜 그러는걸까요? 모든 함수에서 mysql에 연결하고 쿼리문 사용할때 async/await 사용하고있습니다. 로그인 미들웨어는 promise로 사용하고있는데 정확히 어떤점때문에 이러한 오류가 발생하는지 모르겠습니다. 저pending 오류를 어떻게해야 해결이 될까요?

  • node.js
  • mysql
  • mongodb
  • express
  • typescript
  • socket.io
  • jwt
밈몀묘 댓글 1 좋아요 0 조회수 1460

인기 태그

인프런 TOP Writers

주간 인기글