From 7eba0a78b3b6d4b5979bba6936b5d5c4e9550fe2 Mon Sep 17 00:00:00 2001 From: seplease Date: Fri, 10 Jan 2025 21:03:48 +0900 Subject: [PATCH] =?UTF-8?q?Vol2=205,6=EC=9E=A5=20=EB=B0=8F=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...54\264\210\353\202\234\352\260\220 DAO.md" | 0 ...O\354\235\230 \353\266\204\353\246\254.md" | 0 ...O\354\235\230 \355\231\225\354\236\245.md" | 0 ...\235\230 \354\227\255\354\240\204(IoC).md" | 0 ...55\224\204\353\247\201\354\235\230 IoC.md" | 0 ...0 \354\212\244\354\275\224\355\224\204.md" | 0 ...2\263\204 \354\243\274\354\236\205(DI).md" | 0 ...4\354\213\234 \353\263\264\352\270\260.md" | 0 ...2 UserDaoTest \352\260\234\354\204\240.md" | 0 ...\236\204\354\233\214\355\201\254 JUnit.md" | 0 ...4\355\212\270 \354\240\201\354\232\251.md" | 0 ...4 \354\212\244\355\224\204\353\247\201.md" | 0 .../2.6 \354\240\225\353\246\254.md" | 0 ...5 \355\205\234\355\224\214\353\246\277.md" | 0 ...4\353\235\274\354\247\204 SQLException.md" | 0 ...0\354\231\270 \354\240\204\355\231\230.md" | 0 .../4.3 \354\240\225\353\246\254.md" | 0 .../5.2, 5.3.md" | 0 ...4\354\235\230 \353\266\204\353\246\254.md" | 0 ...4 \355\205\214\354\212\244\355\212\270.md" | 0 ...1\355\206\240\353\246\254 \353\271\210.md" | 0 ...1\355\206\240\353\246\254 \353\271\210.md" | 0 ...54\212\244\355\224\204\353\247\201 AOP.md" | 0 ...5\354\205\230 \354\206\215\354\204\261.md" | 0 ...54\354\235\270\355\212\270\354\273\267.md" | 0 ...0 \355\205\214\354\212\244\355\212\270.md" | 0 ...50\355\205\215\354\212\244\355\212\270.md" | 0 ...5\353\263\264 \354\204\244\354\240\225.md" | 0 ...4 \354\212\244\354\275\224\355\224\204.md" | 0 ...24\355\203\200\354\240\225\353\263\264.md" | 0 ...354\235\264\353\204\210\354\231\200 DI.md" | 0 .../1.6 \354\240\225\353\246\254,md" | 0 ...5\355\206\265 \352\260\234\353\205\220.md" | 0 .../2.2 JDBC.md" | 0 .../2.4 JPA.md" | 0 ...04\353\204\244\354\235\264\355\212\270.md" | 0 ...70\353\236\234\354\236\255\354\205\230.md" | 0 .../5\354\236\245 AOP\354\231\200 LTW.md" | 160 ++++++++++++++++++ ...10\354\236\204\354\233\214\355\201\254.md" | 75 ++++++++ 39 files changed, 235 insertions(+) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" (100%) rename "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" => "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" (100%) rename "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" => "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" (100%) rename "\352\271\200\354\213\234\354\235\200/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" => "\352\271\200\354\213\234\354\235\200/Vol1/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" (100%) rename "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" => "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" (100%) rename "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" => "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" (100%) rename "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" => "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" (100%) rename "\352\271\200\354\213\234\354\235\200/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" => "\352\271\200\354\213\234\354\235\200/Vol1/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" (100%) rename "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" => "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" => "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" => "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" => "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" => "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" => "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" (100%) rename "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" => "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" (100%) create mode 100644 "\352\271\200\354\213\234\354\235\200/Vol2/5\354\236\245 AOP\354\231\200 LTW/5\354\236\245 AOP\354\231\200 LTW.md" create mode 100644 "\352\271\200\354\213\234\354\235\200/Vol2/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 \354\264\210\353\202\234\352\260\220 DAO.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 DAO\354\235\230 \353\266\204\353\246\254.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 DAO\354\235\230 \355\231\225\354\236\245.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \354\240\234\354\226\264\354\235\230 \354\227\255\354\240\204(IoC).md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201\354\235\230 IoC.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\213\261\352\270\200\355\206\244 \353\240\210\354\247\200\354\212\244\355\212\270\353\246\254\354\231\200 \354\230\244\353\270\214\354\240\235\355\212\270 \354\212\244\354\275\224\355\224\204.md" diff --git "a/\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" "b/\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.7 \354\235\230\354\241\264\352\264\200\352\263\204 \354\243\274\354\236\205(DI).md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.1 UserDaoTest \353\213\244\354\213\234 \353\263\264\352\270\260.md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.2 UserDaoTest \352\260\234\354\204\240.md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.3 \352\260\234\353\260\234\354\236\220\353\245\274 \354\234\204\355\225\234 \355\205\214\354\212\244\355\214\205 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254 JUnit.md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.4 \354\212\244\355\224\204\353\247\201 \355\205\214\354\212\244\355\212\270 \354\240\201\354\232\251.md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.5 \355\225\231\354\212\265 \355\205\214\354\212\244\355\212\270\353\241\234 \353\260\260\354\232\260\353\212\224 \354\212\244\355\224\204\353\247\201.md" diff --git "a/\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/2\354\236\245 \355\205\214\354\212\244\355\212\270/2.6 \354\240\225\353\246\254.md" diff --git "a/\352\271\200\354\213\234\354\235\200/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/3\354\236\245 \355\205\234\355\224\214\353\246\277/3\354\236\245 \355\205\234\355\224\214\353\246\277.md" diff --git "a/\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.1 \354\202\254\353\235\274\354\247\204 SQLException.md" diff --git "a/\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.2 \354\230\210\354\231\270 \354\240\204\355\231\230.md" diff --git "a/\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/4\354\236\245 \354\230\210\354\231\270/4.3 \354\240\225\353\246\254.md" diff --git "a/\352\271\200\354\213\234\354\235\200/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/5\354\236\245 \354\204\234\353\271\204\354\212\244 \354\266\224\354\203\201\355\231\224/5.2, 5.3.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.1 \355\212\270\353\236\234\354\236\255\354\205\230 \354\275\224\353\223\234\354\235\230 \353\266\204\353\246\254.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.2 \352\263\240\353\246\275\353\220\234 \353\213\250\354\234\204 \355\205\214\354\212\244\355\212\270.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.3 \353\213\244\354\235\264\353\202\264\353\257\271 \355\224\204\353\241\235\354\213\234\354\231\200 \355\214\251\355\206\240\353\246\254 \353\271\210.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.4 \354\212\244\355\224\204\353\247\201\354\235\230 \355\224\204\353\241\235\354\213\234 \355\214\251\355\206\240\353\246\254 \353\271\210.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.5 \354\212\244\355\224\204\353\247\201 AOP.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.6 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.7 \354\225\240\353\205\270\355\205\214\354\235\264\354\205\230 \355\212\270\353\236\234\354\236\255\354\205\230 \354\206\215\354\204\261\352\263\274 \355\217\254\354\235\270\355\212\270\354\273\267.md" diff --git "a/\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" "b/\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" rename to "\352\271\200\354\213\234\354\235\200/Vol1/6\354\236\245 AOP/6.8 \355\212\270\353\236\234\354\236\255\354\205\230 \354\247\200\354\233\220 \355\205\214\354\212\244\355\212\270.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.1 IoC\354\273\250\355\205\214\354\235\264\353\204\210. \353\271\210 \355\214\251\355\206\240\353\246\254\354\231\200 \354\225\240\355\224\214\353\246\254\354\274\200\354\235\264\354\205\230 \354\273\250\355\205\215\354\212\244\355\212\270.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.2 IoC, DI\353\245\274 \354\234\204\355\225\234 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264 \354\204\244\354\240\225.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.3 \355\224\204\353\241\234\355\206\240\355\203\200\354\236\205\352\263\274 \354\212\244\354\275\224\355\224\204.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.4 \352\270\260\355\203\200 \353\271\210 \354\204\244\354\240\225 \353\251\224\355\203\200\354\240\225\353\263\264.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.5 \354\212\244\355\224\204\353\247\201 3.1\354\235\230 IOC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" "b/\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/1\354\236\245 IoC \354\273\250\355\205\214\354\235\264\353\204\210\354\231\200 DI/1.6 \354\240\225\353\246\254,md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.1 \352\263\265\355\206\265 \352\260\234\353\205\220.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.2 JDBC.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.4 JPA.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.5 \355\225\230\354\235\264\353\262\204\353\204\244\354\235\264\355\212\270.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" similarity index 100% rename from "\352\271\200\354\213\234\354\235\200/Vol2 2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" rename to "\352\271\200\354\213\234\354\235\200/Vol2/2\354\236\245 \353\215\260\354\235\264\355\204\260 \354\225\241\354\204\270\354\212\244 \352\270\260\354\210\240/2.6 \355\212\270\353\236\234\354\236\255\354\205\230.md" diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2/5\354\236\245 AOP\354\231\200 LTW/5\354\236\245 AOP\354\231\200 LTW.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/5\354\236\245 AOP\354\231\200 LTW/5\354\236\245 AOP\354\231\200 LTW.md" new file mode 100644 index 0000000..51b0fc0 --- /dev/null +++ "b/\352\271\200\354\213\234\354\235\200/Vol2/5\354\236\245 AOP\354\231\200 LTW/5\354\236\245 AOP\354\231\200 LTW.md" @@ -0,0 +1,160 @@ +AOP와 LTW += +스프링은 AspectJ라는 뛰어난 AOP 프레임워크로부터 포인트컷 표현식과 함께 애노테이션을 이용해 AOP 모듈을 개발하는 방법도 도입했다. 또, 스프링의 프록시 +방식 AOP 대신 AspectJ 라이브러리를 직접 활용하는 방법과 로딩 시점의 바이트코드 조작을 통해 DI 기능을 확장하는 방법등을 알아볼 것이다. +
+ +## 5.1 애스펙트 AOP +### 5.1.1 프록시 기반 AOP +##### 프록시 기반 AOP 개발 스타일의 종류와 특징 +AOP는 모듈화된 부가기능(어드바이스)과 적용 대상(포인트컷)의 조합을 통해 여러 오브젝트에 산재해서 나타나는 공통적인 기능을 손쉽게 개발하고 관리할 수 있는 기술이다. +스프링은 자바 JDK에서 지원하는 다이내믹 프록시 기술을 이용해, 복잡한 빌드 과정이나 바이트코드 조작 기술 없이도 유용한 AOP를 적용할 수 있는 프록시 시반 AOP 개발 기능을 제공한다. + +프록시 방식의 AOP는 객체지향 디자인 패턴의 데코레이터 패턴 또는 프록시 패턴을 응용해서, 기존 코드에 영향을 주지 않은 채로 부가기능을 타깃 오브젝트에 제공할 수 있는 객체지향 프로그래밍 +모델로부터 출발한다. 여기에 포인트컷이라는 적용 대상 선택 기법과 자동 프록시 생성이라는 적용 기법까지 접목하면, 비로소 AOP라고 부를 수 있는 효과적인 +부가기능 모듈화가 가능해진다. + +스프링은 가장 기초적이고 단순한 방법부터 최신 AOP 기술의 개발 방법을 차용한 방법에 이르기까지 여러 가지 종류의 프록시 기반 AOP 개발 방법을 지원한다. +- AOP 인터페이스 구현과 `````` 등록을 이용하는 방법 +- AOP 인터페이스 구현과 aop 네임스페이스의 `````` 태그를 이용하는 방법 +- 임의의 자바 클래스와 aop 네임스페이스의 ``````를 이용하는 방법 +- @AspectJ 애노테이션을 이용한 애스펙트 개발 방법 +##### 자동 프록시 생성기와 프록시 빈 +스프링 AOP를 사용한다면 어떤 개발 방식을 적용하든 모두 프록시 방식의 AOP다. 스프링의 프록시 개념은 데코레이터 패턴에서 나온 것이고, 동작원리는 JDK 다이내믹 +프록시와 DI를 이용한다. +###### 자동 프록시 생성기의 특징 +- AOP 적용은 @Autowired의 타입에 의한 의존관계 설정에 문제를 일으키지 않는다 +- AOP 적용은 다른 빈들이 Target 오브젝트에 직접 의존하지 못하게 한다 +##### 프록시의 종류 +인터페이스를 구현한 프록시와 클래스를 직접 참조하면서 강한 의존관계를 맺고 있는 경우에 Client -> Target과 같이 직접적인 의존관계를 만든 경우에도 인터페이스 없이 프록시를 만들 수 있다. +- 클래스를 이용한 프록시를 적용하는 방법 + 1. 아예 아무런 인터페이스도 구현하지 않은 타깃 클래스에 AOP를 적용한다. + 2. 강제로 클래스 프록시를 만들도록 설정한다. +### 5.1.2 @AspectJ AOP +@AspectJ는 애스펙트를 자바 클래스와 메소드, 그리고 애노테이션을 이용해서 정의하는 방법을 가리키는 말이다. +##### @AspectJ를 이용하기 위한 준비사항 +@AspectJ라는 이름의 애노테이션은 없다. 특정 AOP 개발 방법을 가리키는 용어일뿐이다. 애노테이션 방식의 MVC 개발 방법을 @MVC라고 부르는 것과 마찬가지다. +@AspectJ 방식의 애스펙트를 사용하려면 XML 설정파일에 aop 스키마의 태그를 이용한 선언을 넣어줘야 한다. `````` + +이 선언은 빈으로 등록된 클래스 중에서 클래스 레벨에 @Aspect가 붙은 것을 모두 애스펙트로 자동 등록해준다. @AspectJ 방식에서 사용하는 핵심 애노테이션은 @Aspect다. + +두 번째로, AspectJ의 런타임 라이브러리를 클래스패스에 추가해줘야 한다. +##### @Aspect 클래스와 구성요소 +애스펙트는 자바 클래스에 @Aspect라는 애노테이션을 붙여서 만든다. @Aspect 클래스는 기본적으로 @Configuration처럼 자바 코드로 만든 메타정보로 활용된다. 클래스를 애스펙트로 사용하려면 먼저 빈으로 등록해야 한다. +`````` 태그나 @Component를 붙여서 자동스캔 방식으로 등록해도 된다. +- 포인트컷: @Pointcut + - 포인트컷은 @Pointcut 애노테이션이 달린 메소드를 이용해 선언한다. 선택 로직은 @Pointcut 안에 포인트컷 표현식을 넣어서 정의한다. 메소드의 내부에 코드를 작성할 필요는 없다. 단지 메소드의 선언부를 메타정보로 이용해서 포인트컷의 이름과 파라미터를 정의하는 용도로만 사용한다. +- 어드바이스: @Before, @AfterReturning, @AfterThrowing, @After, @Around + - 어드바이스도 포인트컷과 마찬가지로 애노테이션이 붙은 메소드를 이용해 정의한다. @AspectJ에서는 다섯 가지 종류의 어드바이스를 사용할 수 있다. 각 종류별로 애노테이션이 하나씩 정의되어 있다. 어드바이스 로직은 메소드 내의 자바 코드로 작성한다. 메소드의 파라미터와 리턴 값은 어드바이스 종류와 포인트컷에서 선언한 파라미터에 따라 달라질 수 있다. +##### 포인트컷 메소드와 애노테이션 +###### @Aspect 클래스 안에서 포인트컷을 정의하는 방법 +포인트컷은 @Pointcut 애노테이션과 메소드의 이름, 파라미터로 정의된다. 포인트컷 메소드에는 구현 코드는 필요 없다. 단, 포인트컷 메소드의 리턴 타입은 항상 void형이어야 한다. +```@Pointcut("execution(* sayHello(..))") private void hello();``` + +포인트컷은 적용할 조인 포인트를 선별하는 것이다. 조인 포인트는 어드바이스로 정의된 부가기능을 적용할 수 있는 위치다. 스프링에서는 프록시 방식의 AOP를 사용하기 때문에 +조인 포인트는 메소드 실행 지점뿐이다. 따라서 포인트컷 설명에서 조인 포인트라고 하면 메소드를 가리킨다고 이해하면 된다. + +포인트컷 표현식은 execution()을 포함해서 여러 종류의 포인트컷 지시자(PCD, Pointcut Designator)를 이용해 정의할 수 있다. +- execution() + - 가장 대표적이고 가장 강력한 포인트컷 지시자다. 접근제한자, 리턴 타입, 타입, 메소드, 파라미터 타입, 예외 타입 조건을 조합해서 메소드 단위까지 선택 가능한 가장 정교한 포인트컷을 만들 수 있다. +- within() + - within()은 타입 패턴만을 이용해 조인 포인트 메소드를 선택한다. 패턴을 이용할 수 있기 때문에 자바 패키지 단위의 선택이 가능하다. +- this, target + - this와 target은 여러 개의 타입을 고를 수 있는 타입 패턴이 아니라 하나의 타입을 지정하는 방식이다. this와 target은 오브젝트를 선별한다. this는 빈 오브젝트의 타입을 확인하고, target은 타깃 오브젝트의 타입과 비교한다. +- args + - args 지시자는 메소드의 파라미터 타입만을 이용해 포인트컷을 선정할 때 사용한다. execution() 지사자의 () 안에 들어가는 파라미터 타입과 동일하다고 보면 된다. 보통 args는 다른 지시자와 함께 사용한다. 하나의 포인트컷 표현식 안에 여러 개의 지시자를 함께 사용할 수 있다. args는 포인트컷 파라미터를 적용하기 위해서도 자주 사용된다. +- @target, @within + - @target 지시자는 타깃 오브젝트에 특정 애노테이션이 부여된 것을 선정한다. + - @within은 타깃 오브젝트의 클래스에 특정 애노테이션이 부여된 것을 찾는다. + - @within은 @target과 유사하게 타깃 오브젝트의 클래스에 애노테이션이 부여된 것을 찾지만, 선택될 조인 포인트인 메소드는 타깃 클래스에서 선언되어 있어야 한다. 따라서 슈퍼클래스의 메소드는 해당이 되지 않는다. within과 다르게 패턴을 사용하지 않고 특정 타입을 지정한다. +- @args + - @args는 args와 유사하게 파라미터를 이용해 선정한다. 파라미터 오브젝트에 지정된 애노테이션이 부여되어 있느 ㄴ경우 선정 대상이 된다. +- @annotation + - @annotation은 조인 포인트 메소드에 특정 애노테이션이 있는 것만 선정하는 지시자다. +- bean + - bean은 빈 이름 또는 아이디를 이용해서 선정하는 지시자로, 와이드카드```(*)```를 사용할 수 있다. +> AOP를 학습하기 어려운 이유 중의 하나는 기억해야 할 포인트컷 지시자의 종류가 많고, 이를 적절히 활용해서 깔끔한 포인트컷을 만들기가 쉽지 않기 때문이다. +조건이 복잡한 포인트컷을 만들 때는 하나의 표현식에 모든 내용을 담기보다는 의미있는 작은 단위로 분리해서 정의한 후에 이를 조합하는 것이 좋다. + +> 포인트컷 표현식은 논리연산 기호를 이용해서 여러 개의 포인트컷 지시자 또는 포인트컷 자체를 조합할 수 있다. 포인트컷 표현식 안에 다른 포인트컷 이름을 사용하는 것도 가능하다. + +- && + - 두 개의 포인트컷 또는 지시자를 AND 조건으로 결합한다. +- ||, ! + - ||는 OR 조건이다. 두 가지 지시자 또는 포인트컷의 대상을 모두 포함하는 포인트컷을 정의할 때 사용한다. + - !는 NOT 조건이다. ! 뒤에 나오는 조건에 해당하는 것을 제외할 때 쓴다. +##### 어드바이스 메소드와 애노테이션 +@Aspect 클래스에 정의하는 어드바이스도 포인트컷과 마찬가지로 애노테이션과 메소드를 사용한다. 어드바이스는 다섯 가지 종류가 있다. 메소드 실행 과정의 일부분에만 적용하도록 만든 어드바이스가 있기 때문이다. +- @Around + - @Around는 프록시를 통해서 타깃 오브젝트의 메소드가 호출되는 전 과정을 모두 담을 수 있는 어드바이스다. + - @Around는 가장 강력한 기능을 가진 어드바이스다. @Around 어드바이스 내에서 원한다면 타깃 오브젝트의 메소드를 여러 번 호출하거나, 호출 파라미터를 바꿔치기 하거나, 심지어 타깃 오브젝트 메소드를 호출하지 않도록 만들 수도 있다. + - @Around는 나머지 어드바이스를 먼저 검토해서 어드바이스 로직을 적용할 수 있는지 확인하고, 적용 가능한 어드바이스가 없을 때만 최후의 선택으로 남겨두는 것이 바람직하다. +- @Before + - @Before는 타깃 오브젝트의 메소드가 실행되기 전에 사용되는 어드바이스다. @Before 어드바이스로는 타깃 오브젝트 메소드를 호출하는 방식을 제어할 수 없다. @Before를 적용해도 타깃 오브젝트 메소드 호출은 정상적으로 일어난다. + - @Before에는 JoinPoint 타입의 파라미터를 사용할 수 있다. + - 파라미터 자체를 변경할 수는 없어도 파라미터가 참조하는 오브젝트의 내용을 변경할 수는 있다. 파라미터 자체를 변경하려면 @Around를 사용해야 한다. +- @AfterReturning + - @AfterReturning은 타깃 오브젝트의 메소드가 실행을 마친 뒤에 실행되는 어드바이스다. 단, 예외가 발생하지 않고 정상적으로 종료한 경우에만 해당된다. 따라서 메소드에서 예외가 던져졌다면 이 어드바이스는 적용되지 않는다. + - 타깃 오브젝트의 메소드가 정상 종료된 후에 호출되기 때문에 메소드의 리턴 값을 참조할 수 있다. + - @AfterReturning은 리턴 값 자체를 바꿀 수는 없다. 리턴 값을 변경하려면 @Around를 사용해야 한다. 하지만 리턴 값이 레퍼런스 타입이라면 참조하는 오브젝트를 조작할 수는 있다. + - 리턴 값을 전달받을 파라미터의 타입을 구체적으로 지정해주면 리턴 값의 타입이 일치하는 경우에만 어드바이스가 실행된다. +- @AfterThrowing + - @AfterThrowing은 타깃 오브젝트의 메소드를 호출했을 때 예외가 발생하면 실행되는 어드바이스다. + - @AfterThrowing 애노테이션의 throwing 엘리먼트를 이용해서 예외를 전달받을 메소드 파라미터 이름을 지정할 수 있다. throwing으로 지정한 파라미터의 타입이 발생한 예외와 일치할 경우에만 어드바이스가 호출된다. + - 모든 예외를 다 전달받으려면 Throwable로 파라미터 타입을 지정한다. +- @After + - @After는 메소드 실행이 정상 종료됐을 때와 예외가 발생했을 때 모두 실행되는 어드바이스다. 코드에서 finally를 사용했을 때와 비슷한 용도라고 생각하면 된다. + - 반드시 반환돼야 하는 리소스가 있거나 메소드 실행 결과를 항상 로그로 남겨야 하는경우에 사용할 수 있다. 하지만 리턴 값이나 예외를 직접 전달받을 수는 없다. +##### 파라미터 선언과 바인딩 +어드바이스 메소드에는 JoinPoint, ProceedingJoinPoint를 기본적으로 사용할 수 있다. 또, 어드바이스 종류에 따라 returning이나 throwing을 이용해서 선언된 리턴 값 또는 예외 파라미터를 이용할 수 있다. 이 외에도 +포인트컷 표현식의 타입 정보를 파라미터와 연결하는 방법이 있다. + +> 포인트컷 표현식 내의 파라미터 이름은 포인트컷 메소드 또는 어드바이스 메소드의 파라미터 이름과 일치해야 한다. 스프링은 자바 클래스의 디버깅 정보를 이용해 파라미터 이름을 확인한다. 만약 디버깅 정보를 모두 제거했다면 argsName 엘리먼트를 이용해 직접 파라미터 이름을 지정할 수도 있다. +
+ +## 5.2 AspectJ와 @Configurable +#### 5.2.1 AspectJ AOP +AspectJ는 가장 강력한 AOP 프레임워크다. AspectJ는 아예 타깃 오브젝트 자체의 코드를 바꿈으로써 애스펙트를 적용한다. 따라서 프록시를 사용하지 않는다. 대신 타깃 오브젝트의 자바 코드에 처음부터 애스펙트가 적용되어 있던 것처럼 클래스 바이트코드를 변경하는 작업이 필요하다. 프록시 방식으로는 어드바이스를 적용할 수 없는 조인 포인트와 포인트컷 지시자를 지원하기 위해서다. AspectJ의 조인 포인트는 메소드 실행 지점 외에도 필드 읽기와 쓰기, 스태틱 초기화, 인스턴스 생성, 인스턴스 초기화 등도 지원한다. +#### 빈이 아닌 오브젝트에 DI 적용하기 +어디서든지 도메인 오브젝트가 생성되면 자동 DI 작업을 수행해주는 어드바이스를 적용해주는 것이다. 스프링의 빈이 아니더라도 수정자 메소드를 가진 임의의 오브젝트에는 스프링의 API의 도움을 받아서 간단히 DI를 할 수 있다. 문제는 특정 오브젝트가 생성되는 지점에 자동으로 DI 기능을 가진 어드바이스를 적용해줘야 한다는 점이다. 오브젝트 생성은 스프링 AOP에서 지원하는 조인포인트가 아니다. 따라서 다양한 조인 포인트를 지원하는 AspectJ AOP의 도움이 필요하다. +##### DI 애스펙트 +스프링은 AspectJ 기술로 만들어진 DependencyInjectionAspect라는 애스펙트를 제공한다. DependencyInjectionAspect 애스펙트가 적용되면 @Configurable이 붙은 도메인 오브젝트가 어디서든 생성될 때마다 이 어드바이스가 적용되어 자동 DI 작업이 일어난다. 또, 빈의 초기화 메소드가 정의되어 있다면 실행된다. DI 방식은 도메인 오브젝트를 빈으로 선언해서 명시적으로 지정할 수도 있고 자동와이어링 방식을 이용할 수도 있다. +##### @Configurable +@Configurable을 통해서 DI 애스펙트가 오브젝트 생성자에 적용되는 예 +``` +@Configurable +public class User { + ... +} +``` +> User는 DI 애스펙트의 포인트컷에 의한 선정 대상이 됐다. 남은 것은 어드바이스에서 자동 DI를 수행할 때 어떤 방식으로 사용할지 결정하는 일이다. +- @Configurable이 적용된 클래스의 DI를 설정하는 방법 + - `````` 설정 + - 자동와이어링 + - 애노테이션 의존관계 설정 +##### 로드타임 위버와 자바 에이전트 +- DI 애스펙트를 사용하려면 두 가지 작업이 필요하다. 먼저 AspectJ AOP가 동작할 수 있는 환경설정이 필요하고, 다음은 DI 애스펙트 자체를 등록해서 @Configurable 오브젝트에 어드바이스가 적용되게 해야 한다. +- AspectJ를 사용하려면 클래스를 로딩하는 시점에 바이트코드 조작이 가능하도록 로드타임 위버를 적용해줘야 한다. +- 스프링은 간단히 @Configurable을 이용하는 DI 애스펙트를 등록할 수 있도록 ``````태그를 제공한다. 이 태그를 추가하면 DI 애스펙트가 등록된다. +
+ +## 5.3 로드타임 위버(LTW) +``````는 단순히 @Configurable을 위해서만 사용되는 건 아니다. ``````를 통해 등록되는 로드타임 위버는 스프링에서 여러가지 기능에 활용된다. +1. @Configurable 지원 +2. ``````로 트랜잭션 AOP의 모드를 AspectJ로 설정하기 위함 +3. AspectJ가 아니라 JPA에서 필요로 하는 로드타임 위버로 사용되는 것. +> 스프링 로드타임 위버는 JPA와 AspectJ를 위한 로드타임 위버 기능을 대신해준다. + +주요 WAS는 클래스 로더 레벨에 로드타임 위빙 기능을 적용할 수 있는 방법을 제공한다. 클래스 로더를 사용하면 JVM 레벨에 적용되는 자바에이전트처럼 서버의 모든 클래스에 다 적용되지 않고 특정 애플리케이션 모듈에만 적용이 가능하므로 서버에 부담을 주지 않고 설정에서도 부담이 없다. 스프링은 자동으로 다음의 로드타임 위버 구현 방법 중에서 하나를 적용해준다. +- WAS 전용 로드타임 위버 +- JVM 자바에이전트 +- 관례를 따르는 클래스 로더 +> 스프링의 로드타임 위버는 환경에 따라 최적화된 방식을 자동으로 선정해주기 때문에 환경에 따라 설정을 바꿔야 한다는 부담을 덜어준다. 장기적으로 바이트코드 조작이 필요한 새로운 기술이 추가되더라도 일관된 방식으로 로드타임 위버를 적용할 수 있다. +
+ +## 5.4 스프링 3.1의 AOP와 LTW +### 5.4.1 AOP와 LTW를 위한 애노테이션 +- @EnableAspectJAutoProxy + - @EnableAspectJAutoProxy는 @Aspect로 애스펙트를 정의할 수 있게 해주는 @AspectJ AOP 컨테이너 인프라 빈을 등록해준다. +- @EnableLoadTimeWeaving + - @EnableLoadTimeWeaving은 XML의 ``````처럼 환경에 맞는 로드타임 위버를 등록해주는 애노테이션이다. \ No newline at end of file diff --git "a/\352\271\200\354\213\234\354\235\200/Vol2/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254.md" "b/\352\271\200\354\213\234\354\235\200/Vol2/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254.md" new file mode 100644 index 0000000..3a63cfa --- /dev/null +++ "b/\352\271\200\354\213\234\354\235\200/Vol2/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254/6\354\236\245 \355\205\214\354\212\244\355\212\270 \354\273\250\355\205\215\354\212\244\355\212\270 \355\224\204\353\240\210\354\236\204\354\233\214\355\201\254.md" @@ -0,0 +1,75 @@ +테스트 컨텍스트 프레임워크 += +스프링의 POJO와 DI를 이용한 프로그래밍 모델이 가져온 가장 큰 혜택 중 하나는 바로 테스트다. POJO 프로그래밍 모델은 단위 테스트를 손쉽게 작성할 수 있는 +환경을 제공해주고, 기술에 종속적이지 않은 코드를 작성하게 해준다. IoC와 DI로 인해, 서버에 배치하지 않고도 스프링 컨테이너만으로 DB까지 참여하는 +이상적인 통합테스트가 가능해진다. +
+ +## 6.1 테스트 컨텍스트 프레임워크 +스프링은 테스트에 사용되는 애플리케이션 컨텍스트를 생성하고 관리하고 테스트에 적용해주는 기능을 가진 테스트 프레임워크를 제공한다. 이를 테스트 컨텍스트 프레임워크라고 부른다. 테스트 컨텍스트 프레임워크는 스프링의 IoC/DI를 지원하는 애플리케이션 컨텍스트를 테스트에서 효과적으로 사용하게 해준다. 테스트 컨텍스트 프레임워크를 이용하면, 서버에서와 거의 동일한 구성으로 동작하는 통합 테스트를 손쉽게 만들 수 있다. +### 6.1.1 테스트 프레임워크와 컨텍스트 테스트 +자바에서 가장 많이 사용되는 테스트 프레임워크로는 JUnit과 TestNG가 있다. JUnit은 기존의 JUnit 3와 애노테이션 방식으로 새롭게 만들어진 JUnit 4로 다시 구분할 수 있다. 스프링 컨텍스트 테스트는 이 세 가지 테스트 프레임워크를 모두 지원한다. +##### 테스트용 애플리케이션 컨텍스트 캐싱과 설정파일 +- JUnit 4에서는 특정 클래스를 상속하지 않아도 테스트 코드를 작성할 수 있다. 테스트 메소드에 @Test라는 애노테이션만 붙여주면 메소드가 속한 클래스는 테스트 클래스가 되며, @Test가 붙은 모든 메소드가 각각 하나의 독립적인 테스트가 된다. +- 테스트가 독립적이라고 해서 매번 스프링 컨텍스트, 즉 컨테이너를 새로 만드는 건 매우 비효율적인 방법이기에, 스프링은 테스트가 사용하는 컨텍스트를 캐싱해서 여러 테스트에서 하나의 컨텍스트를 공유할 수 있는 방법을 제공한다. 동일한 컨텍스트 구성을 갖는 테스트끼리는 같은 컨텍스트를 공유하는 것이다. +- 테스트 컨텍스트 프레임워크가 적용된 테스트 예 +``` +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("/test-applicationContext") +public class Test1 { + @Test public void testMethod1() {...} + @Test public void testMethod2() {...} +} +``` +##### 컨텍스트 설정의 상속과 컨텍스트 로더 +- JUnit 4의 장점은 테스트 클래스가 특정 클래스를 상속하도록 강제하지 않는다는 것이다. 따라서 테스트 클래스를 구성할 때 필요하면 상속구조를 활용할 수도 있다. 슈퍼클래스와 서브클래스에서 모두 @ContextConfiguration을 이용해 컨텍스트 파일을 지정했다면 컨텍스트 파일 정보는 상속된다. 따라서 서브클래스의 컨텍스트 파일 정보는 슈퍼클래스에서 정의된 것까지 포함된다. 슈퍼클래스의 컨텍스트 파일 설정을 무시하고 새롭게 정의하고 싶다면 @ContextConfiguration의 inheritLocations를 false로 바꿔주면 된다. +- 테스트 컨텍스트를 로딩하는 방식을 변경하려면 ContextLoader 인터페이스를 구현한 클래스를 만들고 이를 @ContextConfiguration의 loader 엘리먼트에 지정해주면 된다. +#### 테스트 코드의 테스트 컨텍스트 활용 +'테스트 컨텍스트 프레임워크'의 '컨텍스트'는 애플리케이션 컨텍스트가 아니다. 테스트에서 사용되는 애플리케이션 컨텍스트를 생성하고 관리해주는 오브젝트를 가리키는 용어다. +##### 테스트 컨텍스트로부터 DI 받기 +테스트 클래스는 테스트 컨텍스트로부터 애플리케이션 컨텍스트와 그에 담긴 빈을 제공받아 테스트 코드에서 사용한다. 애플리케이션 컨텍스트를 제공받는 방법은 스프링답게 DI를 사용한다. ```@Autowired ApplicationContext context;``` 애플리케이션 컨텍스트 외에도 모든 컨텍스트 내의 원하는 빈을 제공받을 수 있다. +##### 공유 컨텍스트 사용 시 주의할 점 +- 캐싱 기법을 통해 하나의 컨텍스트를 여러 테스트가 공유할 수 있다는 건 테스트 컨텍스트 프레임워크의 장점이지만, 단점도 있다. 컨텍스트를 공유하는 테스트 메소드는 컨텍스트가 자신이 독점하는 것이 아니므로 그 구성이나 내부 정보를 함부로 변경해서는 안 된다. +- 테스트는 모두 고립돼서 동작해야 하고 테스트 결과도 자신이 검증하는 코드가 바뀌지 않는 한 항상 일정해야 한다. +> @DirtiesContext 애노테이션이 붙은 테스트가 수행되고 나면 스프링은 현 테스트 컨텍스트를 강제로 제거한다. 이후에 설정파일이 같은 컨텍스트를 사용하는 테스트가 진행된다면, 이때는 새로운 컨텍스트가 만들어진다. 따라서 다른 테스트에는 영향을 주지 않고 안전하게 컨텍스트를 조작하는 테스트를 만들 수 있다. +
+ +## 6.2 트랜잭션 지원 테스트 +### 6.2.1 테스트의 트랜잭션 지원 필요성 +테스트에서 트랜잭션 지원이 필요한 이유 +1. DAO 단독 테스트 + - DAO를 개발한 후에 서비스 계층을 거치지 않고 직접 DAO만 테스트해야 할 때, 스프링의 데이터 액세스 기술로 만든 DAO는 기본적으로 트랜잭션 동기화를 필요로 한다. +2. 롤백 테스트 + - 테스트에서 진행되는 모든 DB작업을 하나의 트랜잭션으로 묶어서 진행하고, 테스트를 마칠 때 트랜잭션을 모두 롤백시키는 **롤백 테스트**를 진행할 때 +#### 트랜잭션 지원 테스트 작성 방법 +##### 트랜잭션 매니저 +스프링의 모든 트랜잭션은 트랜잭션 매니저를 이용해 만들어지고 관리된다. 따라서 트랜잭션 매니저를 이용할 수 있으면 트랜잭션도 제어할 수 있다. +##### @Transactional 테스트 +테스트에서 트랜잭션 매니저를 DI 받아서 트랜잭션 템플릿과 함께 사용하는 방법은 DB를 이용하는 테스트의 요구조건을 모두 만족하긴 하지만, 테스트 코드가 지저분해진다는 단점이 있다. 템플릿/콜백 방식에서 나타나는 장황한 코드로 인해 테스트 코드를 이해하기도 조금 불편해진다. 그래서 스프링의 테스트 컨텍스트 프레임워크는 마치 AOP를 적용한 것과 유사항 방식으로 트랜잭션 기능을 테스트 메소드에 적용할 수 있게 해준다. 트랜잭션을 적용하고 싶은 메소드가 있으면 다음과 같이 @Transactioanl 애노테이션을 메소드에 부여해주면 된다. +##### ORM 롤백 트랜잭션 테스트의 주의사항 +하이버네이트나 JPA를 사용하는 롤백 테스트를 만들 때는 주의할 점이 있다. ORM은 기본적으로 모든 작업 결과를 바로 DB에 반영하지 않는다. 대신 가능한 한 오랫동안 메모리에 변경사항을 저장하고 있다가 꼭 필요한 시점에서 DB에 반영한다. 최적화를 위한 트랜잭션 내의 캐싱 기법이라고 볼 수 있다. ORM의 엔티티 오브젝트를 이용한 작업을 SQL로 만들어 DB로 보내는 것을 **플러시: flush**라고 한다. 기본적으로 ORM은 자동플러시 모드로 동작한다. 자동플러시 모드에서는 트랜잭션이 커밋되거나, 캐시에 저장해둔 정보가 반영되는 SELECT 쿼리를 실행해야 하거나, 코드에서 flush() 메소드를 실행해서 강제로 플러시하도록 만들 때만 트랜잭션 내의 캐시에 저장해뒀던 ORM 작업 결과를 SQL로 만들어 DB에서 실행시킨다. flush()와 내부 캐시를 강제로 비우도록 clear() 메소드를 잘 사용해야 한다. +##### 트랜잭션 지원 테스트에 DBUnit 이용하기 +DBUnit은 DB가 사용되는 테스트를 만들 때 유용하게 쓸 수 있는 지원 라이브러리다. XML이나 엑셀 파일에 준비해둔 테스트 데이터를 DBUnit의 명령을 이용해 DB에 삽입해주는 것이다. + +DBUnit을 통해 테스트 데이터를 주입하려면 먼저 DB 커넥션을 준비한 후에 IDatabaseConnection 타입 오브젝트로 만들어줘야 한다. 스프링의 트랜잭션 지원 테스트에서는 트랜잭션 매니저를 통해 내부적으로 DB 커넥션과 트랜잭션을 만들기 때문에 트랜잭션에 DBUnit을 참여시키려면 현재 트랜잭션이 사용하는 DB 커넥션을 가져와야 한다. + +현재 진행 중인 트랜잭션이 사용하는 DB 커넥션을 가져올 때는 DataSourceUtils의 getConnection() 메소드를 사용하면 된다. 먼저 DB 커넥션을 가져올 DataSource를 DI 받아 두고 getConnection() 메소드를 호출하면, 현재 진행 중인 트랜잭션이 사용하는 DB 커넥션을 돌려준다. 이를 사용해서 DBUnit의 IDatabaseConnection을 만들고 DBUnit의 테스트 데이터 등록 API를 사용하면, 테스트 코드와 같은 트랜잭션 안에 테스트 데이터를 삽입할 수 있다. 이렇게 준비된 데이터를 사용해서 테스트가 동작하고 트랜잭션이 끝나면, DBUnit의 테스트 데이터 등록 작업을 포함해서 모든 DB 작업이 롤백될 것이다. +
+ +## 6.3 스프링 3.1의 컨텍스트 테스트 프레임워크 +### 6.3.1 자바 코드 설정정보와 프로파일 활용 +##### @Configuration 클래스 테스트 +- 스프링 3.0의 컨텍스트 테스트 프레임워크는 테스트에서 사용할 애플리케이션 컨텍스트의 설정정보로 XML만 사용할 수 있었지만, 스프링 3.1에서는 XML 대신 @Configuration 클래스도 사용할 수 있다. +- 스프링 3.0에서라면 XML을 거치지 않으면 AppConfig 설정을 이용한 테스트를 할 수 없었다. 하지만 스프링 3.1이라면 @ContextConfiguration의 classes 엘리먼트를 이용해 @Configuration 클래스를 바로 지정해서 사용할 수 있다. +- @Configuration 클래스의 경우는 테스트 클래스의 스태틱 멤버 클래스 중에서 @Configuration이 붙은 것을 모두 디폴트 설정정보로 사용한다. +- 중첩 스태틱 클래스로 정의하는 디폴트 설정 클래스들은 private이거나 final로 선언되면 안 된다. 중첩 스태틱이면서 final이 아니고, private도 아닌 클래스만 적용된다. +- XML에도 디폴트 파일이 있고 @Configuration 클래스도 디폴트로 사용 가능한 클래스가 동시에 정의되어 있다면 에러가 난다. +##### @ActiveProfile +테스트는 서버가 아니라 독립 실행환경으로 동작하므로 표준 환경 오브젝트가 지원하는 환경변수와 시스템 프로퍼티를 이용해 활성 프로파일을 지정할 수 있다. 하지만 환경변수나 시스템 프로퍼티 설정은 번거롭다. 테스트를 실행하는 별도의 스크립트로 따로 만들지 않는다면 환경이 바뀔 때마다 테스트용 활성 프로파일 설정을 다시 해줘야 한다. 또, 한 번에 실행하는 테스트 클래스가 여러 개인데 각기 다른 활성 프로파일을 적용하고 싶다면 환경변수나 시스템 프로퍼티로 일괄 적용하는 방법을 사용할 수 없다. +> 그래서 스프링 3.1은 간편하게 테스트용 활성 프로파일을 지정할 수 있는 @ActiveProfiles를 제공한다. 다음 테스트 클래스는 설정정보 중에서 dev 프로파일만 활성화해서 테스트를 수행한다. +``` +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes=AppConfig.class) +@ActiveProfiles("dev") +public class MyAppTest { +``` \ No newline at end of file