게시글
질문&답변
inteliJ 대신 VScode 설치해도 될까요?
안녕하세요 혜빈님! 🙂 네네 VScode로 진행하셔도 괜찮습니다.다만 강의가 IntelliJ로 진행되는 만큼 다른 부분은 vs code 에서 찾아 진행하셔야 할 수도 있어요! 감사합니다. 🙇
- 0
- 2
- 37
질문&답변
Coroutine과 ThreadLocal관련 질문
안녕하세요! 대영님~ 좋은 질문 감사드립니다. ☺먼저, 말씀해주신 문제는 충분히 생길 수 있는 문제입니다. 때문에 코루틴에서 ThreadLocal을 그냥 사용하는 것은 코드가 의도한대로 동작하지 않을 수 있어요! (1) 그런 관점에서 안티패턴 혹은 의도와 다른 동작 이라고 볼 수 있을 것 같습니다. (2) 또한 코루틴을 사용할 때 ThreadLocal을 직접적으로 사용하는 경우는 많이 없습니다. 하지만 간혹 프레임워크에서 ThreadLocal로 관리되는 변수에는 접근해야 할 일이 있는데, (서버 개발자 이신 경우...) Slf4j MDC가 대표적인 것 같습니다.로깅에서 특정한 traceId를 활용하기 위해 Filter 같은 곳에서 MDC.set("traceId", 일정한 난수) 를 수행했다고 해보죠! 그리고 나서 코루틴에 들어가 로직이 실행되는데, 이 안에서 로그를 찍으면 traceId 가 함께 나와야 하는거에요!MDC는 내부적으로 ThreadLocal을 사용해 traceId와 같이 입력된 필드를 저장하기 때문에 말씀해주신 흐름에 따라 코루틴에서는 로그가 제대로 추적되지 않을 수 있습니다. 이런 경우 CoroutineContext를 이용하실 수 있는데요~ 스레드가 변경되더라도 일련의 실행 흐름을 추적할 수 있는 context를 구성하는 방식입니다. 코루틴은 MDC에 대해서 라이브러리 형태로 제공하고 있기에 아래 의존성을 추가하신 후implementation("org.jetbrains.kotlinx:kotlinx-coroutines-slf4j:1.9.0")runBlocking(MDCContext()) 처럼 코루틴 세계에 진입하는 지점에 MDCContext() 를 적어주기만 하면 ThreadLocal로 관리되고 있던 변수들을 CoroutineContext로 옮겨와 관리할 수 있도록 됩니다. 🙂(이 기능의 내부 원리가 CoroutineContext의 Element를 관리하는 것 이고요..! ThreadContextElement를 찾아보셔도 좋습니다!) 참고로, 이런 방식은 spring webflux도 필요합니다. 답변이 도움이 되었으면 좋겠습니다. 감사합니다. 🙇
- 0
- 2
- 41
질문&답변
테스트를 위한 코드
안녕하세요! 71kimty님~ 🙂 정말 좋은 질문이십니다. AI 인턴이 얘기해 준 것 처럼, fixture 함수를 Entity 클래스 안에 (더 정확히는 production 코드 안에) 넣게 되면 장단점이 있다고 생각해요.장점은 멀티 모듈에서 하위 모듈 (보통 하위 모둘에 Entity가 들어가죠) 의 fixture를 상위 모듈에서 쉽게 접근할 수 있다 는 것이고단점은, 어쨌거나 프로덕션 코드에서 fixture에 접근 가능하다는 것이죠.(만약 test 코드 안에 fixture를 작성하면 상위 모듈에서 하위 모듈의 fixture를 사용할 수 없게 되어 상당히 불편합니다 🥲)저는 마치 kotlin의 public var 필드처럼 열어두지만 사용하지 않는 것을 convention으로 하는 편이고, 요즘은 Entity companion object에 fixture를 바로 넣지 않고 같은 패키지에 object UserFixtures 와 같은 싱글톤을 만들어 테스트 함수를 넣는 편입니다. 만약, 위에서 말씀드린 단점을 극복하면서도 장점을 누리고 싶다면, https://tech.kakaopay.com/post/given-test-code-2/를 참고해보셔도 좋습니다.java-test-fixtures 와 같은 라이브러리를 사용하면 프로덕션 폴더도 아니고 테스트 폴더도 아닌 제 3의 구조를 만들어 의존성 설정이 되어 있는 모듈에서 쓸 수 있게끔 처리할 수 있습니다. 개인적으로도 좋은 방법이라 생각합니다. 🙂 답변이 도움이 되었으면 좋겠습니다. 감사합니다. 🙇
- 1
- 2
- 29
질문&답변
30강 질문
안녕하세요! 🙂 성장하자님~ 항상 디테일한 부분까지 질문 주셔서 감사합니다. repository를 user를 다룰때는 repository라는 패키지를 따로 만들어서 했는데, 지금 강의의 book에 관한 repositorty를 따로 만들지 않고 인터페이스만 객체와 같은 패키지에 만들어서 extends로 jpa를 받기 때문에 따로 만들 필요가 없어서 이렇게 만든거라고 이해 했는데 맞게 이해한걸까요? 제가 질문을 정확히 이해한 것인지 모르겠지만JpaRepository를 extends하는 interface를 만들 때는 패키지를 repository 로 분리하지 않고,JdbcTemplate을 사용하는 Repository를 만들 때는 repository 패키지를 왜 분리했는가가 질문인 것 처럼 느껴집니다! 결론부터 말씀드리면... 개인 취향에 가깝습니다. 🙂어떤 분들은JpaRepository 이건 SQL을 직접 사용하는 Repository 이건 repository패키지로 분리하는 것을 선호하시고요!어떤 분들은@Entity 와 같은 패키지에 JpaRepository 및 관련 Repository (ex. Querydsl) 을 함께 넣으시는 것을 선호하시기도 합니다. 저는 개인적으로 후자의 취향을 갖고 있고, 프로젝트 내 일관성만 유지되면 어떤 방식이건 크게 다르지 않다 라고 생각하고 있습니다. 감사합니다. 🙏
- 0
- 1
- 48
질문&답변
20강 인터페이스
안녕하세요! ☺ 인터페이스에서 @Override 어노테이션을 붙이지 않은 것에 대해 문의 주신 것 같아요~ (타임라인 - 13:54)강의 상에서 코드 변경과 스프링 컨테이너의 의의를 설명드리기 위해 슈도 코드를 작성한 것으로 봐주시면 될 것 같습니다. 물론 자바에서는 코틀린과 달리 @Override 를 필수로 작성 하지 않아도 오버라이드 된 것으로 간주되긴 하지만 명확한 가독성을 위해 어노테이션을 작성해주시는게 좋습니다.감사합니다 🙇
- 0
- 2
- 43
질문&답변
15강 질문
안녕하세요~ 좋은 질문이십니다! 🙂 아마 질문 주신 내용은...PUT API (업데이트 API) 에서는 왜 객체를 함수의 매개변수로 사용하고DELETE API (삭제 API) 에서는 왜 단순히 String을 함수의 매개변수를 사용하였는가인 것 같아요! 우선 PUT의 경우 HTTP Body를 함수에 전달 할 수 있어야 하기에 @RequestBody + 객체 조합만 사용할 수 있습니다. 그래서 DTO 를 사용하게 되었고요DELETE는 HTTP query 를 함수에 전달하게 되는데 이때는 @RequestParam 으로 직접 특정 필드를 매개변수에 전달할 수도 있고, DTO와 같은 객체를 사용할 수도 있죠. 저는 개인적으로 매개변수가 1개 정도라면 DTO를 선택적으로 사용하고, 매개변수가 2개 이상이면 DTO를 높은 확률로 사용하는 편입니다. 🙂 답변이 도움이 되었으면 좋겠습니다. 감사합니다~ 🙏
- 1
- 2
- 35
질문&답변
10강 mysql 연결오류
안녕하세요! 성장하자님~ 🙂 다시 한 번 꼼꼼하게 복습하시니 너무 좋네요~Access denied for user.. 라는 에러는 대부분 AI 인턴이 얘기한 것처럼 비밀번호가 틀린 경우입니다!비밀번호가 맞았는지 꼭 한 번 확인해보시면 좋을 것 같습니다.감사합니다. 🙇
- 1
- 2
- 50
질문&답변
6강 복습중에 질문 있습니다
안녕하세요! 성장하자님 🙂 정말 좋은 질문이시네요~인프런 AI 인턴이 대답을 잘 해주었는데요! 스프링이 문자열로 된 HTTP 을 객체로 만드는 과정에서 (이를 어려운 말로 역-직렬화 라고 합니다) GET API를 객체화 하는 코드와 POST API를 개체화 하는 코드의 로직이 달라서 그렇습니다. 보다 자세한 내용은 “어떻게 생성자 없이 number1과 number2에 값이 할당된건지 모르겠습니다.(DTO관련)”에서 추가로 확인해보실 수 있습니다. (왜 스프링이 GET API를 객체화 하는 코드와 POST API를 객체화 하는 코드를 달리 구성하였는지까지는 저도 정확히 모르겠습니다.)감사합니다. 🙇
- 1
- 2
- 38
질문&답변
MySQL 연결 오류
안녕하세요! qkrwlsgh98님 🙂 정말 좋은 질문 감사드립니다.처음에 잘 되다가 몇 번 컴퓨터가 재부팅되면 해당 문제가 발생한다니... 참으로 기이하네요 🥲 우선 저도 올려주신 에러를 한 번도 본 적은 없어 검색해서 나온 결과나 GPT가 알려준 내용과 크게 다르지 않은 답변만 드리게 될 것 같습니다. 예를 들어, 해당 에러를 검색해보면https://hb-in99.tistory.com/159와 같은 글이 나오는데(사진)와 같은 방법으로 해결했다고 하네요 만약 조금 다른 접근을 원하신다면.. 처음이라 정말 어려우시겠지만, docker를 이용해 mysql을 구동해보시는 건 어떠실까 싶습니다.docker를 사용한다는 것은 쉽게 말해 컴퓨터 안의 또 다른 컴퓨터를 구성하는 것 입니다!그리고 그렇게 구성한 컴퓨터 안의 컴퓨터는 쉽게 종료하고 재시작할 수 있기 때문에 그 안에 mysql을 설치해 사용해보실 수 있거든요..!윈도우 MySQL 도커 와 같은 검색어로 구글링을 해보셔도 좋고, GPT와 함께 도전해보셔도 좋을 것 같습니다. 꼭 해결되셨으면 좋겠습니다. 감사합니다. 🙇
- 1
- 2
- 67
질문&답변
[23강] SuperTypeToken의 equals 관련 질문
안녕하세요! denia park님! 🙂 좋은 질문 감사드립니다. 🙇 아래 경우로 조금 더 쉽게 예를 들어볼게요!abstract class A { override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false return true } }여기 제가 추상 클래스를 만들었습니다. 이제 추상 클래스를 익명 클래스화 해보겠습니다!! val a1 = object : A() {} val a2 = object : A() {} println(a1.javaClass == a2.javaClass)이렇게 되면 a1과 a2는 같은 클래스를 인스터스인 것 같지만, 사실 같은 추상 클래스를 구현 받는 서로 다른 익명 클래스이기 때문에a1.javaClass 와 a2.javaClass 는 서로 다르고 항상 false가 나오게 됩니다! 슈퍼 타입 토큰은 항상 익명 클래스와 함께 사용하다보니 해당 구문을 제거하게 되었습니다. 또 궁금하신 점 있으시면 편하게 질문 주세요~~ 감사합니다! 🙇
- 1
- 2
- 36