20년이상 Java 기반 웹 개발에 몸담아온 개발자 및 강사입니다. 대규모 프로젝트 설계부터 성능 최적화까지 폭넓은 실무 경험을 갖추고 있으며, 다수의 기업 교육과 대학 강의로 개발 지식 전달에도 힘써왔습니다. 실무와 교육의 균형 잡힌 시각으로 깊이 있는 통찰을 제공합니다.
Khóa học
Đánh giá khóa học
- Lập trình web với Spring Boot: Website làm như thế này đấy!
- Lập trình web với Spring Boot: Website làm như thế này đấy!
- Lập trình web với Spring Boot: Website làm như thế này đấy!
- Lập trình web với Spring Boot: Website làm như thế này đấy!
Bài viết
Hỏi & Đáp
인터셉터
jsshin님 안녕하세요.^^좋은 질문입니다! 맞습니다. Spring Security를 적용하게 되면 기존에 세션을 기반으로 로그인 여부를 확인하는 인터셉터는 더 이상 필요하지 않습니다. 왜냐하면 Spring Security는 세션 대신 SecurityContext를 통해 인증 정보를 관리하기 때문입니다.그래서 이후 강의에서 기존 인터셉터 코드는 삭제하게 되는데요. 아마 이 부분이 강의 흐름상 다소 혼동을 드렸을 수도 있겠네요. 이 부분은 다른 수강생분들도 헷갈릴 수 있는 부분이라, 조만간 강의에 보완 설명을 추가해서 좀 더 쉽게 이해하실 수 있도록 정리해 드리겠습니다.좋은 피드백 주셔서 진심으로 감사드립니다!
- 0
- 2
- 38
Hỏi & Đáp
DTO 관련
jsshin님 안녕하세요.^^아주 좋은 질문입니다. DTO는 계층 간 데이터를 전달하는 객체로서, 원칙적으로는 값을 변형하지 않는 것이 설계적으로 더 깔끔합니다.현재 코드처럼 memberDto의 pw 값을 passwordEncoder.encode()로 인코딩한 후 다시 memberDto에 반영하면, DTO가 단순 데이터 전달 객체라는 역할과 조금 어긋날 수 있다는 지적은 충분히 타당합니다.DTO의 값이 메서드 실행 중에 변경되면, 이후 코드에서 혼란을 줄 수 있고, 코드의 직관성이 떨어질 수 있습니다.그래서 실무에서는 보통 인코딩된 비밀번호를 별도의 변수로 관리하거나, DTO → Entity 변환 과정에서 처리하는 방식을 더 많이 사용합니다. 이렇게 하면 코드의 가독성과 안정성이 올라갑니다.다만, 이번 온라인 강의에서는 스프링 입문자분들께 패스워드 인코딩이 어떤 시점에 이루어지는지 직관적으로 보여드리기 위해 memberDto의 pw를 직접 변경하는 방식을 사용했습니다.즉, 객체가 한 번 수정되고 그 수정된 값이 저장되는 과정을 명확하게 이해하도록 돕기 위한 교육적인 목적이 있었습니다.결론적으로 실무에서는 더 깔끔한 설계로 개선할 수 있고, 강의에서는 학습자의 이해를 돕기 위해 일부 의도적인 것입니다. 그리고 이런 부분을 예리하게 캐치해서 질문하고, 직접 리팩토링까지 시도해 본 점은 정말 훌륭합니다. 무한 박수를 보냅니다. 이런 자세야말로 진짜 개발자로 성장하는 최고의 밑거름이고, 객체지향 설계에 대한 매우 훌륭한 감각을 가지고 있다는 증거입니다.열심히 공부하는 그 자세에 진심으로 감사드리고, 앞으로도 계속 응원하겠습니다.
- 0
- 2
- 43
Hỏi & Đáp
추가 강의 해주실수 있나요?
culwonder.company님 안녕하세요! 강의를 긍정적으로 봐주셔서 정말 감사합니다.말씀해주신 Swagger와 QueryDSL 모두 실제 프로젝트에서 많이 활용되는 중요한 기술이라 저도 강의 주제로 충분히 고민하고 있는 부분입니다.다만 현재는 단순히 개념만 전달하는 수준이 아니라, 실무 프로젝트와 연계된 실전 중심의 구성을 고민 중인데요,이렇게 접근하다 보면 자연스럽게 강의 범위가 꽤 넓어지고, 학습자분들께 부담이 될 수 있다는 점도 함께 고려하고 있습니다.그래서 아직은 방향만 구상 중이며, 어떤 방식으로 구성해야 가장 효과적일지 신중히 고민하고 있는 단계입니다.앞으로도 학습 흐름을 해치지 않으면서 실무에도 도움이 될 수 있도록 잘 준비해보겠습니다.게다가... 사실 요즘 개인 프로젝트로 밤낮을 코드와 함께 보내고 있어서, 머릿속에서 Swagger랑 QueryDSL이 막 강의 안으로 뛰어들고 싶어 해도제가 “잠깐만… 지금은 말고…” 하고 잠시 말리는 중이기도 합니다. ㅎㅎ그래도 좋은 의견 주신 덕분에 동기부여 확실히 되었고요,조만간 더 좋은 구성으로 찾아뵐 수 있도록 잘 준비해보겠습니다!강의 열심히 들어주셔서 정말 감사드리고,앞으로도 차근차근 실력 쌓아가실 수 있도록 응원하겠습니다! 소중한 의견 정말 감사드리고요, 끝까지 강의 잘 따라오실 수 있도록 끝까지 응원하겠습니다!
- 0
- 1
- 41
Hỏi & Đáp
데이터베이스 테이블이 중복 생성 되는 오류
changhui님 안녕하세요,지방 출장 일정으로 답변이 다소 늦어진 점 양해 부탁드립니다. 말씀해주신 상황을 보면 USER_MEMBER와 user_member 두 개의 테이블이 생성된 이유는 MySQL의 테이블 이름 대소문자 구분 설정과 관련이 있을 가능성이 높습니다.MySQL에서 테이블 이름의 대소문자 구분 여부는 운영체제(OS)에 따라 다르며, 또한 MySQL 자체 설정 값에도 영향을 받습니다. Windows는 기본적으로 대소문자를 구분하지 않지만, Linux는 기본적으로 대소문자를 구분합니다.또한 MySQL 설정 값 중 lower_case_table_names의 값에 따라 테이블 이름 처리 방식이 결정되는데요, 해당 설정은 아래 쿼리로 확인할 수 있습니다.SHOW VARIABLES LIKE 'lower_case_table_names';결괏값(value)으로'0'이면 대소문자를 구분합니다.(Linux, 일부 Mac)'1'이면 테이블 이름을 소문자로 통일해서 처리합니다.(Windows)'2'이면 저장은 원래 이름으로 하되, 비교는 소문자로 합니다.(일부 Mac) changhui님께서 Windows를 사용하고 계시다면 lower_case_table_names 값이 '1'일 가능성이 높고, Mac을 사용 중이시라면 '0'일 가능성이 높습니다.현재 USER_MEMBER와 user_member 테이블이 동시에 존재하고, 로그인 기능이 특정 테이블에만 연결되어 있다면, 설정이나 Entity 매핑에서 일관성이 필요한 상황으로 보입니다.운영체제와 MySQL 설정을 먼저 확인하신 뒤, 실습 환경에 맞게 테이블 매핑을 정리하시면 정상적으로 동작할 수 있을 거예요. 항상 성실하게 실습에 임해주셔서 감사합니다.앞으로도 차근차근 실력을 쌓아가시길 진심으로 응원합니다!
- 0
- 3
- 49
Hỏi & Đáp
mysql 설치파일
culwonder.company님 안녕하세요.이번 강의는 실습 환경의 일관성을 위해 Windows 기반으로 구성되어 있습니다.다만, MacOS에서도 동일한 개발 도구(MySQL, Workbench 등)를 설치하고 실습을 진행하는 것이 충분히 가능합니다. 특히 Homebrew를 사용하면 간편하게 MySQL을 설치하실 수 있고, MySQL Workbench 또한 Mac용 설치 파일이 제공되니 걱정하지 않으셔도 됩니다!현재 본 강의에서는 MacOS 설치 및 환경 설정은 별도로 다루지 않으며, Mac 사용자분들께서는 공식 문서나 설치 가이드를 참고하여 실습 환경을 직접 구성해주셔야 합니다.맥북 사용자분들께는 다소 번거로울 수 있지만, 이를 통해 환경 구성 능력도 함께 키울 수 있는 좋은 기회가 될 수 있으니 긍정적으로 받아들여 주시면 감사하겠습니다.
- 0
- 2
- 38
Hỏi & Đáp
dto 타입
H K님 안녕하세요~^^DTO에서 String 타입을 사용한 데에는 특별한 이유가 있는 것은 아닙니다. 다만 학습자분들께 다양한 경험을 제공하고자 하는 의도가 있을 뿐입니다.ㅎㅎ참고로 학습이 아닌 실무 현장에서는 다양한 상황을 마주하게 되는데요, 어떤 프로젝트에서는 DTO 없이 Entity만 사용하는 경우도 있습니다.이는 절대 잘못된 방식이 아니라, 해당 프로젝트의 설계 방식이나 요구사항에 따른 선택일 뿐이라고 생각하시면 됩니다.지금처럼 다양한 관점에서 사고하고 계속해서 실전 감각을 키워가며 성장해나가시길 진심으로 응원할게요.홧팅~^^
- 0
- 1
- 36
Hỏi & Đáp
메일 보내는 메서드에서
HK님 안녕하세요. 지방 출장 일정으로 인해 답변이 늦어진 점 양해 부탁드립니다. 기다리게 해드려 죄송합니다. 앞으로 더 빠르게 응대할 수 있도록 노력하겠습니다.네. 물론입니다. try ~ catch를 사용하면 다음과 같은 코드가 되겠네요.try { MemberEntity updateMember = memberRepository.save(findedMemberEntity); sendNewPasswordByMail(memberDto.getMail(), newPassword); return NEW_PASSWORD_CREATION_SUCCESS;} catch (Exception e) { e.printStackTrace(); return NEW_PASSWORD_CREATION_FAIL;}감사합니다.
- 0
- 1
- 39
Hỏi & Đáp
인터셉터 질문
HK님 안녕하세요. 지방 출장 일정으로 인해 답변이 늦어진 점 양해 부탁드립니다. 기다리게 해드려 죄송합니다. 앞으로 더 빠르게 응대할 수 있도록 노력하겠습니다. 웹 애플리케이션에서 로그인 인증 여부에 따라 특정 서비스 접근 처리를 할 때 Filter와 Interceptor 모두 사용될 수 있습니다.둘은 동작 시점, 용도, 설계 목적 등에 있어 차이점이 있습니다. filter는 Servlet에 존재하면서 DispatcherServlet 앞에 위치해서 client의 모든 요청을 처리합니다.실행 흐름은 client의 요청 → Filter → DispatcherServlet 순이라고 이해하시면 됩니다.Interceptors는 Spring Framework에 존재하고 DispatcherServlet 뒤에 위치해서 컨트롤러 진입 전후에 실행됩니다.실행 흐름은 client의 요청 → DispatcherServlet → Interceptor → Controller 순이라고 이해하시면 됩니다.일반적으로 로그인 인증이나 권한 확인 등은 Spring MVC에서 처리되는 요청을 대상으로 하므로 Interceptor가 많이 사용됩니다.물론, Spring Security를 사용하면 더 정교하고 안전한 인증 및 권한 처리를 할 수 있습니다.결론적으로 로그인 인증이나 권한 확인이 목적이라면 Interceptor 보다는 Spring secutiry를 사용하면 됩니다.인증 외 요청 전/후에 특정 처리가 목적이라면 Interceptor를 사용할 수 있습니다.excludePathPatterns의 경우 학습자님들께 다양한 방법을 설명 드리고자 함입니다.excludePathPatterns는 특정 경로에 인터셉터를 적용하지 않도록 설정할 때 사용되며,상황에 따라 addPathPatterns와 함께 선택 또는 조합 해서 사용할 수 있습니다.오늘의 코딩 한 줄, 한 줄이 실력을 키우는 발판이 된다고 생각하고 계속 나아가는 마음이 중요하고 HK님의 질문에서 이러한 점이 느껴집니다.분명 멋진 개발자가 될 거예요. 파이팅입니다!감사합니다.
- 0
- 2
- 56
Hỏi & Đáp
AOP에 대한 설명
앗! 저의 다소 부정확한 설명으로 인해 학습에 오해나 불편을 드린 것 같아 먼저 죄송하다는 말씀을 드립니다. 다시 정확하게 정리해드리겠습니다. Spring AOP(Aspect-Oriented Programming)는 스프링 프레임워크의 한 부분입니다.Spring AOP는 스프링 프레임워크의 일부로 제공되며, 별도의 독립적인 프로젝트 이름은 없고, 스프링 프레임워크의 하위 모듈인 spring-aop에 포함되어 있습니다.스프링 프레임워크는 여러 모듈로 구성되어 있으며, 그중 AOP 기능은 spring-aop 모듈을 통해 제공됩니다. 추가로, Spring Boot는 AOP 기능을 쉽게 사용할 수 있도록 spring-boot-starter-aop 스타터를 제공합니다. 이 스타터에는 AOP 관련 기능을 자동으로 포함하고 있기 때문에, spring-boot-starter-aop 의존성을 설정하면 AOP 기능을 사용할 수 있습니다. 즉, spring-boot-starter-aop에 spring-aop 모듈이 포함되어 있어 별도로 spring-aop 의존성을 추가할 필요가 없습니다.다음은 build.gradle에서 spring-boot-starter-aop 의존성을 추가하는 코드입니다.implementation 'org.springframework.boot:spring-boot-starter-aop' 다시 한 번 학습에 불편을 드린 점 진심으로 사과드리며, 관련 동영상은 조속히 업데이트하도록 하겠습니다.추가로 궁금한 점이 있으시면 언제든지 편하게 문의해 주세요. 감사합니다.
- 0
- 2
- 101
Hỏi & Đáp
코드
peanutchan님 안녕하세요! 당연히, 각 수업(차시)마다 진행한 프로젝트가 정리되어 있습니다.프로젝트 소스는 강의자료를 다운로드하면 소스>pjt_intellij에 있습니다.예를 들어 33강 수업에 대한 프로젝트 소스는calendar_33강.zip이고,34강 수업에 대한 프로젝트 소스는 calendar_34강.zip입니다. 다만, '스프링 MVC를 이용한 스마트폰 연락처 서비스 구현 - I : 연락처 등록' 수업에 대한 프로젝트 소스는 'phonebook'으로 되어 있어 다소 불편함을 드린 듯합니다.불편함을 해결하고자 급하게 해당 수업에 진행한 프로젝트를 정리했습니다. 참고하시면 보다 편하게 학습하실 수 있을 거예요. 강의제목(강의번호)(프로젝트 소스 이름) [섹션02]DI 쉽게 이해하기 - I : 그동안 객체를 잘못 다루고 있었네요 (11강)(mycalculator)DI 쉽게 이해하기 - II : 아하! 객체는 이렇게 다루는 거구나!! (12강)(mycalculator)IoC 쉽게 이해하기 : 스프링이 대신 관리해준다고? (13강)(mycalculator)학습 내용을 정리하며 마무리하는 DI와 IoC 실습: 의존성 주입과 제어의 역전, Java 코드로 직접 경험하기 (14강)(mymessage) [섹션03]처음 만들어 보는 스프링 부트 프로젝트 (15강)(ch03_pjt_01)프로젝트 구조 이해하기-I : src 디렉터리의 이해 (16강)(ch03_pjt_01)프로젝트 구조 이해하기-II : 빌드의 이해 (17강)(ch03_pjt_01)서블릿과 스프링 MVC의 이해 - I : 서블릿 컨테이너와 IoC 컨테이너 (18강)(ch03_pjt_01)서블릿과 스프링 MVC의 이해 - II : HTTP 요청과 응답 (19강)(ch03_pjt_01)스프링 MVC를 이용한 회원가입 및 로그인 구현 - I : 양식 화면 (20강)(ch03_pjt_02)스프링 MVC를 이용한 회원가입 및 로그인 구현 - II : 결과 화면 (21강)(ch03_pjt_02)@RequestParam과 Model : 데이터 전달과 화면 렌더링 (22강)(ch03_pjt_02)스프링 MVC를 이용한 스마트폰 연락처 서비스 구현 - I : 연락처 등록 (23강)(phonebook)스프링 MVC를 이용한 스마트폰 연락처 서비스 구현 - II : 연락처 조회 (24강)(phonebook) [섹션04]애플리케이션 예제 준비 : 프로젝트 복사 (25강)(ch04_pjt_01)Service 빈 객체 구현 - I : 스프링 설정파일 (26강)(ch04_pjt_01)Service 빈 객체 구현 - II : @Configuration (27강)(ch04_pjt_01)Service 빈 객체 구현 - III : @Service (28강)(ch04_pjt_01)DAO 빈 객체 구현 (29강)(ch04_pjt_01)로그인 Service, DAO 구현 (30강)(ch04_pjt_01) [섹션05]홈(home.html) 화면 만들기 (33강)(calendar_33강.zip)사용자 회원가입 기능 구현 (34강)(calendar_34강.zip)데이터베이스 연동하기 - I : JdbcTemplate (36강)(calendar_36강.zip)데이터베이스 연동하기 - II : DAO에서 회원가입 처리하기 (37강)(calendar_37강.zip)데이터베이스 연동하기 - III : 비밀번호 암호화 (38강)(calendar_38강.zip)데이터베이스 연동하기 - IV : 회원가입 결과 화면 (39강)(calendar_39강.zip) [섹션06]사용자 로그인 기능 구현 (40강)(calendar_40강.zip)세션을 이용한 로그인 상태유지 (41강)(calendar_41강.zip) [섹션07]계정수정 기능 구현 (42강)(calendar_42강.zip)비밀번호 찾기 기능 구현 - I : 메일 발송 준비 (43강)(calendar_43강.zip)비밀번호 찾기 기능 구현 - II : 메일 발송 구현 (44강)(calendar_44강.zip)인터셉터(Interceptor) (45강)(calendar_45강.zip) [섹션08]다양한 의존성 주입(DI) 방법 (46강)(calendar_46강.zip)롬북(lombok) : 자동 코딩 (47강)(calendar_47강.zip)로거(logger) : Log4j2 - I : log4j2 설정과 사용 (48강)(calendar_48강.zip)로거(logger) : Log4j2 - II : 로그 파일 이용 (49강)(calendar_49강.zip)로거(logger) : Log4j2 - III : 로그 파일 분리 (50강)(calendar_50강.zip) [섹션09]MyBatis - I : 쿼리에만 집중하자! (51강)(calendar_51강.zip)MyBatis - II : 설정 파일과 매핑 기법 (52강)(calendar_52강.zip) [섹션10]멤버 서비스 CRUD에 JPA 적용하기 - I : Entity 만들기 (54강)(calendar_54강.zip)멤버 서비스 CRUD에 JPA 적용하기 - II : EntityManager 만들기 (55강)(calendar_55강.zip)리펙토링 (56강)(calendar_56강.zip) [섹션11]Spring Security 적용 - I (58강)(calendar_58강.zip)Spring Security 적용 - II (59강)(calendar_59강.zip)리펙토링 (60강)(calendar_60강.zip) [섹션12]관리자 프로젝트 생성 (61강)(calendaradmin_61강.zip)관리자 멤버 서비스 (62강)(calendaradmin_62강.zip)관리자 권한 변경 하기 - I : 관리자 목록 구현 (64강)(calendaradmin_64강.zip)관리자 권한 변경 하기 - II : 관리자 권한 변경 구현 (65강)(calendaradmin_65강.zip)사용자 권한 변경 하기 - I : 사용자 목록 구현 (66강)(calendaradmin_66강.zip)사용자 권한 변경 하기 - II : 사용자 권한 변경 구현 (67강)(calendaradmin_67강.zip) [섹션13]Spring Secutiry 인가(Authorization) 설정 (68강)(calendar_68강.zip)캘린더 기본 UI 만들기 (69강)(calendar_69강.zip) [섹션14]일정 등록 기능 구현 - I : 프론트 엔드 (70강)(calendar_70강.zip)일정 등록 기능 구현 - II : 백 엔드 (71강)(calendar_71강.zip)일정 조회 기능 구현 (72강)(calendar_72강.zip) [섹션15]일정 수정 기능 구현 (73강)(calendar_73강.zip)일정 삭제 기능 구현 (74강)(calendar_74강.zip) 추가로 궁금한 점이 있으시면 언제든지 편하게 문의해주세요.항상 응원하고 있겠습니다!
- 0
- 1
- 120